chore(webui): enforce semantic interface patterns
This commit is contained in:
@@ -89,6 +89,17 @@ exceptional canvas needs only the shared heading. Specialized layouts such as
|
|||||||
`AdminPageLayout` compose these lower-level Core contracts; they do not repeat
|
`AdminPageLayout` compose these lower-level Core contracts; they do not repeat
|
||||||
markup or responsive CSS.
|
markup or responsive CSS.
|
||||||
|
|
||||||
|
`PageActionBar` is the semantic action contract for headed pages;
|
||||||
|
`WorkspaceActionBar` applies the identical ordering and lifecycle rules to a
|
||||||
|
full canvas and its collection, detail, and editor panes. Reload is always the
|
||||||
|
leading action on a refreshable projection. Help and ordinary task actions
|
||||||
|
follow contextual controls; Create is the far-right collection action;
|
||||||
|
destructive actions occupy a named separated group; an editor ends with
|
||||||
|
Discard and Save, with Save at the far right. Editor state is explicit:
|
||||||
|
`clean`, `dirty`, `invalid`, `saving`, `save-failed`, or `conflict`. Lower-level
|
||||||
|
`ActionToolbar` remains appropriate for a section-local view switch or compact
|
||||||
|
control group, but it must not recreate page or pane action placement.
|
||||||
|
|
||||||
Composite workspaces whose selected contribution supplies its own semantic
|
Composite workspaces whose selected contribution supplies its own semantic
|
||||||
heading may use `PageLayout` with its visible header delegated. This preserves
|
heading may use `PageLayout` with its visible header delegated. This preserves
|
||||||
the central inset, loading boundary, help identity, and content frame without
|
the central inset, loading boundary, help identity, and content frame without
|
||||||
@@ -120,6 +131,10 @@ The current structural vocabulary is:
|
|||||||
distribution, density, grouping, panel/section surfaces, accessible toolbar
|
distribution, density, grouping, panel/section surfaces, accessible toolbar
|
||||||
naming, help identity, and responsive wrapping. Modules may add
|
naming, help identity, and responsive wrapping. Modules may add
|
||||||
domain-specific presentation; they do not recreate the flex/wrap skeleton.
|
domain-specific presentation; they do not recreate the flex/wrap skeleton.
|
||||||
|
- `PageActionBar` and `WorkspaceActionBar` own semantic ordering, Reload,
|
||||||
|
editor persistence state, destructive separation, and page/pane scope. A
|
||||||
|
module supplies action behavior, authority, blocker reasons, and wording;
|
||||||
|
it does not assemble another panel-header action convention.
|
||||||
- `WorkspaceFrame` and `WorkspaceLayout` own application-viewport framing,
|
- `WorkspaceFrame` and `WorkspaceLayout` own application-viewport framing,
|
||||||
surfaces, overflow, list/detail and navigation/content pane geometry,
|
surfaces, overflow, list/detail and navigation/content pane geometry,
|
||||||
accessible region identity, and responsive pane behavior. Modules own only
|
accessible region identity, and responsive pane behavior. Modules own only
|
||||||
@@ -144,8 +159,13 @@ The current structural vocabulary is:
|
|||||||
validation, permissions, or domain wording.
|
validation, permissions, or domain wording.
|
||||||
- `MetricGrid` owns the responsive grouping around `MetricCard`: fixed one-to-five
|
- `MetricGrid` owns the responsive grouping around `MetricCard`: fixed one-to-five
|
||||||
columns or auto-fit, minimum card width, density, surrounding rhythm, and a
|
columns or auto-fit, minimum card width, density, surrounding rhythm, and a
|
||||||
named collapse point. Modules provide the metric, tone, and consequence;
|
named collapse point. `MetricCard.drilldown` provides an explicit link or
|
||||||
they do not recreate the group grid or reach across module CSS to size it.
|
in-page action when an authorized underlying detail helps the user act; it
|
||||||
|
names that destination and preserves the current scope and filters. The card
|
||||||
|
itself is never the hidden click target. Derived, privacy-suppressed,
|
||||||
|
non-enumerable, and purely informational aggregates remain inert. Modules
|
||||||
|
provide the metric, tone, destination, and consequence; they do not recreate
|
||||||
|
the group grid or reach across module CSS to size it.
|
||||||
- `DescriptionList` and `DescriptionItem` own semantic property presentation.
|
- `DescriptionList` and `DescriptionItem` own semantic property presentation.
|
||||||
The stacked variant supports compact multi-column facts; the inline variant
|
The stacked variant supports compact multi-column facts; the inline variant
|
||||||
supports one-column term/value rows with a standard term width. Both own
|
supports one-column term/value rows with a standard term width. Both own
|
||||||
@@ -230,7 +250,8 @@ one.
|
|||||||
names the object. Do not duplicate that action in a permanently visible side
|
names the object. Do not duplicate that action in a permanently visible side
|
||||||
panel. A side panel used as the creation surface appears for creation and is
|
panel. A side panel used as the creation surface appears for creation and is
|
||||||
otherwise absent or returns to its documented non-creation purpose.
|
otherwise absent or returns to its documented non-creation purpose.
|
||||||
- Put filters beside the list or pane they affect. Put bulk actions immediately
|
- Put filters beside the list or pane they affect. Put collection, detail, and
|
||||||
|
editor-pane actions in `WorkspaceActionBar` with the matching scope. Put bulk actions immediately
|
||||||
above or beside the current selection. Put object actions with the object
|
above or beside the current selection. Put object actions with the object
|
||||||
detail, not in the global title bar.
|
detail, not in the global title bar.
|
||||||
- Full-page create and edit surfaces put their persistent action cluster in the
|
- Full-page create and edit surfaces put their persistent action cluster in the
|
||||||
|
|||||||
@@ -78,10 +78,11 @@ matters.
|
|||||||
|
|
||||||
A Quick Access contribution declares:
|
A Quick Access contribution declares:
|
||||||
|
|
||||||
- a stable id, category and human label;
|
- contract version 1, a stable id, category and human label;
|
||||||
- icon, order and optional badge/summary provider;
|
- icon, order and optional badge/summary provider;
|
||||||
- required permissions and optional dependencies;
|
- required permissions and optional dependencies;
|
||||||
- accepted context references and produced return references;
|
- global or active-object availability, accepted context-reference kinds and
|
||||||
|
produced result-reference kinds;
|
||||||
- an owner-rendered bounded WebUI surface and full-page fallback route;
|
- an owner-rendered bounded WebUI surface and full-page fallback route;
|
||||||
- View surface, help context and availability explanation;
|
- View surface, help context and availability explanation;
|
||||||
- whether the contribution supports preview, create, select or resume.
|
- whether the contribution supports preview, create, select or resume.
|
||||||
@@ -92,6 +93,22 @@ resources and a safe return location. The owner reauthorizes every read and
|
|||||||
effect. Credentials, protected content and permission decisions are never
|
effect. Credentials, protected content and permission decisions are never
|
||||||
embedded in launch context.
|
embedded in launch context.
|
||||||
|
|
||||||
|
Launch-context version 2 identifies reference contract version 1 and carries
|
||||||
|
the exact resolved View revision plus optional recommended and focused tool
|
||||||
|
ids. Recommendations affect order and emphasis only. Focus narrows the rail
|
||||||
|
only when at least one focused contribution survives module enablement,
|
||||||
|
configuration, context compatibility and authorization; otherwise the normal
|
||||||
|
effective rail remains available. Workflow gets the same behavior by resolving
|
||||||
|
the exact View revision instead of acquiring separate presentation authority.
|
||||||
|
|
||||||
|
An owner-rendered tool explicitly returns result contract version 1 as either
|
||||||
|
`completed` with an action and typed owner reference, or `cancelled` with a
|
||||||
|
reason. The shell correlates the result with the source and tool, rejects
|
||||||
|
cross-tenant or undeclared reference kinds, and does not interpret closing the
|
||||||
|
drawer as completion. Owner modules validate, persist, recover and audit their
|
||||||
|
own effects. The overlay leaves the host route mounted, so unsaved host-page
|
||||||
|
state is preserved; the full-page route remains the bounded-work fallback.
|
||||||
|
|
||||||
## Effective Configuration
|
## Effective Configuration
|
||||||
|
|
||||||
The effective rail is resolved from:
|
The effective rail is resolved from:
|
||||||
@@ -125,9 +142,9 @@ workspace layouts do not resize unexpectedly; a later explicit pinned mode may
|
|||||||
reserve layout width on sufficiently wide screens.
|
reserve layout width on sufficiently wide screens.
|
||||||
|
|
||||||
The drawer preserves host-page state, has a deterministic focus return, closes
|
The drawer preserves host-page state, has a deterministic focus return, closes
|
||||||
with Escape, supports keyboard traversal, and provides an explicit full-page
|
with Escape, supports keyboard traversal, and provides explicit completion,
|
||||||
open action. Mobile and narrow layouts use the same category/configuration
|
cancellation and full-page actions. Mobile and narrow layouts use the same
|
||||||
semantics in a bottom sheet or compact menu.
|
category/configuration semantics in a bottom sheet or compact menu.
|
||||||
|
|
||||||
## Product Areas
|
## Product Areas
|
||||||
|
|
||||||
|
|||||||
@@ -28,59 +28,22 @@ CENTRAL_LAYOUT = pathlib.Path("govoplan-core/webui/src/components/PageLayout.tsx
|
|||||||
CENTRAL_WORKSPACE_LAYOUT = pathlib.Path(
|
CENTRAL_WORKSPACE_LAYOUT = pathlib.Path(
|
||||||
"govoplan-core/webui/src/components/WorkspaceLayout.tsx"
|
"govoplan-core/webui/src/components/WorkspaceLayout.tsx"
|
||||||
)
|
)
|
||||||
REQUIRED_CONSUMERS = (
|
CENTRAL_ACTION_BARS = {
|
||||||
pathlib.Path("govoplan-core/webui/src/components/admin/AdminPageLayout.tsx"),
|
pathlib.Path("govoplan-core/webui/src/components/PageActionBar.tsx"),
|
||||||
pathlib.Path("govoplan-core/webui/src/features/dashboard/DashboardPage.tsx"),
|
pathlib.Path("govoplan-core/webui/src/components/WorkspaceActionBar.tsx"),
|
||||||
pathlib.Path("govoplan-dashboard/webui/src/features/dashboard/DashboardPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-ops/webui/src/features/ops/OpsPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-campaign/webui/src/features/campaigns/AttachmentsDataPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-campaign/webui/src/features/campaigns/CampaignAuditPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-campaign/webui/src/features/campaigns/CampaignFieldsPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-campaign/webui/src/features/campaigns/CampaignJsonView.tsx"),
|
|
||||||
pathlib.Path("govoplan-campaign/webui/src/features/campaigns/CampaignListPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-campaign/webui/src/features/campaigns/CampaignOverviewPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-campaign/webui/src/features/campaigns/CampaignReportPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-campaign/webui/src/features/campaigns/GlobalSettingsPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-campaign/webui/src/features/campaigns/MailSettingsPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-campaign/webui/src/features/campaigns/ReviewSendPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-campaign/webui/src/features/campaigns/TemplateDataPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-campaign/webui/src/features/campaigns/components/CampaignDraftPageScaffold.tsx"),
|
|
||||||
pathlib.Path("govoplan-campaign/webui/src/features/campaigns/wizard/WizardDirectoryPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-campaign/webui/src/features/operator/OperatorQueuePage.tsx"),
|
|
||||||
pathlib.Path("govoplan-campaign/webui/src/features/reports/AggregateReportsPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-campaign/webui/src/features/templates/TemplatesPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-access/webui/src/features/admin/AdminPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-core/webui/src/features/settings/SettingsPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-docs/webui/src/features/docs/DocsPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-mail/webui/src/features/mail/MailBouncePage.tsx"),
|
|
||||||
pathlib.Path("govoplan-payments/webui/src/features/payments/PaymentsPage.tsx"),
|
|
||||||
)
|
|
||||||
REQUIRED_WORKSPACE_CONSUMERS = (
|
|
||||||
pathlib.Path("govoplan-campaign/webui/src/features/campaigns/CampaignWorkspace.tsx"),
|
|
||||||
pathlib.Path("govoplan-campaign/webui/src/features/campaigns/CampaignModulePage.tsx"),
|
|
||||||
pathlib.Path("govoplan-campaign/webui/src/features/templates/TemplatesPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-approvals/webui/src/features/approvals/ApprovalsPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-access/webui/src/features/admin/AdminPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-core/webui/src/features/settings/SettingsPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-docs/webui/src/features/docs/DocsPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-organizations/webui/src/features/organizations/OrganizationsPage.tsx"),
|
|
||||||
)
|
|
||||||
HEADERLESS_PAGE_LAYOUT_CONSUMERS = {
|
|
||||||
pathlib.Path("govoplan-access/webui/src/features/admin/AdminPage.tsx"),
|
|
||||||
}
|
}
|
||||||
EDITOR_PAGE_CONSUMERS = (
|
SEMANTIC_ACTION_USAGE = re.compile(r"<(?:Page|Workspace)ActionBar\b")
|
||||||
pathlib.Path("govoplan-core/webui/src/features/settings/SettingsPage.tsx"),
|
EDITOR_ACTION_USAGE = re.compile(
|
||||||
pathlib.Path("govoplan-dashboard/webui/src/features/dashboard/DashboardPage.tsx"),
|
r"<(?:Page|Workspace)ActionBar\b[\s\S]{0,1200}?variant=\"editor\""
|
||||||
pathlib.Path("govoplan-campaign/webui/src/features/campaigns/AttachmentsDataPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-campaign/webui/src/features/campaigns/CampaignFieldsPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-campaign/webui/src/features/campaigns/CampaignOverviewPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-campaign/webui/src/features/campaigns/GlobalSettingsPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-campaign/webui/src/features/campaigns/MailSettingsPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-campaign/webui/src/features/campaigns/TemplateDataPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-campaign/webui/src/features/campaigns/components/CampaignDraftPageScaffold.tsx"),
|
|
||||||
)
|
)
|
||||||
DESTRUCTIVE_PAGE_CONSUMERS = (
|
PANEL_HEADER_ACTION_TOOLBAR = re.compile(
|
||||||
pathlib.Path("govoplan-campaign/webui/src/features/campaigns/CampaignOverviewPage.tsx"),
|
r"<ActionToolbar\b[^>]*\bsurface=\"panel-header\""
|
||||||
|
)
|
||||||
|
UNSAVED_GUARD_MARKERS = (
|
||||||
|
"useUnsavedDraftGuard",
|
||||||
|
"useCampaignDraftEditor",
|
||||||
|
"useRegisterUnsavedChanges",
|
||||||
|
"semantic-editor-guard:",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -108,6 +71,22 @@ def relative(path: pathlib.Path) -> pathlib.Path:
|
|||||||
def main() -> int:
|
def main() -> int:
|
||||||
sources = source_paths()
|
sources = source_paths()
|
||||||
source_text = {relative(path): path.read_text(encoding="utf-8") for path in sources}
|
source_text = {relative(path): path.read_text(encoding="utf-8") for path in sources}
|
||||||
|
page_consumers = {
|
||||||
|
path for path, text in source_text.items()
|
||||||
|
if path != CENTRAL_LAYOUT and PAGE_LAYOUT_USAGE.search(text)
|
||||||
|
}
|
||||||
|
workspace_consumers = {
|
||||||
|
path for path, text in source_text.items()
|
||||||
|
if path != CENTRAL_WORKSPACE_LAYOUT and "<WorkspaceLayout" in text
|
||||||
|
}
|
||||||
|
action_consumers = {
|
||||||
|
path for path, text in source_text.items()
|
||||||
|
if path not in CENTRAL_ACTION_BARS and SEMANTIC_ACTION_USAGE.search(text)
|
||||||
|
}
|
||||||
|
editor_consumers = {
|
||||||
|
path for path, text in source_text.items()
|
||||||
|
if path not in CENTRAL_ACTION_BARS and EDITOR_ACTION_USAGE.search(text)
|
||||||
|
}
|
||||||
raw_frames = {path for path, text in source_text.items() if RAW_PAGE_FRAME in text}
|
raw_frames = {path for path, text in source_text.items() if RAW_PAGE_FRAME in text}
|
||||||
baseline = baseline_paths(BASELINE_PATH)
|
baseline = baseline_paths(BASELINE_PATH)
|
||||||
available_baseline = {
|
available_baseline = {
|
||||||
@@ -160,9 +139,9 @@ def main() -> int:
|
|||||||
if (
|
if (
|
||||||
page_layout_count
|
page_layout_count
|
||||||
and "actions=" in text
|
and "actions=" in text
|
||||||
and path not in HEADERLESS_PAGE_LAYOUT_CONSUMERS
|
|
||||||
and path != pathlib.Path("govoplan-core/webui/src/components/admin/AdminPageLayout.tsx")
|
and path != pathlib.Path("govoplan-core/webui/src/components/admin/AdminPageLayout.tsx")
|
||||||
and "<PageActionBar" not in text
|
and "<PageActionBar" not in text
|
||||||
|
and "semantic-page-actions: delegated" not in text
|
||||||
):
|
):
|
||||||
errors.append(
|
errors.append(
|
||||||
f"Headed page actions must use the semantic PageActionBar: {path}"
|
f"Headed page actions must use the semantic PageActionBar: {path}"
|
||||||
@@ -172,51 +151,31 @@ def main() -> int:
|
|||||||
f"Ambiguous consequential action slots are forbidden; use destructiveActions: {path}"
|
f"Ambiguous consequential action slots are forbidden; use destructiveActions: {path}"
|
||||||
)
|
)
|
||||||
|
|
||||||
for path in REQUIRED_CONSUMERS:
|
if (
|
||||||
absolute_path = REPOS_ROOT / path
|
path not in CENTRAL_ACTION_BARS
|
||||||
if not absolute_path.exists():
|
and PANEL_HEADER_ACTION_TOOLBAR.search(text)
|
||||||
continue
|
):
|
||||||
text = absolute_path.read_text(encoding="utf-8")
|
errors.append(
|
||||||
if "<PageLayout" not in text:
|
"Panel-header actions must use WorkspaceActionBar so their ordering, "
|
||||||
errors.append(f"Required shared-layout consumer no longer uses PageLayout: {path}")
|
f"state, and destructive separation remain semantic: {path}"
|
||||||
if RAW_PAGE_FRAME in text:
|
)
|
||||||
errors.append(f"Required shared-layout consumer restored the raw page frame: {path}")
|
|
||||||
|
|
||||||
for path in REQUIRED_WORKSPACE_CONSUMERS:
|
if "<WorkspaceFrame" in text and not SEMANTIC_ACTION_USAGE.search(text):
|
||||||
absolute_path = REPOS_ROOT / path
|
errors.append(
|
||||||
if not absolute_path.exists():
|
f"WorkspaceFrame routes must declare a semantic page or pane action bar: {path}"
|
||||||
continue
|
)
|
||||||
text = absolute_path.read_text(encoding="utf-8")
|
|
||||||
if "<WorkspaceLayout" not in text:
|
|
||||||
errors.append(f"Required shared-workspace consumer no longer uses WorkspaceLayout: {path}")
|
|
||||||
if RAW_WORKSPACE.search(text):
|
|
||||||
errors.append(f"Required shared-workspace consumer restored the raw workspace: {path}")
|
|
||||||
|
|
||||||
for path in EDITOR_PAGE_CONSUMERS:
|
for path in editor_consumers:
|
||||||
absolute_path = REPOS_ROOT / path
|
text = source_text[path]
|
||||||
if not absolute_path.exists():
|
for required in ('variant="editor"', "state=", "discardAction=", "saveAction="):
|
||||||
continue
|
|
||||||
text = absolute_path.read_text(encoding="utf-8")
|
|
||||||
for required in ('variant="editor"', "dirty=", "discardAction=", "saveAction="):
|
|
||||||
if required not in text:
|
if required not in text:
|
||||||
errors.append(f"Editor page is missing {required}: {path}")
|
errors.append(f"Editor page is missing {required}: {path}")
|
||||||
if path.name != "CampaignDraftPageScaffold.tsx" and not any(
|
if not any(guard in text for guard in UNSAVED_GUARD_MARKERS):
|
||||||
guard in text
|
|
||||||
for guard in (
|
|
||||||
"useUnsavedDraftGuard",
|
|
||||||
"useCampaignDraftEditor",
|
|
||||||
"useRegisterUnsavedChanges",
|
|
||||||
)
|
|
||||||
):
|
|
||||||
errors.append(f"Editor page is missing an unsaved-change guard: {path}")
|
errors.append(f"Editor page is missing an unsaved-change guard: {path}")
|
||||||
|
|
||||||
for path in DESTRUCTIVE_PAGE_CONSUMERS:
|
for path, text in source_text.items():
|
||||||
absolute_path = REPOS_ROOT / path
|
if "destructiveActions=" in text and 'variant="danger"' not in text:
|
||||||
if not absolute_path.exists():
|
errors.append(f"Destructive page actions must contain a danger action: {path}")
|
||||||
continue
|
|
||||||
text = absolute_path.read_text(encoding="utf-8")
|
|
||||||
if "destructiveActions=" not in text or 'variant="danger"' not in text:
|
|
||||||
errors.append(f"Destructive page actions lost their separated slot: {path}")
|
|
||||||
|
|
||||||
core_index = REPOS_ROOT / "govoplan-core/webui/src/index.ts"
|
core_index = REPOS_ROOT / "govoplan-core/webui/src/index.ts"
|
||||||
if core_index.exists() and "PageLayout, PageHeader" not in core_index.read_text(encoding="utf-8"):
|
if core_index.exists() and "PageLayout, PageHeader" not in core_index.read_text(encoding="utf-8"):
|
||||||
@@ -225,6 +184,8 @@ def main() -> int:
|
|||||||
errors.append("Core must export WorkspaceLayout from @govoplan/core-webui.")
|
errors.append("Core must export WorkspaceLayout from @govoplan/core-webui.")
|
||||||
if core_index.exists() and "PageActionBar" not in core_index.read_text(encoding="utf-8"):
|
if core_index.exists() and "PageActionBar" not in core_index.read_text(encoding="utf-8"):
|
||||||
errors.append("Core must export PageActionBar from @govoplan/core-webui.")
|
errors.append("Core must export PageActionBar from @govoplan/core-webui.")
|
||||||
|
if core_index.exists() and "WorkspaceActionBar" not in core_index.read_text(encoding="utf-8"):
|
||||||
|
errors.append("Core must export WorkspaceActionBar from @govoplan/core-webui.")
|
||||||
|
|
||||||
if errors:
|
if errors:
|
||||||
print("\n".join(errors), file=sys.stderr)
|
print("\n".join(errors), file=sys.stderr)
|
||||||
@@ -232,11 +193,12 @@ def main() -> int:
|
|||||||
|
|
||||||
print(
|
print(
|
||||||
"Shared WebUI layout contract passed: "
|
"Shared WebUI layout contract passed: "
|
||||||
f"{len(REQUIRED_CONSUMERS)} central consumers, "
|
f"{len(page_consumers)} discovered page consumers, "
|
||||||
f"{sum(len(PAGE_LAYOUT_USAGE.findall(text)) for text in source_text.values())} semantic pages, "
|
f"{sum(len(PAGE_LAYOUT_USAGE.findall(text)) for text in source_text.values())} semantic pages, "
|
||||||
f"{len(EDITOR_PAGE_CONSUMERS)} guarded editor consumers, "
|
f"{len(action_consumers)} semantic action consumers, "
|
||||||
|
f"{len(editor_consumers)} guarded editor consumers, "
|
||||||
f"{len(raw_frames)} registered legacy page-frame files; "
|
f"{len(raw_frames)} registered legacy page-frame files; "
|
||||||
f"{len(REQUIRED_WORKSPACE_CONSUMERS)} workspace consumers, "
|
f"{len(workspace_consumers)} discovered workspace consumers, "
|
||||||
f"{len(raw_workspaces)} registered legacy workspace files."
|
f"{len(raw_workspaces)} registered legacy workspace files."
|
||||||
)
|
)
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
@@ -125,7 +125,6 @@ REQUIRED_CONSUMERS = {
|
|||||||
pathlib.Path("govoplan-core/webui/src/components/WysiwygEditor.tsx"),
|
pathlib.Path("govoplan-core/webui/src/components/WysiwygEditor.tsx"),
|
||||||
pathlib.Path("govoplan-calendar/webui/src/features/calendar/CalendarPage.tsx"),
|
pathlib.Path("govoplan-calendar/webui/src/features/calendar/CalendarPage.tsx"),
|
||||||
pathlib.Path("govoplan-files/webui/src/features/files/FilesPage.tsx"),
|
pathlib.Path("govoplan-files/webui/src/features/files/FilesPage.tsx"),
|
||||||
pathlib.Path("govoplan-forms/webui/src/features/forms/FormsPage.tsx"),
|
|
||||||
pathlib.Path("govoplan-templates/webui/src/features/templates/TemplatesPage.tsx"),
|
pathlib.Path("govoplan-templates/webui/src/features/templates/TemplatesPage.tsx"),
|
||||||
),
|
),
|
||||||
"ContentGrid": (
|
"ContentGrid": (
|
||||||
|
|||||||
Reference in New Issue
Block a user