From 72e3b16bbd258e63f047392c973ba5e8f0a823c8 Mon Sep 17 00:00:00 2001 From: Sébastien Dailly Date: Tue, 1 Jun 2021 13:11:58 +0200 Subject: Added export button in editor --- editor/actions/actions.ml | 133 ---------------------------------- editor/actions/delete_page.ml | 7 +- editor/actions/dune | 3 +- editor/actions/editor_actions.ml | 150 +++++++++++++++++++++++++++++++++++++++ editor/actions/export.ml | 46 ++++++++++++ 5 files changed, 202 insertions(+), 137 deletions(-) delete mode 100755 editor/actions/actions.ml create mode 100755 editor/actions/editor_actions.ml create mode 100755 editor/actions/export.ml (limited to 'editor/actions') diff --git a/editor/actions/actions.ml b/editor/actions/actions.ml deleted file mode 100755 index f35beef..0000000 --- a/editor/actions/actions.ml +++ /dev/null @@ -1,133 +0,0 @@ -open StdLabels -open Js_of_ocaml -open Brr -open Brr_note - -type button_actions = - { delete : State.event Note.event - ; redirect : State.event Note.event - ; add: State.event Note.event - } - -let populate_menu - : unit -> button_actions option - = fun () -> - match Blog.Sidebar.get () with - | None -> None - | Some element -> - - let () = Blog.Sidebar.clean element in - - let delete_button = El.button - ~at:At.[ class' (Jstr.v "action-button") ] - [ El.i [] - ~at:At.[ class' (Jstr.v "fa") - ; class' (Jstr.v "fa-2x") - ; class' (Jstr.v "fa-trash") ] ] - - and home_button = El.button - ~at:At.[ class' (Jstr.v "action-button") ] - [ El.i [] - ~at:At.[ class' (Jstr.v "fa") - ; class' (Jstr.v "fa-2x") - ; class' (Jstr.v "fa-home") ] ] - - and add_button = El.button - ~at:At.[ class' (Jstr.v "action-button") ] - [ El.i [] - ~at:At.[ class' (Jstr.v "fa") - ; class' (Jstr.v "fa-2x") - ; class' (Jstr.v "fa-plus") ] ] - in - - (* We are waiting for event inside another event ( form validation inside - popup creation. - - Note.E.join is used here in order to get only te popup validation. *) - let delete_event = - Note.E.join ( - Evr.on_el - Ev.click - (fun _ -> Delete_page.create ()) - delete_button) - - (* Event on popup creation *) - and add_event = - Note.E.join ( - Evr.on_el - Ev.click - (fun _ -> Add_page.create ()) - add_button) in - - - let stored_pages = State.Storage.get_ids () in - let pages = - List.map - stored_pages - ~f:(fun id -> - - let name_opt = (State.Storage.load (Some id))##.title in - let name = Js.Opt.get - name_opt - (fun () -> id) in - - let target = Jstr.v "#" in - El.li - [ El.a - ~at:[At.href target] - [ El.txt name ] ]) in - - (* Wait for a click on an existing page in order to sent the associated - event. - - We compose the resulting event with both : - - the home button - - the list for all the pages presents in the sidebar *) - - let redirect_handler = - (module Load_page.M : State.Event with type t = Load_page.M.t ) in - - let redirect_event = Note.E.select - (( Evr.on_el - Ev.click - (fun _ -> State.E (None, redirect_handler)) - home_button - ) :: ( - List.map2 stored_pages pages - ~f:(fun name el -> - Evr.on_el - Ev.click - (fun _ -> State.E ((Some name), redirect_handler)) - el ))) in - - let childs = - [ home_button - ; add_button - ; El.button - ~at:At.[class' (Jstr.v "action-button")] - [ El.i - [] - ~at:At.[ class' (Jstr.v "fa") - ; class' (Jstr.v "fa-2x") - ; class' (Jstr.v "fa-download") ] - ] - ; delete_button - ; El.button - ~at:At.[class' (Jstr.v "action-button")] - [ El.i - [] - ~at:At.[ class' (Jstr.v "fa") - ; class' (Jstr.v "fa-2x") - ; class' (Jstr.v "fa-cog") ] - ] - ; El.hr () - ; El.ul - pages - ] in - - let () = El.append_children element childs in - Some - { delete = delete_event - ; redirect = redirect_event - ; add = add_event - } diff --git a/editor/actions/delete_page.ml b/editor/actions/delete_page.ml index 9086fc3..fb600bd 100755 --- a/editor/actions/delete_page.ml +++ b/editor/actions/delete_page.ml @@ -17,10 +17,13 @@ end let create : unit -> State.event Note.event = fun () -> - let title = Jstr.v "Confirmation" in + let title = Jstr.v "Confirmation" + and message = + Jstr.v "La page sera définitivement supprimée" + in let ev = Elements.Popup.create ~title - ~form:(Some (Forms.Delete_page.create () )) + ~form:(Some (Forms.Validation.create message )) in Note.E.map (fun v -> State.E diff --git a/editor/actions/dune b/editor/actions/dune index 5d269c4..4044b52 100755 --- a/editor/actions/dune +++ b/editor/actions/dune @@ -1,11 +1,10 @@ (library - (name actions) + (name editor_actions) (libraries brr brr.note elements blog - js_lib forms state ) diff --git a/editor/actions/editor_actions.ml b/editor/actions/editor_actions.ml new file mode 100755 index 0000000..8c47363 --- /dev/null +++ b/editor/actions/editor_actions.ml @@ -0,0 +1,150 @@ +open StdLabels +open Js_of_ocaml +open Brr +open Brr_note + +let populate_menu + : unit -> State.event Note.event option + = fun () -> + match Blog.Sidebar.get () with + | None -> None + | Some element -> + + let () = Blog.Sidebar.clean element in + + let delete_button = El.button + ~at:At.[ class' (Jstr.v "action-button") ] + [ El.i [] + ~at:At.[ class' (Jstr.v "fa") + ; class' (Jstr.v "fa-2x") + ; class' (Jstr.v "fa-trash") ] ] + + and home_button = El.button + ~at:At.[ class' (Jstr.v "action-button") ] + [ El.i [] + ~at:At.[ class' (Jstr.v "fa") + ; class' (Jstr.v "fa-2x") + ; class' (Jstr.v "fa-home") ] ] + + and add_button = El.button + ~at:At.[ class' (Jstr.v "action-button") ] + [ El.i [] + ~at:At.[ class' (Jstr.v "fa") + ; class' (Jstr.v "fa-2x") + ; class' (Jstr.v "fa-plus") ] ] + + and export_button = El.button + ~at:At.[class' (Jstr.v "action-button")] + [ El.i + [] + ~at:At.[ class' (Jstr.v "fa") + ; class' (Jstr.v "fa-2x") + ; class' (Jstr.v "fa-download") ] + ] + + and load_button = El.button + ~at:At.[class' (Jstr.v "action-button")] + [ El.i + [] + ~at:At.[ class' (Jstr.v "fa") + ; class' (Jstr.v "fa-2x") + ; class' (Jstr.v "fa-upload") ] + ] + in + + (* We are waiting for event inside another event ( form validation inside + popup creation. + + Note.E.join is used here in order to get only te popup validation. *) + let delete_event = + Note.E.join ( + Evr.on_el + Ev.click + (fun _ -> Delete_page.create ()) + delete_button) + + (* Event on popup creation *) + and add_event = + Note.E.join ( + Evr.on_el + Ev.click + (fun _ -> Add_page.create ()) + add_button) + + and export_event = + Note.E.join ( + Evr.on_el + Ev.click + (fun _ -> Export.create ()) + export_button) + in + + + let stored_pages = State.Storage.get_ids () in + let pages = + List.map + stored_pages + ~f:(fun id -> + + let name_opt = (State.Storage.load (Some id))##.title in + let name = Js.Opt.get + name_opt + (fun () -> id) in + + let target = Jstr.v "#" in + El.li + [ El.a + ~at:[At.href target] + [ El.txt name ] ]) in + + (* Wait for a click on an existing page in order to sent the associated + event. + + We compose the resulting event with both : + - the home button + - the list for all the pages presents in the sidebar *) + + let redirect_handler = + (module Load_page.M : State.Event with type t = Load_page.M.t ) in + + let redirect_event = Note.E.select + (( Evr.on_el + Ev.click + (fun _ -> State.E (None, redirect_handler)) + home_button + ) :: ( + List.map2 stored_pages pages + ~f:(fun name el -> + Evr.on_el + Ev.click + (fun _ -> State.E ((Some name), redirect_handler)) + el ))) in + + let childs = + [ home_button + ; add_button + ; export_button + ; load_button + ; delete_button + ; El.button + ~at:At.[class' (Jstr.v "action-button")] + [ El.i + [] + ~at:At.[ class' (Jstr.v "fa") + ; class' (Jstr.v "fa-2x") + ; class' (Jstr.v "fa-cog") ] + ] + ; El.hr () + ; El.ul + pages + ] in + + let () = El.append_children element childs in + + Some ( + Note.E.select + [ delete_event + ; redirect_event + ; add_event + ; export_event + ]) diff --git a/editor/actions/export.ml b/editor/actions/export.ml new file mode 100755 index 0000000..a97eeac --- /dev/null +++ b/editor/actions/export.ml @@ -0,0 +1,46 @@ +module Js = Js_of_ocaml.Js + +module M = struct + + type t = unit + + let update + : t -> State.t -> State.t + = fun _ state -> + + (* Save this as a json element. The text may contains UTF-16 characters, + which will raise an error in the btoa function. + + As an easy solution, we convert them into UTF-8 through the native + OCaml representation of string. + *) + let json = State.Storage.to_json () + |> Jstr.to_string (* Encode into UTF-8 *) + |> Obj.magic (* Then type the element again as a string. *) + in + Elements.Transfert.send + ~mime_type:(Jstr.v "application/json") + ~filename:(Jstr.v "export.json") + json; + + (* The function does not actually update the state, and return it + unchanged *) + state + +end + +(** Create a new element *) +let create + : unit -> State.event Note.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) -- cgit v1.2.3