Compare commits
No commits in common. "main" and "v1.0.1" have entirely different histories.
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "mapdash-frontend",
|
"name": "mapdash-frontend",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.0.2",
|
"version": "1.0.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@ -420,25 +420,10 @@ async function refreshMap(): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mapDestroyTimer = 0;
|
|
||||||
async function onModeChange(mode: ViewMode): Promise<void> {
|
async function onModeChange(mode: ViewMode): Promise<void> {
|
||||||
if (mode !== 'map') view.applyLayout(); // timeline visible (timeline or split)
|
if (mode !== 'map') view.applyLayout(); // timeline visible (timeline or split)
|
||||||
if (mode === 'timeline') {
|
if (mode === 'timeline') mapView.closePanel(); // map hidden — drop its floating card
|
||||||
mapView.closePanel(); // map hidden — drop its floating card
|
if (mode !== 'timeline') await refreshMap(); // map visible (map or split)
|
||||||
// Free the Yandex map (tiles/canvas/GPU — the bulk of the tab's memory) a
|
|
||||||
// couple of seconds after it's closed; cancelled if a map view returns, so
|
|
||||||
// quick График⇄Карта toggles don't thrash a re-init.
|
|
||||||
window.clearTimeout(mapDestroyTimer);
|
|
||||||
mapDestroyTimer = window.setTimeout(() => {
|
|
||||||
mapView.destroy();
|
|
||||||
// The fresh map/ObjectManager will be empty, so drop the "already loaded"
|
|
||||||
// key — the next open re-fetches + re-renders instead of short-circuiting.
|
|
||||||
mapLoadedKey = '';
|
|
||||||
}, 2000);
|
|
||||||
} else {
|
|
||||||
window.clearTimeout(mapDestroyTimer); // map visible again — keep it
|
|
||||||
await refreshMap(); // map visible (map or split); ensureInit rebuilds if destroyed
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const viewModes = createViewModes(
|
const viewModes = createViewModes(
|
||||||
|
|||||||
@ -63,9 +63,6 @@ export interface MapView {
|
|||||||
ensureInit(): Promise<void>;
|
ensureInit(): Promise<void>;
|
||||||
invalidateSize(): void;
|
invalidateSize(): void;
|
||||||
closePanel(): void;
|
closePanel(): void;
|
||||||
/** Destroy the Yandex map and free its tiles/canvas/GPU memory. The next
|
|
||||||
* ensureInit() re-creates it from scratch. */
|
|
||||||
destroy(): void;
|
|
||||||
/** Pan + zoom the map to the surface's location (its cluster). No-op if it has no coords. */
|
/** Pan + zoom the map to the surface's location (its cluster). No-op if it has no coords. */
|
||||||
focusBoard(boardId: string): void;
|
focusBoard(boardId: string): void;
|
||||||
}
|
}
|
||||||
@ -636,20 +633,6 @@ export function createMapView(els: MapElements, apiKey: string): MapView {
|
|||||||
closePanel(): void {
|
closePanel(): void {
|
||||||
closeMapPanel();
|
closeMapPanel();
|
||||||
},
|
},
|
||||||
destroy(): void {
|
|
||||||
closeMapPanel();
|
|
||||||
// map.destroy() tears down Yandex's DOM inside #map and releases its tile
|
|
||||||
// cache / canvas / GPU textures. Our legend/counter overlays are siblings
|
|
||||||
// of #map, so they survive. Reset state so ensureInit() rebuilds cleanly.
|
|
||||||
if (map) {
|
|
||||||
try { map.destroy(); } catch { /* already torn down */ }
|
|
||||||
}
|
|
||||||
map = null;
|
|
||||||
objectManager = null;
|
|
||||||
initPromise = null;
|
|
||||||
pendingFocus = null;
|
|
||||||
pending = null;
|
|
||||||
},
|
|
||||||
focusBoard(boardId: string): void {
|
focusBoard(boardId: string): void {
|
||||||
pendingFocus = boardId;
|
pendingFocus = boardId;
|
||||||
applyFocus(); // applies now if already rendered, else waits for the next draw
|
applyFocus(); // applies now if already rendered, else waits for the next draw
|
||||||
|
|||||||
@ -327,11 +327,8 @@ input::placeholder { color: var(--text-muted); }
|
|||||||
display: flex; align-items: center; gap: 6px;
|
display: flex; align-items: center; gap: 6px;
|
||||||
padding: 0 12px; box-sizing: border-box; overflow: hidden;
|
padding: 0 12px; box-sizing: border-box; overflow: hidden;
|
||||||
background: var(--bg); border-bottom: 1px solid var(--border);
|
background: var(--bg); border-bottom: 1px solid var(--border);
|
||||||
container-type: inline-size;
|
|
||||||
}
|
}
|
||||||
.ci-label { flex: 0 0 auto; font-size: 11px; color: var(--text-muted); white-space: nowrap; }
|
.ci-label { flex: 0 0 auto; font-size: 11px; color: var(--text-muted); white-space: nowrap; }
|
||||||
/* Narrow column: drop the "Показывать" label so the three pills still fit. */
|
|
||||||
@container (max-width: 255px) { #chart-wrap #col-info .ci-label { display: none; } }
|
|
||||||
.ci-toggle {
|
.ci-toggle {
|
||||||
flex: 0 0 auto; border: none; cursor: pointer; white-space: nowrap;
|
flex: 0 0 auto; border: none; cursor: pointer; white-space: nowrap;
|
||||||
font-size: 12px; font-weight: 500; padding: 5px 11px; border-radius: 999px;
|
font-size: 12px; font-weight: 500; padding: 5px 11px; border-radius: 999px;
|
||||||
@ -773,14 +770,10 @@ html.role-pending .manager-only { display: none !important; }
|
|||||||
/* Row hover */
|
/* Row hover */
|
||||||
.vis-label.row-hover, .vis-group.row-hover { background-color: var(--row-hover) !important; }
|
.vis-label.row-hover, .vis-group.row-hover { background-color: var(--row-hover) !important; }
|
||||||
/* Fixed/resizable label column */
|
/* Fixed/resizable label column */
|
||||||
/* #timeline lifts specificity above vis-timeline's own `.vis-labelset .vis-label
|
.vis-label .vis-inner {
|
||||||
.vis-inner { padding: 5px }`, so the right padding actually applies. */
|
|
||||||
#timeline .vis-label .vis-inner {
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
box-sizing: border-box;
|
|
||||||
min-width: var(--label-w);
|
min-width: var(--label-w);
|
||||||
max-width: var(--label-w);
|
max-width: var(--label-w);
|
||||||
padding-left: 7px; padding-right: 7px; /* keep the address off the column borders */
|
|
||||||
overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: middle;
|
overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -54,7 +54,7 @@ export const zoomSteps: ReadonlyArray<{ days: number; label: string }> = [
|
|||||||
|
|
||||||
const MONTH_BG_ID = '__month_hover_bg';
|
const MONTH_BG_ID = '__month_hover_bg';
|
||||||
const CUR_MONTH_BG_ID = '__cur_month_bg';
|
const CUR_MONTH_BG_ID = '__cur_month_bg';
|
||||||
const MIN_LABEL_W = 200; // fits the three column-info pills (~188px) without clipping
|
const MIN_LABEL_W = 140;
|
||||||
|
|
||||||
// Uniform 3-letter month labels (moment's ru `MMM` mixes full/abbreviated with
|
// Uniform 3-letter month labels (moment's ru `MMM` mixes full/abbreviated with
|
||||||
// dots — "март", "май", "нояб.", "дек."). scale is 'month' at every zoom step.
|
// dots — "март", "май", "нояб.", "дек."). scale is 'month' at every zoom step.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user