From 225068497c5fd41da12030a6bbf58a0fc9c294d0 Mon Sep 17 00:00:00 2001 From: Joris Date: Sun, 9 Aug 2020 14:44:02 +0200 Subject: Import from CSV --- src/View/Map.ml | 128 ++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 78 insertions(+), 50 deletions(-) (limited to 'src/View') diff --git a/src/View/Map.ml b/src/View/Map.ml index 8f74b76..c85a791 100644 --- a/src/View/Map.ml +++ b/src/View/Map.ml @@ -1,4 +1,41 @@ -let mapView state = +let state_from_hash () = + let hash = Js.String.sliceToEnd ~from:1 (Location.hash Document.location) in + State.from_url_string hash + +let rec reload_from_hash state map markers focus = + let update_state new_state = + let () = History.push_state "" "" ("#" ^ State.to_url_string new_state) () in + reload_from_hash state map markers false + in + + let on_remove pos = + update_state (State.remove !state pos) in + + let on_update previousPos pos name color icon = + update_state (State.update !state previousPos { pos = pos; name = name; color = color; icon = icon }) in + + let () = + if Js.Array.length (Leaflet.get_layers markers ()) > 0 then + Leaflet.clear_layers markers + else + () + in + let () = state := state_from_hash () in + let colors = State.colors !state in + let () = + Js.Array.forEach + (fun (m: State.marker_state) -> Leaflet.add_layer markers (Marker.create on_remove on_update colors m.pos m.name m.color m.icon)) + !state + in + if focus then + if Js.Array.length (Leaflet.get_layers markers ()) > 0 then + Leaflet.fit_bounds map (Leaflet.get_bounds markers ()) { padding = [| 50.; 50. |] } + else + Leaflet.setView map [| 51.505; -0.09 |] 2 + else + () + +let mapView state map markers = H.div [| HA.class_ "g-Layout__Page" |] [| H.div @@ -8,9 +45,36 @@ let mapView state = ; HA.href "#" |] [| H.text "Map" |] - ; Button.text - [| HE.on_click (fun _ -> File.download "map.csv" (State.to_csv_string !state)) |] - [| H.text "Export" |] + ; Layout.line + [| |] + [| H.input + [| HA.id "g-Header__ImportInput" + ; HA.type_ "file" + ; HE.on_change (fun e -> + match !map with + | Some map -> + let reader = File.reader () in + let () = Element.add_event_listener reader "load" (fun _ -> + let str = File.result reader in + let new_state = State.from_dicts (CSV.to_dicts (CSV.parse str)) in + let () = History.push_state "" "" ("#" ^ State.to_url_string new_state) () in + reload_from_hash state map markers true) + in + File.read_as_text reader ( + Js.Array.unsafe_get (Element.files (Event.target e)) 0) + | _ -> + ()) + |] + [| |] + ; H.label + [| HA.for_ "g-Header__ImportInput" + ; HA.class_ "g-Header__ImportLabel" + |] + [| H.text "Import" |] + ; Button.text + [| HE.on_click (fun _ -> File.download "map.csv" (State.to_csv_string !state)) |] + [| H.text "Export" |] + |] |] ; H.div [| HA.class_ "g-Map" |] @@ -20,64 +84,26 @@ let mapView state = |] |] -let state_from_hash () = - let hash = Js.String.sliceToEnd ~from:1 (Location.hash Document.location) in - State.from_url_string hash - -let installMap state = - let map = Leaflet.map "g-Map__Content" in +let install_map state map_ref markers = + let map = Leaflet.map "g-Map__Content" { attributionControl = false } in + let () = map_ref := Some map in let title_layer = Leaflet.title_layer "http://{s}.tile.osm.org/{z}/{x}/{y}.png" in - let markers = Leaflet.feature_group [| |] in let () = Leaflet.add_layer map markers in let () = Leaflet.add_layer map title_layer in - let rec reload_from_hash focus = - let update_state new_state = - let () = History.push_state "" "" ("#" ^ State.to_url_string new_state) () in - reload_from_hash false - in - - let on_remove pos = - update_state (State.remove !state pos) in - - let on_update previousPos pos name color icon = - update_state (State.update !state previousPos { pos = pos; name = name; color = color; icon = icon }) in - - let () = - if Js.Array.length (Leaflet.get_layers markers ()) > 0 then - Leaflet.clear_layers markers - else - () - in - let () = state := state_from_hash () in - let colors = State.colors !state in - let () = - Js.Array.forEach - (fun (m: State.marker_state) -> Leaflet.add_layer markers (Marker.create on_remove on_update colors m.pos m.name m.color m.icon)) - !state - in - if focus then - if Js.Array.length (Leaflet.get_layers markers ()) > 0 then - Leaflet.fit_bounds map (Leaflet.get_bounds markers ()) { padding = [| 50.; 50. |] } - else - Leaflet.setView map [| 51.505; -0.09 |] 2 - else - () - in - (* Init markers from url *) - let () = reload_from_hash true in + let () = reload_from_hash state map markers true in (* Reload the map if the URL changes *) let () = Element.add_event_listener Window.window "popstate" (fun _ -> - reload_from_hash true) + reload_from_hash state map markers true) in let add_marker pos name color icon = let new_marker = { State.pos = pos; name = name; color = color; icon = icon } in let new_state = State.update !state pos new_marker in let () = History.push_state "" "" ("#" ^ State.to_url_string new_state) () in - reload_from_hash false + reload_from_hash state map markers false in (* Context menu *) @@ -99,5 +125,7 @@ let installMap state = let render () = let state = ref (state_from_hash ()) in - let _ = Js.Global.setTimeout (fun _ -> installMap state) 0 in - mapView state + let map = ref None in + let markers = Leaflet.feature_group [| |] in + let _ = Js.Global.setTimeout (fun _ -> install_map state map markers) 0 in + mapView state map markers -- cgit v1.2.3