SAFE Stack アプリのデータ保存 (4. クライアントの実装)
SAFE Stack の ToDo アプリはデータを保存できるようにする続き。
データ保存の API をサーバで提供 (link) するになったので、これをクライアントから利用できるようにした。
セーブの状態を SaveState
型で管理するようにしている。
他の処理は既存の Add (ToDo 項目の追加) のやり方を参考した。
(これはサーバの API 周りも同様)
diff --git a/src/Client/Index.fs b/src/Client/Index.fs
--- a/src/Client/Index.fs
+++ b/src/Client/Index.fs
@@ -14,6 +14,8 @@ let (|RE|_|) re str =
type Msg =
| GotTodos of Todo list
+ | SaveTodos
+ | SavedTodos of Todo List
| SetInput of string
| AddTodo
| AddedTodo of Todo
@@ -36,9 +38,15 @@ let logMessage (msg: Msg) =
()
#endif // DEBUG
+type SaveState =
+ | Saved
+ | Saving
+ | ToBeSaved
+
type Model = {
Todos: Todo list;
Input: string;
+ SaveState: SaveState;
DragFrom: string option;
DragOn: string option;
}
@@ -52,6 +60,7 @@ let init () : Model * Cmd<Msg> =
let model = {
Todos = [];
Input = "";
+ SaveState = Saving;
DragFrom = None;
DragOn = None;
}
@@ -95,7 +104,23 @@ let dropTarget_label2posOpt (label: string) =
let update (msg: Msg) (model: Model) : Model * Cmd<Msg> =
logMessage msg
match msg with
- | GotTodos todos -> { model with Todos = todos }, Cmd.none
+ | GotTodos todos ->
+ { model with
+ Todos = todos;
+ SaveState = Saved;
+ },
+ Cmd.none
+ | SaveTodos ->
+ { model with
+ SaveState = Saving
+ },
+ Cmd.OfAsync.perform todosApi.saveTodos () SavedTodos
+ | SavedTodos todos ->
+ { model with
+ Todos = todos;
+ SaveState = Saved;
+ },
+ Cmd.none
| SetInput value -> { model with Input = value }, Cmd.none
| AddTodo ->
let todo = Todo.create model.Input
@@ -106,7 +131,9 @@ let update (msg: Msg) (model: Model) : Model * Cmd<Msg> =
{ model with Input = "" }, cmd
| AddedTodo todo ->
{ model with
- Todos = model.Todos @ [ todo ] },
+ Todos = model.Todos @ [ todo ];
+ SaveState = ToBeSaved;
+ },
Cmd.none
| MoveTodo (srcLabel, dstLabel) ->
// ToDo: implement: more gentle error handling
@@ -128,7 +155,9 @@ let update (msg: Msg) (model: Model) : Model * Cmd<Msg> =
cmd
| MovedTodo todos ->
{ model with
- Todos = todos; },
+ Todos = todos;
+ SaveState = ToBeSaved;
+ },
Cmd.none
| DragStart label ->
{ model with
@@ -260,6 +289,14 @@ let containerBox (model: Model) (dispatch: Msg -> unit) =
]
]
]
+ Bulma.control.p [
+ Bulma.button.a [
+ color.isPrimary
+ prop.disabled (model.SaveState <> ToBeSaved)
+ prop.onClick (fun _ -> dispatch SaveTodos)
+ prop.text "Save"
+ ]
+ ]
]
let view (model: Model) (dispatch: Msg -> unit) =