Skip to content

Commit

Permalink
Define JAT list of junctions on a map. #23
Browse files Browse the repository at this point in the history
UX is clunky, not sure about this
  • Loading branch information
dabreegster committed May 21, 2024
1 parent 7b96da4 commit e889e41
Show file tree
Hide file tree
Showing 3 changed files with 166 additions and 35 deletions.
5 changes: 3 additions & 2 deletions src/routes/route_check/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ export interface CriticalIssue {

export interface Junction {
name: string;
point: Position;
existing: JunctionAssessment;
proposed: JunctionAssessment;
}
Expand Down Expand Up @@ -161,14 +162,14 @@ export interface Movement {
}

function validate(state: State) {
if (state.version != "alpha-0") {
if (state.version != "alpha-1") {
throw new Error("File format appears outdated");
}
}

export function emptyState(): State {
return {
version: "alpha-0",
version: "alpha-1",
summary: {
dateDesignReview: "",
schemeReference: "",
Expand Down
38 changes: 5 additions & 33 deletions src/routes/route_check/jat_check/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
} from "govuk-svelte";
import { state } from "../data";
import EditJunction from "./EditJunction.svelte";
import JunctionList from "./JunctionList.svelte";
type Mode =
| { kind: "list" }
Expand All @@ -21,26 +22,6 @@
return m.idx;
}
function add() {
$state.jat = [
...$state.jat,
{
name: "",
existing: {
arms: [],
movements: [],
notes: "",
},
proposed: {
arms: [],
movements: [],
notes: "",
},
},
];
mode = { kind: "edit", idx: $state.jat.length - 1, stage: "existing" };
}
function deleteJunction(idx: number) {
// TODO Modals
if (!window.confirm("Delete this junction?")) {
Expand All @@ -53,19 +34,10 @@
</script>

{#if mode.kind == "list"}
<SecondaryButton on:click={add}>Add new junction</SecondaryButton>

<ol>
{#each $state.jat as junction, idx}
<li>
<SecondaryButton
on:click={() => (mode = { kind: "edit", idx, stage: "existing" })}
>
{junction.name || "Untitled junction"}
</SecondaryButton>
</li>
{/each}
</ol>
<JunctionList
on:edit={(e) =>
(mode = { kind: "edit", idx: e.detail.idx, stage: "existing" })}
/>
{:else if mode.kind == "edit"}
<h2>{$state.jat[mode.idx].name || "Untitled junction"} - {mode.stage}</h2>

Expand Down
158 changes: 158 additions & 0 deletions src/routes/route_check/jat_check/JunctionList.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
<script lang="ts">
import { Checkbox, SecondaryButton, CollapsibleCard } from "govuk-svelte";
import {
bbox,
MapLibreMap,
Popup,
ContextualMap,
StreetView,
Basemap,
type Position,
} from "$lib/map";
import { GeoreferenceLayer, GeoreferenceControls } from "$lib/map/georef";
import {
Marker,
GeoJSON,
LineLayer,
hoverStateFilter,
type LayerClickInfo,
SymbolLayer,
CircleLayer,
MapEvents,
} from "svelte-maplibre";
import type { MapMouseEvent, Map } from "maplibre-gl";
import { state } from "../data";
import { onMount, createEventDispatcher } from "svelte";
import type { FeatureCollection } from "geojson";
let dispatch = createEventDispatcher<{
edit: { idx: number };
}>();
let map: Map;
let streetviewOn = false;
let showContext = true;
// TODO Wait for loaded
onMount(() => {
zoom(false);
});
function zoom(animate: boolean) {
let gj: FeatureCollection = {
type: "FeatureCollection",
features: $state.jat.map((junction) => {
return {
type: "Feature",
properties: {},
geometry: {
type: "Point",
coordinates: junction.point,
},
};
}),
};
for (let f of $state.summary.networkMap.features) {
gj.features.push(f);
}
if (gj.features.length > 0) {
map.fitBounds(bbox(gj), {
padding: 20,
animate,
});
}
}
function onMapClick(e: CustomEvent<MapMouseEvent>) {
if (streetviewOn) {
return;
}
$state.jat = [
...$state.jat,
{
name: "",
point: e.detail.lngLat.toArray() as Position,
existing: {
arms: [],
movements: [],
notes: "",
},
proposed: {
arms: [],
movements: [],
notes: "",
},
},
];
dispatch("edit", { idx: $state.jat.length - 1 });
}
</script>

<div style="display: flex; height: 80vh">
<div
style="width: 30%; overflow-y: scroll; padding: 10px; border: 1px solid black;"
>
<CollapsibleCard label="Tools">
<SecondaryButton on:click={() => zoom(true)}>Zoom to fit</SecondaryButton>
<Basemap />
<GeoreferenceControls />
{#if map}
<StreetView {map} bind:enabled={streetviewOn} />
{/if}
<Checkbox bind:checked={showContext}>Show scheme context</Checkbox>
</CollapsibleCard>

<ol>
{#each $state.jat as junction, idx}
<li>
<SecondaryButton on:click={() => dispatch("edit", { idx })}>
{junction.name || "Untitled junction"}
</SecondaryButton>
</li>
{/each}
</ol>
</div>
<div style="position: relative; width: 100%">
<MapLibreMap bind:map>
<MapEvents on:click={onMapClick} />

<ContextualMap gj={$state.summary.networkMap} show={showContext} />

{#each $state.jat as junction, idx}
<Marker
draggable
bind:lngLat={junction.point}
on:click={() => dispatch("edit", { idx })}
>
<span class="dot">
{junction.name}
</span>
</Marker>
{/each}
</MapLibreMap>
</div>
</div>

<style>
.dot {
width: 30px;
height: 30px;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
background: white;
color: black;
font-size: 25px;
font-weight: bold;
}
.dot:hover {
border: 3px solid black;
cursor: pointer;
}
</style>

0 comments on commit e889e41

Please sign in to comment.