Fix tasks page permissions handling

Signed-off-by: Émile Ré <nemile.re@gmail.com>
This commit is contained in:
Émile Ré
2025-12-31 11:21:27 +01:00
committed by Bryan Frimin
parent e46a11001a
commit 21353f35e7
12 changed files with 643 additions and 409 deletions

View File

@@ -2,31 +2,27 @@ import { graphql } from "relay-runtime";
import type { MeasureTasksTabQuery } from "/__generated__/core/MeasureTasksTabQuery.graphql";
import { useOutletContext } from "react-router";
import { useLazyLoadQuery } from "react-relay";
import TasksCard from "/components/tasks/TasksCard";
import { TasksCard } from "/components/tasks/TasksCard";
import { Button, IconPlusLarge } from "@probo/ui";
import { useTranslate } from "@probo/i18n";
import TaskFormDialog from "/components/tasks/TaskFormDialog";
const tasksQuery = graphql`
query MeasureTasksTabQuery($measureId: ID!) {
node(id: $measureId) {
node(id: $measureId) @required(action: THROW) {
__typename
... on Measure {
id
tasks(first: 100) @connection(key: "Measure__tasks") {
tasks(first: 100)
@connection(key: "Measure__tasks")
@required(action: THROW) {
__id
edges {
edges @required(action: THROW) {
node {
id
name
state
description
timeEstimate
deadline
...TaskFormDialogFragment
assignedTo {
id
fullName
}
...TasksCard_TaskRowFragment
}
}
}
@@ -40,19 +36,17 @@ export default function MeasureTasksTab() {
const { measure } = useOutletContext<{
measure: { id: string };
}>();
const data = useLazyLoadQuery<MeasureTasksTabQuery>(tasksQuery, {
const { node } = useLazyLoadQuery<MeasureTasksTabQuery>(tasksQuery, {
measureId: measure.id,
});
const node = data.node;
if (!node || !node.tasks) {
return null;
if (node.__typename !== "Measure") {
throw new Error("invalid node type");
}
const connectionId = node.tasks.__id;
const tasks = node.tasks.edges?.map((edge) => edge.node) ?? [];
return (
<div className="relative">
<TasksCard connectionId={connectionId} tasks={tasks} />
<TasksCard connectionId={connectionId} tasks={node.tasks.edges} />
<TaskFormDialog connection={connectionId} measureId={measure.id}>
<Button
variant="secondary"

View File

@@ -10,10 +10,8 @@ import { useTranslate } from "@probo/i18n";
import type { TasksPageFragment$key } from "/__generated__/core/TasksPageFragment.graphql";
import { tasksQuery } from "/hooks/graph/TaskGraph";
import { usePageTitle } from "@probo/hooks";
import TasksCard from "/components/tasks/TasksCard";
import { TasksCard } from "/components/tasks/TasksCard";
import TaskFormDialog from "/components/tasks/TaskFormDialog";
import { PermissionsContext } from "/providers/PermissionsContext";
import { use } from "react";
const tasksFragment = graphql`
fragment TasksPageFragment on Organization
@@ -25,31 +23,21 @@ const tasksFragment = graphql`
before: { type: "CursorKey", defaultValue: null }
last: { type: "Int", defaultValue: null }
) {
canCreateTask: permission(action: "core:task:create")
tasks(
first: $first
after: $after
last: $last
before: $before
orderBy: $order
) @connection(key: "TasksPageFragment_tasks") {
) @connection(key: "TasksPageFragment_tasks") @required(action: THROW) {
__id
edges {
edges @required(action: THROW) {
node {
id
name
state
description
timeEstimate
deadline
...TaskFormDialogFragment
measure {
id
name
}
assignedTo {
id
fullName
}
...TasksCard_TaskRowFragment
}
}
}
@@ -67,9 +55,7 @@ export default function TasksPage({ queryRef }: Props) {
tasksFragment,
query.organization as TasksPageFragment$key,
);
const tasks = data.tasks?.edges.map((edge) => edge.node);
const connectionId = data.tasks.__id;
const { isAuthorized } = use(PermissionsContext);
usePageTitle(__("Tasks"));
return (
@@ -80,13 +66,13 @@ export default function TasksPage({ queryRef }: Props) {
"Track your assigned compliance tasks and keep progress on track.",
)}
>
{isAuthorized("Organization", "createTask") && (
{data.canCreateTask && (
<TaskFormDialog connection={connectionId}>
<Button icon={IconPlusLarge}>{__("New task")}</Button>
</TaskFormDialog>
)}
</PageHeader>
<TasksCard connectionId={connectionId} tasks={tasks ?? []} />
<TasksCard connectionId={connectionId} tasks={data.tasks.edges} />
</div>
);
}

View File

@@ -277,6 +277,7 @@ export default function TrustCenterOverviewTab() {
<h2 className="text-base font-medium">{__("Integrations")}</h2>
<Card padded>
<SlackConnections
canUpdate={!!organization.trustCenter?.canUpdate}
organizationId={organization.id!}
slackConnections={
organization.slackConnections?.edges?.map((edge) => edge.node) ??