Fix people pages permissions handling
Signed-off-by: Émile Ré <nemile.re@gmail.com>
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
||||
IconGroup1,
|
||||
IconInboxEmpty,
|
||||
IconListStack,
|
||||
IconLock,
|
||||
IconMedal,
|
||||
IconPageCheck,
|
||||
IconPageTextLine,
|
||||
@@ -47,12 +48,13 @@ const fragment = graphql`
|
||||
canListProcessingActivities: permission(
|
||||
action: "core:processing-activity:list"
|
||||
)
|
||||
canListStatesOfApplicability: permission(
|
||||
action: "core:state-of-applicability:list"
|
||||
)
|
||||
canListRightsRequests: permission(action: "core:rights-request:list")
|
||||
canListSnapshots: permission(action: "core:snapshot:list")
|
||||
canGetTrustCenter: permission(action: "core:trust-center:get")
|
||||
canUpdateOrganization: permission(action: "iam:organization:update")
|
||||
canListStatesOfApplicability: permission(
|
||||
action: "core:state-of-applicability:list"
|
||||
)
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -180,6 +182,13 @@ export function Sidebar(props: { fKey: SidebarFragment$key }) {
|
||||
to={`${prefix}/states-of-applicability`}
|
||||
/>
|
||||
)}
|
||||
{organization.canListRightsRequests && (
|
||||
<SidebarItem
|
||||
label={__("Rights Requests")}
|
||||
icon={IconLock}
|
||||
to={`${prefix}/rights-requests`}
|
||||
/>
|
||||
)}
|
||||
{organization.canListSnapshots && (
|
||||
<SidebarItem
|
||||
label={__("Snapshots")}
|
||||
|
||||
@@ -21,8 +21,6 @@ import {
|
||||
import { useTranslate } from "@probo/i18n";
|
||||
import { useOrganizationId } from "/hooks/useOrganizationId";
|
||||
import { Outlet } from "react-router";
|
||||
import { use } from "react";
|
||||
import { PermissionsContext } from "/providers/PermissionsContext";
|
||||
|
||||
type Props = {
|
||||
queryRef: PreloadedQuery<PeopleGraphNodeQuery>;
|
||||
@@ -33,7 +31,6 @@ export default function PeopleDetailPage(props: Props) {
|
||||
const people = data.node;
|
||||
const { __ } = useTranslate();
|
||||
const organizationId = useOrganizationId();
|
||||
const { isAuthorized } = use(PermissionsContext);
|
||||
const deletePeople = useDeletePeople(
|
||||
people,
|
||||
ConnectionHandler.getConnectionID(organizationId, PeopleConnectionKey),
|
||||
@@ -57,7 +54,7 @@ export default function PeopleDetailPage(props: Props) {
|
||||
<Avatar name={people.fullName ?? ""} size="xl" />
|
||||
<div className="text-2xl">{people.fullName}</div>
|
||||
</div>
|
||||
{isAuthorized("People", "deletePeople") && (
|
||||
{data.node.canDelete && (
|
||||
<ActionDropdown variant="secondary">
|
||||
<DropdownItem
|
||||
variant="danger"
|
||||
|
||||
@@ -23,10 +23,12 @@ import type { NodeOf } from "/types";
|
||||
import { usePageTitle } from "@probo/hooks";
|
||||
import { getRole } from "@probo/helpers";
|
||||
import { CreatePeopleDialog } from "./dialogs/CreatePeopleDialog";
|
||||
import { SetEndOfContractDialog, type SetEndOfContractDialogRef } from "./dialogs/SetEndOfContractDialog";
|
||||
import {
|
||||
SetEndOfContractDialog,
|
||||
type SetEndOfContractDialogRef,
|
||||
} from "./dialogs/SetEndOfContractDialog";
|
||||
import { useOrganizationId } from "/hooks/useOrganizationId";
|
||||
import { PermissionsContext } from "/providers/PermissionsContext";
|
||||
import { use, useRef } from "react";
|
||||
import { useRef } from "react";
|
||||
|
||||
type People = NodeOf<PeopleGraphPaginatedFragment$data["peoples"]>;
|
||||
|
||||
@@ -44,25 +46,31 @@ export default function PeopleListPage({
|
||||
queryRef: PreloadedQuery<PeopleGraphPaginatedQuery>;
|
||||
}) {
|
||||
const { __ } = useTranslate();
|
||||
const { isAuthorized } = use(PermissionsContext);
|
||||
const { people, refetch, connectionId, hasNext, loadNext, isLoadingNext } =
|
||||
usePeopleQuery(queryRef);
|
||||
const {
|
||||
data,
|
||||
people,
|
||||
refetch,
|
||||
connectionId,
|
||||
hasNext,
|
||||
loadNext,
|
||||
isLoadingNext,
|
||||
} = usePeopleQuery(queryRef);
|
||||
|
||||
usePageTitle(__("Members"));
|
||||
|
||||
const hasAnyAction =
|
||||
isAuthorized("People", "updatePeople") ||
|
||||
isAuthorized("People", "deletePeople");
|
||||
const hasAnyAction = people.some(
|
||||
({ canDelete, canUpdate }) => canDelete || canUpdate
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<PageHeader
|
||||
title={__("Members")}
|
||||
description={__(
|
||||
"Keep track of your company's workforce and their progress towards completing tasks assigned to them.",
|
||||
"Keep track of your company's workforce and their progress towards completing tasks assigned to them."
|
||||
)}
|
||||
>
|
||||
{isAuthorized("Organization", "createPeople") && (
|
||||
{data.canCreatePeople && (
|
||||
<CreatePeopleDialog connectionId={connectionId}>
|
||||
<Button icon={IconPlusLarge}>{__("Add member")}</Button>
|
||||
</CreatePeopleDialog>
|
||||
@@ -110,7 +118,6 @@ function PeopleRow({
|
||||
const { __ } = useTranslate();
|
||||
const deletePeople = useDeletePeople(people, connectionId);
|
||||
const contractEnded = isContractEnded(people);
|
||||
const { isAuthorized } = use(PermissionsContext);
|
||||
const dialogRef = useRef<SetEndOfContractDialogRef>(null);
|
||||
|
||||
return (
|
||||
@@ -140,7 +147,7 @@ function PeopleRow({
|
||||
{hasAnyAction && (
|
||||
<Td noLink width={50} className="text-end">
|
||||
<ActionDropdown>
|
||||
{isAuthorized("People", "updatePeople") && (
|
||||
{people.canUpdate && (
|
||||
<DropdownItem
|
||||
icon={IconCalendar2}
|
||||
onClick={() => dialogRef.current?.open()}
|
||||
@@ -148,7 +155,7 @@ function PeopleRow({
|
||||
{__("Set end of contract")}
|
||||
</DropdownItem>
|
||||
)}
|
||||
{isAuthorized("People", "deletePeople") && (
|
||||
{people.canDelete && (
|
||||
<DropdownItem
|
||||
icon={IconTrashCan}
|
||||
variant="danger"
|
||||
|
||||
@@ -31,7 +31,7 @@ const schema = z.object({
|
||||
additionalEmailAddresses: z.preprocess(
|
||||
// Empty additional emails are skipped
|
||||
(v) => (v as string[]).filter((v) => !!v),
|
||||
z.array(z.string().email())
|
||||
z.array(z.string().email()),
|
||||
),
|
||||
kind: z.enum(peopleRoles),
|
||||
});
|
||||
@@ -50,6 +50,8 @@ export const createPeopleMutation = graphql`
|
||||
position
|
||||
kind
|
||||
additionalEmailAddresses
|
||||
canDelete: permission(action: "core:people:delete")
|
||||
canUpdate: permission(action: "core:people:update")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,6 @@ import type { PeopleGraphUpdateMutation } from "/__generated__/core/PeopleGraphU
|
||||
import { updatePeopleMutation } from "/hooks/graph/PeopleGraph";
|
||||
import { Button, Card, Field, Input } from "@probo/ui";
|
||||
import { EmailsField } from "/components/form/EmailsField";
|
||||
import { PermissionsContext } from "/providers/PermissionsContext";
|
||||
import { use } from "react";
|
||||
|
||||
const schema = z.object({
|
||||
fullName: z.string().min(1),
|
||||
@@ -50,7 +48,6 @@ export default function PeopleProfileTab() {
|
||||
errorMessage: __("Failed to update member"),
|
||||
},
|
||||
);
|
||||
const { isAuthorized } = use(PermissionsContext);
|
||||
const onSubmit = handleSubmit((data) => {
|
||||
const input = {
|
||||
id: people.id!,
|
||||
@@ -80,22 +77,32 @@ export default function PeopleProfileTab() {
|
||||
{...register("position")}
|
||||
type="text"
|
||||
placeholder={__("e.g. CEO, CFO, etc.")}
|
||||
disabled={!people.canUpdate}
|
||||
/>
|
||||
<Field
|
||||
label={__("Primary email")}
|
||||
{...register("primaryEmailAddress")}
|
||||
type="email"
|
||||
disabled={!people.canUpdate}
|
||||
/>
|
||||
<EmailsField control={control} register={register} />
|
||||
<Field label={__("Contract start date")}>
|
||||
<Input {...register("contractStartDate")} type="date" />
|
||||
<Input
|
||||
{...register("contractStartDate")}
|
||||
type="date"
|
||||
disabled={!people.canUpdate}
|
||||
/>
|
||||
</Field>
|
||||
<Field label={__("Contract end date")}>
|
||||
<Input {...register("contractEndDate")} type="date" />
|
||||
<Input
|
||||
{...register("contractEndDate")}
|
||||
type="date"
|
||||
disabled={!people.canUpdate}
|
||||
/>
|
||||
</Field>
|
||||
</Card>
|
||||
<div className="flex justify-end">
|
||||
{formState.isDirty && isAuthorized("People", "updatePeople") && (
|
||||
{formState.isDirty && people.canUpdate && (
|
||||
<Button type="submit" disabled={isMutating}>
|
||||
{__("Update")}
|
||||
</Button>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useTranslate } from "@probo/i18n";
|
||||
import { Button, Card, IconCheckmark1 } from "@probo/ui";
|
||||
import { use, type PropsWithChildren } from "react";
|
||||
import { type PropsWithChildren } from "react";
|
||||
import z from "zod";
|
||||
import { useFormWithSchema } from "/hooks/useFormWithSchema";
|
||||
import { ControlledField } from "/components/form/ControlledField";
|
||||
@@ -11,7 +11,6 @@ import { useOutletContext } from "react-router";
|
||||
import { updatePeopleMutation } from "/hooks/graph/PeopleGraph";
|
||||
import { useMutationWithToasts } from "/hooks/useMutationWithToasts";
|
||||
import type { PeopleGraphUpdateMutation } from "/__generated__/core/PeopleGraphUpdateMutation.graphql";
|
||||
import { PermissionsContext } from "/providers/PermissionsContext";
|
||||
|
||||
const schema = z.object({
|
||||
kind: z.enum(peopleRoles),
|
||||
@@ -22,8 +21,6 @@ export default function PeopleRoleTab() {
|
||||
people: PeopleGraphNodeQuery$data["node"];
|
||||
}>();
|
||||
const { __ } = useTranslate();
|
||||
const { isAuthorized } = use(PermissionsContext);
|
||||
const canUpdatePeople = isAuthorized("People", "updatePeople");
|
||||
const { control, formState, handleSubmit, reset } = useFormWithSchema(
|
||||
schema,
|
||||
{
|
||||
@@ -68,7 +65,7 @@ export default function PeopleRoleTab() {
|
||||
name="kind"
|
||||
type="select"
|
||||
label={__("Role")}
|
||||
disabled={!canUpdatePeople}
|
||||
disabled={!people.canUpdate}
|
||||
>
|
||||
{getRoles(__).map((role) => (
|
||||
<Option key={role.value} value={role.value}>
|
||||
@@ -97,7 +94,7 @@ export default function PeopleRoleTab() {
|
||||
</ul>
|
||||
</div>
|
||||
</Card>
|
||||
{canUpdatePeople && (
|
||||
{people.canUpdate && (
|
||||
<div className="flex justify-end">
|
||||
{formState.isDirty && (
|
||||
<Button type="submit" disabled={isMutating}>
|
||||
|
||||
Reference in New Issue
Block a user