From 4921b888eb397d2008d769c878b63cc17b51495f Mon Sep 17 00:00:00 2001
From: GaelFerrand <45355989+GaelFerrand@users.noreply.github.com>
Date: Fri, 11 Oct 2024 14:58:00 +0200
Subject: [PATCH] =?UTF-8?q?[TRA-15092]=20ETQ=20utilisateur=20je=20peux=20c?=
=?UTF-8?q?r=C3=A9er,=20r=C3=A9voquer=20et=20consulter=20mes=20demandes=20?=
=?UTF-8?q?de=20d=C3=A9l=C3=A9gation=20RNDTS=20(#3588)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* feat: implemented create endpoint
* feat: added endpoint rndtsDeclarationDelegation
* refacto: improved condition check on overlap + tests
* refacto
* feat: checking that delegator & delegate are different
* feat: small opti on queries
* refacto: making endpoints session only
* feat: removed isDeleted, using isRevoked instead + added status sub-resolver
* feat: cleaned up dates to midnight
* feat: huge refactoring, nesting companies within delegation + started revoke endpoint
* test: added test for revocation
* fix: fixed tests
* feat: added endpoints delegationS
* fix: fixes & refacto
* fix: fixed test
* fix: moved delegate & delegator to subResolvers + dates fixing to zod only
* fix: changing where.id to where.orgId
* feat: started implemeting front
* fix: submitting create form
* fix: using .nullish() instead of .optional()
* feat: added prisma migration script
* feat: started implementing lists
* feat: starting table pagination. need backend fix first
* feat: changed pagination args
* feat: polishes the table
* feat: added revoke
* feat: trying to fix test
* fix: trying to fix tests
* fix: fixing typing issues due to sub-resolvers
* fix: let's chill on the capslock
* fix: trying to fix subresolvers (isDormant error)
* feat: adding created delegation to table
* feat: added givenName to CompanyPublic
* feat: displaying givenName
* feat: sending email on creation. Needing content though
* fix: displaying error message on required for delegatorId (companySelector)
* feat: added email content. Still some details missing
* fix: lint
* feat: added feature flag on companies
* feat: not showing action buttons to non-admins
* fix: fixes after reviews with the bowss
* fix: fixed email with links
* fix: fixed permissions using can()
* fix: renamed rndtsDeclarationDelegation -> registryDelegation
* feat: re-generated migration script with new name registryDelegation
* feat: added events in repository methods
* lint: format
* feat: renamed rndtsDeclarationDelegation -> registryDelegation
* fix: PR review fixes
* feat: added endDate in mail
---
front/src/Apps/Companies/CompanyDetails.tsx | 19 +-
.../CompanyRegistryDelegation.tsx | 18 ++
.../CompanyRegistryDelegationAsDelegate.tsx | 23 ++
.../CompanyRegistryDelegationAsDelegator.tsx | 54 ++++
.../CreateRegistryDelegationModal.tsx | 231 +++++++++++++++++
.../RegistryDelegationsTable.tsx | 234 ++++++++++++++++++
.../RevokeRegistryDelegationModal.tsx | 95 +++++++
.../companyRegistryDelegation.scss | 17 ++
.../Creation/bspaoh/steps/Destination.tsx | 2 +-
.../queries/registryDelegation/queries.ts | 68 +++++
10 files changed, 757 insertions(+), 4 deletions(-)
create mode 100644 front/src/Apps/Companies/CompanyRegistryDelegation/CompanyRegistryDelegation.tsx
create mode 100644 front/src/Apps/Companies/CompanyRegistryDelegation/CompanyRegistryDelegationAsDelegate.tsx
create mode 100644 front/src/Apps/Companies/CompanyRegistryDelegation/CompanyRegistryDelegationAsDelegator.tsx
create mode 100644 front/src/Apps/Companies/CompanyRegistryDelegation/CreateRegistryDelegationModal.tsx
create mode 100644 front/src/Apps/Companies/CompanyRegistryDelegation/RegistryDelegationsTable.tsx
create mode 100644 front/src/Apps/Companies/CompanyRegistryDelegation/RevokeRegistryDelegationModal.tsx
create mode 100644 front/src/Apps/Companies/CompanyRegistryDelegation/companyRegistryDelegation.scss
create mode 100644 front/src/Apps/common/queries/registryDelegation/queries.ts
diff --git a/front/src/Apps/Companies/CompanyDetails.tsx b/front/src/Apps/Companies/CompanyDetails.tsx
index bd8f678dbc..da2ff5bdaa 100644
--- a/front/src/Apps/Companies/CompanyDetails.tsx
+++ b/front/src/Apps/Companies/CompanyDetails.tsx
@@ -22,11 +22,14 @@ import CompanyMembers from "./CompanyMembers/CompanyMembers";
import CompanyDigestSheetForm from "./CompanyDigestSheet/CompanyDigestSheet";
import { Tabs, TabsProps } from "@codegouvfr/react-dsfr/Tabs";
import { FrIconClassName } from "@codegouvfr/react-dsfr";
+import { CompanyRegistryDelegation } from "./CompanyRegistryDelegation/CompanyRegistryDelegation";
export type TabContentProps = {
company: CompanyPrivate;
};
+const REGISTRY_V2_FLAG = "REGISTRY_V2";
+
const buildTabs = (
company: CompanyPrivate
): {
@@ -35,6 +38,9 @@ const buildTabs = (
} => {
const isAdmin = company.userRole === UserRole.Admin;
+ // RNDTS features protected by feature flag
+ const canViewRndtsFeatures = company.featureFlags.includes(REGISTRY_V2_FLAG);
+
const iconId = "fr-icon-checkbox-line" as FrIconClassName;
const tabs = [
{
@@ -70,14 +76,21 @@ const buildTabs = (
tab4: CompanyContactForm,
tab5: CompanyDigestSheetForm
};
-
- if (isAdmin) {
+ if (canViewRndtsFeatures) {
tabs.push({
tabId: "tab6",
+ label: "Délégations RNDTS",
+ iconId
+ });
+ tabsContent["tab6"] = CompanyRegistryDelegation;
+ }
+ if (isAdmin) {
+ tabs.push({
+ tabId: "tab7",
label: "Avancé",
iconId
});
- tabsContent["tab6"] = CompanyAdvanced;
+ tabsContent["tab7"] = CompanyAdvanced;
}
return { tabs, tabsContent };
diff --git a/front/src/Apps/Companies/CompanyRegistryDelegation/CompanyRegistryDelegation.tsx b/front/src/Apps/Companies/CompanyRegistryDelegation/CompanyRegistryDelegation.tsx
new file mode 100644
index 0000000000..1443d70d09
--- /dev/null
+++ b/front/src/Apps/Companies/CompanyRegistryDelegation/CompanyRegistryDelegation.tsx
@@ -0,0 +1,18 @@
+import React from "react";
+import "./companyRegistryDelegation.scss";
+import { CompanyPrivate } from "@td/codegen-ui";
+import { CompanyRegistryDelegationAsDelegator } from "./CompanyRegistryDelegationAsDelegator";
+import { CompanyRegistryDelegationAsDelegate } from "./CompanyRegistryDelegationAsDelegate";
+
+interface Props {
+ company: CompanyPrivate;
+}
+
+export const CompanyRegistryDelegation = ({ company }: Props) => {
+ return (
+ <>
+
+
+ >
+ );
+};
diff --git a/front/src/Apps/Companies/CompanyRegistryDelegation/CompanyRegistryDelegationAsDelegate.tsx b/front/src/Apps/Companies/CompanyRegistryDelegation/CompanyRegistryDelegationAsDelegate.tsx
new file mode 100644
index 0000000000..5e7087ebd3
--- /dev/null
+++ b/front/src/Apps/Companies/CompanyRegistryDelegation/CompanyRegistryDelegationAsDelegate.tsx
@@ -0,0 +1,23 @@
+import React from "react";
+import "./companyRegistryDelegation.scss";
+import { CompanyPrivate } from "@td/codegen-ui";
+import { RegistryDelegationsTable } from "./RegistryDelegationsTable";
+
+interface Props {
+ company: CompanyPrivate;
+}
+
+export const CompanyRegistryDelegationAsDelegate = ({ company }: Props) => {
+ return (
+ <>
+
Délégataires
+
+ Les entreprises ci-dessous m'autorisent à faire leurs déclarations au
+ Registre National des Déchets, Terres Excavées et Sédiments (RNDTS)
+
+
+
+
+ >
+ );
+};
diff --git a/front/src/Apps/Companies/CompanyRegistryDelegation/CompanyRegistryDelegationAsDelegator.tsx b/front/src/Apps/Companies/CompanyRegistryDelegation/CompanyRegistryDelegationAsDelegator.tsx
new file mode 100644
index 0000000000..4758d8901b
--- /dev/null
+++ b/front/src/Apps/Companies/CompanyRegistryDelegation/CompanyRegistryDelegationAsDelegator.tsx
@@ -0,0 +1,54 @@
+import React, { useState } from "react";
+import "./companyRegistryDelegation.scss";
+import { CompanyPrivate, UserRole } from "@td/codegen-ui";
+import Button from "@codegouvfr/react-dsfr/Button";
+import { CreateRegistryDelegationModal } from "./CreateRegistryDelegationModal";
+import { RegistryDelegationsTable } from "./RegistryDelegationsTable";
+
+interface Props {
+ company: CompanyPrivate;
+}
+
+export const CompanyRegistryDelegationAsDelegator = ({ company }: Props) => {
+ const isAdmin = company.userRole === UserRole.Admin;
+
+ const [isModalOpen, setIsModalOpen] = useState(false);
+
+ return (
+ <>
+ Délégations
+
+ J'autorise les entreprises ci-dessous à faire mes déclarations au
+ Registre National des Déchets, Terres Excavées et Sédiments (RNDTS)
+
+
+ {isAdmin && (
+
+
+
+ )}
+
+
+
+
+
+ setIsModalOpen(false)}
+ />
+ >
+ );
+};
diff --git a/front/src/Apps/Companies/CompanyRegistryDelegation/CreateRegistryDelegationModal.tsx b/front/src/Apps/Companies/CompanyRegistryDelegation/CreateRegistryDelegationModal.tsx
new file mode 100644
index 0000000000..7aea16b09e
--- /dev/null
+++ b/front/src/Apps/Companies/CompanyRegistryDelegation/CreateRegistryDelegationModal.tsx
@@ -0,0 +1,231 @@
+import React from "react";
+import {
+ CompanyPrivate,
+ Mutation,
+ MutationCreateRegistryDelegationArgs
+} from "@td/codegen-ui";
+import { FieldError, useForm } from "react-hook-form";
+import { Modal } from "../../../common/components";
+import CompanySelectorWrapper from "../../common/Components/CompanySelectorWrapper/CompanySelectorWrapper";
+import Input from "@codegouvfr/react-dsfr/Input";
+import Button from "@codegouvfr/react-dsfr/Button";
+import { zodResolver } from "@hookform/resolvers/zod";
+import { z } from "zod";
+import { isSiret } from "@td/constants";
+import { datetimeToYYYYMMDD } from "../../Dashboard/Validation/BSPaoh/paohUtils";
+import { startOfDay } from "date-fns";
+import { useMutation } from "@apollo/client";
+import {
+ CREATE_REGISTRY_DELEGATION,
+ REGISTRY_DELEGATIONS
+} from "../../common/queries/registryDelegation/queries";
+import toast from "react-hot-toast";
+
+const displayError = (error: FieldError | undefined) => {
+ return error ? <>{error.message}> : null;
+};
+
+const getSchema = () =>
+ z
+ .object({
+ delegateOrgId: z
+ .string({ required_error: "Ce champ est requis" })
+ .refine(isSiret, "Siret non valide"),
+ startDate: z.coerce
+ .date({
+ required_error: "La date de début est requise",
+ invalid_type_error: "La date de début est invalide"
+ })
+ .min(startOfDay(new Date()), {
+ message: "La date de début ne peut pas être dans le passé"
+ })
+ .transform(val => val.toISOString())
+ .nullish(),
+ // Date & "" hack: https://github.com/colinhacks/zod/issues/1721
+ endDate: z.preprocess(
+ arg => (arg === "" ? null : arg),
+ z.coerce
+ .date({
+ invalid_type_error: "La date de fin est invalide"
+ })
+ .min(new Date(), {
+ message: "La date de fin ne peut pas être dans le passé"
+ })
+ .transform(val => {
+ if (val) return val.toISOString();
+ return val;
+ })
+ .nullish()
+ ),
+ comment: z.string().max(500).optional()
+ })
+ .refine(
+ data => {
+ const { startDate, endDate } = data;
+
+ if (startDate && endDate) {
+ return new Date(startDate) < new Date(endDate);
+ }
+
+ return true;
+ },
+ {
+ path: ["startDate"],
+ message: "La date de début doit être avant la date de fin."
+ }
+ );
+
+interface Props {
+ company: CompanyPrivate;
+ isOpen: boolean;
+ onClose: () => void;
+}
+
+export const CreateRegistryDelegationModal = ({
+ company,
+ onClose,
+ isOpen
+}: Props) => {
+ const [createRegistryDelegation, { loading }] = useMutation<
+ Pick,
+ MutationCreateRegistryDelegationArgs
+ >(CREATE_REGISTRY_DELEGATION, {
+ refetchQueries: [REGISTRY_DELEGATIONS]
+ });
+
+ const validationSchema = getSchema();
+ const {
+ register,
+ handleSubmit,
+ setValue,
+ watch,
+ reset,
+ formState: { errors, isSubmitting }
+ } = useForm>({
+ defaultValues: {
+ startDate: datetimeToYYYYMMDD(new Date())
+ },
+ resolver: zodResolver(validationSchema)
+ });
+
+ const closeModal = () => {
+ reset();
+ onClose();
+ };
+
+ const onSubmit = async input => {
+ await createRegistryDelegation({
+ variables: {
+ input: {
+ ...input,
+ delegatorOrgId: company.orgId
+ }
+ },
+ onCompleted: () => toast.success("Délégation créée!"),
+ onError: err => toast.error(err.message)
+ });
+
+ closeModal();
+ };
+
+ const delegateOrgId = watch("delegateOrgId") ?? {};
+
+ const isLoading = loading || isSubmitting;
+
+ return (
+
+
+
+ );
+};
diff --git a/front/src/Apps/Companies/CompanyRegistryDelegation/RegistryDelegationsTable.tsx b/front/src/Apps/Companies/CompanyRegistryDelegation/RegistryDelegationsTable.tsx
new file mode 100644
index 0000000000..7146e31b65
--- /dev/null
+++ b/front/src/Apps/Companies/CompanyRegistryDelegation/RegistryDelegationsTable.tsx
@@ -0,0 +1,234 @@
+import React, { useState } from "react";
+import {
+ CompanyPrivate,
+ Query,
+ QueryRegistryDelegationsArgs,
+ RegistryDelegation,
+ RegistryDelegationStatus,
+ UserRole
+} from "@td/codegen-ui";
+import { isDefinedStrict } from "../../../common/helper";
+import { formatDateViewDisplay } from "../common/utils";
+import Pagination from "@codegouvfr/react-dsfr/Pagination";
+import "./companyRegistryDelegation.scss";
+import { useQuery } from "@apollo/client";
+import { REGISTRY_DELEGATIONS } from "../../common/queries/registryDelegation/queries";
+import Button from "@codegouvfr/react-dsfr/Button";
+import { RevokeRegistryDelegationModal } from "./RevokeRegistryDelegationModal";
+import Badge from "@codegouvfr/react-dsfr/Badge";
+import { AlertProps } from "@codegouvfr/react-dsfr/Alert";
+
+const getStatusLabel = (status: RegistryDelegationStatus) => {
+ switch (status) {
+ case RegistryDelegationStatus.Ongoing:
+ return "EN COURS";
+ case RegistryDelegationStatus.Incoming:
+ return "À VENIR";
+ case RegistryDelegationStatus.Closed:
+ return "CLÔTURÉE";
+ }
+};
+
+const getStatusBadge = (status: RegistryDelegationStatus) => {
+ let severity: AlertProps.Severity = "success";
+ if (status === RegistryDelegationStatus.Incoming) severity = "info";
+ if (status === RegistryDelegationStatus.Closed) severity = "error";
+
+ return (
+
+ {getStatusLabel(status)}
+
+ );
+};
+
+const getTextTooltip = (id: string, value: string | undefined | null) => {
+ return (
+
+ {value}
+
+ );
+};
+
+interface Props {
+ as: "delegator" | "delegate";
+ company: CompanyPrivate;
+}
+
+export const RegistryDelegationsTable = ({ as, company }: Props) => {
+ const [pageIndex, setPageIndex] = useState(0);
+ const [delegationToRevoke, setDelegationToRevoke] =
+ useState(null);
+
+ const isAdmin = company.userRole === UserRole.Admin;
+
+ const { data, loading, refetch } = useQuery<
+ Pick,
+ QueryRegistryDelegationsArgs
+ >(REGISTRY_DELEGATIONS, {
+ skip: !company.orgId,
+ fetchPolicy: "network-only",
+ variables: {
+ where:
+ as === "delegate"
+ ? { delegateOrgId: company.orgId }
+ : { delegatorOrgId: company.orgId }
+ }
+ });
+
+ const totalCount = data?.registryDelegations.totalCount;
+ const delegations =
+ data?.registryDelegations.edges.map(edge => edge.node) ?? [];
+
+ const PAGE_SIZE = 10;
+ const pageCount = totalCount ? Math.ceil(totalCount / PAGE_SIZE) : 0;
+
+ const gotoPage = (page: number) => {
+ setPageIndex(page);
+
+ refetch({
+ skip: page * PAGE_SIZE,
+ first: PAGE_SIZE
+ });
+ };
+
+ return (
+
+
+
+
+
+
+
+
+ Établissement
+ |
+ Siret |
+ Objet |
+ Début |
+ Fin |
+ Statut |
+ {isAdmin && Révoquer | }
+
+
+
+ {delegations.map(delegation => {
+ const {
+ id,
+ delegate,
+ delegator,
+ startDate,
+ endDate,
+ comment,
+ status
+ } = delegation;
+
+ const company = as === "delegate" ? delegator : delegate;
+
+ const name = isDefinedStrict(company.givenName)
+ ? company.givenName
+ : company.name;
+
+ return (
+
+
+ {name}
+
+ {getTextTooltip(
+ `company-name-${company.orgId}-${as}`,
+ `${name} ${
+ company.givenName ? `(${company.name})` : ""
+ }`
+ )}
+ |
+ {company?.orgId} |
+
+ {isDefinedStrict(comment) ? (
+ <>
+ {comment}
+ {getTextTooltip(
+ `company-comment-${company.orgId}-${as}`,
+ comment
+ )}
+ >
+ ) : (
+ "-"
+ )}
+ |
+ {formatDateViewDisplay(startDate)} |
+
+ {endDate ? formatDateViewDisplay(endDate) : "Illimité"}
+ |
+ {getStatusBadge(status)} |
+ {isAdmin && (
+
+ {status !== RegistryDelegationStatus.Closed && (
+
+ )}
+ |
+ )}
+
+ );
+ })}
+
+ {loading && Chargement...
}
+ {!loading && !delegations.length && (
+ Aucune délégation
+ )}
+
+
+
+
+
+
+
+
({
+ onClick: event => {
+ event.preventDefault();
+ gotoPage(pageNumber - 1);
+ },
+ href: "#",
+ key: `pagination-link-${pageNumber}`
+ })}
+ className={"fr-mt-1w"}
+ />
+
+
+ {delegationToRevoke && (
+
setDelegationToRevoke(null)}
+ />
+ )}
+
+ );
+};
diff --git a/front/src/Apps/Companies/CompanyRegistryDelegation/RevokeRegistryDelegationModal.tsx b/front/src/Apps/Companies/CompanyRegistryDelegation/RevokeRegistryDelegationModal.tsx
new file mode 100644
index 0000000000..f46a070aaa
--- /dev/null
+++ b/front/src/Apps/Companies/CompanyRegistryDelegation/RevokeRegistryDelegationModal.tsx
@@ -0,0 +1,95 @@
+import React from "react";
+import { Mutation, MutationRevokeRegistryDelegationArgs } from "@td/codegen-ui";
+import { Modal } from "../../../common/components";
+import Button from "@codegouvfr/react-dsfr/Button";
+import { useMutation } from "@apollo/client";
+import { REVOKE_REGISTRY_DELEGATION } from "../../common/queries/registryDelegation/queries";
+import toast from "react-hot-toast";
+import { isDefined } from "../../../common/helper";
+
+const WarningIcon = () => (
+
+);
+
+interface Props {
+ delegationId: string;
+ to: string | null | undefined;
+ from: string | null | undefined;
+ onClose: () => void;
+}
+
+export const RevokeRegistryDelegationModal = ({
+ delegationId,
+ to,
+ from,
+ onClose
+}: Props) => {
+ const [revokeRegistryDelegation, { loading }] = useMutation<
+ Pick,
+ MutationRevokeRegistryDelegationArgs
+ >(REVOKE_REGISTRY_DELEGATION);
+
+ const onRevoke = async () => {
+ await revokeRegistryDelegation({
+ variables: {
+ delegationId
+ },
+ onCompleted: () => toast.success("Délégation révoquée!"),
+ onError: err => toast.error(err.message)
+ });
+
+ // Delegation is automatically updated in Apollo's cache
+ onClose();
+ };
+
+ // Wording changes if delegator or delegate
+ let title = "Révoquer la délégation";
+ let content = `Vous vous apprêtez à révoquer la délégation pour ${to}.`;
+ let acceptLabel = "Révoquer";
+ let refuseLabel = "Ne pas révoquer";
+ let closeModalLabel = "Ne pas révoquer";
+
+ if (isDefined(from)) {
+ title = "Annuler la délégation";
+ content = `Vous vous apprêtez à annuler la délégation de ${from}.`;
+ acceptLabel = "Annuler";
+ refuseLabel = "Ne pas annuler";
+ closeModalLabel = "Ne pas annuler";
+ }
+
+ return (
+
+
+
+ {title}
+
+
+
{content}
+
+
+
+
+
+
+
+ );
+};
diff --git a/front/src/Apps/Companies/CompanyRegistryDelegation/companyRegistryDelegation.scss b/front/src/Apps/Companies/CompanyRegistryDelegation/companyRegistryDelegation.scss
new file mode 100644
index 0000000000..5a7c9f39f1
--- /dev/null
+++ b/front/src/Apps/Companies/CompanyRegistryDelegation/companyRegistryDelegation.scss
@@ -0,0 +1,17 @@
+h4 {
+ font-size: 1.5rem; //24px;
+ font-weight: 700;
+ margin: 0;
+ padding: 0;
+ margin-bottom: 2vh;
+}
+
+.delegations-table {
+ th,
+ td {
+ max-width: 200px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+}
diff --git a/front/src/Apps/Dashboard/Creation/bspaoh/steps/Destination.tsx b/front/src/Apps/Dashboard/Creation/bspaoh/steps/Destination.tsx
index cd30c6aa30..347b56004c 100644
--- a/front/src/Apps/Dashboard/Creation/bspaoh/steps/Destination.tsx
+++ b/front/src/Apps/Dashboard/Creation/bspaoh/steps/Destination.tsx
@@ -98,7 +98,7 @@ export function Destination({ errors }) {
);
const selectedCompanyError = (company?: CompanySearchResult) => {
- // Le destinatiare doi être inscrit et avec un profil crématorium ou sous-type crémation
+ // Le destinatiare doit être inscrit et avec un profil crématorium ou sous-type crémation
// Le profil crématorium sera bientôt supprimé
if (company) {
if (!company.isRegistered) {
diff --git a/front/src/Apps/common/queries/registryDelegation/queries.ts b/front/src/Apps/common/queries/registryDelegation/queries.ts
new file mode 100644
index 0000000000..2e341cfbbb
--- /dev/null
+++ b/front/src/Apps/common/queries/registryDelegation/queries.ts
@@ -0,0 +1,68 @@
+import { gql } from "@apollo/client";
+
+export const CREATE_REGISTRY_DELEGATION = gql`
+ mutation createRegistryDelegation($input: CreateRegistryDelegationInput!) {
+ createRegistryDelegation(input: $input) {
+ id
+ updatedAt
+ delegate {
+ orgId
+ }
+ delegator {
+ orgId
+ }
+ startDate
+ endDate
+ comment
+ status
+ }
+ }
+`;
+
+export const REGISTRY_DELEGATIONS = gql`
+ query registryDelegations(
+ $skip: Int
+ $first: Int
+ $where: RegistryDelegationWhere
+ ) {
+ registryDelegations(skip: $skip, first: $first, where: $where) {
+ totalCount
+ pageInfo {
+ startCursor
+ endCursor
+ hasNextPage
+ hasPreviousPage
+ }
+ edges {
+ node {
+ id
+ updatedAt
+ delegate {
+ name
+ givenName
+ orgId
+ }
+ delegator {
+ name
+ givenName
+ orgId
+ }
+ startDate
+ endDate
+ comment
+ status
+ }
+ }
+ }
+ }
+`;
+
+export const REVOKE_REGISTRY_DELEGATION = gql`
+ mutation revokeRegistryDelegation($delegationId: ID!) {
+ revokeRegistryDelegation(delegationId: $delegationId) {
+ id
+ isRevoked
+ status
+ }
+ }
+`;