Add viewport controls, collapsible panels with persisted state, filters modal, and refined context menus; preserve map layout on navigation and let contacts be edited with relations on /contacts/:id instead of list modals. Co-authored-by: Cursor <cursoragent@cursor.com>
54 lines
1.2 KiB
JavaScript
54 lines
1.2 KiB
JavaScript
const STORAGE_KEY = 'sg-map-layout-v1'
|
|
|
|
const EMPTY = { positions: {}, scale: 1, view: null }
|
|
|
|
let memoryByMapId = null
|
|
|
|
function readAll() {
|
|
if (memoryByMapId) return memoryByMapId
|
|
try {
|
|
const raw = sessionStorage.getItem(STORAGE_KEY)
|
|
memoryByMapId = raw ? JSON.parse(raw) : {}
|
|
} catch {
|
|
memoryByMapId = {}
|
|
}
|
|
return memoryByMapId
|
|
}
|
|
|
|
export function readMapLayoutCache(mapId) {
|
|
if (!mapId) return { ...EMPTY }
|
|
const all = readAll()
|
|
const entry = all[String(mapId)]
|
|
return entry ? { ...EMPTY, ...entry } : { ...EMPTY }
|
|
}
|
|
|
|
export function writeMapLayoutCache(mapId, { positions, scale, view }) {
|
|
if (!mapId) return
|
|
const key = String(mapId)
|
|
const all = readAll()
|
|
const prev = all[key] || { ...EMPTY }
|
|
all[key] = {
|
|
positions: positions ?? prev.positions,
|
|
scale: scale ?? prev.scale,
|
|
view: view ?? prev.view,
|
|
}
|
|
memoryByMapId = all
|
|
try {
|
|
sessionStorage.setItem(STORAGE_KEY, JSON.stringify(all))
|
|
} catch {
|
|
/* sessionStorage quota */
|
|
}
|
|
}
|
|
|
|
export function clearMapLayoutCache(mapId) {
|
|
if (!mapId) return
|
|
const all = readAll()
|
|
delete all[String(mapId)]
|
|
memoryByMapId = all
|
|
try {
|
|
sessionStorage.setItem(STORAGE_KEY, JSON.stringify(all))
|
|
} catch {
|
|
/* ignore */
|
|
}
|
|
}
|