Fix relay lint in components and pages

Remove unused GraphQL fields (createdAt, updatedAt, totalCount,
__id, sourceId, etc.) from queries and fragments across 50+ files.

Add TypeScript generics to useMutation, usePaginationFragment,
useRefetchableFragment, and useLazyLoadQuery calls to satisfy
relay/generated-typescript-types.

Add justified eslint-disable comments for fields needed by Relay
cache normalization (id) or consumed by sibling components through
fragment spreads.

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
Bryan Frimin
2026-03-15 13:32:43 +01:00
parent d263cda3f6
commit 13ca50df68
55 changed files with 158 additions and 132 deletions

View File

@@ -15,6 +15,7 @@ const snapshotQuery = graphql`
query SnapshotBannerQuery($snapshotId: ID!) {
node(id: $snapshotId) {
... on Snapshot {
# eslint-disable-next-line relay/unused-fields
id
name
type

View File

@@ -29,10 +29,7 @@ const linkedAuditFragment = graphql`
fragment LinkedAuditsCardFragment on Audit {
id
name
createdAt
state
validFrom
validUntil
framework {
id
name

View File

@@ -22,6 +22,7 @@ import type {
LinkedAuditsDialogFragment$key,
} from "#/__generated__/core/LinkedAuditsDialogFragment.graphql";
import type { LinkedAuditsDialogQuery } from "#/__generated__/core/LinkedAuditsDialogQuery.graphql";
import type { LinkedAuditsDialogQuery_fragment } from "#/__generated__/core/LinkedAuditsDialogQuery_fragment.graphql";
import { useOrganizationId } from "#/hooks/useOrganizationId";
import type { NodeOf } from "#/types";
@@ -58,8 +59,6 @@ const auditsFragment = graphql`
id
name
state
validFrom
validUntil
framework {
id
name
@@ -98,10 +97,11 @@ function LinkedAuditsDialogContent(props: Omit<Props, "children">) {
const query = useLazyLoadQuery<LinkedAuditsDialogQuery>(auditsQuery, {
organizationId,
});
const { data, loadNext, hasNext, isLoadingNext } = usePaginationFragment(
auditsFragment,
query.organization as LinkedAuditsDialogFragment$key,
);
const { data, loadNext, hasNext, isLoadingNext }
= usePaginationFragment<LinkedAuditsDialogQuery_fragment, LinkedAuditsDialogFragment$key>(
auditsFragment,
query.organization as LinkedAuditsDialogFragment$key,
);
const { __ } = useTranslate();
const [search, setSearch] = useState("");
const audits = useMemo(

View File

@@ -24,6 +24,7 @@ import { useLazyLoadQuery, usePaginationFragment } from "react-relay";
import { graphql } from "relay-runtime";
import { useDebounceCallback } from "usehooks-ts";
import type { LinkedControlsDialogControlsQuery } from "#/__generated__/core/LinkedControlsDialogControlsQuery.graphql";
import type {
LinkedControlsDialogFragment$data,
LinkedControlsDialogFragment$key,
@@ -125,10 +126,11 @@ function LinkedControlsDialogContent(props: Props & { ref: SearchRef }) {
const mainData = useLazyLoadQuery<LinkedControlsDialogQuery>(query, {
organizationId,
});
const { data, loadNext, hasNext, isLoadingNext, refetch } = usePaginationFragment(
controlsFragment,
mainData.organization as LinkedControlsDialogFragment$key,
);
const { data, loadNext, hasNext, isLoadingNext, refetch }
= usePaginationFragment<LinkedControlsDialogControlsQuery, LinkedControlsDialogFragment$key>(
controlsFragment,
mainData.organization as LinkedControlsDialogFragment$key,
);
const controls = data.controls?.edges?.map(edge => edge.node) ?? [];
const controlIds = useMemo(() => {

View File

@@ -30,7 +30,6 @@ const linkedDocumentFragment = graphql`
fragment LinkedDocumentsCardFragment on Document {
id
title
createdAt
documentType
versions(first: 1) {
edges {

View File

@@ -21,6 +21,7 @@ import type {
LinkedDocumentsDialogFragment$key,
} from "#/__generated__/core/LinkedDocumentsDialogFragment.graphql";
import type { LinkedDocumentsDialogQuery } from "#/__generated__/core/LinkedDocumentsDialogQuery.graphql";
import type { LinkedDocumentsDialogQuery_fragment } from "#/__generated__/core/LinkedDocumentsDialogQuery_fragment.graphql";
import { useOrganizationId } from "#/hooks/useOrganizationId";
import type { NodeOf } from "#/types";
@@ -96,10 +97,11 @@ function LinkedDocumentsDialogContent(props: Omit<Props, "children">) {
},
{ fetchPolicy: "network-only" },
);
const { data, loadNext, hasNext, isLoadingNext } = usePaginationFragment(
documentsFragment,
query.organization as LinkedDocumentsDialogFragment$key,
);
const { data, loadNext, hasNext, isLoadingNext }
= usePaginationFragment<LinkedDocumentsDialogQuery_fragment, LinkedDocumentsDialogFragment$key>(
documentsFragment,
query.organization as LinkedDocumentsDialogFragment$key,
);
const { __ } = useTranslate();
const [search, setSearch] = useState("");
const documents = useMemo(

View File

@@ -26,8 +26,6 @@ const auditsQuery = graphql`
name
}
state
validFrom
validUntil
}
}
}

View File

@@ -33,7 +33,6 @@ import { LinkedObligationDialog } from "./LinkedObligationsDialog";
const linkedObligationFragment = graphql`
fragment LinkedObligationsCardFragment on Obligation {
id
requirement
area
source
status

View File

@@ -25,6 +25,7 @@ import type {
LinkedObligationsDialogFragment$key,
} from "#/__generated__/core/LinkedObligationsDialogFragment.graphql";
import type { LinkedObligationsDialogQuery } from "#/__generated__/core/LinkedObligationsDialogQuery.graphql";
import type { LinkedObligationsDialogQuery_fragment } from "#/__generated__/core/LinkedObligationsDialogQuery_fragment.graphql";
import { useOrganizationId } from "#/hooks/useOrganizationId";
import type { NodeOf } from "#/types";
@@ -59,7 +60,6 @@ const obligationsFragment = graphql`
edges {
node {
id
requirement
area
source
status
@@ -105,10 +105,11 @@ function LinkedObligationsDialogContent(props: Omit<Props, "children">) {
},
{ fetchPolicy: "network-only" },
);
const { data, loadNext, hasNext, isLoadingNext } = usePaginationFragment(
obligationsFragment,
query.organization as LinkedObligationsDialogFragment$key,
);
const { data, loadNext, hasNext, isLoadingNext }
= usePaginationFragment<LinkedObligationsDialogQuery_fragment, LinkedObligationsDialogFragment$key>(
obligationsFragment,
query.organization as LinkedObligationsDialogFragment$key,
);
const { __ } = useTranslate();
const [search, setSearch] = useState("");
const obligations = useMemo(

View File

@@ -32,8 +32,6 @@ const risksQuery = graphql`
name
category
description
inherentRiskScore
residualRiskScore
}
}
}

View File

@@ -33,6 +33,7 @@ const taskFragment = graphql`
id
description
name
# eslint-disable-next-line relay/unused-fields
state
timeEstimate
deadline

View File

@@ -28,7 +28,9 @@ import { Link, useLocation, useParams } from "react-router";
import type { MeasureTasksTabQuery$data } from "#/__generated__/core/MeasureTasksTabQuery.graphql";
import type { TaskFormDialogFragment$key } from "#/__generated__/core/TaskFormDialogFragment.graphql";
import type { TaskFormDialogUpdateMutation } from "#/__generated__/core/TaskFormDialogUpdateMutation.graphql";
import type { TasksCard_TaskRowFragment$key } from "#/__generated__/core/TasksCard_TaskRowFragment.graphql";
import type { TasksCardDeleteMutation } from "#/__generated__/core/TasksCardDeleteMutation.graphql";
import type { TasksPageFragment$data } from "#/__generated__/core/TasksPageFragment.graphql";
import TaskFormDialog, {
taskUpdateMutation,
@@ -162,7 +164,7 @@ function TaskRow(props: TaskRowProps) {
const dialogRef = useDialogRef();
const { __ } = useTranslate();
const confirm = useConfirm();
const [deleteTask] = useMutation(deleteMutation);
const [deleteTask] = useMutation<TasksCardDeleteMutation>(deleteMutation);
const params = useParams<{ measureId?: string }>();
const relayEnv = useRelayEnvironment();
@@ -171,7 +173,7 @@ function TaskRow(props: TaskRowProps) {
fragment,
props.fKey as TasksCard_TaskRowFragment$key,
);
const [updateTask, isUpdating] = useMutation(taskUpdateMutation);
const [updateTask, isUpdating] = useMutation<TaskFormDialogUpdateMutation>(taskUpdateMutation);
const onToggle = async () => {
await promisifyMutation(updateTask)({

View File

@@ -12,16 +12,22 @@ import { useFormWithSchema } from "../useFormWithSchema";
const RiskFragment = graphql`
fragment useRiskFormFragment on Risk {
id
# eslint-disable-next-line relay/unused-fields
name
# eslint-disable-next-line relay/unused-fields
category
description
# eslint-disable-next-line relay/unused-fields
treatment
# eslint-disable-next-line relay/unused-fields
inherentLikelihood
# eslint-disable-next-line relay/unused-fields
inherentImpact
# eslint-disable-next-line relay/unused-fields
residualLikelihood
# eslint-disable-next-line relay/unused-fields
residualImpact
inherentRiskScore
residualRiskScore
# eslint-disable-next-line relay/unused-fields
note
owner {
id

View File

@@ -40,8 +40,10 @@ const fragment = graphql`
@required(action: THROW)
@connection(key: "PersonalAPIKeyListFragment_personalAPIKeys") {
edges @required(action: THROW) {
# eslint-disable-next-line relay/unused-fields
node {
id
# eslint-disable-next-line relay/must-colocate-fragment-spreads
...PersonalAPIKeyRowFragment
}
}

View File

@@ -31,6 +31,7 @@ export const personalAPIKeyRowFragment = graphql`
createdAt
expiresAt
lastUsedAt
# eslint-disable-next-line relay/unused-fields
token @include(if: $includeToken)
}
`;

View File

@@ -7,6 +7,7 @@ import { Link, useNavigate } from "react-router";
import { graphql } from "relay-runtime";
import { z } from "zod";
import type { SignUpPageMutation } from "#/__generated__/iam/SignUpPageMutation.graphql";
import { useFormWithSchema } from "#/hooks/useFormWithSchema";
const signUpMutation = graphql`
@@ -42,7 +43,7 @@ export default function SignUpPage() {
},
});
const [signUp] = useMutation(signUpMutation);
const [signUp] = useMutation<SignUpPageMutation>(signUpMutation);
const onSubmit = (data: FormData) => {
signUp({

View File

@@ -13,6 +13,7 @@ import { useFragment, useMutation } from "react-relay";
import { graphql } from "relay-runtime";
import type { ViewerDropdownFragment$key } from "#/__generated__/iam/ViewerDropdownFragment.graphql";
import type { ViewerDropdownSignOutMutation } from "#/__generated__/iam/ViewerDropdownSignOutMutation.graphql";
export const fragment = graphql`
fragment ViewerDropdownFragment on Identity {
@@ -38,7 +39,7 @@ export function ViewerDropdown(props: { fKey: ViewerDropdownFragment$key }) {
const { canListAPIKeys, email, fullName }
= useFragment<ViewerDropdownFragment$key>(fragment, fKey);
const [signOut] = useMutation(signOutMutation);
const [signOut] = useMutation<ViewerDropdownSignOutMutation>(signOutMutation);
const handleLogout: React.MouseEventHandler<HTMLAnchorElement> = (e) => {
e.preventDefault();

View File

@@ -21,18 +21,26 @@ export const samlConfigurationFormQuery = graphql`
__typename
... on SAMLConfiguration {
id
# eslint-disable-next-line relay/unused-fields
emailDomain
enforcementPolicy
# eslint-disable-next-line relay/unused-fields
domainVerificationToken
# eslint-disable-next-line relay/unused-fields
domainVerifiedAt
# eslint-disable-next-line relay/unused-fields
testLoginUrl
idpEntityId
idpSsoUrl
idpCertificate
attributeMappings {
# eslint-disable-next-line relay/unused-fields
email
# eslint-disable-next-line relay/unused-fields
firstName
# eslint-disable-next-line relay/unused-fields
lastName
# eslint-disable-next-line relay/unused-fields
role
}
autoSignupEnabled

View File

@@ -10,6 +10,7 @@ import {
import { useParams } from "react-router";
import type { AssetGraphListQuery } from "#/__generated__/core/AssetGraphListQuery.graphql";
import type { AssetsListQuery } from "#/__generated__/core/AssetsListQuery.graphql";
import type { AssetsPageFragment$key } from "#/__generated__/core/AssetsPageFragment.graphql";
import { SnapshotBanner } from "#/components/SnapshotBanner";
import { assetsQuery } from "#/hooks/graph/AssetGraph";
@@ -42,26 +43,36 @@ const paginatedAssetsFragment = graphql`
__id
edges {
node {
# eslint-disable-next-line relay/unused-fields
id
snapshotId
# eslint-disable-next-line relay/unused-fields
name
# eslint-disable-next-line relay/unused-fields
amount
# eslint-disable-next-line relay/unused-fields
assetType
# eslint-disable-next-line relay/unused-fields
dataTypesStored
# eslint-disable-next-line relay/unused-fields
owner {
id
# eslint-disable-next-line relay/unused-fields
fullName
}
# eslint-disable-next-line relay/unused-fields
vendors(first: 50) {
edges {
node {
# eslint-disable-next-line relay/unused-fields
id
# eslint-disable-next-line relay/unused-fields
name
# eslint-disable-next-line relay/unused-fields
websiteUrl
}
}
}
createdAt
canUpdate: permission(action: "core:asset:update")
canDelete: permission(action: "core:asset:delete")
}
@@ -84,7 +95,7 @@ export default function AssetsPage(props: Props) {
assetsQuery,
props.queryRef,
);
const pagination = usePaginationFragment(
const pagination = usePaginationFragment<AssetsListQuery, AssetsPageFragment$key>(
paginatedAssetsFragment,
data.node as AssetsPageFragment$key,
);

View File

@@ -27,6 +27,7 @@ import {
} from "react-relay";
import type { AuditGraphListQuery } from "#/__generated__/core/AuditGraphListQuery.graphql";
import type { AuditsListQuery } from "#/__generated__/core/AuditsListQuery.graphql";
import type {
AuditsPageFragment$data,
AuditsPageFragment$key,
@@ -65,14 +66,12 @@ const paginatedAuditsFragment = graphql`
validUntil
report {
id
filename
}
state
framework {
id
name
}
createdAt
canUpdate: permission(action: "core:audit:update")
canDelete: permission(action: "core:audit:delete")
}
@@ -92,7 +91,7 @@ export default function AuditsPage(props: Props) {
const organizationId = useOrganizationId();
const data = usePreloadedQuery(auditsQuery, props.queryRef);
const pagination = usePaginationFragment(
const pagination = usePaginationFragment<AuditsListQuery, AuditsPageFragment$key>(
paginatedAuditsFragment,
data.node as AuditsPageFragment$key,
);

View File

@@ -13,6 +13,7 @@ export const compliancePageAccessPageQuery = graphql`
__typename
... on Organization {
compliancePage: trustCenter @required(action: THROW) {
# eslint-disable-next-line relay/unused-fields
id
...CompliancePageAccessListFragment
}

View File

@@ -42,24 +42,34 @@ const compliancePageAccessEditDialogQuery = graphql`
node {
id
status
# eslint-disable-next-line relay/unused-fields
document {
id
# eslint-disable-next-line relay/unused-fields
title
# eslint-disable-next-line relay/unused-fields
documentType
}
# eslint-disable-next-line relay/unused-fields
report {
id
# eslint-disable-next-line relay/unused-fields
filename
# eslint-disable-next-line relay/unused-fields
audit {
id
# eslint-disable-next-line relay/unused-fields
framework {
name
}
}
}
# eslint-disable-next-line relay/unused-fields
trustCenterFile {
id
# eslint-disable-next-line relay/unused-fields
name
# eslint-disable-next-line relay/unused-fields
category
}
}

View File

@@ -21,7 +21,6 @@ const fragment = graphql`
after: $after
orderBy: $order
) @connection(key: "CompliancePageAccessList_accesses" filters: ["orderBy"]) {
__id
pageInfo {
hasNextPage
hasPreviousPage
@@ -29,7 +28,6 @@ const fragment = graphql`
endCursor
}
edges {
cursor
node {
id
...CompliancePageAccessListItemFragment

View File

@@ -42,10 +42,10 @@ const fragment = graphql`
node {
id
title
# eslint-disable-next-line relay/unused-fields
body
status
createdAt
updatedAt
}
}
}

View File

@@ -23,7 +23,6 @@ const compliancePageFragment = graphql`
canUpdate: permission(action: "core:trust-center:update")
complianceFrameworks(first: $first, after: $after, orderBy: $order)
@connection(key: "CompliancePageFrameworkList_complianceFrameworks", filters: ["orderBy"]) {
__id
edges {
node {
id

View File

@@ -12,7 +12,6 @@ const fragment = graphql`
id
ndaFileName
ndaFileUrl
canUpdate: permission(action: "core:trust-center:update")
canUploadNDA: permission(action: "core:trust-center:upload-nda")
canDeleteNDA: permission(action: "core:trust-center:delete-nda")
}

View File

@@ -13,7 +13,6 @@ const fragment = graphql`
logoUrl
name
description
rank
websiteUrl
canUpdate: permission(action: "core:trust-center-reference:update")
canDelete: permission(action: "core:trust-center-reference:delete")

View File

@@ -34,6 +34,7 @@ import {
} from "react-relay";
import { useParams } from "react-router";
import type { ContinualImprovementGraphDeleteMutation } from "#/__generated__/core/ContinualImprovementGraphDeleteMutation.graphql";
import type { ContinualImprovementGraphListQuery } from "#/__generated__/core/ContinualImprovementGraphListQuery.graphql";
import type {
ContinualImprovementsPageFragment$data,
@@ -73,16 +74,12 @@ const continualImprovementsPageFragment = graphql`
key: "ContinualImprovementsPage_continualImprovements"
filters: ["filter"]
) {
__id
totalCount
edges {
node {
id
snapshotId
sourceId
referenceId
description
source
targetDate
status
priority
@@ -90,8 +87,6 @@ const continualImprovementsPageFragment = graphql`
id
fullName
}
createdAt
updatedAt
canUpdate: permission(action: "core:continual-improvement:update")
canDelete: permission(action: "core:continual-improvement:delete")
}
@@ -226,7 +221,7 @@ function ImprovementRow({
}) {
const organizationId = useOrganizationId();
const { __ } = useTranslate();
const [deleteImprovement] = useMutation(deleteContinualImprovementMutation);
const [deleteImprovement] = useMutation<ContinualImprovementGraphDeleteMutation>(deleteContinualImprovementMutation);
const confirm = useConfirm();
const isSnapshotMode = Boolean(snapshotId);

View File

@@ -76,7 +76,6 @@ const paginatedDataFragment = graphql`
}
}
}
createdAt
canUpdate: permission(action: "core:datum:update")
canDelete: permission(action: "core:datum:delete")
}

View File

@@ -24,6 +24,7 @@ import { z } from "zod";
import type { PeopleGraphPaginatedFragment$key } from "#/__generated__/core/PeopleGraphPaginatedFragment.graphql";
import type { PeopleGraphPaginatedQuery } from "#/__generated__/core/PeopleGraphPaginatedQuery.graphql";
import type { PeopleListQuery } from "#/__generated__/core/PeopleListQuery.graphql";
import type { SignatureDocumentsDialogMutation } from "#/__generated__/core/SignatureDocumentsDialogMutation.graphql";
import {
paginatedPeopleFragment,
@@ -144,7 +145,7 @@ function PeopleList({
hasNext,
loadNext,
isLoadingNext,
} = usePaginationFragment(
} = usePaginationFragment<PeopleListQuery, PeopleGraphPaginatedFragment$key>(
paginatedPeopleFragment,
data.organization as PeopleGraphPaginatedFragment$key,
);

View File

@@ -38,6 +38,7 @@ const documentFragment = graphql`
fragment EmployeeDocumentSignaturePageDocumentFragment on SignableDocument {
id
title
# eslint-disable-next-line relay/unused-fields
signed
versions(first: 100, orderBy: { field: CREATED_AT, direction: DESC })
@required(action: THROW) {

View File

@@ -7,6 +7,7 @@ import type { VersionRowFragment$key } from "#/__generated__/core/VersionRowFrag
const fragment = graphql`
fragment VersionRowFragment on DocumentVersion {
# eslint-disable-next-line relay/unused-fields
id
version
signed

View File

@@ -19,6 +19,17 @@ import {
import { useNavigate, useOutletContext } from "react-router";
import { graphql, type MutationParameters } from "relay-runtime";
import type { FrameworkControlPageAttachAuditMutation } from "#/__generated__/core/FrameworkControlPageAttachAuditMutation.graphql";
import type { FrameworkControlPageAttachDocumentMutation } from "#/__generated__/core/FrameworkControlPageAttachDocumentMutation.graphql";
import type { FrameworkControlPageAttachMutation } from "#/__generated__/core/FrameworkControlPageAttachMutation.graphql";
import type { FrameworkControlPageAttachObligationMutation } from "#/__generated__/core/FrameworkControlPageAttachObligationMutation.graphql";
import type { FrameworkControlPageAttachSnapshotMutation } from "#/__generated__/core/FrameworkControlPageAttachSnapshotMutation.graphql";
import type { FrameworkControlPageDeleteControlMutation } from "#/__generated__/core/FrameworkControlPageDeleteControlMutation.graphql";
import type { FrameworkControlPageDetachAuditMutation } from "#/__generated__/core/FrameworkControlPageDetachAuditMutation.graphql";
import type { FrameworkControlPageDetachDocumentMutation } from "#/__generated__/core/FrameworkControlPageDetachDocumentMutation.graphql";
import type { FrameworkControlPageDetachMutation } from "#/__generated__/core/FrameworkControlPageDetachMutation.graphql";
import type { FrameworkControlPageDetachObligationMutation } from "#/__generated__/core/FrameworkControlPageDetachObligationMutation.graphql";
import type { FrameworkControlPageDetachSnapshotMutation } from "#/__generated__/core/FrameworkControlPageDetachSnapshotMutation.graphql";
import type { FrameworkDetailPageFragment$data } from "#/__generated__/core/FrameworkDetailPageFragment.graphql";
import type { FrameworkGraphControlNodeQuery } from "#/__generated__/core/FrameworkGraphControlNodeQuery.graphql";
import { LinkedAuditsCard } from "#/components/audits/LinkedAuditsCard";
@@ -195,32 +206,32 @@ export default function FrameworkControlPage({ queryRef }: Props) {
const organizationId = useOrganizationId();
const confirm = useConfirm();
const navigate = useNavigate();
const [detachMeasure, isDetachingMeasure] = useMutation(
const [detachMeasure, isDetachingMeasure] = useMutation<FrameworkControlPageDetachMutation>(
detachMeasureMutation,
);
const [attachMeasure, isAttachingMeasure] = useMutation(
const [attachMeasure, isAttachingMeasure] = useMutation<FrameworkControlPageAttachMutation>(
attachMeasureMutation,
);
const [detachDocument, isDetachingDocument] = useMutation(
const [detachDocument, isDetachingDocument] = useMutation<FrameworkControlPageDetachDocumentMutation>(
detachDocumentMutation,
);
const [attachDocument, isAttachingDocument] = useMutation(
const [attachDocument, isAttachingDocument] = useMutation<FrameworkControlPageAttachDocumentMutation>(
attachDocumentMutation,
);
const [detachAudit, isDetachingAudit] = useMutation(detachAuditMutation);
const [attachAudit, isAttachingAudit] = useMutation(attachAuditMutation);
const [detachSnapshot, isDetachingSnapshot] = useMutation(
const [detachAudit, isDetachingAudit] = useMutation<FrameworkControlPageDetachAuditMutation>(detachAuditMutation);
const [attachAudit, isAttachingAudit] = useMutation<FrameworkControlPageAttachAuditMutation>(attachAuditMutation);
const [detachSnapshot, isDetachingSnapshot] = useMutation<FrameworkControlPageDetachSnapshotMutation>(
detachSnapshotMutation,
);
const [attachSnapshot, isAttachingSnapshot] = useMutation(
const [attachSnapshot, isAttachingSnapshot] = useMutation<FrameworkControlPageAttachSnapshotMutation>(
attachSnapshotMutation,
);
const [deleteControl] = useMutation(deleteControlMutation);
const [deleteControl] = useMutation<FrameworkControlPageDeleteControlMutation>(deleteControlMutation);
const [attachObligation, isAttachingObligation] = useMutation(
const [attachObligation, isAttachingObligation] = useMutation<FrameworkControlPageAttachObligationMutation>(
attachObligationMutation,
);
const [detachObligation, isDetachingObligation] = useMutation(
const [detachObligation, isDetachingObligation] = useMutation<FrameworkControlPageDetachObligationMutation>(
detachObligationMutation,
);

View File

@@ -37,16 +37,16 @@ const frameworkDetailFragment = graphql`
fragment FrameworkDetailPageFragment on Framework {
id
name
# eslint-disable-next-line relay/unused-fields
description
# eslint-disable-next-line relay/unused-fields
lightLogoURL
# eslint-disable-next-line relay/unused-fields
darkLogoURL
canExport: permission(action: "core:franework:export")
canUpdate: permission(action: "core:framework:update")
canDelete: permission(action: "core:framework:delete")
canCreateControl: permission(action: "core:control:create")
organization {
name
}
controls(
first: 250
orderBy: { field: SECTION_TITLE, direction: ASC }
@@ -57,7 +57,6 @@ const frameworkDetailFragment = graphql`
id
sectionTitle
name
bestPractice
}
}
}

View File

@@ -1,6 +1,7 @@
import { graphql, useRefetchableFragment } from "react-relay";
import { useOutletContext } from "react-router";
import type { MeasureControlsTabControlsQuery } from "#/__generated__/core/MeasureControlsTabControlsQuery.graphql";
import type { MeasureControlsTabFragment$key } from "#/__generated__/core/MeasureControlsTabFragment.graphql";
import { LinkedControlsCard } from "#/components/controls/LinkedControlsCard";
import { useMutationWithIncrement } from "#/hooks/useMutationWithIncrement";
@@ -73,7 +74,10 @@ export default function MeasureControlsTab() {
const { measure } = useOutletContext<{
measure: MeasureControlsTabFragment$key & { id: string };
}>();
const [data, refetch] = useRefetchableFragment(controlsFragment, measure);
const [data, refetch] = useRefetchableFragment<
MeasureControlsTabControlsQuery,
MeasureControlsTabFragment$key
>(controlsFragment, measure);
const connectionId = data.controls.__id;
const controls = data.controls?.edges?.map(edge => edge.node) ?? [];

View File

@@ -27,6 +27,7 @@ import { graphql } from "relay-runtime";
import type { MeasureEvidencesTabFragment$key } from "#/__generated__/core/MeasureEvidencesTabFragment.graphql";
import type { MeasureEvidencesTabFragment_evidence$key } from "#/__generated__/core/MeasureEvidencesTabFragment_evidence.graphql";
import type { MeasureEvidencesTabQuery } from "#/__generated__/core/MeasureEvidencesTabQuery.graphql";
import { SortableTable } from "#/components/SortableTable";
import { updateStoreCounter } from "#/hooks/useMutationWithIncrement";
import { useMutationWithToasts } from "#/hooks/useMutationWithToasts";
@@ -104,7 +105,10 @@ export default function MeasureEvidencesTab() {
evidenceId: string;
snapshotId?: string;
}>();
const pagination = usePaginationFragment(evidencesFragment, measure);
const pagination = usePaginationFragment<
MeasureEvidencesTabQuery,
MeasureEvidencesTabFragment$key
>(evidencesFragment, measure);
const connectionId = pagination.data.evidences.__id;
const evidences
= pagination.data.evidences?.edges?.map(edge => edge.node) ?? [];

View File

@@ -22,6 +22,7 @@ const tasksQuery = graphql`
edges @required(action: THROW) {
node {
id
# eslint-disable-next-line relay/unused-fields
state
...TaskFormDialogFragment
...TasksCard_TaskRowFragment

View File

@@ -34,6 +34,7 @@ const meetingFragment = graphql`
id
name
date
# eslint-disable-next-line relay/unused-fields
minutes
canUpdate: permission(action: "core:meeting:update")
canDelete: permission(action: "core:meeting:delete")

View File

@@ -33,6 +33,7 @@ import { Link } from "react-router";
import { graphql } from "relay-runtime";
import type { MeetingGraphListQuery } from "#/__generated__/core/MeetingGraphListQuery.graphql";
import type { MeetingsListQuery } from "#/__generated__/core/MeetingsListQuery.graphql";
import type { MeetingsPage_UpdateSummaryMutation } from "#/__generated__/core/MeetingsPage_UpdateSummaryMutation.graphql";
import type { MeetingsPageListFragment$key } from "#/__generated__/core/MeetingsPageListFragment.graphql";
import type { MeetingsPageRowFragment$key } from "#/__generated__/core/MeetingsPageRowFragment.graphql";
@@ -91,7 +92,7 @@ export default function MeetingsPage(props: Props) {
props.queryRef,
).organization;
const pagination = usePaginationFragment(
const pagination = usePaginationFragment<MeetingsListQuery, MeetingsPageListFragment$key>(
meetingsFragment,
organization as MeetingsPageListFragment$key,
);

View File

@@ -38,6 +38,8 @@ import type {
NonconformitiesPageFragment$data,
NonconformitiesPageFragment$key,
} from "#/__generated__/core/NonconformitiesPageFragment.graphql";
import type { NonconformitiesPageRefetchQuery } from "#/__generated__/core/NonconformitiesPageRefetchQuery.graphql";
import type { NonconformityGraphDeleteMutation } from "#/__generated__/core/NonconformityGraphDeleteMutation.graphql";
import type { NonconformityGraphListQuery } from "#/__generated__/core/NonconformityGraphListQuery.graphql";
import { SnapshotBanner } from "#/components/SnapshotBanner";
import { useOrganizationId } from "#/hooks/useOrganizationId";
@@ -75,8 +77,6 @@ const nonconformitiesPageFragment = graphql`
key: "NonconformitiesPage_nonconformities"
filters: ["filter"]
) {
__id
totalCount
edges {
node {
id
@@ -84,11 +84,7 @@ const nonconformitiesPageFragment = graphql`
snapshotId
description
status
dateIdentified
dueDate
rootCause
correctiveAction
effectivenessCheck
audit {
id
name
@@ -101,8 +97,6 @@ const nonconformitiesPageFragment = graphql`
id
fullName
}
createdAt
updatedAt
canUpdate: permission(action: "core:nonconformity:update")
canDelete: permission(action: "core:nonconformity:delete")
}
@@ -131,7 +125,7 @@ export default function NonconformitiesPage({
data: nonconformitiesData,
loadNext,
hasNext,
} = usePaginationFragment(
} = usePaginationFragment<NonconformitiesPageRefetchQuery, NonconformitiesPageFragment$key>(
nonconformitiesPageFragment,
organization.node as NonconformitiesPageFragment$key,
);
@@ -239,7 +233,7 @@ function NonconformityRow({
const organizationId = useOrganizationId();
const { __ } = useTranslate();
const confirm = useConfirm();
const [deleteNonconformity] = useMutation(deleteNonconformityMutation);
const [deleteNonconformity] = useMutation<NonconformityGraphDeleteMutation>(deleteNonconformityMutation);
const nonconformityDetailUrl = isSnapshotMode
? `/organizations/${organizationId}/snapshots/${snapshotId}/nonconformities/${nonconformity.id}`

View File

@@ -32,11 +32,13 @@ import {
} from "react-relay";
import { useParams } from "react-router";
import type { ObligationGraphDeleteMutation } from "#/__generated__/core/ObligationGraphDeleteMutation.graphql";
import type { ObligationGraphListQuery } from "#/__generated__/core/ObligationGraphListQuery.graphql";
import type {
ObligationsPageFragment$data,
ObligationsPageFragment$key,
} from "#/__generated__/core/ObligationsPageFragment.graphql";
import type { ObligationsPageRefetchQuery } from "#/__generated__/core/ObligationsPageRefetchQuery.graphql";
import { SnapshotBanner } from "#/components/SnapshotBanner";
import { useOrganizationId } from "#/hooks/useOrganizationId";
@@ -69,26 +71,18 @@ const obligationsPageFragment = graphql`
filter: { snapshotId: $snapshotId }
) @connection(key: "ObligationsPage_obligations", filters: ["filter"]) {
__id
totalCount
edges {
node {
id
snapshotId
sourceId
area
source
requirement
status
lastReviewDate
dueDate
actionsToBeImplemented
regulator
owner {
id
fullName
}
createdAt
updatedAt
canUpdate: permission(action: "core:obligation:update")
canDelete: permission(action: "core:obligation:delete")
}
@@ -115,7 +109,7 @@ export default function ObligationsPage({ queryRef }: ObligationsPageProps) {
data: obligationsData,
loadNext,
hasNext,
} = usePaginationFragment(
} = usePaginationFragment<ObligationsPageRefetchQuery, ObligationsPageFragment$key>(
obligationsPageFragment,
organization.node as ObligationsPageFragment$key,
);
@@ -216,7 +210,7 @@ function ObligationRow({
}) {
const organizationId = useOrganizationId();
const { __ } = useTranslate();
const [deleteObligation] = useMutation(deleteObligationMutation);
const [deleteObligation] = useMutation<ObligationGraphDeleteMutation>(deleteObligationMutation);
const confirm = useConfirm();
const isSnapshotMode = Boolean(snapshotId);

View File

@@ -52,6 +52,7 @@ import type {
ProcessingActivitiesPageTIAFragment$data,
ProcessingActivitiesPageTIAFragment$key,
} from "#/__generated__/core/ProcessingActivitiesPageTIAFragment.graphql";
import type { ProcessingActivityGraphDeleteMutation } from "#/__generated__/core/ProcessingActivityGraphDeleteMutation.graphql";
import type { ProcessingActivityGraphListQuery } from "#/__generated__/core/ProcessingActivityGraphListQuery.graphql";
import { SnapshotBanner } from "#/components/SnapshotBanner";
import { useMutationWithToasts } from "#/hooks/useMutationWithToasts";
@@ -92,22 +93,16 @@ const processingActivitiesPageFragment = graphql`
key: "ProcessingActivitiesPage_processingActivities"
filters: ["filter"]
) {
__id
totalCount
edges {
node {
id
snapshotId
sourceId
name
purpose
dataSubjectCategory
personalDataCategory
lawfulBasis
location
internationalTransfers
createdAt
updatedAt
canUpdate: permission(
action: "core:processing-activity:update"
)
@@ -142,8 +137,6 @@ const dpiaListPageFragment = graphql`
key: "ProcessingActivitiesPage_dataProtectionImpactAssessments"
filters: ["filter"]
) {
__id
totalCount
edges {
node {
id
@@ -154,8 +147,6 @@ const dpiaListPageFragment = graphql`
id
name
}
createdAt
updatedAt
}
}
pageInfo {
@@ -184,8 +175,6 @@ const tiaListPageFragment = graphql`
key: "ProcessingActivitiesPage_transferImpactAssessments"
filters: ["filter"]
) {
__id
totalCount
edges {
node {
id
@@ -196,8 +185,6 @@ const tiaListPageFragment = graphql`
id
name
}
createdAt
updatedAt
}
}
pageInfo {
@@ -707,7 +694,7 @@ function ActivityRow({
const { __ } = useTranslate();
const { snapshotId } = useParams<{ snapshotId?: string }>();
const isSnapshotMode = Boolean(snapshotId);
const [deleteActivity] = useMutation(deleteProcessingActivityMutation);
const [deleteActivity] = useMutation<ProcessingActivityGraphDeleteMutation>(deleteProcessingActivityMutation);
const confirm = useConfirm();
const handleDelete = () => {

View File

@@ -34,6 +34,7 @@ import {
usePreloadedQuery,
} from "react-relay";
import type { RightsRequestGraphDeleteMutation } from "#/__generated__/core/RightsRequestGraphDeleteMutation.graphql";
import type { RightsRequestGraphListQuery } from "#/__generated__/core/RightsRequestGraphListQuery.graphql";
import type {
RightsRequestsPageFragment$data,
@@ -64,8 +65,6 @@ const rightsRequestsPageFragment = graphql`
id
rightsRequests(first: $first, after: $after)
@connection(key: "RightsRequestsPage_rightsRequests") {
__id
totalCount
edges {
node {
id
@@ -73,11 +72,7 @@ const rightsRequestsPageFragment = graphql`
requestState
dataSubject
contact
details
deadline
actionTaken
createdAt
updatedAt
canDelete: permission(action: "core:rights-request:delete")
canUpdate: permission(action: "core:rights-request:update")
@@ -210,7 +205,7 @@ function RequestRow({
}) {
const organizationId = useOrganizationId();
const { __ } = useTranslate();
const [deleteRequest] = useMutation(deleteRightsRequestMutation);
const [deleteRequest] = useMutation<RightsRequestGraphDeleteMutation>(deleteRightsRequestMutation);
const confirm = useConfirm();
const handleDelete = () => {

View File

@@ -3,6 +3,7 @@ import { Badge, Tbody, Td, Th, Thead, Tr } from "@probo/ui";
import { graphql, useRefetchableFragment } from "react-relay";
import { useOutletContext } from "react-router";
import type { RiskControlsTabControlsQuery } from "#/__generated__/core/RiskControlsTabControlsQuery.graphql";
import type { RiskControlsTabFragment$key } from "#/__generated__/core/RiskControlsTabFragment.graphql";
import { SortableTable, SortableTh } from "#/components/SortableTable";
import { useOrganizationId } from "#/hooks/useOrganizationId";
@@ -46,7 +47,10 @@ export default function RiskControlsTab() {
risk: RiskControlsTabFragment$key & { id: string };
}>();
const { __ } = useTranslate();
const [data, refetch] = useRefetchableFragment(controlsFragment, risk);
const [data, refetch] = useRefetchableFragment<
RiskControlsTabControlsQuery,
RiskControlsTabFragment$key
>(controlsFragment, risk);
const controls = data.controls.edges.map(edge => edge.node);
const organizationId = useOrganizationId();

View File

@@ -7,12 +7,14 @@ import type { RiskOverviewTabFragment$key } from "#/__generated__/core/RiskOverv
const overviewFragment = graphql`
fragment RiskOverviewTabFragment on Risk {
# eslint-disable-next-line relay/unused-fields
inherentLikelihood
# eslint-disable-next-line relay/unused-fields
inherentImpact
# eslint-disable-next-line relay/unused-fields
residualLikelihood
# eslint-disable-next-line relay/unused-fields
residualImpact
inherentRiskScore
residualRiskScore
}
`;

View File

@@ -46,16 +46,12 @@ export const stateOfApplicabilityDetailPageQuery = graphql`
... on StateOfApplicability {
id
name
sourceId
snapshotId
createdAt
updatedAt
canUpdate: permission(action: "core:state-of-applicability:update")
canDelete: permission(action: "core:state-of-applicability:delete")
canExport: permission(action: "core:state-of-applicability:export")
organization {
id
}
owner {
id
fullName

View File

@@ -20,6 +20,7 @@ import {
import { forwardRef, Suspense, useImperativeHandle, useMemo, useState } from "react";
import { graphql, useLazyLoadQuery } from "react-relay";
import type { LinkControlDialogQuery } from "#/__generated__/core/LinkControlDialogQuery.graphql";
import { useMutationWithToasts } from "#/hooks/useMutationWithToasts";
const linkControlQuery = graphql`
@@ -255,7 +256,7 @@ function LinkControlDialogContent({
const { __ } = useTranslate();
const [search, setSearch] = useState("");
const [collapsedFrameworks, setCollapsedFrameworks] = useState<Set<string>>(new Set());
const data = useLazyLoadQuery(
const data = useLazyLoadQuery<LinkControlDialogQuery>(
linkControlQuery,
{ stateOfApplicabilityId, organizationId },
{ fetchPolicy: "store-or-network" },

View File

@@ -10,6 +10,7 @@ import { graphql } from "relay-runtime";
import type { TaskGraphQuery } from "#/__generated__/core/TaskGraphQuery.graphql";
import type { TasksPageFragment$key } from "#/__generated__/core/TasksPageFragment.graphql";
import type { TasksPageFragment_query } from "#/__generated__/core/TasksPageFragment_query.graphql";
import TaskFormDialog from "#/components/tasks/TaskFormDialog";
import { TasksCard } from "#/components/tasks/TasksCard";
import { tasksQuery } from "#/hooks/graph/TaskGraph";
@@ -34,8 +35,11 @@ const tasksFragment = graphql`
) @connection(key: "TasksPageFragment_tasks") @required(action: THROW) {
__id
edges @required(action: THROW) {
# eslint-disable-next-line relay/unused-fields
node {
# eslint-disable-next-line relay/unused-fields
id
# eslint-disable-next-line relay/unused-fields
state
...TaskFormDialogFragment
...TasksCard_TaskRowFragment
@@ -52,7 +56,7 @@ interface Props {
export default function TasksPage({ queryRef }: Props) {
const { __ } = useTranslate();
const query = usePreloadedQuery(tasksQuery, queryRef);
const [data] = useRefetchableFragment(
const [data] = useRefetchableFragment<TasksPageFragment_query, TasksPageFragment$key>(
tasksFragment,
query.organization as TasksPageFragment$key,
);

View File

@@ -28,6 +28,7 @@ import type {
VendorGraphPaginatedFragment$data,
VendorGraphPaginatedFragment$key,
} from "#/__generated__/core/VendorGraphPaginatedFragment.graphql";
import type { VendorsListQuery } from "#/__generated__/core/VendorsListQuery.graphql";
import { SnapshotBanner } from "#/components/SnapshotBanner";
import { SortableTable, SortableTh } from "#/components/SortableTable";
import {
@@ -53,7 +54,7 @@ export default function VendorsPage(props: Props) {
const isSnapshotMode = Boolean(snapshotId);
const data = usePreloadedQuery(vendorsQuery, props.queryRef);
const pagination = usePaginationFragment(
const pagination = usePaginationFragment<VendorsListQuery, VendorGraphPaginatedFragment$key>(
paginatedVendorsFragment,
data.node as VendorGraphPaginatedFragment$key,
);

View File

@@ -67,7 +67,6 @@ const complianceReportFragment = graphql`
reportName
file {
fileName
mimeType
size
downloadUrl
}

View File

@@ -71,8 +71,6 @@ const contactFragment = graphql`
email
phone
role
createdAt
updatedAt
canUpdate: permission(action: "core:vendor-contact:update")
canDelete: permission(action: "core:vendor-contact:delete")
}

View File

@@ -40,7 +40,6 @@ const vendorBusinessAssociateAgreementFragment = graphql`
fileUrl
validFrom
validUntil
createdAt
canUpdate: permission(
action: "core:vendor-business-associate-agreement:update"
)
@@ -59,7 +58,6 @@ const vendorDataPrivacyAgreementFragment = graphql`
fileUrl
validFrom
validUntil
createdAt
canUpdate: permission(action: "core:vendor-data-privacy-agreement:update")
canDelete: permission(action: "core:vendor-data-privacy-agreement:delete")
}

View File

@@ -69,8 +69,6 @@ const serviceFragment = graphql`
id
name
description
createdAt
updatedAt
canUpdate: permission(action: "core:vendor-service:update")
canDelete: permission(action: "core:vendor-service:delete")
}