Skip to content

Commit d670e87

Browse files
authored
fix: complete map editor rollout iteration (#804)
Completes the #804 map editor iteration by routing remaining new/edit entrypoints through the shared map editor, restoring site search and beam preview, and removing stale old-editor paths.
1 parent 2ac227b commit d670e87

8 files changed

Lines changed: 533 additions & 401 deletions

File tree

src/components/MapView.tsx

Lines changed: 93 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -686,7 +686,7 @@ export function MapView({
686686
const setSiteDragPreview = useAppStore((state) => state.setSiteDragPreview);
687687
const clearSiteDragPreview = useAppStore((state) => state.clearSiteDragPreview);
688688
const setEndpointPickTarget = useAppStore((state) => state.setEndpointPickTarget);
689-
const requestSiteLibraryDraftAt = useAppStore((state) => state.requestSiteLibraryDraftAt);
689+
const openMapEditor = useAppStore((state) => state.openMapEditor);
690690
const requestOpenSiteLibraryEntry = useAppStore((state) => state.requestOpenSiteLibraryEntry);
691691
const coverageSamples = useCoverageStore((state) => state.coverageSamples);
692692
const srtmTiles = useAppStore((state) => state.srtmTiles);
@@ -2141,7 +2141,26 @@ export function MapView({
21412141
setSiteDraftStatus("Preparing site draft...");
21422142
try {
21432143
const suggestedName = await guessSiteNameForPosition(pendingNewSiteDraft.lat, pendingNewSiteDraft.lon);
2144-
requestSiteLibraryDraftAt(pendingNewSiteDraft.lat, pendingNewSiteDraft.lon, suggestedName);
2144+
openMapEditor({
2145+
kind: "site",
2146+
resourceId: null,
2147+
isNew: true,
2148+
label: "New Site",
2149+
anchorRect: {
2150+
top: window.innerHeight / 2,
2151+
right: window.innerWidth / 2,
2152+
bottom: window.innerHeight / 2,
2153+
left: window.innerWidth / 2,
2154+
width: 0,
2155+
height: 0,
2156+
},
2157+
siteSeed: {
2158+
lat: pendingNewSiteDraft.lat,
2159+
lon: pendingNewSiteDraft.lon,
2160+
name: suggestedName,
2161+
insertIntoSimulation: true,
2162+
},
2163+
});
21452164
setPendingNewSiteDraft(null);
21462165
setSiteDraftStatus(null);
21472166
} catch (error) {
@@ -2395,16 +2414,36 @@ export function MapView({
23952414
setSiteDraftStatus(`Node already exists as "${existing.name}". Choose add existing or create a copy.`);
23962415
return;
23972416
}
2398-
requestSiteLibraryDraftAt(node.lat, node.lon, node.longName ?? node.shortName ?? node.nodeId, {
2399-
sourceType: "mqtt-feed",
2400-
sourceUrl: "/meshmap/nodes.json",
2401-
nodeId: node.nodeId,
2402-
longName: node.longName,
2403-
shortName: node.shortName,
2404-
hwModel: node.hwModel,
2405-
role: node.role,
2417+
openMapEditor({
2418+
kind: "site",
2419+
resourceId: null,
2420+
isNew: true,
2421+
label: "New Site",
2422+
anchorRect: {
2423+
top: window.innerHeight / 2,
2424+
right: window.innerWidth / 2,
2425+
bottom: window.innerHeight / 2,
2426+
left: window.innerWidth / 2,
2427+
width: 0,
2428+
height: 0,
2429+
},
2430+
siteSeed: {
2431+
lat: node.lat,
2432+
lon: node.lon,
2433+
name: node.longName ?? node.shortName ?? node.nodeId,
2434+
insertIntoSimulation: true,
2435+
sourceMeta: {
2436+
sourceType: "mqtt-feed",
2437+
sourceUrl: "/meshmap/nodes.json",
2438+
nodeId: node.nodeId,
2439+
longName: node.longName,
2440+
shortName: node.shortName,
2441+
hwModel: node.hwModel,
2442+
role: node.role,
2443+
},
2444+
},
24062445
});
2407-
setSiteDraftStatus("Opened MQTT node in Add Site form. Review and save to add it.");
2446+
setSiteDraftStatus("Opened MQTT node in the site editor. Review and save to add it.");
24082447
};
24092448

24102449
const addExistingDuplicateMqttNode = () => {
@@ -2417,16 +2456,36 @@ export function MapView({
24172456
const createDuplicateMqttCopy = () => {
24182457
if (!mqttDuplicatePrompt) return;
24192458
const node = mqttDuplicatePrompt.node;
2420-
requestSiteLibraryDraftAt(node.lat, node.lon, node.longName ?? node.shortName ?? node.nodeId, {
2421-
sourceType: "mqtt-feed",
2422-
sourceUrl: "/meshmap/nodes.json",
2423-
nodeId: node.nodeId,
2424-
longName: node.longName,
2425-
shortName: node.shortName,
2426-
hwModel: node.hwModel,
2427-
role: node.role,
2459+
openMapEditor({
2460+
kind: "site",
2461+
resourceId: null,
2462+
isNew: true,
2463+
label: "New Site",
2464+
anchorRect: {
2465+
top: window.innerHeight / 2,
2466+
right: window.innerWidth / 2,
2467+
bottom: window.innerHeight / 2,
2468+
left: window.innerWidth / 2,
2469+
width: 0,
2470+
height: 0,
2471+
},
2472+
siteSeed: {
2473+
lat: node.lat,
2474+
lon: node.lon,
2475+
name: node.longName ?? node.shortName ?? node.nodeId,
2476+
insertIntoSimulation: true,
2477+
sourceMeta: {
2478+
sourceType: "mqtt-feed",
2479+
sourceUrl: "/meshmap/nodes.json",
2480+
nodeId: node.nodeId,
2481+
longName: node.longName,
2482+
shortName: node.shortName,
2483+
hwModel: node.hwModel,
2484+
role: node.role,
2485+
},
2486+
},
24282487
});
2429-
setSiteDraftStatus(`Opened copy draft for "${mqttDuplicatePrompt.existingName}".`);
2488+
setSiteDraftStatus(`Opened copy in the site editor for "${mqttDuplicatePrompt.existingName}".`);
24302489
setMqttDuplicatePrompt(null);
24312490
};
24322491

@@ -2699,7 +2758,20 @@ export function MapView({
26992758
<div className="chip-group">
27002759
{inspectorPrimaryLibraryEntryId ? (
27012760
<ActionButton
2702-
onClick={() => requestOpenSiteLibraryEntry(inspectorPrimaryLibraryEntryId)}
2761+
onClick={(event) => {
2762+
const entry = siteLibrary.find((candidate) => candidate.id === inspectorPrimaryLibraryEntryId);
2763+
if (!entry) {
2764+
requestOpenSiteLibraryEntry(inspectorPrimaryLibraryEntryId);
2765+
return;
2766+
}
2767+
openMapEditor({
2768+
kind: "site",
2769+
resourceId: entry.id,
2770+
isNew: false,
2771+
label: entry.name,
2772+
anchorRect: event.currentTarget.getBoundingClientRect(),
2773+
});
2774+
}}
27032775
>
27042776
Details
27052777
</ActionButton>

src/components/Sidebar.tsx

Lines changed: 68 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -671,15 +671,20 @@ export function Sidebar({
671671
setShowNewSimulationRequest(false);
672672
return;
673673
}
674-
setNewSimulationName("");
675-
setNewSimulationDescription("");
676-
setNewSimulationNameError("");
677-
setModalFreqPresetId(getDefaultFrequencyPresetIdForNewSimulation());
678-
setModalAutoPropEnv(autoPropagationEnvironment);
679-
setShowNewSimulationModal(true);
674+
openMapEditor({
675+
kind: "simulation",
676+
resourceId: null,
677+
isNew: true,
678+
label: "New Simulation",
679+
anchorRect: { top: 96, right: 320, bottom: 96, left: 320, width: 0, height: 0 },
680+
simulationSeed: {
681+
frequencyPresetId: getDefaultFrequencyPresetIdForNewSimulation(),
682+
autoPropagationEnvironment,
683+
},
684+
});
680685
setShowNewSimulationRequest(false);
681686
}
682-
}, [hideLibraryBrowsing, showNewSimulationRequest, setShowNewSimulationRequest, getDefaultFrequencyPresetIdForNewSimulation]);
687+
}, [autoPropagationEnvironment, hideLibraryBrowsing, openMapEditor, showNewSimulationRequest, setShowNewSimulationRequest, getDefaultFrequencyPresetIdForNewSimulation]);
683688
useEffect(() => {
684689
if (showSiteLibraryRequest) {
685690
if (hideLibraryBrowsing) {
@@ -961,34 +966,22 @@ export function Sidebar({
961966

962967
useEffect(() => {
963968
if (!pendingSiteLibraryDraft) return;
964-
setShowSiteLibraryManager(true);
965-
setShowAddLibraryForm(true);
966-
setNewLibraryNameError("");
967-
setNewLibraryVisibility("private");
968-
setNewLibraryCollaboratorUserIds([]);
969-
setNewLibraryCollaboratorRoles({});
970-
setNewLibrarySourceMeta(pendingSiteLibraryDraft.sourceMeta);
971-
setNewLibrarySeparateGain(shouldUseSeparateSiteGain(newLibraryTxGainDbi, newLibraryRxGainDbi));
972-
setPendingDraftAutoInsert(true);
973-
setNewLibraryName(pendingSiteLibraryDraft.suggestedName ?? "");
974-
setNewLibraryDescription("");
975-
setNewLibraryLat(pendingSiteLibraryDraft.lat);
976-
setNewLibraryLon(pendingSiteLibraryDraft.lon);
977-
const terrainElev = Number(
978-
sampleSrtmElevation(srtmTiles, pendingSiteLibraryDraft.lat, pendingSiteLibraryDraft.lon),
979-
);
980-
if (Number.isFinite(terrainElev)) {
981-
setNewLibraryGroundM(Math.round(terrainElev));
982-
setLibrarySearchStatus(
983-
`Draft opened at ${pendingSiteLibraryDraft.lat.toFixed(5)}, ${pendingSiteLibraryDraft.lon.toFixed(5)} (terrain ${Math.round(terrainElev)} m).`,
984-
);
985-
} else {
986-
setLibrarySearchStatus(
987-
`Draft opened at ${pendingSiteLibraryDraft.lat.toFixed(5)}, ${pendingSiteLibraryDraft.lon.toFixed(5)}.`,
988-
);
989-
}
969+
openMapEditor({
970+
kind: "site",
971+
resourceId: null,
972+
isNew: true,
973+
label: "New Site",
974+
anchorRect: { top: 96, right: 320, bottom: 96, left: 320, width: 0, height: 0 },
975+
siteSeed: {
976+
lat: pendingSiteLibraryDraft.lat,
977+
lon: pendingSiteLibraryDraft.lon,
978+
name: pendingSiteLibraryDraft.suggestedName,
979+
sourceMeta: pendingSiteLibraryDraft.sourceMeta,
980+
insertIntoSimulation: true,
981+
},
982+
});
990983
clearPendingSiteLibraryDraft();
991-
}, [pendingSiteLibraryDraft, srtmTiles, clearPendingSiteLibraryDraft]);
984+
}, [pendingSiteLibraryDraft, clearPendingSiteLibraryDraft, openMapEditor]);
992985
useEffect(() => {
993986
if (!pendingSiteLibraryOpenEntryId) return;
994987
const entry = siteLibrary.find((candidate) => candidate.id === pendingSiteLibraryOpenEntryId);
@@ -1204,27 +1197,22 @@ export function Sidebar({
12041197
isNew: true,
12051198
label: "New Site",
12061199
anchorRect,
1200+
siteSeed: {
1201+
lat: site.position.lat,
1202+
lon: site.position.lon,
1203+
name: site.name,
1204+
insertIntoSimulation: true,
1205+
},
12071206
});
12081207
};
1209-
const openNewSiteForm = () => {
1210-
setShowSiteLibraryManager(true);
1211-
setShowAddLibraryForm(true);
1212-
setNewLibraryName("");
1213-
setNewLibraryDescription("");
1214-
setNewLibraryVisibility("private");
1215-
setNewLibraryCollaboratorUserIds([]);
1216-
setNewLibraryCollaboratorRoles({});
1217-
setNewLibrarySourceMeta(undefined);
1218-
setNewLibraryLat(0);
1219-
setNewLibraryLon(0);
1220-
setNewLibraryGroundM(0);
1221-
setNewLibraryAntennaM(10);
1222-
setNewLibraryTxPowerDbm(20);
1223-
setNewLibraryTxGainDbi(0);
1224-
setNewLibraryRxGainDbi(0);
1225-
setNewLibrarySeparateGain(false);
1226-
setNewLibraryCableLossDb(0);
1227-
setLibrarySearchStatus("");
1208+
const openNewSiteForm = (triggerEl?: Element | null) => {
1209+
openMapEditor({
1210+
kind: "site",
1211+
resourceId: null,
1212+
isNew: true,
1213+
label: "New Site",
1214+
anchorRect: triggerEl?.getBoundingClientRect() ?? { top: 96, right: 320, bottom: 96, left: 320, width: 0, height: 0 },
1215+
});
12281216
};
12291217
const addLibraryEntryNow = () => {
12301218
if (!currentUser?.id) {
@@ -1780,13 +1768,18 @@ export function Sidebar({
17801768
Library
17811769
</ActionButton>
17821770
<ActionButton
1783-
onClick={() => {
1784-
setNewSimulationName("");
1785-
setNewSimulationDescription("");
1786-
setNewSimulationNameError("");
1787-
setModalFreqPresetId(getDefaultFrequencyPresetIdForNewSimulation());
1788-
setModalAutoPropEnv(autoPropagationEnvironment);
1789-
setShowNewSimulationModal(true);
1771+
onClick={(event) => {
1772+
openMapEditor({
1773+
kind: "simulation",
1774+
resourceId: null,
1775+
isNew: true,
1776+
label: "New Simulation",
1777+
anchorRect: event.currentTarget.getBoundingClientRect(),
1778+
simulationSeed: {
1779+
frequencyPresetId: getDefaultFrequencyPresetIdForNewSimulation(),
1780+
autoPropagationEnvironment,
1781+
},
1782+
});
17901783
}}
17911784
type="button"
17921785
>
@@ -1859,7 +1852,7 @@ export function Sidebar({
18591852
{!hideLibraryBrowsing ? (
18601853
<>
18611854
{!readOnly ? (
1862-
<ActionButton onClick={openNewSiteForm} type="button">
1855+
<ActionButton onClick={(event) => openNewSiteForm(event.currentTarget)} type="button">
18631856
New
18641857
</ActionButton>
18651858
) : null}
@@ -3056,7 +3049,20 @@ export function Sidebar({
30563049
resourceId: params.resourceId,
30573050
isNew: false,
30583051
label: params.label,
3059-
anchorRect: { top: 0, right: 0, bottom: 0, left: 0, width: 0, height: 0 },
3052+
anchorRect: params.anchorRect,
3053+
})
3054+
}
3055+
onCreateSimulation={(triggerEl) =>
3056+
openMapEditor({
3057+
kind: "simulation",
3058+
resourceId: null,
3059+
isNew: true,
3060+
label: "New Simulation",
3061+
anchorRect: triggerEl?.getBoundingClientRect() ?? { top: 96, right: 320, bottom: 96, left: 320, width: 0, height: 0 },
3062+
simulationSeed: {
3063+
frequencyPresetId: getDefaultFrequencyPresetIdForNewSimulation(),
3064+
autoPropagationEnvironment,
3065+
},
30603066
})
30613067
}
30623068
/>
@@ -3290,20 +3296,6 @@ export function Sidebar({
32903296
</ActionButton>
32913297
</div>
32923298
<div className="chip-group">
3293-
<ActionButton
3294-
onClick={(e) => {
3295-
openMapEditor({
3296-
kind: "site",
3297-
resourceId: null,
3298-
isNew: true,
3299-
label: "New Site",
3300-
anchorRect: e.currentTarget.getBoundingClientRect(),
3301-
});
3302-
}}
3303-
type="button"
3304-
>
3305-
Add Site
3306-
</ActionButton>
33073299
<ActionButton
33083300
onClick={() => setSelectedLibraryIds(new Set(filteredSiteLibrary.map((entry) => entry.id)))}
33093301
type="button"

0 commit comments

Comments
 (0)