Files

144 lines
3.9 KiB
TypeScript

import { useEffect, useMemo, useState } from "react";
import { ActionToolbar,
ActionBlockerHint,
FormField,
hasScope,
i18nMessage,
type ApiSettings,
type AuthInfo
} from "@govoplan/core-webui";
import ViewsAdminPanel from "./ViewsAdminPanel";
import type { ViewScopeType } from "../../api/views";
import {
VIEWS_DOCUMENTATION,
VIEWS_FIELD_DOCUMENTATION,
VIEWS_INTERFACE_I18N
} from "./interfacePatterns";
type OwnerOption = {
key: string;
scopeType: Extract<ViewScopeType, "group" | "user">;
scopeId: string;
label: string;
description: string;
canWrite: boolean;
};
export default function PersonalViewsPanel({
settings,
auth
}: {
settings: ApiSettings;
auth: AuthInfo;
}) {
const options = useMemo(() => ownerOptions(auth), [auth]);
const [ownerKey, setOwnerKey] = useState(options[0]?.key ?? "");
useEffect(() => {
if (!options.some((option) => option.key === ownerKey)) {
setOwnerKey(options[0]?.key ?? "");
}
}, [options, ownerKey]);
const owner = options.find((option) => option.key === ownerKey) ?? options[0];
if (!owner) {
return (
<ActionBlockerHint
reason={{
summary: "i18n:govoplan-views.no_personal_access",
requiredAction: VIEWS_INTERFACE_I18N.permissionGuidanceText,
actor: VIEWS_INTERFACE_I18N.administratorText,
target: VIEWS_INTERFACE_I18N.administrationTargetText
}}
labels={{
requiredAction: VIEWS_INTERFACE_I18N.requiredActionText,
actor: VIEWS_INTERFACE_I18N.actorText,
target: VIEWS_INTERFACE_I18N.destinationText
}}
documentation={VIEWS_DOCUMENTATION}
/>
);
}
return (
<div className="views-personal-panel">
{options.length > 1 && (
<ActionToolbar className="views-owner-toolbar">
<FormField
label="i18n:govoplan-views.view_owner"
documentation={VIEWS_FIELD_DOCUMENTATION}
>
<select
value={owner.key}
onChange={(event) => setOwnerKey(event.target.value)}
>
{options.map((option) => (
<option key={option.key} value={option.key}>
{option.label}
</option>
))}
</select>
</FormField>
</ActionToolbar>
)}
<ViewsAdminPanel
key={owner.key}
settings={settings}
scopeType={owner.scopeType}
scopeId={owner.scopeId}
canWriteDefinitions={owner.canWrite}
canWriteAssignments={false}
showAssignments={false}
embedded
title={owner.label}
description={owner.description}
/>
</div>
);
}
function ownerOptions(auth: AuthInfo): OwnerOption[] {
const tenantManager = hasScope(auth, "views:definition:write");
const options: OwnerOption[] = [];
if (
tenantManager ||
hasScope(auth, "views:personal_definition:read") ||
hasScope(auth, "views:personal_definition:write")
) {
options.push({
key: `user:${auth.user.account_id}`,
scopeType: "user",
scopeId: auth.user.account_id,
label: "i18n:govoplan-views.my_views",
description: "i18n:govoplan-views.personal_description",
canWrite:
tenantManager ||
hasScope(auth, "views:personal_definition:write")
});
}
const canReadGroups =
tenantManager ||
hasScope(auth, "views:group_definition:read") ||
hasScope(auth, "views:group_definition:write");
if (canReadGroups) {
for (const group of auth.groups) {
options.push({
key: `group:${group.id}`,
scopeType: "group",
scopeId: group.id,
label: i18nMessage("i18n:govoplan-views.group_value", {
value0: group.name
}),
description: "i18n:govoplan-views.group_description",
canWrite:
tenantManager ||
hasScope(auth, "views:group_definition:write")
});
}
}
return options;
}