144 lines
3.9 KiB
TypeScript
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;
|
|
}
|