From 28417d795a6922c3df3c2c0aea78a51648b0428e Mon Sep 17 00:00:00 2001 From: Sébastien Dailly Date: Mon, 7 Feb 2022 15:27:05 +0100 Subject: Added import button in editor --- editor/actions/add_page.ml | 8 +------ editor/actions/delete_page.ml | 3 +-- editor/actions/editor_actions.ml | 11 ++++++++-- editor/actions/export.ml | 16 ++++---------- editor/actions/import.ml | 31 ++++++++++++++++++++++++++ editor/actions/load_page.ml | 3 +-- editor/forms/selector.ml | 47 ++++++++++++++++++++++++++++++++++++++++ editor/state/state.ml | 26 ++++++++++++++++++++-- editor/state/state.mli | 5 ++++- editor/state/storage.ml | 24 ++++++++++++++++++++ editor/state/storage.mli | 3 +++ 11 files changed, 149 insertions(+), 28 deletions(-) create mode 100755 editor/actions/import.ml create mode 100755 editor/forms/selector.ml diff --git a/editor/actions/add_page.ml b/editor/actions/add_page.ml index 4a3fcf3..e5e8541 100755 --- a/editor/actions/add_page.ml +++ b/editor/actions/add_page.ml @@ -13,13 +13,7 @@ module M = struct : t -> State.t -> State.t = fun {title} state -> let page_id = key_of_title title in - let new_date = (new%js Js.date_now)##getTime in - let content_obj = object%js - val content = Js.null - val title = Js.some title - val date = Js.some new_date - end in - State.load_page (Some page_id) state content_obj + State.new_page ~title (Some page_id) state end (** Create a new element *) diff --git a/editor/actions/delete_page.ml b/editor/actions/delete_page.ml index fb600bd..58c1d32 100755 --- a/editor/actions/delete_page.ml +++ b/editor/actions/delete_page.ml @@ -9,8 +9,7 @@ module M = struct | None -> state | Some page_id -> State.Storage.delete (fun () -> Some page_id); - let json = State.Storage.load None in - State.load_page None state json + State.load_page None state end diff --git a/editor/actions/editor_actions.ml b/editor/actions/editor_actions.ml index 8c47363..70b078b 100755 --- a/editor/actions/editor_actions.ml +++ b/editor/actions/editor_actions.ml @@ -72,11 +72,17 @@ let populate_menu add_button) and export_event = + Evr.on_el + Ev.click + (fun _ -> Export.create ()) + export_button + + and import_event = Note.E.join ( Evr.on_el Ev.click - (fun _ -> Export.create ()) - export_button) + (fun _ -> Import.create ()) + load_button) in @@ -147,4 +153,5 @@ let populate_menu ; redirect_event ; add_event ; export_event + ; import_event ]) diff --git a/editor/actions/export.ml b/editor/actions/export.ml index a97eeac..71e3b64 100755 --- a/editor/actions/export.ml +++ b/editor/actions/export.ml @@ -31,16 +31,8 @@ end (** Create a new element *) let create - : unit -> State.event Note.event + : unit -> State.event = fun () -> - let title = Jstr.v "Confirmation" - and message = Jstr.v "Exporter les notes" in - let ev = Elements.Popup.create - ~title - ~form:(Some (Forms.Validation.create message )) - in - Note.E.map - (fun v -> State.E - ( v - , (module M : State.Event with type t = M.t ))) - (Note.E.Option.on_some ev) + State.E + ( () + , (module M : State.Event with type t = M.t )) diff --git a/editor/actions/import.ml b/editor/actions/import.ml new file mode 100755 index 0000000..fd4bef8 --- /dev/null +++ b/editor/actions/import.ml @@ -0,0 +1,31 @@ +module Js = Js_of_ocaml.Js + +module M = struct + + type t = Forms.Selector.t + + let update + : t -> State.t -> State.t + = fun t state -> + match t with + | None -> state + | Some file -> + (* Back to UTF-16 *) + let content = file.Forms.Selector.content in + Brr.Console.(log [content] ); + match State.Storage.of_json content with + | Error _ -> state + | Ok _obj -> + State.load_page state.State.page_id state +end + +let create () = + let title = Jstr.v "Importer des notes" in + let ev = Elements.Popup.create + ~title + ~form:(Some (Forms.Selector.create ())) in + Note.E.map + (fun v -> State.E + ( v + , (module M : State.Event with type t = M.t ))) + (Note.E.Option.on_some ev) diff --git a/editor/actions/load_page.ml b/editor/actions/load_page.ml index ceee038..349eaad 100755 --- a/editor/actions/load_page.ml +++ b/editor/actions/load_page.ml @@ -5,8 +5,7 @@ module M = struct let update : t -> State.t -> State.t = fun page_id state -> - let json = State.Storage.load page_id in - State.load_page page_id state json + State.load_page page_id state end diff --git a/editor/forms/selector.ml b/editor/forms/selector.ml new file mode 100755 index 0000000..1354dcc --- /dev/null +++ b/editor/forms/selector.ml @@ -0,0 +1,47 @@ +open Brr + +type file = + { file : File.t + ; content : Jstr.t + } + +type t = file option + +(** Read the content from the file *) +let file_loader + : file option Note.E.send -> File.t -> unit + = fun event file -> + let blob = File.as_blob file in + Fut.await + (Blob.text blob) + (Result.iter + (fun content -> + event (Some {file; content}) )) +let create + : unit -> t Note.signal * Brr.El.t + = fun () -> + + let add_file_event, add_file_sender = Note.E.create () in + + let i = El.input () + ~at:[ At.type' (Jstr.v "file") + ; (At.v (Jstr.v "accept")) (Jstr.v ".json") + ] in + + (* The event return a list of files. + + We are only interested by a single on, and keep only the first from the + list. *) + let on_change files = + file_loader add_file_sender (List.hd files) in + + Ev.listen + Ev.change + (fun _e -> on_change (El.Input.files i)) (El.as_target i); + + let state = Note.S.hold + None + add_file_event + in + ( state + , i ) diff --git a/editor/state/state.ml b/editor/state/state.ml index 649473c..2662a48 100755 --- a/editor/state/state.ml +++ b/editor/state/state.ml @@ -60,8 +60,9 @@ let state_of_storage PM.State.fromJSON pm obj page_content) let load_page - : Jstr.t option -> t -> Storage.content Js.t -> t - = fun page_id state json -> + : Jstr.t option -> t -> t + = fun page_id state -> + let json = Storage.load page_id in let editor_state = state_of_storage state.pm json state.view##.state##.schema in let () = state.view##updateState editor_state and () = set_title json in @@ -74,6 +75,27 @@ let load_page { state with page_id ; last_backup } +let new_page + : Jstr.t option -> title:Jstr.t -> t -> t + = fun page_id ~title state -> + let new_date = (new%js Js.date_now)##getTime in + let content_obj = object%js + val content = Js.null + val title = Js.some title + val date = Js.some new_date + end in + let editor_state = state_of_storage state.pm content_obj state.view##.state##.schema in + let () = state.view##updateState editor_state + and () = set_title content_obj in + + let last_backup = + Js.Opt.case content_obj##.date + (fun () -> state.last_backup ) + (fun v -> v) in + + { state with page_id + ; last_backup } + let init : PM.t -> PM.View.editor_view Js.t -> float -> Jstr.t option -> t diff --git a/editor/state/state.mli b/editor/state/state.mli index 20d5288..2f3e9c4 100755 --- a/editor/state/state.mli +++ b/editor/state/state.mli @@ -22,7 +22,10 @@ val state_of_storage : Prosemirror.t -> Storage.content Js.t -> Prosemirror.Model.schema Js.t -> Prosemirror.State.editor_state Js.t val load_page - : Jstr.t option -> t -> Storage.content Js.t -> t + : Jstr.t option -> t -> t + +val new_page + : Jstr.t option -> title:Jstr.t -> t -> t (** Initialise a new state *) val init diff --git a/editor/state/storage.ml b/editor/state/storage.ml index a790a9d..1bb8b81 100755 --- a/editor/state/storage.ml +++ b/editor/state/storage.ml @@ -157,3 +157,27 @@ let to_json (* Also add the home page *) let pages = Array.of_list @@ (save_for_id None)::pages in Brr.Json.encode (Jv.Id.to_jv pages) + +let of_json + : Jstr.t -> (unit, Jv.Error.t) result + = fun json -> + let result = Json.decode json in + Result.map + (fun v -> + Array.iter (Jv.Id.of_jv v) + ~f:(fun element -> + let key = element##.id + and content = object%js + val title = element##.title + val content = element##.content + val date = element##.date + end in + ignore @@ + save + ~check:(fun _ -> true) + content + key + )) + result + + diff --git a/editor/state/storage.mli b/editor/state/storage.mli index 50e164e..4d022d1 100755 --- a/editor/state/storage.mli +++ b/editor/state/storage.mli @@ -37,3 +37,6 @@ val get_ids val to_json : unit -> Jstr.t + +val of_json + : Jstr.t -> (unit, Jv.Error.t) result -- cgit v1.2.3