From 2fc4e793b12341df6264e22c0b8bd0f6dd2bd27d Mon Sep 17 00:00:00 2001 From: Sébastien Dailly Date: Thu, 29 Apr 2021 15:20:11 +0200 Subject: Added pop-up and events in editor --- editor/editor.ml | 136 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 120 insertions(+), 16 deletions(-) (limited to 'editor/editor.ml') diff --git a/editor/editor.ml b/editor/editor.ml index fccaa76..d3a9624 100755 --- a/editor/editor.ml +++ b/editor/editor.ml @@ -7,11 +7,34 @@ type state = { editable : bool ; view : PM.View.editor_view Js.t ; last_backup: float + ; page_id: Jstr.t option + + ; window : El.t list } type events = | DeleteEvent | StoreEvent + | LoadEvent of Jstr.t option + | AddEvent + | CloseEvent of Forms.Events.kind option + +let set_title + : Storage.content Js.t -> unit + = fun content -> + let title = + Js.Opt.get + content##.title + (fun () -> Jstr.empty) in + let title_element = Document.find_el_by_id G.document (Jstr.v "title") in + Option.iter + (fun el -> El.set_prop (El.Prop.value) title el) + title_element + +let key_of_title + : Jstr.t -> Jstr.t + = fun title -> + title let state_of_storage : PM.t -> Storage.content Js.t -> PM.Model.schema Js.t -> PM.State.editor_state Js.t @@ -22,8 +45,7 @@ let state_of_storage let obj = PM.State.creation_prop () in obj##.plugins := Plugins.default pm schema; obj##.schema := Js.some schema; - PM.State.create pm obj - ) + PM.State.create pm obj) (fun page_content -> let obj = PM.State.configuration_prop () in obj##.plugins := Plugins.default pm schema; @@ -36,9 +58,8 @@ let state_of_storage *) let build_view - : El.t -> PM.View.editor_view Js.t * float - = fun editor -> - let pm = PM.v () in + : PM.t -> Jstr.t option -> El.t -> PM.View.editor_view Js.t * float + = fun pm page_id editor -> (* Remove all the elements if any *) El.set_children editor []; @@ -62,8 +83,7 @@ let build_view (Some custom_schema##.spec##.marks) None in let full_schema = PM.Model.schema pm specs in - (* Load the cache for the given page *) - let stored_content = Storage.load Storage.page_id in + let stored_content = Storage.load page_id in (* This variable contains the last update time, either because it is stored, or because it is the date where we create the first page. *) @@ -85,26 +105,88 @@ let build_view props in view, last_backup +let load_page + : PM.t -> Jstr.t option -> state -> Storage.content Js.t -> state + = fun pm page_id state json -> + let editor_state = state_of_storage pm json state.view##.state##.schema in + let () = state.view##updateState editor_state + and () = set_title json in + { state with page_id } + (** [update] is the event loop. The function take a new event, and apply it to the current state. *) + let update - : (events, state) Application.t - = fun event state -> + : PM.t -> 'a option Note.E.send -> (events, state) Application.t + = fun pm close_sender event state -> match event with + + | AddEvent -> + let title = Jstr.v "Nouvelle page" in + let popup = Ui.popup + ~title + ~form:(Some (Forms.Add_page.create ())) + close_sender in + { state with window = popup::state.window} + | DeleteEvent -> - state + begin match state.page_id with + | None -> state + | Some page_id -> + let title = Jstr.v "Confirmation" in + let popup = Ui.popup + ~title + ~form:(Some (Forms.Delete_page.create page_id)) + close_sender in + { state with window = popup::state.window} + end + + | CloseEvent res -> + + let state = match state.window with + | [] -> { state with window = [] } + | el::tl -> El.remove el + ; { state with window = tl } in + + (* The actions is confirmed by the user. Handle the form result *) + begin match res with + (* Delete the current page, then load the home page *) + | Some (Forms.Delete_page.DeletePage id) -> + Storage.delete (fun () -> Some id); + let json = Storage.load None in + load_page pm None state json + (* Add a new page *) + | Some (Forms.Add_page.AddPage {title}) -> + let page_id = key_of_title title in + Console.(log [title]); + 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 + load_page pm (Some page_id) state content_obj + + | _ -> state + end | StoreEvent -> + + let title_element = Document.find_el_by_id G.document (Jstr.v "title") in + let content = Option.map + (fun el -> El.prop (El.Prop.value) el) + title_element in + let new_date = (new%js Js.date_now)##getTime in let content_obj = object%js val content = Js.some @@ Jv.Id.to_jv (state.view##.state##toJSON ()) - val title = Js.null + val title = Js.Opt.option content val date = Js.some new_date end in let save = Storage.save content_obj - Storage.page_id + state.page_id ~check:(fun previous_state -> Js.Opt.case previous_state##.date (fun () -> true) @@ -119,9 +201,16 @@ let update date <= state.last_backup)) in begin match save with | Ok true -> { state with last_backup = new_date } - | _ -> state + | _ -> + (* TODO In case of error, notify the user *) + state end + | LoadEvent page_id -> + let json = Storage.load page_id in + load_page pm page_id state json + + let app id content = (* Check the pre-requisite *) @@ -129,22 +218,37 @@ let app id content = match (Jv.is_none id), (Jv.is_none content), events_opt with | false, false, Some btn_events -> + let pm = PM.v () in let editor:El.t = Jv.Id.of_jv id in - let view, last_backup = build_view editor in + (* Load the cache for the given page *) + let page_id = Storage.page_id () in + let view, last_backup = build_view pm page_id editor in + + + (* This event is used in the pop process. The sender is given to the + subroutine in order to track the window closing *) + let event, sender = Note.E.create () in + let _ = sender in let init_state = { editable = true ; view ; last_backup + ; page_id + + ; window = [] } in let app_state = Application.run - update + (update pm sender) init_state (Note.E.select - [ Note.E.map (fun () -> DeleteEvent) (snd btn_events.Actions.delete) + [ Note.E.map (fun () -> DeleteEvent) btn_events.Actions.delete ; Brr_note.Evr.on_el Ev.focusout (fun _ -> StoreEvent) editor + ; Note.E.map (fun v -> LoadEvent v) btn_events.Actions.redirect + ; Note.E.map (fun () -> AddEvent) btn_events.Actions.add + ; Note.E.map (fun v -> CloseEvent v) event ]) in let () = -- cgit v1.2.3