Release govoplan-views v0.1.22: unify interface contracts and documentation

This commit is contained in:
2026-09-08 01:32:54 +02:00
parent 9a53898388
commit 655aea6662
13 changed files with 235 additions and 13 deletions
+33 -5
View File
@@ -26,6 +26,7 @@ import { FormGrid,
ExplorerTree,
FormField,
IconButton,
NavigationPreferenceEditor,
SearchableSelect,
SegmentedControl,
SelectionList,
@@ -33,6 +34,7 @@ import { FormGrid,
StatusBadge,
ToggleSwitch,
adminErrorMessage,
configurableNavigationItemsForModules,
dispatchPlatformViewChanged,
i18nMessage,
usePlatformLanguage,
@@ -134,6 +136,8 @@ export default function ViewsAdminPanel({
}) {
const surfaces = useViewSurfaces();
const modules = usePlatformModules();
const navigationItems = useMemo(() => configurableNavigationItemsForModules(modules), [modules]);
const navigationProductAreas = useMemo(() => modules.flatMap((module) => module.productAreas ?? []), [modules]);
const productAreas = useMemo(() => aggregateProductAreas(modules), [modules]);
const { requestDiscard } = useUnsavedChanges();
const { translateText } = usePlatformLanguage();
@@ -763,6 +767,26 @@ export default function ViewsAdminPanel({
</FormField>
</div>
<section className="views-product-area-section">
<div className="views-section-heading">
<div>
<h4>i18n:govoplan-views.navigation_layout</h4>
<p className="muted small-note">i18n:govoplan-views.navigation_editor_help</p>
</div>
</div>
<NavigationPreferenceEditor
scope="view"
items={navigationItems}
productAreas={navigationProductAreas}
value={draft.presentation.navigation ?? null}
disabled={!definitionEditable || busy}
onChange={(navigation) => setDraft({
...draft,
presentation: { ...draft.presentation, navigation }
})}
/>
</section>
{productAreas.length > 0 && (
<ProductAreaEditor
areas={productAreas}
@@ -1480,6 +1504,7 @@ function ProductAreaEditor({
}) {
const { translateText } = usePlatformLanguage();
const ordered = orderedProductAreas(areas, draft.presentation.productAreaOrder);
const customNavigation = draft.presentation.navigation != null;
const requiredSurfaceIds = new Set(
surfaces.filter((surface) => surface.required).map((surface) => surface.id)
);
@@ -1518,14 +1543,14 @@ function ProductAreaEditor({
<div>
<h4>i18n:govoplan-views.product_areas</h4>
<p className="muted small-note">
i18n:govoplan-views.product_areas_help
{customNavigation ? "i18n:govoplan-views.product_areas_custom_navigation_help" : "i18n:govoplan-views.product_areas_help"}
</p>
</div>
<SegmentedControl<"grouped" | "flat">
ariaLabel={translateText("i18n:govoplan-views.navigation_layout")}
role="group"
value={draft.presentation.navigationMode ?? "grouped"}
disabled={disabled}
disabled={disabled || customNavigation}
onChange={(navigationMode) =>
updatePresentation({ ...draft.presentation, navigationMode })
}
@@ -1558,7 +1583,7 @@ function ProductAreaEditor({
{ value0: translateText(area.label) }
)}
maxLength={200}
disabled={disabled}
disabled={disabled || customNavigation}
onChange={(event) => setLabel(area.id, event.target.value)}
/>
<ToggleSwitch
@@ -1575,14 +1600,14 @@ function ProductAreaEditor({
label="i18n:govoplan-views.move_up"
icon={<ArrowUp size={16} />}
variant="ghost"
disabled={disabled || index === 0}
disabled={disabled || customNavigation || index === 0}
onClick={() => move(area.id, -1)}
/>
<IconButton
label="i18n:govoplan-views.move_down"
icon={<ArrowDown size={16} />}
variant="ghost"
disabled={disabled || index === ordered.length - 1}
disabled={disabled || customNavigation || index === ordered.length - 1}
onClick={() => move(area.id, 1)}
/>
</div>
@@ -1879,6 +1904,7 @@ function aggregateProductAreas(modules: PlatformWebModule[]): ViewProductArea[]
function defaultPresentation(areas: ViewProductArea[]): ViewPresentation {
return {
navigation: null,
navigationMode: "grouped",
productAreaOrder: areas.map((area) => area.id),
productAreaLabels: {},
@@ -1917,6 +1943,7 @@ function revisionPresentation(
): ViewPresentation {
const defaults = defaultPresentation(areas);
return {
navigation: value?.navigation ?? null,
navigationMode: value?.navigation_mode ?? defaults.navigationMode,
productAreaOrder:
value?.product_area_order?.length
@@ -1945,6 +1972,7 @@ function orderedProductAreas(
function presentationKey(value: ViewPresentation): string {
return JSON.stringify({
navigation: value.navigation ?? null,
navigationMode: value.navigationMode ?? "grouped",
productAreaOrder: value.productAreaOrder ?? [],
productAreaLabels: Object.fromEntries(