refactor(webui): use central data grids
This commit is contained in:
@@ -3,6 +3,7 @@ import { Link, useLocation } from "react-router-dom";
|
|||||||
import { ChevronDown, ChevronRight, RefreshCw } from "lucide-react";
|
import { ChevronDown, ChevronRight, RefreshCw } from "lucide-react";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
|
DataGrid,
|
||||||
DismissibleAlert,
|
DismissibleAlert,
|
||||||
ExplorerTree,
|
ExplorerTree,
|
||||||
LoadingFrame,
|
LoadingFrame,
|
||||||
@@ -12,7 +13,8 @@ import {
|
|||||||
adminErrorMessage,
|
adminErrorMessage,
|
||||||
useGuardedNavigate,
|
useGuardedNavigate,
|
||||||
usePlatformLanguage,
|
usePlatformLanguage,
|
||||||
type ApiSettings
|
type ApiSettings,
|
||||||
|
type DataGridColumn
|
||||||
} from "@govoplan/core-webui";
|
} from "@govoplan/core-webui";
|
||||||
import {
|
import {
|
||||||
fetchDocsContext,
|
fetchDocsContext,
|
||||||
@@ -404,34 +406,18 @@ function ReferenceDetails({ topic, showTechnical, documentationType, topicById }
|
|||||||
}
|
}
|
||||||
|
|
||||||
function ReferenceFieldTable({ id, fields, showTechnical }: { id: string; fields: Record<string, unknown>[]; showTechnical: boolean }) {
|
function ReferenceFieldTable({ id, fields, showTechnical }: { id: string; fields: Record<string, unknown>[]; showTechnical: boolean }) {
|
||||||
|
const columns: DataGridColumn<Record<string, unknown>>[] = [
|
||||||
|
{ id: "field", header: "i18n:govoplan-docs.field.7558c082", width: "minmax(180px, .8fr)", minWidth: 160, resizable: true, sortable: true, filterable: true, value: (field) => metadataString(field, "label"), render: (field) => <strong>{metadataString(field, "label")}</strong> },
|
||||||
|
{ id: "meaning", header: "i18n:govoplan-docs.meaning.584d8aa0", width: "minmax(260px, 1.3fr)", minWidth: 220, resizable: true, filterable: true, value: (field) => [metadataString(field, "user_description"), metadataString(field, "admin_description"), metadataString(field, "provenance")].join(" "), render: (field) => <div>{metadataString(field, "user_description")}{showTechnical && metadataString(field, "admin_description") && <span className="muted block">{metadataString(field, "admin_description")}</span>}{showTechnical && metadataString(field, "provenance") && <span className="muted block">{metadataString(field, "provenance")}</span>}</div> },
|
||||||
|
...(showTechnical ? [
|
||||||
|
{ id: "api", header: "i18n:govoplan-docs.api_mapping.e969f6f7", width: "minmax(190px, .8fr)", minWidth: 170, resizable: true, filterable: true, value: (field: Record<string, unknown>) => `${metadataString(field, "api_path")} ${metadataString(field, "api_field")}`, render: (field: Record<string, unknown>) => <div>{metadataString(field, "api_path")}<span className="muted block">{metadataString(field, "api_field")}</span></div> },
|
||||||
|
{ id: "permission", header: "i18n:govoplan-docs.permission.d71c9448", width: 190, filterable: true, value: (field: Record<string, unknown>) => metadataString(field, "permission_scope") || "-", render: (field: Record<string, unknown>) => metadataString(field, "permission_scope") || "-" }
|
||||||
|
] satisfies DataGridColumn<Record<string, unknown>>[] : []),
|
||||||
|
{ id: "validation", header: "i18n:govoplan-docs.validation.ef7f6d9c", width: "minmax(180px, .7fr)", minWidth: 160, resizable: true, filterable: true, value: (field) => metadataString(field, "validation") || "-", render: (field) => metadataString(field, "validation") || "-" }
|
||||||
|
];
|
||||||
return (
|
return (
|
||||||
<div className="admin-table-wrap" id={id}>
|
<div id={id}>
|
||||||
<table className="admin-table">
|
<DataGrid id={`${id}-grid`} rows={fields} columns={columns} getRowKey={(field) => metadataString(field, "field_id") || metadataString(field, "label")} />
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>i18n:govoplan-docs.field.7558c082</th>
|
|
||||||
<th>i18n:govoplan-docs.meaning.584d8aa0</th>
|
|
||||||
{showTechnical && <th>i18n:govoplan-docs.api_mapping.e969f6f7</th>}
|
|
||||||
{showTechnical && <th>i18n:govoplan-docs.permission.d71c9448</th>}
|
|
||||||
<th>i18n:govoplan-docs.validation.ef7f6d9c</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{fields.map((field) =>
|
|
||||||
<tr key={metadataString(field, "field_id") || metadataString(field, "label")}>
|
|
||||||
<td><strong>{metadataString(field, "label")}</strong></td>
|
|
||||||
<td>
|
|
||||||
{metadataString(field, "user_description")}
|
|
||||||
{showTechnical && metadataString(field, "admin_description") && <span className="muted block">{metadataString(field, "admin_description")}</span>}
|
|
||||||
{showTechnical && metadataString(field, "provenance") && <span className="muted block">{metadataString(field, "provenance")}</span>}
|
|
||||||
</td>
|
|
||||||
{showTechnical && <td>{metadataString(field, "api_path")}<span className="muted block">{metadataString(field, "api_field")}</span></td>}
|
|
||||||
{showTechnical && <td>{metadataString(field, "permission_scope") || "-"}</td>}
|
|
||||||
<td>{metadataString(field, "validation") || "-"}</td>
|
|
||||||
</tr>
|
|
||||||
)}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -861,49 +847,29 @@ function metadataRecords(metadata: Record<string, unknown>, key: string): Record
|
|||||||
|
|
||||||
function ModuleTable({ modules }: { modules: DocsModule[] }) {
|
function ModuleTable({ modules }: { modules: DocsModule[] }) {
|
||||||
if (!modules.length) return <p className="muted">i18n:govoplan-docs.no_configured_modules_found.f6f9ce24</p>;
|
if (!modules.length) return <p className="muted">i18n:govoplan-docs.no_configured_modules_found.f6f9ce24</p>;
|
||||||
|
const columns: DataGridColumn<DocsModule>[] = [
|
||||||
|
{ id: "module", header: "i18n:govoplan-docs.module.b8ff0289", width: "minmax(220px, 1fr)", minWidth: 190, resizable: true, sortable: true, filterable: true, value: (module) => `${module.name} ${module.id} ${module.version}`, render: (module) => <div><strong>{module.name}</strong><span className="muted block">{module.id} {module.version}</span></div> },
|
||||||
|
{ id: "routes", header: "i18n:govoplan-docs.routes.03730e58", width: 170, sortable: true, value: (module) => module.route_count, render: (module) => <>{module.route_count} i18n:govoplan-docs.route.200e2a66 {module.nav_count} nav</> },
|
||||||
|
{ id: "permissions", header: "i18n:govoplan-docs.permissions.d06d5557", width: 130, sortable: true, value: (module) => module.permission_count },
|
||||||
|
{ id: "frontend", header: "i18n:govoplan-docs.frontend.152d1cf2", width: "minmax(180px, .8fr)", minWidth: 160, resizable: true, sortable: true, filterable: true, value: (module) => module.frontend_package || "-", render: (module) => module.frontend_package || "-" },
|
||||||
|
{ id: "capabilities", header: "i18n:govoplan-docs.capabilities.ca09c54b", width: "minmax(260px, 1.2fr)", minWidth: 220, resizable: true, filterable: true, value: (module) => module.capabilities.join(" "), render: (module) => <div>{module.capabilities.length ? module.capabilities.join(", ") : "-"}{module.documentation_count || module.documentation_provider_count ? <span className="muted block">{module.documentation_count} i18n:govoplan-docs.docs.5dc1e9b8 {module.documentation_provider_count} provider</span> : null}</div> }
|
||||||
|
];
|
||||||
return (
|
return (
|
||||||
<div className="admin-table-wrap">
|
<DataGrid id="docs-configured-modules" rows={modules} columns={columns} getRowKey={(module) => module.id} />
|
||||||
<table className="admin-table">
|
|
||||||
<thead>
|
|
||||||
<tr><th>i18n:govoplan-docs.module.b8ff0289</th><th>i18n:govoplan-docs.routes.03730e58</th><th>i18n:govoplan-docs.permissions.d06d5557</th><th>i18n:govoplan-docs.frontend.152d1cf2</th><th>i18n:govoplan-docs.capabilities.ca09c54b</th></tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{modules.map((module) =>
|
|
||||||
<tr key={module.id}>
|
|
||||||
<td><strong>{module.name}</strong><span className="muted block">{module.id} {module.version}</span></td>
|
|
||||||
<td>{module.route_count} i18n:govoplan-docs.route.200e2a66 {module.nav_count} nav</td>
|
|
||||||
<td>{module.permission_count}</td>
|
|
||||||
<td>{module.frontend_package || "-"}</td>
|
|
||||||
<td>{module.capabilities.length ? module.capabilities.join(", ") : "-"}{module.documentation_count || module.documentation_provider_count ? <span className="muted block">{module.documentation_count} i18n:govoplan-docs.docs.5dc1e9b8 {module.documentation_provider_count} provider</span> : null}</td>
|
|
||||||
</tr>
|
|
||||||
)}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function RouteTable({ routes, emptyText }: { routes: DocsRoute[]; emptyText: string }) {
|
function RouteTable({ routes, emptyText }: { routes: DocsRoute[]; emptyText: string }) {
|
||||||
if (!routes.length) return <p className="muted">{emptyText}</p>;
|
if (!routes.length) return <p className="muted">{emptyText}</p>;
|
||||||
|
const columns: DataGridColumn<DocsRoute>[] = [
|
||||||
|
{ id: "route", header: "i18n:govoplan-docs.route.4999528e", width: "minmax(240px, 1fr)", minWidth: 200, resizable: true, sortable: true, filterable: true, value: (route) => `${route.label} ${route.path}`, render: (route) => <div><strong>{route.label}</strong><span className="muted block">{route.path}</span></div> },
|
||||||
|
{ id: "module", header: "i18n:govoplan-docs.module.b8ff0289", width: 160, sortable: true, filterable: true, value: (route) => route.module_id },
|
||||||
|
{ id: "source", header: "i18n:govoplan-docs.source.6da13add", width: 160, sortable: true, filterable: true, value: (route) => route.source },
|
||||||
|
{ id: "requirements", header: "i18n:govoplan-docs.requirements.09a428f9", width: "minmax(220px, 1fr)", minWidth: 180, resizable: true, filterable: true, value: (route) => routeRequirements(route) },
|
||||||
|
{ id: "status", header: "i18n:govoplan-docs.status.bae7d5be", width: 160, sortable: true, filterable: true, value: (route) => route.visible ? "visible" : route.reason, render: (route) => <StatusBadge status={route.visible ? "success" : "warning"} label={route.visible ? "visible" : route.reason} /> }
|
||||||
|
];
|
||||||
return (
|
return (
|
||||||
<div className="admin-table-wrap">
|
<DataGrid id={`docs-routes-${emptyText}`} rows={routes} columns={columns} getRowKey={(route) => `${route.source}-${route.module_id}-${route.path}`} />
|
||||||
<table className="admin-table">
|
|
||||||
<thead>
|
|
||||||
<tr><th>i18n:govoplan-docs.route.4999528e</th><th>i18n:govoplan-docs.module.b8ff0289</th><th>i18n:govoplan-docs.source.6da13add</th><th>i18n:govoplan-docs.requirements.09a428f9</th><th>i18n:govoplan-docs.status.bae7d5be</th></tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{routes.map((route) =>
|
|
||||||
<tr key={`${route.source}-${route.module_id}-${route.path}`}>
|
|
||||||
<td><strong>{route.label}</strong><span className="muted block">{route.path}</span></td>
|
|
||||||
<td>{route.module_id}</td>
|
|
||||||
<td>{route.source}</td>
|
|
||||||
<td>{routeRequirements(route)}</td>
|
|
||||||
<td><StatusBadge status={route.visible ? "success" : "warning"} label={route.visible ? "visible" : route.reason} /></td>
|
|
||||||
</tr>
|
|
||||||
)}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user