fix(map): canonicalize facet visibility and compact header

This commit is contained in:
Codex
2026-08-09 15:48:23 +03:00
parent 71c1528b83
commit bfa3af896b
8 changed files with 213 additions and 91 deletions
+44 -14
View File
@@ -17,10 +17,12 @@ import type { MapRuntimeFact } from "./useMapDataProductRuntime.js";
import {
compareMapRuntimeFacts,
mapFactMatchesFilters,
mapPresentationFacetValueIsEnabled,
mapPresentationFacetCounts,
mapPresentationProfileForFact,
mapRuntimeDisplayLabel,
mapRuntimeFactIsRenderable,
normalizeMapPresentationFacetSelections,
normalizeClientMapPresentationProfiles,
resolveMapPresentationClass,
toggleMapPresentationFacetSelection,
@@ -665,11 +667,23 @@ const defaultSubjectCardRect: WorkspaceWindowRect = {
height: 520,
};
function initialSubjectState(bindings: MapDataProductBinding[], saved: MapSubjectState[] | undefined) {
function initialSubjectState(
bindings: MapDataProductBinding[],
saved: MapSubjectState[] | undefined,
profiles: MapPresentationProfile[],
) {
const savedByBinding = new Map((saved ?? []).map((state) => [state.bindingId, state]));
return Object.fromEntries(bindings.map((binding, index) => {
const state = savedByBinding.get(binding.id);
return [binding.id, state ?? {
const profile = mapPresentationProfileForFact(
profiles,
binding.presentationProfileId,
binding.semanticTypes[0] ?? "",
);
return [binding.id, state ? {
...state,
filters: profile ? normalizeMapPresentationFacetSelections(state.filters, profile) : state.filters,
} : {
bindingId: binding.id,
visible: true,
filters: {},
@@ -796,14 +810,22 @@ export const MapFixturePreview = forwardRef<MapFixturePreviewHandle, {
initialMapReferenceLayers(initialLayout?.referenceLayers)
));
const [subjectStates, setSubjectStates] = useState<Record<string, MapSubjectState>>(() => (
initialSubjectState(initialLayout?.dataProductBindings ?? [], initialLayout?.subjectStates)
initialSubjectState(initialLayout?.dataProductBindings ?? [], initialLayout?.subjectStates, presentationProfiles)
));
const presentationFilters = useMemo<MapPresentationFilters>(() => Object.fromEntries(
Object.entries(subjectStates).map(([bindingId, state]) => [bindingId, {
visible: state.visible,
facets: state.filters,
}]),
), [subjectStates]);
Object.entries(subjectStates).map(([bindingId, state]) => {
const binding = dataProductBindings.find((candidate) => candidate.id === bindingId);
const profile = mapPresentationProfileForFact(
presentationProfiles,
binding?.presentationProfileId,
binding?.semanticTypes[0] ?? "",
);
return [bindingId, {
visible: state.visible,
facets: profile ? normalizeMapPresentationFacetSelections(state.filters, profile) : state.filters,
}];
}),
), [dataProductBindings, presentationProfiles, subjectStates]);
const runtimeBindings = useMapDataProductRuntime({
applicationId,
pageId,
@@ -1339,9 +1361,12 @@ export const MapFixturePreview = forwardRef<MapFixturePreviewHandle, {
window: defaultSubjectWindowState(0),
}).map((state) => {
const summary = presentationSummaries.find((candidate) => candidate.bindingId === state.bindingId);
return summary && !hasSubjectWindowControls(summary.profile)
? { ...state, window: { ...state.window, open: false } }
const normalizedState = summary
? { ...state, filters: normalizeMapPresentationFacetSelections(state.filters, summary.profile) }
: state;
return summary && !hasSubjectWindowControls(summary.profile)
? { ...normalizedState, window: { ...normalizedState.window, open: false } }
: normalizedState;
}),
}),
}), [dataProductBindings, inspectorOpenSections, mapCamera, mapHeight, mapSettings, pinBindings, presentationProfiles, presentationSummaries, referenceLayers, subjectDetailProfiles, subjectStates]);
@@ -1359,13 +1384,13 @@ export const MapFixturePreview = forwardRef<MapFixturePreviewHandle, {
});
}, [dataProductBindings]);
const togglePresentationFilter = (bindingId: string, field: string, value: string) => {
const togglePresentationFilter = (bindingId: string, field: string, value: string, availableValues: string[]) => {
updateSubjectState(bindingId, (state) => {
const filters = state.visible ? state.filters : {};
return {
...state,
visible: true,
filters: toggleMapPresentationFacetSelection(filters, field, value),
filters: toggleMapPresentationFacetSelection(filters, field, value, availableValues),
};
});
};
@@ -2619,7 +2644,7 @@ export const MapFixturePreview = forwardRef<MapFixturePreviewHandle, {
<div className="catalog-map-fixture__target-filter-list">
{summary.profile.facets.filter((facet) => facet.counter || facet.filterable).flatMap((facet) => (
facet.values.map((item) => {
const active = state.filters[facet.field]?.includes(item.value) ?? false;
const active = mapPresentationFacetValueIsEnabled(state.filters, facet.field, item.value);
const rowId = `${summary.bindingId}:${facet.field}:${item.value}`;
const expanded = Boolean(expandedFacetRows[rowId]);
const matchingEntities = selectable.filter((entity) => (
@@ -2644,7 +2669,12 @@ export const MapFixturePreview = forwardRef<MapFixturePreviewHandle, {
className="catalog-map-fixture__target-filter-body"
aria-pressed={active}
disabled={!facet.filterable}
onClick={() => togglePresentationFilter(summary.bindingId, facet.field, item.value)}
onClick={() => togglePresentationFilter(
summary.bindingId,
facet.field,
item.value,
facet.values.map((value) => value.value),
)}
>
<span className="catalog-map-fixture__target-filter-label">{item.label}</span>
<span className="catalog-map-fixture__target-filter-count">{summary.counts[facet.field]?.[item.value] ?? 0}</span>