Show recent maps; name maps
This commit is contained in:
parent
6b02b73b9b
commit
e6a51f162d
6 changed files with 268 additions and 50 deletions
158
app.js
158
app.js
|
@ -5160,15 +5160,19 @@ var $elm$core$Task$perform = F2(
|
|||
});
|
||||
var $elm$browser$Browser$document = _Browser_document;
|
||||
var $elm$json$Json$Decode$decodeValue = _Json_run;
|
||||
var $author$project$App$Flags = F3(
|
||||
function (emoji, markers, map_id) {
|
||||
return {emoji: emoji, map_id: map_id, markers: markers};
|
||||
var $author$project$App$Flags = F5(
|
||||
function (emoji, markers, map_id, map_ids, map_name) {
|
||||
return {emoji: emoji, map_id: map_id, map_ids: map_ids, map_name: map_name, markers: markers};
|
||||
});
|
||||
var $elm$json$Json$Decode$field = _Json_decodeField;
|
||||
var $elm$json$Json$Decode$at = F2(
|
||||
function (fields, decoder) {
|
||||
return A3($elm$core$List$foldr, $elm$json$Json$Decode$field, decoder, fields);
|
||||
});
|
||||
var $author$project$App$Emoji = F2(
|
||||
function (emoji, description) {
|
||||
return {description: description, emoji: emoji};
|
||||
});
|
||||
var $elm$json$Json$Decode$field = _Json_decodeField;
|
||||
var $elm$json$Json$Decode$string = _Json_decodeString;
|
||||
var $author$project$App$decode_emoji = A3(
|
||||
$elm$json$Json$Decode$map2,
|
||||
|
@ -5198,19 +5202,37 @@ var $author$project$App$decode_marker = A5(
|
|||
A2($elm$json$Json$Decode$field, 'name', $elm$json$Json$Decode$string),
|
||||
A2($elm$json$Json$Decode$field, 'note', $elm$json$Json$Decode$string));
|
||||
var $elm$json$Json$Decode$list = _Json_decodeList;
|
||||
var $elm$json$Json$Decode$map3 = _Json_map3;
|
||||
var $author$project$App$decode_flags = A4(
|
||||
$elm$json$Json$Decode$map3,
|
||||
var $elm$json$Json$Decode$map5 = _Json_map5;
|
||||
var $author$project$App$decode_flags = A6(
|
||||
$elm$json$Json$Decode$map5,
|
||||
$author$project$App$Flags,
|
||||
A2(
|
||||
$elm$json$Json$Decode$field,
|
||||
'emoji',
|
||||
$elm$json$Json$Decode$list($author$project$App$decode_emoji)),
|
||||
A2(
|
||||
$elm$json$Json$Decode$field,
|
||||
'markers',
|
||||
$elm$json$Json$Decode$at,
|
||||
_List_fromArray(
|
||||
['data', 'markers']),
|
||||
$elm$json$Json$Decode$list($author$project$App$decode_marker)),
|
||||
A2($elm$json$Json$Decode$field, 'map_id', $elm$json$Json$Decode$string));
|
||||
A2($elm$json$Json$Decode$field, 'map_id', $elm$json$Json$Decode$string),
|
||||
A2(
|
||||
$elm$json$Json$Decode$field,
|
||||
'map_ids',
|
||||
$elm$json$Json$Decode$list(
|
||||
A3(
|
||||
$elm$json$Json$Decode$map2,
|
||||
F2(
|
||||
function (name, id) {
|
||||
return {id: id, name: name};
|
||||
}),
|
||||
A2($elm$json$Json$Decode$field, 'name', $elm$json$Json$Decode$string),
|
||||
A2($elm$json$Json$Decode$field, 'id', $elm$json$Json$Decode$string)))),
|
||||
A2(
|
||||
$elm$json$Json$Decode$at,
|
||||
_List_fromArray(
|
||||
['data', 'name']),
|
||||
$elm$json$Json$Decode$string));
|
||||
var $author$project$App$CurrentPositionCentre = {$: 'CurrentPositionCentre'};
|
||||
var $author$project$App$NoSelection = {$: 'NoSelection'};
|
||||
var $author$project$App$blank_marker = {
|
||||
|
@ -5228,6 +5250,8 @@ var $author$project$App$init_model = {
|
|||
current_position: {lat: 55.04, lon: -1.46},
|
||||
emoji: _List_Nil,
|
||||
map_id: '',
|
||||
map_ids: _List_Nil,
|
||||
map_name: '',
|
||||
markers: _List_Nil,
|
||||
new_marker: $author$project$App$blank_marker,
|
||||
selection: $author$project$App$NoSelection
|
||||
|
@ -5247,7 +5271,7 @@ var $author$project$App$init = function (vflags) {
|
|||
var flags = _v0.a;
|
||||
return _Utils_update(
|
||||
$author$project$App$init_model,
|
||||
{emoji: flags.emoji, map_id: flags.map_id, markers: flags.markers});
|
||||
{emoji: flags.emoji, map_id: flags.map_id, map_ids: flags.map_ids, map_name: flags.map_name, markers: flags.markers});
|
||||
}
|
||||
}());
|
||||
};
|
||||
|
@ -5566,6 +5590,11 @@ var $author$project$App$save = function (model) {
|
|||
_Utils_Tuple2(
|
||||
'type',
|
||||
$elm$json$Json$Encode$string('save')),
|
||||
_Utils_Tuple2(
|
||||
'data',
|
||||
$elm$json$Json$Encode$object(
|
||||
_List_fromArray(
|
||||
[
|
||||
_Utils_Tuple2(
|
||||
'markers',
|
||||
A2(
|
||||
|
@ -5580,7 +5609,11 @@ var $author$project$App$save = function (model) {
|
|||
$elm$core$String$fromInt(i),
|
||||
m);
|
||||
}),
|
||||
model.markers)))
|
||||
model.markers))),
|
||||
_Utils_Tuple2(
|
||||
'name',
|
||||
$elm$json$Json$Encode$string(model.map_name))
|
||||
])))
|
||||
]))));
|
||||
};
|
||||
var $elm$core$Basics$always = F2(
|
||||
|
@ -5712,11 +5745,19 @@ var $author$project$App$update = F2(
|
|||
markers: A2($elm_community$list_extra$List$Extra$removeAt, i, model.markers),
|
||||
selection: $author$project$App$NoSelection
|
||||
}));
|
||||
default:
|
||||
case 'ClickCurrentPosition':
|
||||
return $author$project$App$nocmd(
|
||||
_Utils_update(
|
||||
model,
|
||||
{centre: $author$project$App$CurrentPositionCentre, selection: $author$project$App$NoSelection}));
|
||||
case 'SetMapName':
|
||||
var name = msg.a;
|
||||
return $author$project$App$nocmd(
|
||||
_Utils_update(
|
||||
model,
|
||||
{map_name: name}));
|
||||
default:
|
||||
return $author$project$App$save(model);
|
||||
}
|
||||
});
|
||||
var $author$project$App$AddMarker = {$: 'AddMarker'};
|
||||
|
@ -5727,6 +5768,10 @@ var $author$project$App$EditMarker = F2(
|
|||
var $author$project$App$RemoveMarker = function (a) {
|
||||
return {$: 'RemoveMarker', a: a};
|
||||
};
|
||||
var $author$project$App$Save = {$: 'Save'};
|
||||
var $author$project$App$SetMapName = function (a) {
|
||||
return {$: 'SetMapName', a: a};
|
||||
};
|
||||
var $author$project$App$UpdateExistingMarker = F2(
|
||||
function (a, b) {
|
||||
return {$: 'UpdateExistingMarker', a: a, b: b};
|
||||
|
@ -5761,10 +5806,6 @@ var $elm$html$Html$datalist = _VirtualDom_node('datalist');
|
|||
var $author$project$App$MapClicked = function (a) {
|
||||
return {$: 'MapClicked', a: a};
|
||||
};
|
||||
var $elm$json$Json$Decode$at = F2(
|
||||
function (fields, decoder) {
|
||||
return A3($elm$core$List$foldr, $elm$json$Json$Decode$field, decoder, fields);
|
||||
});
|
||||
var $author$project$App$decode_map_click = A2(
|
||||
$elm$json$Json$Decode$map,
|
||||
$author$project$App$MapClicked,
|
||||
|
@ -5845,6 +5886,7 @@ var $elm$html$Html$form = _VirtualDom_node('form');
|
|||
var $elm$core$String$fromFloat = _String_fromNumber;
|
||||
var $elm$html$Html$h1 = _VirtualDom_node('h1');
|
||||
var $elm$html$Html$h2 = _VirtualDom_node('h2');
|
||||
var $elm$html$Html$h3 = _VirtualDom_node('h3');
|
||||
var $elm$html$Html$Attributes$href = function (url) {
|
||||
return A2(
|
||||
$elm$html$Html$Attributes$stringProperty,
|
||||
|
@ -6011,6 +6053,7 @@ var $elm$core$Tuple$second = function (_v0) {
|
|||
var y = _v0.b;
|
||||
return y;
|
||||
};
|
||||
var $elm$html$Html$small = _VirtualDom_node('small');
|
||||
var $elm$core$List$sortBy = _List_sortBy;
|
||||
var $author$project$App$space = $elm$html$Html$text(' ');
|
||||
var $elm$html$Html$span = _VirtualDom_node('span');
|
||||
|
@ -6378,6 +6421,32 @@ var $author$project$App$view = function (model) {
|
|||
$elm$html$Html$text('Closest markers')
|
||||
])),
|
||||
A2(
|
||||
$elm$html$Html$p,
|
||||
_List_Nil,
|
||||
_List_fromArray(
|
||||
[
|
||||
$elm$html$Html$text('🗺️ '),
|
||||
A2(
|
||||
$elm$html$Html$form,
|
||||
_List_fromArray(
|
||||
[
|
||||
$elm$html$Html$Events$onSubmit($author$project$App$Save),
|
||||
$elm$html$Html$Attributes$id('name-form')
|
||||
]),
|
||||
_List_fromArray(
|
||||
[
|
||||
A2(
|
||||
$elm$html$Html$input,
|
||||
_List_fromArray(
|
||||
[
|
||||
$elm$html$Html$Attributes$type_('text'),
|
||||
$elm$html$Html$Events$onInput($author$project$App$SetMapName),
|
||||
$elm$html$Html$Attributes$value(model.map_name)
|
||||
]),
|
||||
_List_Nil)
|
||||
]))
|
||||
])),
|
||||
A2(
|
||||
$elm$html$Html$ul,
|
||||
_List_Nil,
|
||||
A2(
|
||||
|
@ -6409,6 +6478,61 @@ var $author$project$App$view = function (model) {
|
|||
[
|
||||
$elm$html$Html$text('🔗 Link to this map')
|
||||
]))
|
||||
])),
|
||||
A2(
|
||||
$elm$html$Html$h3,
|
||||
_List_Nil,
|
||||
_List_fromArray(
|
||||
[
|
||||
$elm$html$Html$text('Recently-used maps')
|
||||
])),
|
||||
A2(
|
||||
$elm$html$Html$ul,
|
||||
_List_Nil,
|
||||
A2(
|
||||
$elm$core$List$map,
|
||||
function (d) {
|
||||
return A2(
|
||||
$elm$html$Html$li,
|
||||
_List_Nil,
|
||||
_List_fromArray(
|
||||
[
|
||||
A2(
|
||||
$elm$html$Html$a,
|
||||
_List_fromArray(
|
||||
[
|
||||
$elm$html$Html$Attributes$href('?map=' + d.id)
|
||||
]),
|
||||
_List_fromArray(
|
||||
[
|
||||
$elm$html$Html$text(d.name),
|
||||
$elm$html$Html$text(' '),
|
||||
A2(
|
||||
$elm$html$Html$small,
|
||||
_List_Nil,
|
||||
_List_fromArray(
|
||||
[
|
||||
$elm$html$Html$text(d.id)
|
||||
]))
|
||||
]))
|
||||
]));
|
||||
},
|
||||
model.map_ids)),
|
||||
A2(
|
||||
$elm$html$Html$p,
|
||||
_List_Nil,
|
||||
_List_fromArray(
|
||||
[
|
||||
A2(
|
||||
$elm$html$Html$a,
|
||||
_List_fromArray(
|
||||
[
|
||||
$elm$html$Html$Attributes$href('?')
|
||||
]),
|
||||
_List_fromArray(
|
||||
[
|
||||
$elm$html$Html$text('New map')
|
||||
]))
|
||||
]))
|
||||
]));
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<title>Elm app by clp</title>
|
||||
<link rel="manifest" href="manifest.json" />
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
|
||||
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
|
||||
|
@ -11,7 +12,6 @@
|
|||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
|
||||
integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
|
||||
crossorigin=""></script>
|
||||
<script src="https://unpkg.com/protomaps-leaflet@4.0.1/dist/protomaps-leaflet.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
43
load-app.js
43
load-app.js
|
@ -146,33 +146,55 @@ async function init_app() {
|
|||
}
|
||||
|
||||
const params = (new URL(window.location)).searchParams;
|
||||
console.log(params);
|
||||
|
||||
let data = {
|
||||
name: '',
|
||||
markers: []
|
||||
}
|
||||
|
||||
let map_id = params.get('map') || '';
|
||||
if(!map_id) {
|
||||
map_id = Math.floor(Math.random()*Number.MAX_SAFE_INTEGER).toString(16).padStart(8,'0').slice(0,8);
|
||||
}
|
||||
|
||||
let markers = [];
|
||||
map_id = map_id.slice(0,20).replace(/\W/g,'');
|
||||
data.name = map_id;
|
||||
|
||||
try {
|
||||
markers = await (await fetch(`data/markers-${map_id}.json`)).json();
|
||||
|
||||
data = await (await fetch(`data/markers-${map_id}.json`)).json();
|
||||
} catch(e) {
|
||||
try {
|
||||
const fh = await opfs.getFileHandle(`markers-${map_id}.json`);
|
||||
const f = await fh.getFile();
|
||||
markers = JSON.parse(await f.text())
|
||||
data = JSON.parse(await f.text())
|
||||
} catch(e) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let map_ids = [];
|
||||
try {
|
||||
for await(const [f,fh] of opfs.entries()) {
|
||||
const m = f.match(/^markers-(.*).json/);
|
||||
|
||||
const data = JSON.parse(await (await fh.getFile()).text());
|
||||
const name = data.name;
|
||||
|
||||
const id = m[1];
|
||||
|
||||
if(m) {
|
||||
map_ids.push({name,id});
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
|
||||
const emoji = await (await fetch('emoji_metadata.json')).json();
|
||||
|
||||
const app = Elm.App.init({
|
||||
node: document.body,
|
||||
flags: {emoji, markers, map_id}
|
||||
flags: {emoji, data, map_id, map_ids}
|
||||
});
|
||||
|
||||
navigator.geolocation.watchPosition(
|
||||
|
@ -184,18 +206,19 @@ async function init_app() {
|
|||
);
|
||||
|
||||
const send_value_handlers = {
|
||||
save: async ({markers}) => {
|
||||
save: async ({data}) => {
|
||||
const content = JSON.stringify(data);
|
||||
try {
|
||||
const f = await opfs.getFileHandle(`markers-${map_id}.json`, {create:true});
|
||||
const w = await f.createWritable();
|
||||
await w.write(JSON.stringify(markers));
|
||||
await w.write(content);
|
||||
await w.close();
|
||||
} catch(e) {
|
||||
|
||||
}
|
||||
|
||||
const fd = new FormData();
|
||||
fd.set('content', JSON.stringify(markers));
|
||||
fd.set('content', content);
|
||||
fd.set('map_id', map_id);
|
||||
fetch('cgi-bin/save_data.py', {
|
||||
method: 'POST',
|
||||
|
|
8
manifest.json
Normal file
8
manifest.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"name": "CLP's map",
|
||||
"description": "A personalised map",
|
||||
"start_url": "https://map.think.somethingorotherwhatever.com/",
|
||||
"display": "standalone",
|
||||
"background_color": "#feb300",
|
||||
"theme_color": "#feb300"
|
||||
}
|
60
src/App.elm
60
src/App.elm
|
@ -51,6 +51,8 @@ type alias Model =
|
|||
{ markers : List Marker
|
||||
, emoji : List Emoji
|
||||
, map_id : String
|
||||
, map_name : String
|
||||
, map_ids : List ({name: String, id: String})
|
||||
, current_position : LatLon
|
||||
, selection : Selection
|
||||
, new_marker : Marker
|
||||
|
@ -62,6 +64,8 @@ init_model =
|
|||
{ markers = []
|
||||
, emoji = []
|
||||
, map_id = ""
|
||||
, map_name = ""
|
||||
, map_ids = []
|
||||
, current_position = {lat = 55.04, lon = -1.46}
|
||||
, selection = NoSelection
|
||||
, new_marker = blank_marker
|
||||
|
@ -79,6 +83,8 @@ type Msg
|
|||
| EditMarker Int Marker
|
||||
| RemoveMarker Int
|
||||
| ClickCurrentPosition
|
||||
| SetMapName String
|
||||
| Save
|
||||
|
||||
type alias Emoji =
|
||||
{ emoji : String
|
||||
|
@ -94,19 +100,30 @@ type alias Flags =
|
|||
{ emoji : List Emoji
|
||||
, markers : List Marker
|
||||
, map_id : String
|
||||
, map_ids : List ({name: String, id: String})
|
||||
, map_name : String
|
||||
}
|
||||
|
||||
decode_flags =
|
||||
JD.map3 Flags
|
||||
JD.map5 Flags
|
||||
(JD.field "emoji" (JD.list decode_emoji))
|
||||
(JD.field "markers" (JD.list decode_marker))
|
||||
(JD.at ["data", "markers"] (JD.list decode_marker))
|
||||
(JD.field "map_id" JD.string)
|
||||
(JD.field "map_ids"
|
||||
(JD.list
|
||||
(JD.map2 (\name id -> { name = name, id = id})
|
||||
(JD.field "name" JD.string)
|
||||
(JD.field "id" JD.string)
|
||||
)
|
||||
)
|
||||
)
|
||||
(JD.at ["data", "name"] JD.string)
|
||||
|
||||
init : (JD.Value) -> (Model, Cmd msg)
|
||||
init vflags =
|
||||
(case JD.decodeValue decode_flags vflags of
|
||||
Err _ -> init_model
|
||||
Ok flags -> { init_model | emoji = flags.emoji, markers = flags.markers, map_id = flags.map_id }
|
||||
Ok flags -> { init_model | emoji = flags.emoji, markers = flags.markers, map_id = flags.map_id, map_ids = flags.map_ids, map_name = flags.map_name }
|
||||
) |> nocmd
|
||||
|
||||
nocmd m = (m, Cmd.none)
|
||||
|
@ -117,7 +134,11 @@ save model =
|
|||
, send_value
|
||||
<| JE.object
|
||||
[ ("type", JE.string "save")
|
||||
, ("markers", JE.list identity <| List.indexedMap (\i m -> encode_marker (String.fromInt i) m) model.markers)
|
||||
, ("data", JE.object
|
||||
[ ("markers", JE.list identity <| List.indexedMap (\i m -> encode_marker (String.fromInt i) m) model.markers)
|
||||
, ("name", JE.string model.map_name)
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
|
@ -157,6 +178,10 @@ update msg model =
|
|||
|
||||
ClickCurrentPosition -> { model | centre = CurrentPositionCentre, selection = NoSelection } |> nocmd
|
||||
|
||||
SetMapName name -> { model | map_name = name } |> nocmd
|
||||
|
||||
Save -> model |> save
|
||||
|
||||
add_marker model = case model.selection of
|
||||
SelectedPosition pos ->
|
||||
let
|
||||
|
@ -383,6 +408,21 @@ view model =
|
|||
, HA.class "marker-detail"
|
||||
]
|
||||
[ H.h1 [] [ H.text "Closest markers" ]
|
||||
, H.p
|
||||
[]
|
||||
[ H.text <| "🗺️ "
|
||||
, H.form
|
||||
[ HE.onSubmit Save
|
||||
, HA.id "name-form"
|
||||
]
|
||||
[ H.input
|
||||
[ HA.type_ "text"
|
||||
, HE.onInput SetMapName
|
||||
, HA.value model.map_name
|
||||
]
|
||||
[]
|
||||
]
|
||||
]
|
||||
, H.ul
|
||||
[]
|
||||
(List.map (\(i,m) ->
|
||||
|
@ -397,6 +437,18 @@ view model =
|
|||
[ HA.href <| "?map=" ++ model.map_id ]
|
||||
[ H.text "🔗 Link to this map" ]
|
||||
]
|
||||
, H.h3
|
||||
[]
|
||||
[ H.text "Recently-used maps"]
|
||||
, H.ul
|
||||
[]
|
||||
(List.map
|
||||
(\d -> H.li [] [H.a [HA.href <| "?map="++d.id] [H.text d.name, H.text " ", H.small [] [H.text d.id]]])
|
||||
model.map_ids
|
||||
)
|
||||
, H.p
|
||||
[]
|
||||
[ H.a [HA.href "?"] [H.text "New map"]]
|
||||
]
|
||||
|
||||
closest_markers =
|
||||
|
|
11
style.css
11
style.css
|
@ -24,6 +24,17 @@ body > main {
|
|||
overflow: auto;
|
||||
}
|
||||
|
||||
#name-form {
|
||||
display: inline;
|
||||
|
||||
& input {
|
||||
border: none;
|
||||
padding: 0;
|
||||
font-size: inherit;
|
||||
border-bottom: thin solid;
|
||||
}
|
||||
}
|
||||
|
||||
#marker-form {
|
||||
& label {
|
||||
margin: 0 0.5em;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue