Release govoplan-organizations v0.1.21: unify interface contracts and documentation
Module Package Release / publish-packages (push) Successful in 12s
Module Package Release / publish-packages (push) Successful in 12s
This commit is contained in:
+2
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@govoplan/organizations-webui",
|
||||
"version": "0.1.20",
|
||||
"version": "0.1.21",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"main": "src/index.ts",
|
||||
@@ -19,7 +19,7 @@
|
||||
"./styles/organizations.css": "./src/styles/organizations.css"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@govoplan/core-webui": "^0.1.18",
|
||||
"@govoplan/core-webui": "^0.1.45",
|
||||
"@vitejs/plugin-react": "^5.2.0",
|
||||
"lucide-react": "^1.23.0",
|
||||
"react": ">=19.2.7 <20",
|
||||
|
||||
@@ -17,7 +17,8 @@ const translations = source("../src/i18n/generatedTranslations.ts");
|
||||
assert(page.includes("DocumentationHelpLink") && settings.includes("DocumentationHelpLink"), "Workspace and tenant settings expose contextual documentation");
|
||||
assert(page.includes("ActionBlockerHint") && settings.includes("ActionBlockerHint"), "Read-only states identify action, actor, and destination");
|
||||
assert(page.includes("disabledReason") && settings.includes("disabledReason"), "Unavailable organization actions explain their state");
|
||||
assert(page.includes("requestDiscard(() => void loadModel())") && settings.includes("requestDiscard(() => void load())"), "Reload preserves dirty organization drafts and settings");
|
||||
assert(page.includes("<PageActionBar") && page.includes("reloadAction={{") && page.includes("onReload: () => void loadModel()") && settings.includes("requestDiscard(() => void load())"), "Reload uses the guarded semantic page action or the settings draft guard");
|
||||
assert((page.match(/<Card bodyLayout="table"/g) ?? []).length === 7, "All seven organization collection tables use the shared edge-to-edge card body");
|
||||
assert(page.includes("hasDirtyDraft ? requestDiscard(discardDrafts)"), "Editor close uses the shared unsaved-change guard");
|
||||
assert(page.includes("ORGANIZATIONS_FIELD_DOCUMENTATION"), "Model fields link to stable consequence documentation");
|
||||
assert(patterns.includes('topicId: "organizations.model"') && patterns.includes('topicId: "organizations.reference.fields-and-consequences"'), "Organizations uses manifest-backed help references");
|
||||
|
||||
@@ -178,8 +178,9 @@ export default function OrganizationTemplateUpgradePanel({ settings, auth }: { s
|
||||
return <>
|
||||
{error && <DismissibleAlert tone="danger" resetKey={error}>{error}</DismissibleAlert>}
|
||||
{success && <DismissibleAlert tone="success" resetKey={success}>{success}</DismissibleAlert>}
|
||||
<Card title="Organization template upgrades" actions={<Button onClick={() => void load()} disabled={loading || busy}><RefreshCw aria-hidden="true" /> Reload</Button>}>
|
||||
<Card bodyLayout="table" title="Organization template upgrades" actions={<Button onClick={() => void load()} disabled={loading || busy}><RefreshCw aria-hidden="true" /> Reload</Button>}>
|
||||
<LoadingFrame loading={loading} label="Loading organization template upgrade state">
|
||||
<div className="content-pad">
|
||||
<MetricGrid density="compact">
|
||||
<MetricCard label="Applied version" value={currentVersion?.version ?? "Custom model"} tone="info" />
|
||||
<MetricCard label="Available upgrades" value={targets.length} tone={targets.length ? "info" : "good"} />
|
||||
@@ -191,6 +192,7 @@ export default function OrganizationTemplateUpgradePanel({ settings, auth }: { s
|
||||
<FormField label="Published target version"><select value={targetVersionId} disabled={!canWrite || busy || !targets.length} onChange={(event) => setTargetVersionId(event.target.value)}>{targets.length ? targets.map((version) => <option key={version.id} value={version.id}>{templateVersionLabel(templates, version)}</option>) : <option value="">No newer published version</option>}</select></FormField>
|
||||
<Button variant="primary" onClick={() => void createPreview()} disabled={!canWrite || busy || !targetVersionId}><GitCompareArrows aria-hidden="true" /> Create preview</Button>
|
||||
</ActionToolbar>
|
||||
</div>
|
||||
<div className="organization-upgrade-table"><DataGrid id="organization-model-upgrades" rows={upgrades} columns={upgradeColumns} initialFit="container" getRowKey={(row) => row.id} emptyText={current ? "No organization template upgrades have been previewed." : "This tenant model was not instantiated from a system template."} /></div>
|
||||
</LoadingFrame>
|
||||
</Card>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useCallback, useEffect, useMemo, useRef, useState, type FormEvent } from "react";
|
||||
import { Edit3, Plus, RefreshCw } from "lucide-react";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState, type FormEvent, type JSX } from "react";
|
||||
import { Edit3, Plus } from "lucide-react";
|
||||
import { FormLayout, ActionToolbar,
|
||||
ActionBlockerHint,
|
||||
AdminIconButton,
|
||||
@@ -282,7 +282,7 @@ function mapById<T extends { id: string }>(items: T[]): Map<string, T> {
|
||||
function sectionGroupsFor(sections: ReadonlySet<OrganizationSection>): ModuleSubnavGroup<OrganizationSection>[] {
|
||||
return SECTION_GROUPS.map((group) => ({
|
||||
...group,
|
||||
items: group.items.filter((item) => sections.has(item.id))
|
||||
items: group.items.filter((item) => "id" in item && sections.has(item.id))
|
||||
})).filter((group) => group.items.length > 0);
|
||||
}
|
||||
|
||||
@@ -309,14 +309,14 @@ function activeStatus(active: boolean): JSX.Element {
|
||||
return <StatusBadge status={active ? "success" : "inactive"} label={active ? "i18n:govoplan-organizations.active.a733b809" : "i18n:govoplan-organizations.inactive.09af574c"} />;
|
||||
}
|
||||
|
||||
function SluggedFields({
|
||||
function SluggedFields<T extends SluggedDraft>({
|
||||
draft,
|
||||
onChange,
|
||||
disabled,
|
||||
disabledReason
|
||||
}: {
|
||||
draft: SluggedDraft;
|
||||
onChange: (next: SluggedDraft) => void;
|
||||
draft: T;
|
||||
onChange: (next: T) => void;
|
||||
disabled: boolean;
|
||||
disabledReason?: string;
|
||||
}) {
|
||||
@@ -1066,7 +1066,7 @@ export default function OrganizationsPage({
|
||||
)}
|
||||
primaryLabel="i18n:govoplan-organizations.organization_model.5945c48a"
|
||||
contentLabel={title}
|
||||
documentationType={mode === "admin" ? "admin" : "user"}
|
||||
documentationType="user"
|
||||
>
|
||||
{content}
|
||||
</WorkspaceLayout>
|
||||
@@ -1075,16 +1075,16 @@ export default function OrganizationsPage({
|
||||
function renderModelSection() {
|
||||
return (
|
||||
<div className="organizations-table-stack">
|
||||
<Card title="i18n:govoplan-organizations.unit_types.c7afc174" actions={<AdminIconButton label="i18n:govoplan-organizations.add_unit_type.58f2c05a" icon={<Plus size={16} aria-hidden="true" />} variant="primary" disabled={!canWriteModel || busy} disabledReason={organizationWriteReason(canWriteModel, busy, "model")} onClick={openUnitTypeCreate} />}>
|
||||
<Card bodyLayout="table" title="i18n:govoplan-organizations.unit_types.c7afc174" actions={<AdminIconButton label="i18n:govoplan-organizations.add_unit_type.58f2c05a" icon={<Plus size={16} aria-hidden="true" />} variant="primary" disabled={!canWriteModel || busy} disabledReason={organizationWriteReason(canWriteModel, busy, "model")} onClick={openUnitTypeCreate} />}>
|
||||
<DataGrid id="organizations-unit-types" rows={model.unit_types} columns={unitTypeColumns} getRowKey={(row) => row.id} emptyText="i18n:govoplan-organizations.no_unit_types_found.c81fb2a7" initialFit="container" />
|
||||
</Card>
|
||||
<Card title="i18n:govoplan-organizations.structures.f9b7f3b4" actions={<AdminIconButton label="i18n:govoplan-organizations.add_structure.b722042a" icon={<Plus size={16} aria-hidden="true" />} variant="primary" disabled={!canWriteModel || busy} disabledReason={organizationWriteReason(canWriteModel, busy, "model")} onClick={openStructureCreate} />}>
|
||||
<Card bodyLayout="table" title="i18n:govoplan-organizations.structures.f9b7f3b4" actions={<AdminIconButton label="i18n:govoplan-organizations.add_structure.b722042a" icon={<Plus size={16} aria-hidden="true" />} variant="primary" disabled={!canWriteModel || busy} disabledReason={organizationWriteReason(canWriteModel, busy, "model")} onClick={openStructureCreate} />}>
|
||||
<DataGrid id="organizations-structures" rows={model.structures} columns={structureColumns} getRowKey={(row) => row.id} emptyText="i18n:govoplan-organizations.no_structures_found.20b382d0" initialFit="container" />
|
||||
</Card>
|
||||
<Card title="i18n:govoplan-organizations.relation_types.e5890528" actions={<AdminIconButton label="i18n:govoplan-organizations.add_relation_type.2ad19d03" icon={<Plus size={16} aria-hidden="true" />} variant="primary" disabled={!canWriteModel || busy} disabledReason={organizationWriteReason(canWriteModel, busy, "model")} onClick={openRelationTypeCreate} />}>
|
||||
<Card bodyLayout="table" title="i18n:govoplan-organizations.relation_types.e5890528" actions={<AdminIconButton label="i18n:govoplan-organizations.add_relation_type.2ad19d03" icon={<Plus size={16} aria-hidden="true" />} variant="primary" disabled={!canWriteModel || busy} disabledReason={organizationWriteReason(canWriteModel, busy, "model")} onClick={openRelationTypeCreate} />}>
|
||||
<DataGrid id="organizations-relation-types" rows={model.relation_types} columns={relationTypeColumns} getRowKey={(row) => row.id} emptyText="i18n:govoplan-organizations.no_relation_types_found.6f90bb81" initialFit="container" />
|
||||
</Card>
|
||||
<Card title="i18n:govoplan-organizations.function_types.172c01fe" actions={<AdminIconButton label="i18n:govoplan-organizations.add_function_type.90d793f1" icon={<Plus size={16} aria-hidden="true" />} variant="primary" disabled={!canWriteModel || busy} disabledReason={organizationWriteReason(canWriteModel, busy, "model")} onClick={openFunctionTypeCreate} />}>
|
||||
<Card bodyLayout="table" title="i18n:govoplan-organizations.function_types.172c01fe" actions={<AdminIconButton label="i18n:govoplan-organizations.add_function_type.90d793f1" icon={<Plus size={16} aria-hidden="true" />} variant="primary" disabled={!canWriteModel || busy} disabledReason={organizationWriteReason(canWriteModel, busy, "model")} onClick={openFunctionTypeCreate} />}>
|
||||
<DataGrid id="organizations-function-types" rows={model.function_types} columns={functionTypeColumns} getRowKey={(row) => row.id} emptyText="i18n:govoplan-organizations.no_function_types_found.5eef31b1" initialFit="container" />
|
||||
</Card>
|
||||
</div>
|
||||
@@ -1129,7 +1129,7 @@ export default function OrganizationsPage({
|
||||
/>
|
||||
) : <p className="muted small-note">i18n:govoplan-organizations.no_units_found.eea2dd0c</p>}
|
||||
</Card>
|
||||
<Card title="i18n:govoplan-organizations.units.e14d0d92" actions={<AdminIconButton label="i18n:govoplan-organizations.add_unit.8fa12fb1" icon={<Plus size={16} aria-hidden="true" />} variant="primary" disabled={!canWriteUnits || busy} disabledReason={organizationWriteReason(canWriteUnits, busy, "unit")} onClick={() => openUnitCreate()} />}>
|
||||
<Card bodyLayout="table" title="i18n:govoplan-organizations.units.e14d0d92" actions={<AdminIconButton label="i18n:govoplan-organizations.add_unit.8fa12fb1" icon={<Plus size={16} aria-hidden="true" />} variant="primary" disabled={!canWriteUnits || busy} disabledReason={organizationWriteReason(canWriteUnits, busy, "unit")} onClick={() => openUnitCreate()} />}>
|
||||
<DataGrid id="organizations-units" rows={model.units} columns={unitColumns} getRowKey={(row) => row.id} emptyText="i18n:govoplan-organizations.no_units_found.eea2dd0c" initialFit="container" />
|
||||
</Card>
|
||||
</div>
|
||||
@@ -1139,7 +1139,7 @@ export default function OrganizationsPage({
|
||||
function renderRelationsSection() {
|
||||
return (
|
||||
<div className="organizations-table-stack">
|
||||
<Card title="i18n:govoplan-organizations.relations.1c796711" actions={<AdminIconButton label="i18n:govoplan-organizations.add_relation.6b6e67ea" icon={<Plus size={16} aria-hidden="true" />} variant="primary" disabled={!canWriteUnits || busy} disabledReason={organizationWriteReason(canWriteUnits, busy, "unit")} onClick={openRelationCreate} />}>
|
||||
<Card bodyLayout="table" title="i18n:govoplan-organizations.relations.1c796711" actions={<AdminIconButton label="i18n:govoplan-organizations.add_relation.6b6e67ea" icon={<Plus size={16} aria-hidden="true" />} variant="primary" disabled={!canWriteUnits || busy} disabledReason={organizationWriteReason(canWriteUnits, busy, "unit")} onClick={openRelationCreate} />}>
|
||||
<DataGrid id="organizations-relations" rows={model.relations} columns={relationColumns} getRowKey={(row) => row.id} emptyText="i18n:govoplan-organizations.no_relations_found.4e75b11d" initialFit="container" />
|
||||
</Card>
|
||||
</div>
|
||||
@@ -1149,7 +1149,7 @@ export default function OrganizationsPage({
|
||||
function renderFunctionsSection() {
|
||||
return (
|
||||
<div className="organizations-table-stack">
|
||||
<Card title="i18n:govoplan-organizations.functions.805dc49b" actions={<AdminIconButton label="i18n:govoplan-organizations.add_function.6abafee0" icon={<Plus size={16} aria-hidden="true" />} variant="primary" disabled={!canWriteFunctions || busy} disabledReason={organizationWriteReason(canWriteFunctions, busy, "function")} onClick={() => openFunctionCreate()} />}>
|
||||
<Card bodyLayout="table" title="i18n:govoplan-organizations.functions.805dc49b" actions={<AdminIconButton label="i18n:govoplan-organizations.add_function.6abafee0" icon={<Plus size={16} aria-hidden="true" />} variant="primary" disabled={!canWriteFunctions || busy} disabledReason={organizationWriteReason(canWriteFunctions, busy, "function")} onClick={() => openFunctionCreate()} />}>
|
||||
<DataGrid id="organizations-functions" rows={model.functions} columns={functionColumns} getRowKey={(row) => row.id} emptyText="i18n:govoplan-organizations.no_functions_found.54e759a0" initialFit="container" />
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user