aboutsummaryrefslogtreecommitdiff
path: root/editor/storage.ml
blob: f893c2df408f4e5b4a20ccdec4c18750f6b763ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
open Brr
module Js = Js_of_ocaml.Js

let storage_key = (Jstr.v "editor")

let storage = Brr_io.Storage.local G.window

class type content = object

  method title
    : Jstr.t Js.opt Js.readonly_prop

  method content
    : Jv.t Js.opt Js.readonly_prop

  method date
    : float Js.opt Js.readonly_prop

end

let page_id
  : unit -> Jstr.t option
  = fun () ->
    let uri = Brr.Window.location Brr.G.window in
    let query = Brr.Uri.query uri in
    let params = Brr.Uri.Params.of_jstr query in
    Brr.Uri.Params.find (Jstr.v "page") params

(** [load' pm schema content key] will load the content stored in the local
    storage for the [key].
*)
let load'
  : Jstr.t -> content Js.t
  = fun key ->

    let opt_data = Brr_io.Storage.get_item storage key in
    match opt_data with
    | None ->
      object%js
        val title = Js.null
        val content = Js.null
        val date = Js.null
      end
    | Some contents ->

      (* Try to load from the storage *)
      match Json.decode contents with
      | Error _ ->
        object%js
          val title = Js.null
          val content = Js.null
          val date = Js.null
        end

      | Ok json ->
        Jv.Id.of_jv json

(** Save the view *)
let save'
  : check:(content Js.t -> bool) -> content Js.t -> Jstr.t -> (bool, Jv.Error.t) result
  = fun ~check object_content key ->

    (* First load the content from the storage *)
    match check (load' key) with
    | false -> Ok false
    | true ->
      let storage = Brr_io.Storage.local G.window in
      let operation = Brr_io.Storage.set_item
          storage
          key
          (Json.encode @@ Jv.Id.to_jv @@ object_content) in
      Result.map (fun () -> true) operation


(** [load pm schema content f] will try load the content stored in the local
    storage. The right key is given by the result of the function [f]
*)
let load
  : Jstr.t option -> content Js.t
  = fun key ->
    match key with
    | None -> load' storage_key
    | Some value ->
      let key = Jstr.concat
          ~sep:(Jstr.v "_")
          [storage_key ;  value] in
      load' key

let save
  : check:(content Js.t -> bool) -> content Js.t -> Jstr.t option -> (bool, Jv.Error.t) result
  = fun ~check object_content key ->
    match key with
    | None ->
      save' ~check object_content storage_key
    | Some value ->
      let key = Jstr.concat
          ~sep:(Jstr.v "_")
          [storage_key ;  value] in
      save' ~check object_content key

let delete
  : (unit -> Jstr.t option) -> unit
  = fun f ->
    match f () with
    | None -> ()
    | Some value ->
      let key = Jstr.concat
          ~sep:(Jstr.v "_")
          [storage_key ;  value] in
      let storage = Brr_io.Storage.local G.window in
      Brr_io.Storage.remove_item storage key

let get_ids
  : unit -> Jstr.t list
  = fun () ->
    let open Brr_io in
    let storage = Storage.local G.window in
    let items = Storage.length storage in

    let sub = Jstr.( storage_key + (v "_") ) in
    let start = Jstr.length sub in

    let rec add_element acc = function
      | -1 -> acc
      | nb ->
        begin match Storage.key storage nb with
          | Some key when (Jstr.starts_with ~sub key) ->

            let key_name = Jstr.sub key
                ~start in
            add_element (key_name::acc) (nb -1)
          | _ ->
            add_element acc (nb -1)
        end

    in
    add_element [] items