mirror of
https://github.com/koala73/worldmonitor.git
synced 2026-04-25 17:14:57 +02:00
Instability country navigation (#932)
* feat: enhance map resizing with automatic container observation, top-edge pinning, and responsive height adjustments. * fix: Correct map resizing and prevent duplicate transition end events during height adjustments. * feat: enable country clicks in the CII panel to open country briefs and add hover styling for clickable countries on maps. * feat: Add globe map resize support and refactor map resize event handling logic. * refactor: Streamline map destruction logic, remove redundant map resizing calls, and format CSS keyframe rules. * fix: revert unintended destroy() behavior change and CSS formatting noise - destroy(): restore unconditional cleanup of all map instances (safer for edge cases where stale refs might exist after mode switches) - Revert cosmetic CSS changes: combinator spacing, keyframe reformatting, missing newline at EOF --------- Co-authored-by: Elie Habib <elie.habib@gmail.com>
This commit is contained in:
@@ -300,6 +300,10 @@ export class App {
|
||||
|
||||
this.panelLayout = new PanelLayoutManager(this.state, {
|
||||
openCountryStory: (code, name) => this.countryIntel.openCountryStory(code, name),
|
||||
openCountryBrief: (code) => {
|
||||
const name = CountryIntelManager.resolveCountryName(code);
|
||||
void this.countryIntel.openCountryBriefByCode(code, name);
|
||||
},
|
||||
loadAllData: () => this.dataLoader.loadAllData(),
|
||||
updateMonitorResults: () => this.dataLoader.updateMonitorResults(),
|
||||
loadSecurityAdvisories: () => this.dataLoader.loadSecurityAdvisories(),
|
||||
|
||||
@@ -162,6 +162,7 @@ export class CountryIntelManager implements AppModule {
|
||||
|
||||
this.ctx.countryBriefPage.show(country, code, score, signals);
|
||||
this.ctx.map?.highlightCountry(code);
|
||||
this.ctx.map?.fitCountry(code);
|
||||
|
||||
if (opts?.maximize) {
|
||||
requestAnimationFrame(() => {
|
||||
|
||||
@@ -66,6 +66,7 @@ import { trackCriticalBannerAction } from '@/services/analytics';
|
||||
|
||||
export interface PanelLayoutCallbacks {
|
||||
openCountryStory: (code: string, name: string) => void;
|
||||
openCountryBrief: (code: string) => void;
|
||||
loadAllData: () => Promise<void>;
|
||||
updateMonitorResults: () => void;
|
||||
loadSecurityAdvisories?: () => Promise<void>;
|
||||
@@ -572,6 +573,9 @@ export class PanelLayoutManager implements AppModule {
|
||||
ciiPanel.setShareStoryHandler((code, name) => {
|
||||
this.callbacks.openCountryStory(code, name);
|
||||
});
|
||||
ciiPanel.setCountryClickHandler((code) => {
|
||||
this.callbacks.openCountryBrief(code);
|
||||
});
|
||||
this.ctx.panels['cii'] = ciiPanel;
|
||||
|
||||
const cascadePanel = new CascadePanel();
|
||||
|
||||
@@ -8,6 +8,7 @@ export class CIIPanel extends Panel {
|
||||
private scores: CountryScore[] = [];
|
||||
private focalPointsReady = false;
|
||||
private onShareStory?: (code: string, name: string) => void;
|
||||
private onCountryClick?: (code: string) => void;
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
@@ -22,6 +23,10 @@ export class CIIPanel extends Panel {
|
||||
this.onShareStory = handler;
|
||||
}
|
||||
|
||||
public setCountryClickHandler(handler: (code: string) => void): void {
|
||||
this.onCountryClick = handler;
|
||||
}
|
||||
|
||||
private getLevelColor(level: CountryScore['level']): string {
|
||||
switch (level) {
|
||||
case 'critical': return getCSSColor('--semantic-critical');
|
||||
@@ -82,14 +87,25 @@ export class CIIPanel extends Panel {
|
||||
}
|
||||
|
||||
private bindShareButtons(): void {
|
||||
if (!this.onShareStory) return;
|
||||
if (!this.onShareStory && !this.onCountryClick) return;
|
||||
|
||||
this.content.querySelectorAll('.cii-country').forEach(el => {
|
||||
el.addEventListener('click', (e) => {
|
||||
const target = e.currentTarget as HTMLElement;
|
||||
const code = target.dataset.code;
|
||||
if (code && this.onCountryClick) {
|
||||
this.onCountryClick(code);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.content.querySelectorAll('.cii-share-btn').forEach(btn => {
|
||||
btn.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
const el = e.currentTarget as HTMLElement;
|
||||
const code = el.dataset.code || '';
|
||||
const name = el.dataset.name || '';
|
||||
if (code && name) this.onShareStory!(code, name);
|
||||
if (code && name && this.onShareStory) this.onShareStory(code, name);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -196,6 +196,10 @@ export class MapContainer {
|
||||
}
|
||||
|
||||
public resize(): void {
|
||||
if (this.useGlobe) {
|
||||
this.globeMap?.resize();
|
||||
return;
|
||||
}
|
||||
if (this.useDeckGL) {
|
||||
this.deckGLMap?.resize();
|
||||
} else {
|
||||
|
||||
@@ -9933,6 +9933,14 @@ a.prediction-link:hover {
|
||||
background: var(--darken-medium);
|
||||
border-radius: 4px;
|
||||
padding: 8px;
|
||||
cursor: pointer;
|
||||
transition: background 0.1s ease, border-color 0.1s ease;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.cii-country:hover {
|
||||
background: var(--surface-hover);
|
||||
border-color: var(--border);
|
||||
}
|
||||
|
||||
.cii-header {
|
||||
@@ -16619,6 +16627,7 @@ body.has-breaking-alert .panels-grid {
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* ─── Globe Map Styles ──────────────────────────────────────────────────────── */
|
||||
|
||||
.globe-mode {
|
||||
|
||||
Reference in New Issue
Block a user