|
|
|
@@ -1,6 +1,7 @@
|
|
|
|
|
import { useCallback, useEffect, useMemo, useRef, useState, type FormEvent } from "react";
|
|
|
|
|
import { Edit3, Plus, RefreshCw } from "lucide-react";
|
|
|
|
|
import {
|
|
|
|
|
ActionBlockerHint,
|
|
|
|
|
AdminIconButton,
|
|
|
|
|
ApiError,
|
|
|
|
|
Button,
|
|
|
|
@@ -8,6 +9,7 @@ import {
|
|
|
|
|
DataGrid,
|
|
|
|
|
Dialog,
|
|
|
|
|
DismissibleAlert,
|
|
|
|
|
DocumentationHelpLink,
|
|
|
|
|
ExplorerTree,
|
|
|
|
|
FormField,
|
|
|
|
|
IconButton,
|
|
|
|
@@ -20,6 +22,7 @@ import {
|
|
|
|
|
hasScope,
|
|
|
|
|
isViewSurfaceVisible,
|
|
|
|
|
useEffectiveView,
|
|
|
|
|
useUnsavedChanges,
|
|
|
|
|
useUnsavedDraftGuard,
|
|
|
|
|
usePlatformUiCapabilities,
|
|
|
|
|
useViewSurfaces,
|
|
|
|
@@ -62,6 +65,12 @@ import {
|
|
|
|
|
type StructureCreatePayload,
|
|
|
|
|
type UnitCreatePayload
|
|
|
|
|
} from "../../api/organizations";
|
|
|
|
|
import {
|
|
|
|
|
ORGANIZATIONS_DOCUMENTATION,
|
|
|
|
|
ORGANIZATIONS_FIELD_DOCUMENTATION,
|
|
|
|
|
ORGANIZATIONS_INTERFACE_I18N,
|
|
|
|
|
organizationWriteReason
|
|
|
|
|
} from "./interfacePatterns";
|
|
|
|
|
|
|
|
|
|
export type OrganizationSection = "model" | "units" | "relations" | "functions";
|
|
|
|
|
type OrganizationsPageMode = "workspace" | "admin";
|
|
|
|
@@ -302,22 +311,36 @@ function activeStatus(active: boolean): JSX.Element {
|
|
|
|
|
function SluggedFields({
|
|
|
|
|
draft,
|
|
|
|
|
onChange,
|
|
|
|
|
disabled
|
|
|
|
|
disabled,
|
|
|
|
|
disabledReason
|
|
|
|
|
}: {
|
|
|
|
|
draft: SluggedDraft;
|
|
|
|
|
onChange: (next: SluggedDraft) => void;
|
|
|
|
|
disabled: boolean;
|
|
|
|
|
disabledReason?: string;
|
|
|
|
|
}) {
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.name.709a2322">
|
|
|
|
|
<FormField
|
|
|
|
|
label="i18n:govoplan-organizations.name.709a2322"
|
|
|
|
|
help={disabledReason}
|
|
|
|
|
documentation={ORGANIZATIONS_FIELD_DOCUMENTATION}
|
|
|
|
|
>
|
|
|
|
|
<input value={draft.name} disabled={disabled} onChange={(event) => onChange({ ...draft, name: event.target.value })} />
|
|
|
|
|
</FormField>
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.slug.094da9b9">
|
|
|
|
|
<FormField
|
|
|
|
|
label="i18n:govoplan-organizations.slug.094da9b9"
|
|
|
|
|
help={disabledReason}
|
|
|
|
|
documentation={ORGANIZATIONS_FIELD_DOCUMENTATION}
|
|
|
|
|
>
|
|
|
|
|
<input value={draft.slug} disabled={disabled} onChange={(event) => onChange({ ...draft, slug: event.target.value })} />
|
|
|
|
|
</FormField>
|
|
|
|
|
<div className="wide">
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.description.55f8ebc8">
|
|
|
|
|
<FormField
|
|
|
|
|
label="i18n:govoplan-organizations.description.55f8ebc8"
|
|
|
|
|
help={disabledReason}
|
|
|
|
|
documentation={ORGANIZATIONS_FIELD_DOCUMENTATION}
|
|
|
|
|
>
|
|
|
|
|
<textarea rows={3} value={draft.description} disabled={disabled} onChange={(event) => onChange({ ...draft, description: event.target.value })} />
|
|
|
|
|
</FormField>
|
|
|
|
|
</div>
|
|
|
|
@@ -325,6 +348,7 @@ function SluggedFields({
|
|
|
|
|
<ToggleSwitch
|
|
|
|
|
checked={draft.is_active}
|
|
|
|
|
disabled={disabled}
|
|
|
|
|
help={disabledReason}
|
|
|
|
|
onChange={(checked) => onChange({ ...draft, is_active: checked })}
|
|
|
|
|
label="i18n:govoplan-organizations.active.a733b809"
|
|
|
|
|
/>
|
|
|
|
@@ -362,6 +386,7 @@ export default function OrganizationsPage({
|
|
|
|
|
const [busy, setBusy] = useState(false);
|
|
|
|
|
const [error, setError] = useState("");
|
|
|
|
|
const [success, setSuccess] = useState("");
|
|
|
|
|
const { requestDiscard } = useUnsavedChanges();
|
|
|
|
|
|
|
|
|
|
const [unitTypeDraft, setUnitTypeDraft] = useState<SluggedDraft>(() => emptySluggedDraft());
|
|
|
|
|
const [structureDraft, setStructureDraft] = useState<StructureDraft>(() => emptyStructureDraft());
|
|
|
|
@@ -871,7 +896,7 @@ export default function OrganizationsPage({
|
|
|
|
|
{ id: "slug", header: "i18n:govoplan-organizations.slug.094da9b9", width: 160, sortable: true, filterable: true, value: (row) => row.slug },
|
|
|
|
|
{ id: "status", header: "i18n:govoplan-organizations.status.bae7d5be", width: 120, render: (row) => activeStatus(row.is_active) },
|
|
|
|
|
{ id: "description", header: "i18n:govoplan-organizations.description.55f8ebc8", minWidth: 220, value: (row) => row.description ?? "" },
|
|
|
|
|
{ id: "actions", header: "i18n:govoplan-core.actions.c3cd636a", width: 72, sticky: "end", resizable: false, align: "right", render: (row) => <TableActionGroup actions={[{ id: "edit", label: "i18n:govoplan-organizations.edit.7dce1220", icon: <Edit3 size={16} aria-hidden="true" />, disabled: !canWriteModel || busy, onClick: () => editUnitType(row) }]} /> }
|
|
|
|
|
{ id: "actions", header: "i18n:govoplan-core.actions.c3cd636a", width: 72, sticky: "end", resizable: false, align: "right", render: (row) => <TableActionGroup actions={[{ id: "edit", label: "i18n:govoplan-organizations.edit.7dce1220", icon: <Edit3 size={16} aria-hidden="true" />, disabled: !canWriteModel || busy, disabledReason: organizationWriteReason(canWriteModel, busy, "model"), onClick: () => editUnitType(row) }]} /> }
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const structureColumns: DataGridColumn<OrganizationStructureItem>[] = [
|
|
|
|
@@ -879,7 +904,7 @@ export default function OrganizationsPage({
|
|
|
|
|
{ id: "kind", header: "i18n:govoplan-organizations.kind.794c9d9c", width: 140, sortable: true, filterable: true, value: (row) => row.structure_kind },
|
|
|
|
|
{ id: "slug", header: "i18n:govoplan-organizations.slug.094da9b9", width: 160, value: (row) => row.slug },
|
|
|
|
|
{ id: "status", header: "i18n:govoplan-organizations.status.bae7d5be", width: 120, render: (row) => activeStatus(row.is_active) },
|
|
|
|
|
{ id: "actions", header: "i18n:govoplan-core.actions.c3cd636a", width: 72, sticky: "end", resizable: false, align: "right", render: (row) => <TableActionGroup actions={[{ id: "edit", label: "i18n:govoplan-organizations.edit.7dce1220", icon: <Edit3 size={16} aria-hidden="true" />, disabled: !canWriteModel || busy, onClick: () => editStructure(row) }]} /> }
|
|
|
|
|
{ id: "actions", header: "i18n:govoplan-core.actions.c3cd636a", width: 72, sticky: "end", resizable: false, align: "right", render: (row) => <TableActionGroup actions={[{ id: "edit", label: "i18n:govoplan-organizations.edit.7dce1220", icon: <Edit3 size={16} aria-hidden="true" />, disabled: !canWriteModel || busy, disabledReason: organizationWriteReason(canWriteModel, busy, "model"), onClick: () => editStructure(row) }]} /> }
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const relationTypeColumns: DataGridColumn<OrganizationRelationTypeItem>[] = [
|
|
|
|
@@ -889,7 +914,7 @@ export default function OrganizationsPage({
|
|
|
|
|
{ id: "target", header: "i18n:govoplan-organizations.target_unit.a1507d86", minWidth: 170, render: (row) => optionalLabel(unitTypeById.get(row.target_unit_type_id || "")?.name) },
|
|
|
|
|
{ id: "hierarchical", header: "i18n:govoplan-organizations.hierarchical.8964f313", width: 130, render: (row) => activeStatus(row.is_hierarchical) },
|
|
|
|
|
{ id: "status", header: "i18n:govoplan-organizations.status.bae7d5be", width: 120, render: (row) => activeStatus(row.is_active) },
|
|
|
|
|
{ id: "actions", header: "i18n:govoplan-core.actions.c3cd636a", width: 72, sticky: "end", resizable: false, align: "right", render: (row) => <TableActionGroup actions={[{ id: "edit", label: "i18n:govoplan-organizations.edit.7dce1220", icon: <Edit3 size={16} aria-hidden="true" />, disabled: !canWriteModel || busy, onClick: () => editRelationType(row) }]} /> }
|
|
|
|
|
{ id: "actions", header: "i18n:govoplan-core.actions.c3cd636a", width: 72, sticky: "end", resizable: false, align: "right", render: (row) => <TableActionGroup actions={[{ id: "edit", label: "i18n:govoplan-organizations.edit.7dce1220", icon: <Edit3 size={16} aria-hidden="true" />, disabled: !canWriteModel || busy, disabledReason: organizationWriteReason(canWriteModel, busy, "model"), onClick: () => editRelationType(row) }]} /> }
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const unitColumns: DataGridColumn<OrganizationUnitItem>[] = [
|
|
|
|
@@ -898,7 +923,7 @@ export default function OrganizationsPage({
|
|
|
|
|
{ id: "parent", header: "i18n:govoplan-organizations.parent_unit.1986c35e", minWidth: 180, render: (row) => optionalLabel(unitById.get(row.parent_id || "")?.name) },
|
|
|
|
|
{ id: "slug", header: "i18n:govoplan-organizations.slug.094da9b9", width: 160, value: (row) => row.slug },
|
|
|
|
|
{ id: "status", header: "i18n:govoplan-organizations.status.bae7d5be", width: 120, render: (row) => activeStatus(row.is_active) },
|
|
|
|
|
{ id: "actions", header: "i18n:govoplan-core.actions.c3cd636a", width: 72, sticky: "end", resizable: false, align: "right", render: (row) => <TableActionGroup actions={[{ id: "edit", label: "i18n:govoplan-organizations.edit.7dce1220", icon: <Edit3 size={16} aria-hidden="true" />, disabled: !canWriteUnits || busy, onClick: () => editUnit(row) }]} /> }
|
|
|
|
|
{ id: "actions", header: "i18n:govoplan-core.actions.c3cd636a", width: 72, sticky: "end", resizable: false, align: "right", render: (row) => <TableActionGroup actions={[{ id: "edit", label: "i18n:govoplan-organizations.edit.7dce1220", icon: <Edit3 size={16} aria-hidden="true" />, disabled: !canWriteUnits || busy, disabledReason: organizationWriteReason(canWriteUnits, busy, "unit"), onClick: () => editUnit(row) }]} /> }
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const relationColumns: DataGridColumn<OrganizationRelationItem>[] = [
|
|
|
|
@@ -907,7 +932,7 @@ export default function OrganizationsPage({
|
|
|
|
|
{ id: "source", header: "i18n:govoplan-organizations.source_unit.2fbd8baa", minWidth: 190, render: (row) => optionalLabel(unitById.get(row.source_unit_id)?.name) },
|
|
|
|
|
{ id: "target", header: "i18n:govoplan-organizations.target_unit.a1507d86", minWidth: 190, render: (row) => optionalLabel(unitById.get(row.target_unit_id)?.name) },
|
|
|
|
|
{ id: "status", header: "i18n:govoplan-organizations.status.bae7d5be", width: 120, render: (row) => activeStatus(row.is_active) },
|
|
|
|
|
{ id: "actions", header: "i18n:govoplan-core.actions.c3cd636a", width: 72, sticky: "end", resizable: false, align: "right", render: (row) => <TableActionGroup actions={[{ id: "edit", label: "i18n:govoplan-organizations.edit.7dce1220", icon: <Edit3 size={16} aria-hidden="true" />, disabled: !canWriteUnits || busy, onClick: () => editRelation(row) }]} /> }
|
|
|
|
|
{ id: "actions", header: "i18n:govoplan-core.actions.c3cd636a", width: 72, sticky: "end", resizable: false, align: "right", render: (row) => <TableActionGroup actions={[{ id: "edit", label: "i18n:govoplan-organizations.edit.7dce1220", icon: <Edit3 size={16} aria-hidden="true" />, disabled: !canWriteUnits || busy, disabledReason: organizationWriteReason(canWriteUnits, busy, "unit"), onClick: () => editRelation(row) }]} /> }
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const functionTypeColumns: DataGridColumn<OrganizationFunctionTypeItem>[] = [
|
|
|
|
@@ -916,7 +941,7 @@ export default function OrganizationsPage({
|
|
|
|
|
{ id: "delegable", header: "i18n:govoplan-organizations.delegable.b4f0137d", width: 120, render: (row) => activeStatus(row.delegable) },
|
|
|
|
|
{ id: "actInPlace", header: "i18n:govoplan-organizations.act_in_place.49b942bd", width: 140, render: (row) => activeStatus(row.act_in_place_allowed) },
|
|
|
|
|
{ id: "status", header: "i18n:govoplan-organizations.status.bae7d5be", width: 120, render: (row) => activeStatus(row.is_active) },
|
|
|
|
|
{ id: "actions", header: "i18n:govoplan-core.actions.c3cd636a", width: 72, sticky: "end", resizable: false, align: "right", render: (row) => <TableActionGroup actions={[{ id: "edit", label: "i18n:govoplan-organizations.edit.7dce1220", icon: <Edit3 size={16} aria-hidden="true" />, disabled: !canWriteModel || busy, onClick: () => editFunctionType(row) }]} /> }
|
|
|
|
|
{ id: "actions", header: "i18n:govoplan-core.actions.c3cd636a", width: 72, sticky: "end", resizable: false, align: "right", render: (row) => <TableActionGroup actions={[{ id: "edit", label: "i18n:govoplan-organizations.edit.7dce1220", icon: <Edit3 size={16} aria-hidden="true" />, disabled: !canWriteModel || busy, disabledReason: organizationWriteReason(canWriteModel, busy, "model"), onClick: () => editFunctionType(row) }]} /> }
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const functionColumns: DataGridColumn<OrganizationFunctionItem>[] = [
|
|
|
|
@@ -938,6 +963,7 @@ export default function OrganizationsPage({
|
|
|
|
|
label: "i18n:govoplan-organizations.edit.7dce1220",
|
|
|
|
|
icon: <Edit3 size={16} aria-hidden="true" />,
|
|
|
|
|
disabled: !canWriteFunctions || busy,
|
|
|
|
|
disabledReason: organizationWriteReason(canWriteFunctions, busy, "function"),
|
|
|
|
|
onClick: () => editFunction(row)
|
|
|
|
|
},
|
|
|
|
|
...functionActionContributions.map((contribution) => ({
|
|
|
|
@@ -950,7 +976,26 @@ export default function OrganizationsPage({
|
|
|
|
|
}
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const canWriteActive = active === "model" ? canWriteModel : active === "units" || active === "relations" ? canWriteUnits : canWriteFunctions;
|
|
|
|
|
const activeWriteKind = active === "model"
|
|
|
|
|
? "model"
|
|
|
|
|
: active === "units" || active === "relations"
|
|
|
|
|
? "unit"
|
|
|
|
|
: "function";
|
|
|
|
|
const canWriteActive = activeWriteKind === "model"
|
|
|
|
|
? canWriteModel
|
|
|
|
|
: activeWriteKind === "unit"
|
|
|
|
|
? canWriteUnits
|
|
|
|
|
: canWriteFunctions;
|
|
|
|
|
const activeWriteReason = organizationWriteReason(
|
|
|
|
|
canWriteActive,
|
|
|
|
|
busy,
|
|
|
|
|
activeWriteKind
|
|
|
|
|
);
|
|
|
|
|
const reloadDisabledReason = loading
|
|
|
|
|
? ORGANIZATIONS_INTERFACE_I18N.loading
|
|
|
|
|
: busy
|
|
|
|
|
? ORGANIZATIONS_INTERFACE_I18N.busy
|
|
|
|
|
: undefined;
|
|
|
|
|
|
|
|
|
|
const content = (
|
|
|
|
|
<div className={`${mode === "workspace" ? "content-pad " : ""}organizations-page ${mode === "admin" ? "organizations-admin-page" : ""}`.trim()}>
|
|
|
|
@@ -960,7 +1005,14 @@ export default function OrganizationsPage({
|
|
|
|
|
<p>{description}</p>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="organizations-toolbar">
|
|
|
|
|
<Button type="button" onClick={() => void loadModel()} disabled={loading || busy} title="i18n:govoplan-organizations.reload.cce71553">
|
|
|
|
|
<DocumentationHelpLink reference={ORGANIZATIONS_DOCUMENTATION} />
|
|
|
|
|
<Button
|
|
|
|
|
type="button"
|
|
|
|
|
onClick={() => requestDiscard(() => void loadModel())}
|
|
|
|
|
disabled={Boolean(reloadDisabledReason)}
|
|
|
|
|
disabledReason={reloadDisabledReason}
|
|
|
|
|
title="i18n:govoplan-organizations.reload.cce71553"
|
|
|
|
|
>
|
|
|
|
|
<RefreshCw size={16} aria-hidden="true" /> i18n:govoplan-organizations.reload.cce71553
|
|
|
|
|
</Button>
|
|
|
|
|
</div>
|
|
|
|
@@ -968,7 +1020,23 @@ export default function OrganizationsPage({
|
|
|
|
|
|
|
|
|
|
{error && <DismissibleAlert tone="danger" resetKey={error} floating>{error}</DismissibleAlert>}
|
|
|
|
|
{success && !error && <DismissibleAlert tone="success" resetKey={success} floating>{success}</DismissibleAlert>}
|
|
|
|
|
{!canWriteActive && <DismissibleAlert tone="warning" dismissible={false}>i18n:govoplan-organizations.write_permission_required.8b09fd67</DismissibleAlert>}
|
|
|
|
|
{!canWriteActive && (
|
|
|
|
|
<ActionBlockerHint
|
|
|
|
|
reason={{
|
|
|
|
|
summary: ORGANIZATIONS_INTERFACE_I18N.readOnlySummary,
|
|
|
|
|
details: activeWriteReason,
|
|
|
|
|
requiredAction: ORGANIZATIONS_INTERFACE_I18N.permissionGuidance,
|
|
|
|
|
actor: ORGANIZATIONS_INTERFACE_I18N.administrator,
|
|
|
|
|
target: ORGANIZATIONS_INTERFACE_I18N.administrationTarget
|
|
|
|
|
}}
|
|
|
|
|
labels={{
|
|
|
|
|
requiredAction: ORGANIZATIONS_INTERFACE_I18N.requiredAction,
|
|
|
|
|
actor: ORGANIZATIONS_INTERFACE_I18N.actor,
|
|
|
|
|
target: ORGANIZATIONS_INTERFACE_I18N.destination
|
|
|
|
|
}}
|
|
|
|
|
documentation={ORGANIZATIONS_DOCUMENTATION}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
<LoadingFrame loading={loading || busy} label="i18n:govoplan-organizations.loading_organization_model.846aa317">
|
|
|
|
|
{active === "model" && renderModelSection()}
|
|
|
|
@@ -984,7 +1052,11 @@ export default function OrganizationsPage({
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="workspace organizations-workspace">
|
|
|
|
|
<ModuleSubnav active={active} groups={visibleSectionGroups} onSelect={setActive} />
|
|
|
|
|
<ModuleSubnav
|
|
|
|
|
active={active}
|
|
|
|
|
groups={visibleSectionGroups}
|
|
|
|
|
onSelect={(section) => requestDiscard(() => setActive(section))}
|
|
|
|
|
/>
|
|
|
|
|
<main className="workspace-content">
|
|
|
|
|
{content}
|
|
|
|
|
</main>
|
|
|
|
@@ -994,16 +1066,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} onClick={openUnitTypeCreate} />}>
|
|
|
|
|
<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} />}>
|
|
|
|
|
<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} onClick={openStructureCreate} />}>
|
|
|
|
|
<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} />}>
|
|
|
|
|
<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} onClick={openRelationTypeCreate} />}>
|
|
|
|
|
<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} />}>
|
|
|
|
|
<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} onClick={openFunctionTypeCreate} />}>
|
|
|
|
|
<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} />}>
|
|
|
|
|
<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>
|
|
|
|
@@ -1013,9 +1085,9 @@ export default function OrganizationsPage({
|
|
|
|
|
function renderUnitsSection() {
|
|
|
|
|
return (
|
|
|
|
|
<div className="organizations-table-stack">
|
|
|
|
|
<Card title="i18n:govoplan-organizations.organization_tree.e5bfb195" actions={<AdminIconButton label="i18n:govoplan-organizations.add_root_unit.1ef8a9f5" icon={<Plus size={16} aria-hidden="true" />} variant="primary" disabled={!canWriteUnits || busy} onClick={() => openUnitCreate()} />}>
|
|
|
|
|
<Card title="i18n:govoplan-organizations.organization_tree.e5bfb195" actions={<AdminIconButton label="i18n:govoplan-organizations.add_root_unit.1ef8a9f5" icon={<Plus size={16} aria-hidden="true" />} variant="primary" disabled={!canWriteUnits || busy} disabledReason={organizationWriteReason(canWriteUnits, busy, "unit")} onClick={() => openUnitCreate()} />}>
|
|
|
|
|
<div className="explorer-tree-toolbar">
|
|
|
|
|
{selectedUnitId && <Button type="button" variant="ghost" disabled={busy} onClick={() => setSelectedUnitId("")}>i18n:govoplan-organizations.none.334c4a4c</Button>}
|
|
|
|
|
{selectedUnitId && <Button type="button" variant="ghost" disabled={busy} disabledReason={busy ? ORGANIZATIONS_INTERFACE_I18N.busy : undefined} onClick={() => setSelectedUnitId("")}>i18n:govoplan-organizations.none.334c4a4c</Button>}
|
|
|
|
|
</div>
|
|
|
|
|
{model.units.length ? (
|
|
|
|
|
<ExplorerTree
|
|
|
|
@@ -1041,13 +1113,14 @@ export default function OrganizationsPage({
|
|
|
|
|
icon={<Plus size={16} aria-hidden="true" />}
|
|
|
|
|
variant="ghost"
|
|
|
|
|
disabled={!canWriteUnits || busy}
|
|
|
|
|
disabledReason={organizationWriteReason(canWriteUnits, busy, "unit")}
|
|
|
|
|
onClick={() => addSubunit(unit)}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
/>
|
|
|
|
|
) : <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} onClick={() => openUnitCreate()} />}>
|
|
|
|
|
<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()} />}>
|
|
|
|
|
<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>
|
|
|
|
@@ -1057,7 +1130,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} onClick={openRelationCreate} />}>
|
|
|
|
|
<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} />}>
|
|
|
|
|
<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>
|
|
|
|
@@ -1067,7 +1140,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} onClick={() => openFunctionCreate()} />}>
|
|
|
|
|
<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()} />}>
|
|
|
|
|
<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>
|
|
|
|
@@ -1077,7 +1150,11 @@ export default function OrganizationsPage({
|
|
|
|
|
function renderChangeRequestField() {
|
|
|
|
|
return (
|
|
|
|
|
<div className="wide organizations-dialog-change-request">
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.change_request_id.a6e7fd6b">
|
|
|
|
|
<FormField
|
|
|
|
|
label="i18n:govoplan-organizations.change_request_id.a6e7fd6b"
|
|
|
|
|
help={busy ? ORGANIZATIONS_INTERFACE_I18N.busy : undefined}
|
|
|
|
|
documentation={ORGANIZATIONS_FIELD_DOCUMENTATION}
|
|
|
|
|
>
|
|
|
|
|
<input value={changeRequestId} onChange={(event) => setChangeRequestId(event.target.value)} placeholder="cfgreq-..." disabled={busy} />
|
|
|
|
|
</FormField>
|
|
|
|
|
<p className="organizations-field-note">i18n:govoplan-organizations.change_request_id_help.0c119a5d</p>
|
|
|
|
@@ -1099,18 +1176,32 @@ export default function OrganizationsPage({
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function editorSubmitDisabled(): boolean {
|
|
|
|
|
if (busy || !activeEditor) return true;
|
|
|
|
|
if ((activeEditor === "unitType" || activeEditor === "structure" || activeEditor === "relationType" || activeEditor === "functionType") && !canWriteModel) return true;
|
|
|
|
|
if ((activeEditor === "unit" || activeEditor === "relation") && !canWriteUnits) return true;
|
|
|
|
|
if (activeEditor === "function" && !canWriteFunctions) return true;
|
|
|
|
|
if (activeEditor === "unitType") return !unitTypeDraft.name.trim();
|
|
|
|
|
if (activeEditor === "structure") return !structureDraft.name.trim();
|
|
|
|
|
if (activeEditor === "relationType") return !relationTypeDraft.name.trim();
|
|
|
|
|
if (activeEditor === "unit") return !unitDraft.name.trim();
|
|
|
|
|
if (activeEditor === "relation") return !relationDraft.structure_id || !relationDraft.relation_type_id || !relationDraft.source_unit_id || !relationDraft.target_unit_id;
|
|
|
|
|
if (activeEditor === "functionType") return !functionTypeDraft.name.trim();
|
|
|
|
|
if (activeEditor === "function") return !functionDraft.name.trim() || !functionDraft.organization_unit_id;
|
|
|
|
|
return true;
|
|
|
|
|
return Boolean(editorSubmitDisabledReason());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function editorSubmitDisabledReason(): string | undefined {
|
|
|
|
|
if (busy) return ORGANIZATIONS_INTERFACE_I18N.busy;
|
|
|
|
|
if (!activeEditor) return ORGANIZATIONS_INTERFACE_I18N.incomplete;
|
|
|
|
|
if (activeEditor === "unitType" || activeEditor === "structure" || activeEditor === "relationType" || activeEditor === "functionType") {
|
|
|
|
|
const reason = organizationWriteReason(canWriteModel, busy, "model");
|
|
|
|
|
if (reason) return reason;
|
|
|
|
|
}
|
|
|
|
|
if (activeEditor === "unit" || activeEditor === "relation") {
|
|
|
|
|
const reason = organizationWriteReason(canWriteUnits, busy, "unit");
|
|
|
|
|
if (reason) return reason;
|
|
|
|
|
}
|
|
|
|
|
if (activeEditor === "function") {
|
|
|
|
|
const reason = organizationWriteReason(canWriteFunctions, busy, "function");
|
|
|
|
|
if (reason) return reason;
|
|
|
|
|
}
|
|
|
|
|
if (activeEditor === "unitType" && !unitTypeDraft.name.trim()) return ORGANIZATIONS_INTERFACE_I18N.incomplete;
|
|
|
|
|
if (activeEditor === "structure" && !structureDraft.name.trim()) return ORGANIZATIONS_INTERFACE_I18N.incomplete;
|
|
|
|
|
if (activeEditor === "relationType" && !relationTypeDraft.name.trim()) return ORGANIZATIONS_INTERFACE_I18N.incomplete;
|
|
|
|
|
if (activeEditor === "unit" && !unitDraft.name.trim()) return ORGANIZATIONS_INTERFACE_I18N.incomplete;
|
|
|
|
|
if (activeEditor === "relation" && (!relationDraft.structure_id || !relationDraft.relation_type_id || !relationDraft.source_unit_id || !relationDraft.target_unit_id)) return ORGANIZATIONS_INTERFACE_I18N.incomplete;
|
|
|
|
|
if (activeEditor === "functionType" && !functionTypeDraft.name.trim()) return ORGANIZATIONS_INTERFACE_I18N.incomplete;
|
|
|
|
|
if (activeEditor === "function" && (!functionDraft.name.trim() || !functionDraft.organization_unit_id)) return ORGANIZATIONS_INTERFACE_I18N.incomplete;
|
|
|
|
|
return undefined;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function renderEditorDialog() {
|
|
|
|
@@ -1127,16 +1218,38 @@ export default function OrganizationsPage({
|
|
|
|
|
<Dialog
|
|
|
|
|
open={Boolean(activeEditor)}
|
|
|
|
|
title={editorTitle()}
|
|
|
|
|
onClose={() => !busy && discardDrafts()}
|
|
|
|
|
onClose={() => {
|
|
|
|
|
if (busy) return;
|
|
|
|
|
if (hasDirtyDraft) requestDiscard(discardDrafts);
|
|
|
|
|
else discardDrafts();
|
|
|
|
|
}}
|
|
|
|
|
closeDisabled={busy}
|
|
|
|
|
className="admin-dialog admin-dialog-wide organizations-editor-dialog"
|
|
|
|
|
footer={(
|
|
|
|
|
<>
|
|
|
|
|
<Button type="button" onClick={discardDrafts} disabled={busy}>i18n:govoplan-organizations.cancel_edit.309c2a6f</Button>
|
|
|
|
|
<Button type="submit" form={formId} variant="primary" disabled={editorSubmitDisabled()}>{editorTitle()}</Button>
|
|
|
|
|
<Button
|
|
|
|
|
type="button"
|
|
|
|
|
onClick={() => hasDirtyDraft ? requestDiscard(discardDrafts) : discardDrafts()}
|
|
|
|
|
disabled={busy}
|
|
|
|
|
disabledReason={busy ? ORGANIZATIONS_INTERFACE_I18N.busy : undefined}
|
|
|
|
|
>
|
|
|
|
|
i18n:govoplan-organizations.cancel_edit.309c2a6f
|
|
|
|
|
</Button>
|
|
|
|
|
<Button
|
|
|
|
|
type="submit"
|
|
|
|
|
form={formId}
|
|
|
|
|
variant="primary"
|
|
|
|
|
disabled={editorSubmitDisabled()}
|
|
|
|
|
disabledReason={editorSubmitDisabledReason()}
|
|
|
|
|
>
|
|
|
|
|
{editorTitle()}
|
|
|
|
|
</Button>
|
|
|
|
|
</>
|
|
|
|
|
)}
|
|
|
|
|
>
|
|
|
|
|
<div className="button-row organizations-dialog-help">
|
|
|
|
|
<DocumentationHelpLink reference={ORGANIZATIONS_FIELD_DOCUMENTATION} />
|
|
|
|
|
</div>
|
|
|
|
|
<form id={formId} className="admin-form-grid two-columns" onSubmit={(event) => void submit(event)}>
|
|
|
|
|
{renderEditorFields()}
|
|
|
|
|
</form>
|
|
|
|
@@ -1148,7 +1261,7 @@ export default function OrganizationsPage({
|
|
|
|
|
if (activeEditor === "unitType") {
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<SluggedFields draft={unitTypeDraft} onChange={setUnitTypeDraft} disabled={!canWriteModel || busy} />
|
|
|
|
|
<SluggedFields draft={unitTypeDraft} onChange={setUnitTypeDraft} disabled={!canWriteModel || busy} disabledReason={organizationWriteReason(canWriteModel, busy, "model")} />
|
|
|
|
|
{renderChangeRequestField()}
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
@@ -1156,8 +1269,8 @@ export default function OrganizationsPage({
|
|
|
|
|
if (activeEditor === "structure") {
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<SluggedFields draft={structureDraft} onChange={setStructureDraft} disabled={!canWriteModel || busy} />
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.kind.794c9d9c">
|
|
|
|
|
<SluggedFields draft={structureDraft} onChange={setStructureDraft} disabled={!canWriteModel || busy} disabledReason={organizationWriteReason(canWriteModel, busy, "model")} />
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.kind.794c9d9c" help={organizationWriteReason(canWriteModel, busy, "model")} documentation={ORGANIZATIONS_FIELD_DOCUMENTATION}>
|
|
|
|
|
<select value={structureDraft.structure_kind} disabled={!canWriteModel || busy} onChange={(event) => setStructureDraft({ ...structureDraft, structure_kind: event.target.value as OrganizationStructureKind })}>
|
|
|
|
|
{STRUCTURE_KINDS.map((item) => <option key={item.value} value={item.value}>{item.label}</option>)}
|
|
|
|
|
</select>
|
|
|
|
@@ -1169,28 +1282,28 @@ export default function OrganizationsPage({
|
|
|
|
|
if (activeEditor === "relationType") {
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<SluggedFields draft={relationTypeDraft} onChange={setRelationTypeDraft} disabled={!canWriteModel || busy} />
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.structure.7732fb0b">
|
|
|
|
|
<SluggedFields draft={relationTypeDraft} onChange={setRelationTypeDraft} disabled={!canWriteModel || busy} disabledReason={organizationWriteReason(canWriteModel, busy, "model")} />
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.structure.7732fb0b" help={organizationWriteReason(canWriteModel, busy, "model")} documentation={ORGANIZATIONS_FIELD_DOCUMENTATION}>
|
|
|
|
|
<select value={relationTypeDraft.structure_id} disabled={!canWriteModel || busy} onChange={(event) => setRelationTypeDraft({ ...relationTypeDraft, structure_id: event.target.value })}>
|
|
|
|
|
<option value="">i18n:govoplan-organizations.none.334c4a4c</option>
|
|
|
|
|
{model.structures.map((item) => <option key={item.id} value={item.id}>{item.name}</option>)}
|
|
|
|
|
</select>
|
|
|
|
|
</FormField>
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.source_unit.2fbd8baa">
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.source_unit.2fbd8baa" help={organizationWriteReason(canWriteModel, busy, "model")} documentation={ORGANIZATIONS_FIELD_DOCUMENTATION}>
|
|
|
|
|
<select value={relationTypeDraft.source_unit_type_id} disabled={!canWriteModel || busy} onChange={(event) => setRelationTypeDraft({ ...relationTypeDraft, source_unit_type_id: event.target.value })}>
|
|
|
|
|
<option value="">i18n:govoplan-organizations.none.334c4a4c</option>
|
|
|
|
|
{model.unit_types.map((item) => <option key={item.id} value={item.id}>{item.name}</option>)}
|
|
|
|
|
</select>
|
|
|
|
|
</FormField>
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.target_unit.a1507d86">
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.target_unit.a1507d86" help={organizationWriteReason(canWriteModel, busy, "model")} documentation={ORGANIZATIONS_FIELD_DOCUMENTATION}>
|
|
|
|
|
<select value={relationTypeDraft.target_unit_type_id} disabled={!canWriteModel || busy} onChange={(event) => setRelationTypeDraft({ ...relationTypeDraft, target_unit_type_id: event.target.value })}>
|
|
|
|
|
<option value="">i18n:govoplan-organizations.none.334c4a4c</option>
|
|
|
|
|
{model.unit_types.map((item) => <option key={item.id} value={item.id}>{item.name}</option>)}
|
|
|
|
|
</select>
|
|
|
|
|
</FormField>
|
|
|
|
|
<div className="organizations-check-list">
|
|
|
|
|
<ToggleSwitch checked={relationTypeDraft.is_hierarchical} disabled={!canWriteModel || busy} onChange={(checked) => setRelationTypeDraft({ ...relationTypeDraft, is_hierarchical: checked })} label="i18n:govoplan-organizations.hierarchical.8964f313" />
|
|
|
|
|
<ToggleSwitch checked={relationTypeDraft.allow_cycles} disabled={!canWriteModel || busy} onChange={(checked) => setRelationTypeDraft({ ...relationTypeDraft, allow_cycles: checked })} label="i18n:govoplan-organizations.allow_cycles.31327578" />
|
|
|
|
|
<ToggleSwitch checked={relationTypeDraft.is_hierarchical} disabled={!canWriteModel || busy} help={organizationWriteReason(canWriteModel, busy, "model")} onChange={(checked) => setRelationTypeDraft({ ...relationTypeDraft, is_hierarchical: checked })} label="i18n:govoplan-organizations.hierarchical.8964f313" />
|
|
|
|
|
<ToggleSwitch checked={relationTypeDraft.allow_cycles} disabled={!canWriteModel || busy} help={organizationWriteReason(canWriteModel, busy, "model")} onChange={(checked) => setRelationTypeDraft({ ...relationTypeDraft, allow_cycles: checked })} label="i18n:govoplan-organizations.allow_cycles.31327578" />
|
|
|
|
|
</div>
|
|
|
|
|
{renderChangeRequestField()}
|
|
|
|
|
</>
|
|
|
|
@@ -1199,14 +1312,14 @@ export default function OrganizationsPage({
|
|
|
|
|
if (activeEditor === "unit") {
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<SluggedFields draft={unitDraft} onChange={setUnitDraft} disabled={!canWriteUnits || busy} />
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.unit_type.9e62810d">
|
|
|
|
|
<SluggedFields draft={unitDraft} onChange={setUnitDraft} disabled={!canWriteUnits || busy} disabledReason={organizationWriteReason(canWriteUnits, busy, "unit")} />
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.unit_type.9e62810d" help={organizationWriteReason(canWriteUnits, busy, "unit")} documentation={ORGANIZATIONS_FIELD_DOCUMENTATION}>
|
|
|
|
|
<select value={unitDraft.unit_type_id} disabled={!canWriteUnits || busy} onChange={(event) => setUnitDraft({ ...unitDraft, unit_type_id: event.target.value })}>
|
|
|
|
|
<option value="">i18n:govoplan-organizations.none.334c4a4c</option>
|
|
|
|
|
{model.unit_types.map((item) => <option key={item.id} value={item.id}>{item.name}</option>)}
|
|
|
|
|
</select>
|
|
|
|
|
</FormField>
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.parent_unit.1986c35e">
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.parent_unit.1986c35e" help={organizationWriteReason(canWriteUnits, busy, "unit")} documentation={ORGANIZATIONS_FIELD_DOCUMENTATION}>
|
|
|
|
|
<select value={unitDraft.parent_id} disabled={!canWriteUnits || busy} onChange={(event) => setUnitDraft({ ...unitDraft, parent_id: event.target.value })}>
|
|
|
|
|
<option value="">i18n:govoplan-organizations.none.334c4a4c</option>
|
|
|
|
|
{model.units.filter((item) => item.id !== editingUnitId).map((item) => <option key={item.id} value={item.id}>{item.name}</option>)}
|
|
|
|
@@ -1224,25 +1337,25 @@ export default function OrganizationsPage({
|
|
|
|
|
if (activeEditor === "relation") {
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.structure.7732fb0b">
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.structure.7732fb0b" help={organizationWriteReason(canWriteUnits, busy, "unit")} documentation={ORGANIZATIONS_FIELD_DOCUMENTATION}>
|
|
|
|
|
<select value={relationDraft.structure_id} disabled={!canWriteUnits || busy} onChange={(event) => setRelationDraft({ ...relationDraft, structure_id: event.target.value })}>
|
|
|
|
|
<option value="">i18n:govoplan-organizations.select_structure.c10f551c</option>
|
|
|
|
|
{model.structures.map((item) => <option key={item.id} value={item.id}>{item.name}</option>)}
|
|
|
|
|
</select>
|
|
|
|
|
</FormField>
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.relation_type.d0aee2e7">
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.relation_type.d0aee2e7" help={organizationWriteReason(canWriteUnits, busy, "unit")} documentation={ORGANIZATIONS_FIELD_DOCUMENTATION}>
|
|
|
|
|
<select value={relationDraft.relation_type_id} disabled={!canWriteUnits || busy} onChange={(event) => setRelationDraft({ ...relationDraft, relation_type_id: event.target.value })}>
|
|
|
|
|
<option value="">i18n:govoplan-organizations.select_relation_type.73f92478</option>
|
|
|
|
|
{model.relation_types.map((item) => <option key={item.id} value={item.id}>{item.name}</option>)}
|
|
|
|
|
</select>
|
|
|
|
|
</FormField>
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.source_unit.2fbd8baa">
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.source_unit.2fbd8baa" help={organizationWriteReason(canWriteUnits, busy, "unit")} documentation={ORGANIZATIONS_FIELD_DOCUMENTATION}>
|
|
|
|
|
<select value={relationDraft.source_unit_id} disabled={!canWriteUnits || busy} onChange={(event) => setRelationDraft({ ...relationDraft, source_unit_id: event.target.value })}>
|
|
|
|
|
<option value="">i18n:govoplan-organizations.select_source_unit.9b5a29c8</option>
|
|
|
|
|
{model.units.map((item) => <option key={item.id} value={item.id}>{item.name}</option>)}
|
|
|
|
|
</select>
|
|
|
|
|
</FormField>
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.target_unit.a1507d86">
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.target_unit.a1507d86" help={organizationWriteReason(canWriteUnits, busy, "unit")} documentation={ORGANIZATIONS_FIELD_DOCUMENTATION}>
|
|
|
|
|
<select value={relationDraft.target_unit_id} disabled={!canWriteUnits || busy} onChange={(event) => setRelationDraft({ ...relationDraft, target_unit_id: event.target.value })}>
|
|
|
|
|
<option value="">i18n:govoplan-organizations.select_target_unit.8d607541</option>
|
|
|
|
|
{model.units.map((item) => <option key={item.id} value={item.id}>{item.name}</option>)}
|
|
|
|
@@ -1252,6 +1365,7 @@ export default function OrganizationsPage({
|
|
|
|
|
<ToggleSwitch
|
|
|
|
|
checked={relationDraft.is_active}
|
|
|
|
|
disabled={!canWriteUnits || busy}
|
|
|
|
|
help={organizationWriteReason(canWriteUnits, busy, "unit")}
|
|
|
|
|
onChange={(checked) => setRelationDraft({ ...relationDraft, is_active: checked })}
|
|
|
|
|
label="i18n:govoplan-organizations.active.a733b809"
|
|
|
|
|
/>
|
|
|
|
@@ -1263,16 +1377,16 @@ export default function OrganizationsPage({
|
|
|
|
|
if (activeEditor === "functionType") {
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<SluggedFields draft={functionTypeDraft} onChange={setFunctionTypeDraft} disabled={!canWriteModel || busy} />
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.unit_type.9e62810d">
|
|
|
|
|
<SluggedFields draft={functionTypeDraft} onChange={setFunctionTypeDraft} disabled={!canWriteModel || busy} disabledReason={organizationWriteReason(canWriteModel, busy, "model")} />
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.unit_type.9e62810d" help={organizationWriteReason(canWriteModel, busy, "model")} documentation={ORGANIZATIONS_FIELD_DOCUMENTATION}>
|
|
|
|
|
<select value={functionTypeDraft.organization_unit_type_id} disabled={!canWriteModel || busy} onChange={(event) => setFunctionTypeDraft({ ...functionTypeDraft, organization_unit_type_id: event.target.value })}>
|
|
|
|
|
<option value="">i18n:govoplan-organizations.none.334c4a4c</option>
|
|
|
|
|
{model.unit_types.map((item) => <option key={item.id} value={item.id}>{item.name}</option>)}
|
|
|
|
|
</select>
|
|
|
|
|
</FormField>
|
|
|
|
|
<div className="organizations-check-list">
|
|
|
|
|
<ToggleSwitch checked={functionTypeDraft.delegable} disabled={!canWriteModel || busy} onChange={(checked) => setFunctionTypeDraft({ ...functionTypeDraft, delegable: checked })} label="i18n:govoplan-organizations.delegable.b4f0137d" />
|
|
|
|
|
<ToggleSwitch checked={functionTypeDraft.act_in_place_allowed} disabled={!canWriteModel || busy} onChange={(checked) => setFunctionTypeDraft({ ...functionTypeDraft, act_in_place_allowed: checked })} label="i18n:govoplan-organizations.act_in_place.49b942bd" />
|
|
|
|
|
<ToggleSwitch checked={functionTypeDraft.delegable} disabled={!canWriteModel || busy} help={organizationWriteReason(canWriteModel, busy, "model")} onChange={(checked) => setFunctionTypeDraft({ ...functionTypeDraft, delegable: checked })} label="i18n:govoplan-organizations.delegable.b4f0137d" />
|
|
|
|
|
<ToggleSwitch checked={functionTypeDraft.act_in_place_allowed} disabled={!canWriteModel || busy} help={organizationWriteReason(canWriteModel, busy, "model")} onChange={(checked) => setFunctionTypeDraft({ ...functionTypeDraft, act_in_place_allowed: checked })} label="i18n:govoplan-organizations.act_in_place.49b942bd" />
|
|
|
|
|
</div>
|
|
|
|
|
{renderChangeRequestField()}
|
|
|
|
|
</>
|
|
|
|
@@ -1280,22 +1394,22 @@ export default function OrganizationsPage({
|
|
|
|
|
}
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<SluggedFields draft={functionDraft} onChange={setFunctionDraft} disabled={!canWriteFunctions || busy} />
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.unit.8fe4d595">
|
|
|
|
|
<SluggedFields draft={functionDraft} onChange={setFunctionDraft} disabled={!canWriteFunctions || busy} disabledReason={organizationWriteReason(canWriteFunctions, busy, "function")} />
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.unit.8fe4d595" help={organizationWriteReason(canWriteFunctions, busy, "function")} documentation={ORGANIZATIONS_FIELD_DOCUMENTATION}>
|
|
|
|
|
<select value={functionDraft.organization_unit_id} disabled={!canWriteFunctions || busy} onChange={(event) => setFunctionDraft({ ...functionDraft, organization_unit_id: event.target.value })}>
|
|
|
|
|
<option value="">i18n:govoplan-organizations.select_unit.013bf13a</option>
|
|
|
|
|
{model.units.map((item) => <option key={item.id} value={item.id}>{item.name}</option>)}
|
|
|
|
|
</select>
|
|
|
|
|
</FormField>
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.function_type.501fe7c0">
|
|
|
|
|
<FormField label="i18n:govoplan-organizations.function_type.501fe7c0" help={organizationWriteReason(canWriteFunctions, busy, "function")} documentation={ORGANIZATIONS_FIELD_DOCUMENTATION}>
|
|
|
|
|
<select value={functionDraft.function_type_id} disabled={!canWriteFunctions || busy} onChange={(event) => setFunctionDraft({ ...functionDraft, function_type_id: event.target.value })}>
|
|
|
|
|
<option value="">i18n:govoplan-organizations.none.334c4a4c</option>
|
|
|
|
|
{model.function_types.map((item) => <option key={item.id} value={item.id}>{item.name}</option>)}
|
|
|
|
|
</select>
|
|
|
|
|
</FormField>
|
|
|
|
|
<div className="organizations-check-list">
|
|
|
|
|
<ToggleSwitch checked={functionDraft.delegable} disabled={!canWriteFunctions || busy} onChange={(checked) => setFunctionDraft({ ...functionDraft, delegable: checked })} label="i18n:govoplan-organizations.delegable.b4f0137d" />
|
|
|
|
|
<ToggleSwitch checked={functionDraft.act_in_place_allowed} disabled={!canWriteFunctions || busy} onChange={(checked) => setFunctionDraft({ ...functionDraft, act_in_place_allowed: checked })} label="i18n:govoplan-organizations.act_in_place.49b942bd" />
|
|
|
|
|
<ToggleSwitch checked={functionDraft.delegable} disabled={!canWriteFunctions || busy} help={organizationWriteReason(canWriteFunctions, busy, "function")} onChange={(checked) => setFunctionDraft({ ...functionDraft, delegable: checked })} label="i18n:govoplan-organizations.delegable.b4f0137d" />
|
|
|
|
|
<ToggleSwitch checked={functionDraft.act_in_place_allowed} disabled={!canWriteFunctions || busy} help={organizationWriteReason(canWriteFunctions, busy, "function")} onChange={(checked) => setFunctionDraft({ ...functionDraft, act_in_place_allowed: checked })} label="i18n:govoplan-organizations.act_in_place.49b942bd" />
|
|
|
|
|
</div>
|
|
|
|
|
{renderChangeRequestField()}
|
|
|
|
|
</>
|
|
|
|
|