Fix invitations totalCount update

Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
Émile Ré
2026-01-05 19:50:14 +01:00
committed by Bryan Frimin
parent 1cf4d6125a
commit f8accc2d40
11 changed files with 209 additions and 215 deletions

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<d415b10cc562b5554452cc3ed15bc31e>> * @generated SignedSource<<26877e6a0dc423e87108c5b2ea1b11a3>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -20,7 +20,6 @@ export type InvitationListFragment$data = {
readonly " $fragmentSpreads": FragmentRefs<"InvitationListItemFragment">; readonly " $fragmentSpreads": FragmentRefs<"InvitationListItemFragment">;
}; };
}>; }>;
readonly totalCount: number | null | undefined;
}; };
readonly " $fragmentType": "InvitationListFragment"; readonly " $fragmentType": "InvitationListFragment";
}; };
@@ -123,13 +122,6 @@ return {
"name": "__InvitationListFragment_invitations_connection", "name": "__InvitationListFragment_invitations_connection",
"plural": false, "plural": false,
"selections": [ "selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "totalCount",
"storageKey": null
},
{ {
"kind": "RequiredField", "kind": "RequiredField",
"field": { "field": {
@@ -239,6 +231,6 @@ return {
}; };
})(); })();
(node as any).hash = "d6f8750bb89b233418c3a66669c4aa23"; (node as any).hash = "224d655216572cb18f193cdfcae64172";
export default node; export default node;

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<23d03caf79ac153cc19aae8e87c38a27>> * @generated SignedSource<<d5f15badabf09f653790f78494c229fe>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -198,13 +198,6 @@ return {
"name": "invitations", "name": "invitations",
"plural": false, "plural": false,
"selections": [ "selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "totalCount",
"storageKey": null
},
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -373,16 +366,16 @@ return {
] ]
}, },
"params": { "params": {
"cacheID": "2f419e2fcb92f5a188dcd35ff5661fd7", "cacheID": "afc5598fd9e211b2e7af8ac8bce27511",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "InvitationListFragment_RefetchQuery", "name": "InvitationListFragment_RefetchQuery",
"operationKind": "query", "operationKind": "query",
"text": "query InvitationListFragment_RefetchQuery(\n $after: CursorKey = null\n $before: CursorKey = null\n $first: Int = 20\n $last: Int = null\n $order: InvitationOrder = {direction: ASC, field: CREATED_AT}\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...InvitationListFragment_16fISc\n id\n }\n}\n\nfragment InvitationListFragment_16fISc on Organization {\n invitations(first: $first, after: $after, last: $last, before: $before, orderBy: $order) {\n totalCount\n edges {\n node {\n id\n ...InvitationListItemFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n\nfragment InvitationListItemFragment on Invitation {\n id\n fullName\n email\n role\n status\n createdAt\n expiresAt\n acceptedAt\n canDelete: permission(action: \"iam:invitation:delete\")\n}\n" "text": "query InvitationListFragment_RefetchQuery(\n $after: CursorKey = null\n $before: CursorKey = null\n $first: Int = 20\n $last: Int = null\n $order: InvitationOrder = {direction: ASC, field: CREATED_AT}\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...InvitationListFragment_16fISc\n id\n }\n}\n\nfragment InvitationListFragment_16fISc on Organization {\n invitations(first: $first, after: $after, last: $last, before: $before, orderBy: $order) {\n edges {\n node {\n id\n ...InvitationListItemFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n\nfragment InvitationListItemFragment on Invitation {\n id\n fullName\n email\n role\n status\n createdAt\n expiresAt\n acceptedAt\n canDelete: permission(action: \"iam:invitation:delete\")\n}\n"
} }
}; };
})(); })();
(node as any).hash = "d6f8750bb89b233418c3a66669c4aa23"; (node as any).hash = "224d655216572cb18f193cdfcae64172";
export default node; export default node;

View File

@@ -1,60 +0,0 @@
/**
* @generated SignedSource<<de896a2d4f3d1dce06f7b88630afb445>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ReaderFragment } from 'relay-runtime';
export type MembershipRole = "ADMIN" | "AUDITOR" | "EMPLOYEE" | "OWNER" | "VIEWER";
import { FragmentRefs } from "relay-runtime";
export type InviteUserDialog_currentRoleFragment$data = {
readonly viewerMembership: {
readonly role: MembershipRole;
};
readonly " $fragmentType": "InviteUserDialog_currentRoleFragment";
};
export type InviteUserDialog_currentRoleFragment$key = {
readonly " $data"?: InviteUserDialog_currentRoleFragment$data;
readonly " $fragmentSpreads": FragmentRefs<"InviteUserDialog_currentRoleFragment">;
};
const node: ReaderFragment = {
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
"name": "InviteUserDialog_currentRoleFragment",
"selections": [
{
"kind": "RequiredField",
"field": {
"alias": null,
"args": null,
"concreteType": "Membership",
"kind": "LinkedField",
"name": "viewerMembership",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "role",
"storageKey": null
}
],
"storageKey": null
},
"action": "THROW"
}
],
"type": "Organization",
"abstractKey": null
};
(node as any).hash = "167528734d4ad650128d5ed8f201c97e";
export default node;

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<d7435d1c1ee31d5ddc186fd67fa9401f>> * @generated SignedSource<<4d9333564d383b3af80a4d6c2ce68277>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -18,12 +18,13 @@ export type MembersPageQuery$data = {
readonly __typename: "Organization"; readonly __typename: "Organization";
readonly canInviteUser: boolean; readonly canInviteUser: boolean;
readonly invitations: { readonly invitations: {
readonly $updatableFragmentSpreads: FragmentRefs<"MembersPage_invitationsTotalCountFragment">;
readonly totalCount: number | null | undefined; readonly totalCount: number | null | undefined;
}; };
readonly members: { readonly members: {
readonly totalCount: number | null | undefined; readonly totalCount: number | null | undefined;
}; };
readonly " $fragmentSpreads": FragmentRefs<"InvitationListFragment" | "InviteUserDialog_currentRoleFragment" | "MemberListFragment">; readonly " $fragmentSpreads": FragmentRefs<"InvitationListFragment" | "MemberListFragment">;
} | { } | {
// This will never be '%other', but we need some // This will never be '%other', but we need some
// value in case none of the concrete values match. // value in case none of the concrete values match.
@@ -58,41 +59,6 @@ v2 = {
"storageKey": null "storageKey": null
}, },
v3 = { v3 = {
"kind": "Literal",
"name": "first",
"value": 20
},
v4 = {
"direction": "ASC",
"field": "CREATED_AT"
},
v5 = [
(v3/*: any*/),
{
"kind": "Literal",
"name": "order",
"value": (v4/*: any*/)
}
],
v6 = [
(v3/*: any*/),
{
"kind": "Literal",
"name": "orderBy",
"value": (v4/*: any*/)
}
],
v7 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "totalCount",
"storageKey": null
},
v8 = [
(v7/*: any*/)
],
v9 = {
"alias": "canInviteUser", "alias": "canInviteUser",
"args": [ "args": [
{ {
@@ -105,49 +71,81 @@ v9 = {
"name": "permission", "name": "permission",
"storageKey": "permission(action:\"iam:invitation:create\")" "storageKey": "permission(action:\"iam:invitation:create\")"
}, },
v10 = { v4 = {
"kind": "Literal",
"name": "first",
"value": 20
},
v5 = {
"direction": "ASC",
"field": "CREATED_AT"
},
v6 = [
(v4/*: any*/),
{
"kind": "Literal",
"name": "order",
"value": (v5/*: any*/)
}
],
v7 = [
(v4/*: any*/),
{
"kind": "Literal",
"name": "orderBy",
"value": (v5/*: any*/)
}
],
v8 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "totalCount",
"storageKey": null
},
v9 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "id", "name": "id",
"storageKey": null "storageKey": null
}, },
v11 = { v10 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "role", "name": "role",
"storageKey": null "storageKey": null
}, },
v12 = { v11 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "fullName", "name": "fullName",
"storageKey": null "storageKey": null
}, },
v13 = { v12 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "email", "name": "email",
"storageKey": null "storageKey": null
}, },
v14 = { v13 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "createdAt", "name": "createdAt",
"storageKey": null "storageKey": null
}, },
v15 = { v14 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "cursor", "name": "cursor",
"storageKey": null "storageKey": null
}, },
v16 = { v15 = {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PageInfo", "concreteType": "PageInfo",
@@ -186,7 +184,7 @@ v16 = {
], ],
"storageKey": null "storageKey": null
}, },
v17 = { v16 = {
"kind": "ClientExtension", "kind": "ClientExtension",
"selections": [ "selections": [
{ {
@@ -198,7 +196,7 @@ v17 = {
} }
] ]
}, },
v18 = [ v17 = [
"orderBy" "orderBy"
]; ];
return { return {
@@ -222,13 +220,9 @@ return {
{ {
"kind": "InlineFragment", "kind": "InlineFragment",
"selections": [ "selections": [
(v3/*: any*/),
{ {
"args": null, "args": (v6/*: any*/),
"kind": "FragmentSpread",
"name": "InviteUserDialog_currentRoleFragment"
},
{
"args": (v5/*: any*/),
"kind": "FragmentSpread", "kind": "FragmentSpread",
"name": "MemberListFragment" "name": "MemberListFragment"
}, },
@@ -236,18 +230,20 @@ return {
"kind": "RequiredField", "kind": "RequiredField",
"field": { "field": {
"alias": null, "alias": null,
"args": (v6/*: any*/), "args": (v7/*: any*/),
"concreteType": "MembershipConnection", "concreteType": "MembershipConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "members", "name": "members",
"plural": false, "plural": false,
"selections": (v8/*: any*/), "selections": [
(v8/*: any*/)
],
"storageKey": "members(first:20,orderBy:{\"direction\":\"ASC\",\"field\":\"CREATED_AT\"})" "storageKey": "members(first:20,orderBy:{\"direction\":\"ASC\",\"field\":\"CREATED_AT\"})"
}, },
"action": "THROW" "action": "THROW"
}, },
{ {
"args": (v5/*: any*/), "args": (v6/*: any*/),
"kind": "FragmentSpread", "kind": "FragmentSpread",
"name": "InvitationListFragment" "name": "InvitationListFragment"
}, },
@@ -255,17 +251,23 @@ return {
"kind": "RequiredField", "kind": "RequiredField",
"field": { "field": {
"alias": null, "alias": null,
"args": (v6/*: any*/), "args": (v7/*: any*/),
"concreteType": "InvitationConnection", "concreteType": "InvitationConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "invitations", "name": "invitations",
"plural": false, "plural": false,
"selections": (v8/*: any*/), "selections": [
(v8/*: any*/),
{
"args": null,
"kind": "FragmentSpread",
"name": "MembersPage_invitationsTotalCountFragment"
}
],
"storageKey": "invitations(first:20,orderBy:{\"direction\":\"ASC\",\"field\":\"CREATED_AT\"})" "storageKey": "invitations(first:20,orderBy:{\"direction\":\"ASC\",\"field\":\"CREATED_AT\"})"
}, },
"action": "THROW" "action": "THROW"
}, }
(v9/*: any*/)
], ],
"type": "Organization", "type": "Organization",
"abstractKey": null "abstractKey": null
@@ -294,32 +296,20 @@ return {
"plural": false, "plural": false,
"selections": [ "selections": [
(v2/*: any*/), (v2/*: any*/),
(v10/*: any*/), (v9/*: any*/),
{ {
"kind": "InlineFragment", "kind": "InlineFragment",
"selections": [ "selections": [
(v3/*: any*/),
{ {
"alias": null, "alias": null,
"args": null, "args": (v7/*: any*/),
"concreteType": "Membership",
"kind": "LinkedField",
"name": "viewerMembership",
"plural": false,
"selections": [
(v11/*: any*/),
(v10/*: any*/)
],
"storageKey": null
},
{
"alias": null,
"args": (v6/*: any*/),
"concreteType": "MembershipConnection", "concreteType": "MembershipConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "members", "name": "members",
"plural": false, "plural": false,
"selections": [ "selections": [
(v7/*: any*/), (v8/*: any*/),
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -336,8 +326,8 @@ return {
"name": "node", "name": "node",
"plural": false, "plural": false,
"selections": [ "selections": [
(v9/*: any*/),
(v10/*: any*/), (v10/*: any*/),
(v11/*: any*/),
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -360,8 +350,8 @@ return {
"name": "profile", "name": "profile",
"plural": false, "plural": false,
"selections": [ "selections": [
(v12/*: any*/), (v11/*: any*/),
(v10/*: any*/) (v9/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
@@ -373,12 +363,12 @@ return {
"name": "identity", "name": "identity",
"plural": false, "plural": false,
"selections": [ "selections": [
(v13/*: any*/), (v12/*: any*/),
(v10/*: any*/) (v9/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
(v14/*: any*/), (v13/*: any*/),
{ {
"alias": "canUpdate", "alias": "canUpdate",
"args": [ "args": [
@@ -409,19 +399,19 @@ return {
], ],
"storageKey": null "storageKey": null
}, },
(v15/*: any*/) (v14/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
(v16/*: any*/), (v15/*: any*/),
(v17/*: any*/) (v16/*: any*/)
], ],
"storageKey": "members(first:20,orderBy:{\"direction\":\"ASC\",\"field\":\"CREATED_AT\"})" "storageKey": "members(first:20,orderBy:{\"direction\":\"ASC\",\"field\":\"CREATED_AT\"})"
}, },
{ {
"alias": null, "alias": null,
"args": (v6/*: any*/), "args": (v7/*: any*/),
"filters": (v18/*: any*/), "filters": (v17/*: any*/),
"handle": "connection", "handle": "connection",
"key": "MemberListFragment_members", "key": "MemberListFragment_members",
"kind": "LinkedHandle", "kind": "LinkedHandle",
@@ -429,13 +419,12 @@ return {
}, },
{ {
"alias": null, "alias": null,
"args": (v6/*: any*/), "args": (v7/*: any*/),
"concreteType": "InvitationConnection", "concreteType": "InvitationConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "invitations", "name": "invitations",
"plural": false, "plural": false,
"selections": [ "selections": [
(v7/*: any*/),
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -452,10 +441,10 @@ return {
"name": "node", "name": "node",
"plural": false, "plural": false,
"selections": [ "selections": [
(v10/*: any*/), (v9/*: any*/),
(v12/*: any*/),
(v13/*: any*/),
(v11/*: any*/), (v11/*: any*/),
(v12/*: any*/),
(v10/*: any*/),
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -463,7 +452,7 @@ return {
"name": "status", "name": "status",
"storageKey": null "storageKey": null
}, },
(v14/*: any*/), (v13/*: any*/),
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -495,25 +484,26 @@ return {
], ],
"storageKey": null "storageKey": null
}, },
(v15/*: any*/) (v14/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
(v15/*: any*/),
(v16/*: any*/), (v16/*: any*/),
(v17/*: any*/) (v8/*: any*/),
(v2/*: any*/)
], ],
"storageKey": "invitations(first:20,orderBy:{\"direction\":\"ASC\",\"field\":\"CREATED_AT\"})" "storageKey": "invitations(first:20,orderBy:{\"direction\":\"ASC\",\"field\":\"CREATED_AT\"})"
}, },
{ {
"alias": null, "alias": null,
"args": (v6/*: any*/), "args": (v7/*: any*/),
"filters": (v18/*: any*/), "filters": (v17/*: any*/),
"handle": "connection", "handle": "connection",
"key": "InvitationListFragment_invitations", "key": "InvitationListFragment_invitations",
"kind": "LinkedHandle", "kind": "LinkedHandle",
"name": "invitations" "name": "invitations"
}, }
(v9/*: any*/)
], ],
"type": "Organization", "type": "Organization",
"abstractKey": null "abstractKey": null
@@ -524,16 +514,16 @@ return {
] ]
}, },
"params": { "params": {
"cacheID": "9cc9ff1663db9c476c1cd67f097a4ab9", "cacheID": "bff4e08ce3b3a6923bfb9d24fc609b18",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "MembersPageQuery", "name": "MembersPageQuery",
"operationKind": "query", "operationKind": "query",
"text": "query MembersPageQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n ...InviteUserDialog_currentRoleFragment\n ...MemberListFragment_1jRT0c\n members(first: 20, orderBy: {direction: ASC, field: CREATED_AT}) {\n totalCount\n }\n ...InvitationListFragment_1jRT0c\n invitations(first: 20, orderBy: {direction: ASC, field: CREATED_AT}) {\n totalCount\n }\n canInviteUser: permission(action: \"iam:invitation:create\")\n }\n id\n }\n}\n\nfragment InvitationListFragment_1jRT0c on Organization {\n invitations(first: 20, orderBy: {direction: ASC, field: CREATED_AT}) {\n totalCount\n edges {\n node {\n id\n ...InvitationListItemFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n\nfragment InvitationListItemFragment on Invitation {\n id\n fullName\n email\n role\n status\n createdAt\n expiresAt\n acceptedAt\n canDelete: permission(action: \"iam:invitation:delete\")\n}\n\nfragment InviteUserDialog_currentRoleFragment on Organization {\n viewerMembership {\n role\n id\n }\n}\n\nfragment MemberListFragment_1jRT0c on Organization {\n members(first: 20, orderBy: {direction: ASC, field: CREATED_AT}) {\n totalCount\n edges {\n node {\n id\n ...MemberListItemFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n\nfragment MemberListItemFragment on Membership {\n id\n role\n source\n state\n profile {\n fullName\n id\n }\n identity {\n email\n id\n }\n createdAt\n canUpdate: permission(action: \"iam:membership:update\")\n canDelete: permission(action: \"iam:membership:delete\")\n}\n" "text": "query MembersPageQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n canInviteUser: permission(action: \"iam:invitation:create\")\n ...MemberListFragment_1jRT0c\n members(first: 20, orderBy: {direction: ASC, field: CREATED_AT}) {\n totalCount\n }\n ...InvitationListFragment_1jRT0c\n invitations(first: 20, orderBy: {direction: ASC, field: CREATED_AT}) {\n totalCount\n __typename\n }\n }\n id\n }\n}\n\nfragment InvitationListFragment_1jRT0c on Organization {\n invitations(first: 20, orderBy: {direction: ASC, field: CREATED_AT}) {\n edges {\n node {\n id\n ...InvitationListItemFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n\nfragment InvitationListItemFragment on Invitation {\n id\n fullName\n email\n role\n status\n createdAt\n expiresAt\n acceptedAt\n canDelete: permission(action: \"iam:invitation:delete\")\n}\n\nfragment MemberListFragment_1jRT0c on Organization {\n members(first: 20, orderBy: {direction: ASC, field: CREATED_AT}) {\n totalCount\n edges {\n node {\n id\n ...MemberListItemFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n\nfragment MemberListItemFragment on Membership {\n id\n role\n source\n state\n profile {\n fullName\n id\n }\n identity {\n email\n id\n }\n createdAt\n canUpdate: permission(action: \"iam:membership:update\")\n canDelete: permission(action: \"iam:membership:delete\")\n}\n"
} }
}; };
})(); })();
(node as any).hash = "591a88a5e1b0bd427daff74dc27ac512"; (node as any).hash = "96c00bf5db547e829eaefb042658be73";
export default node; export default node;

View File

@@ -0,0 +1,42 @@
/**
* @generated SignedSource<<ff0b4fa95a5c304058379d21994833ff>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ReaderFragment } from 'relay-runtime';
import { FragmentRefs } from "relay-runtime";
export type MembersPage_invitationsTotalCountFragment$data = {
totalCount: number | null | undefined;
readonly " $fragmentType": "MembersPage_invitationsTotalCountFragment";
};
export type MembersPage_invitationsTotalCountFragment$key = {
readonly " $data"?: MembersPage_invitationsTotalCountFragment$data;
readonly $updatableFragmentSpreads: FragmentRefs<"MembersPage_invitationsTotalCountFragment">;
};
const node: ReaderFragment = {
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
"name": "MembersPage_invitationsTotalCountFragment",
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "totalCount",
"storageKey": null
}
],
"type": "InvitationConnection",
"abstractKey": null
};
(node as any).hash = "af477ef9a8b791eee11ab26caee3d304";
export default node;

View File

@@ -2,7 +2,7 @@ import { Environment, Network, RecordSource, Store } from "relay-runtime";
import { makeFetchQuery } from "@probo/relay"; import { makeFetchQuery } from "@probo/relay";
export const coreEnvironment = new Environment({ export const coreEnvironment = new Environment({
configName: "console", configName: "core",
network: Network.create(makeFetchQuery("/api/console/v1/graphql")), network: Network.create(makeFetchQuery("/api/console/v1/graphql")),
store: new Store(new RecordSource(), { store: new Store(new RecordSource(), {
queryCacheExpirationTime: 1 * 60 * 1000, queryCacheExpirationTime: 1 * 60 * 1000,

View File

@@ -14,7 +14,7 @@ export const membersPageQuery = graphql`
organization: node(id: $organizationId) @required(action: THROW) { organization: node(id: $organizationId) @required(action: THROW) {
__typename __typename
... on Organization { ... on Organization {
...InviteUserDialog_currentRoleFragment canInviteUser: permission(action: "iam:invitation:create")
...MemberListFragment ...MemberListFragment
@arguments(first: 20, order: { direction: ASC, field: CREATED_AT }) @arguments(first: 20, order: { direction: ASC, field: CREATED_AT })
members(first: 20, orderBy: { direction: ASC, field: CREATED_AT }) members(first: 20, orderBy: { direction: ASC, field: CREATED_AT })
@@ -26,13 +26,20 @@ export const membersPageQuery = graphql`
invitations(first: 20, orderBy: { direction: ASC, field: CREATED_AT }) invitations(first: 20, orderBy: { direction: ASC, field: CREATED_AT })
@required(action: THROW) { @required(action: THROW) {
totalCount totalCount
...MembersPage_invitationsTotalCountFragment
} }
canInviteUser: permission(action: "iam:invitation:create")
} }
} }
} }
`; `;
export const invitationCountFragment = graphql`
fragment MembersPage_invitationsTotalCountFragment on InvitationConnection
@updatable {
totalCount
}
`;
export function MembersPage(props: { export function MembersPage(props: {
queryRef: PreloadedQuery<MembersPageQuery>; queryRef: PreloadedQuery<MembersPageQuery>;
}) { }) {
@@ -68,7 +75,7 @@ export function MembersPage(props: {
{organization.canInviteUser && ( {organization.canInviteUser && (
<InviteUserDialog <InviteUserDialog
connectionId={invitationListConnectionId} connectionId={invitationListConnectionId}
viewerMembershipFKey={organization} fKey={organization.invitations}
> >
<Button variant="secondary">{__("Invite member")}</Button> <Button variant="secondary">{__("Invite member")}</Button>
</InviteUserDialog> </InviteUserDialog>
@@ -103,6 +110,8 @@ export function MembersPage(props: {
{activeTab === "invitations" && ( {activeTab === "invitations" && (
<InvitationList <InvitationList
fKey={organization} fKey={organization}
totalCount={organization.invitations.totalCount ?? 0}
totalCountFKey={organization.invitations}
onConnectionIdChange={setInvitationListConnectionId} onConnectionIdChange={setInvitationListConnectionId}
/> />
)} )}

View File

@@ -11,6 +11,7 @@ import type { InvitationListFragment$key } from "/__generated__/iam/InvitationLi
import type { InvitationListFragment_RefetchQuery } from "/__generated__/iam/InvitationListFragment_RefetchQuery.graphql"; import type { InvitationListFragment_RefetchQuery } from "/__generated__/iam/InvitationListFragment_RefetchQuery.graphql";
import { type ComponentProps } from "react"; import { type ComponentProps } from "react";
import { useOrganizationId } from "/hooks/useOrganizationId"; import { useOrganizationId } from "/hooks/useOrganizationId";
import type { MembersPage_invitationsTotalCountFragment$key } from "/__generated__/iam/MembersPage_invitationsTotalCountFragment.graphql";
const fragment = graphql` const fragment = graphql`
fragment InvitationListFragment on Organization fragment InvitationListFragment on Organization
@@ -38,7 +39,6 @@ const fragment = graphql`
) )
@required(action: THROW) { @required(action: THROW) {
__id __id
totalCount
edges @required(action: THROW) { edges @required(action: THROW) {
node { node {
id id
@@ -52,8 +52,10 @@ const fragment = graphql`
export function InvitationList(props: { export function InvitationList(props: {
fKey: InvitationListFragment$key; fKey: InvitationListFragment$key;
onConnectionIdChange: (connectionId: string) => void; onConnectionIdChange: (connectionId: string) => void;
totalCount: number;
totalCountFKey: MembersPage_invitationsTotalCountFragment$key;
}) { }) {
const { fKey, onConnectionIdChange } = props; const { fKey, onConnectionIdChange, totalCount, totalCountFKey } = props;
const organizationId = useOrganizationId(); const organizationId = useOrganizationId();
const { __ } = useTranslate(); const { __ } = useTranslate();
@@ -109,7 +111,7 @@ export function InvitationList(props: {
</Tr> </Tr>
</Thead> </Thead>
<Tbody> <Tbody>
{invitationsPagination.data.invitations.totalCount === 0 ? ( {totalCount === 0 ? (
<Tr> <Tr>
<Td colSpan={7} className="text-center text-txt-secondary"> <Td colSpan={7} className="text-center text-txt-secondary">
{__("No invitations")} {__("No invitations")}
@@ -123,6 +125,7 @@ export function InvitationList(props: {
key={invitation.id} key={invitation.id}
fKey={invitation} fKey={invitation}
onRefetch={refetchInvitations} onRefetch={refetchInvitations}
totalCountFKey={totalCountFKey}
/> />
), ),
) )

View File

@@ -15,6 +15,8 @@ import { useMutationWithToasts } from "/hooks/useMutationWithToasts";
import { sprintf } from "@probo/helpers"; import { sprintf } from "@probo/helpers";
import { useOrganizationId } from "/hooks/useOrganizationId"; import { useOrganizationId } from "/hooks/useOrganizationId";
import type { InvitationListItemFragment$key } from "/__generated__/iam/InvitationListItemFragment.graphql"; import type { InvitationListItemFragment$key } from "/__generated__/iam/InvitationListItemFragment.graphql";
import { invitationCountFragment } from "../MembersPage";
import type { MembersPage_invitationsTotalCountFragment$key } from "/__generated__/iam/MembersPage_invitationsTotalCountFragment.graphql";
const fragment = graphql` const fragment = graphql`
fragment InvitationListItemFragment on Invitation { fragment InvitationListItemFragment on Invitation {
@@ -44,9 +46,10 @@ const deleteInvitationMutation = graphql`
export function InvitationListItem(props: { export function InvitationListItem(props: {
connectionId: string; connectionId: string;
fKey: InvitationListItemFragment$key; fKey: InvitationListItemFragment$key;
totalCountFKey: MembersPage_invitationsTotalCountFragment$key;
onRefetch: () => void; onRefetch: () => void;
}) { }) {
const { connectionId, fKey } = props; const { connectionId, fKey, totalCountFKey } = props;
const organizationId = useOrganizationId(); const organizationId = useOrganizationId();
const { __ } = useTranslate(); const { __ } = useTranslate();
@@ -76,6 +79,17 @@ export function InvitationListItem(props: {
}, },
connections: [connectionId], connections: [connectionId],
}, },
updater: (store) => {
const { updatableData } =
store.readUpdatableFragment<MembersPage_invitationsTotalCountFragment$key>(
invitationCountFragment,
totalCountFKey,
);
if (typeof updatableData.totalCount === "number") {
updatableData.totalCount -= 1;
}
},
}); });
}, },
{ {

View File

@@ -11,22 +11,16 @@ import {
useDialogRef, useDialogRef,
} from "@probo/ui"; } from "@probo/ui";
import { Controller } from "react-hook-form"; import { Controller } from "react-hook-form";
import { useFragment } from "react-relay";
import { graphql } from "relay-runtime"; import { graphql } from "relay-runtime";
import z from "zod"; import z from "zod";
import { useFormWithSchema } from "/hooks/useFormWithSchema"; import { useFormWithSchema } from "/hooks/useFormWithSchema";
import { useMutationWithToasts } from "/hooks/useMutationWithToasts"; import { useMutationWithToasts } from "/hooks/useMutationWithToasts";
import { useOrganizationId } from "/hooks/useOrganizationId"; import { useOrganizationId } from "/hooks/useOrganizationId";
import type { PropsWithChildren } from "react"; import { use, type PropsWithChildren } from "react";
import type { InviteUserDialog_currentRoleFragment$key } from "/__generated__/iam/InviteUserDialog_currentRoleFragment.graphql"; import { CurrentUser } from "/providers/CurrentUser";
import type { InviteUserDialogMutation } from "/__generated__/iam/InviteUserDialogMutation.graphql";
const currentRoleFragment = graphql` import { invitationCountFragment } from "../MembersPage";
fragment InviteUserDialog_currentRoleFragment on Organization { import type { MembersPage_invitationsTotalCountFragment$key } from "/__generated__/iam/MembersPage_invitationsTotalCountFragment.graphql";
viewerMembership @required(action: THROW) {
role
}
}
`;
const inviteMutation = graphql` const inviteMutation = graphql`
mutation InviteUserDialogMutation( mutation InviteUserDialogMutation(
@@ -50,37 +44,41 @@ const inviteMutation = graphql`
} }
`; `;
// const totalCountFragment = graphql`
// fragment InviteUserDialog_totalCountFragment on InvitationConnection
// @updatable {
// totalCount
// }
// `;
const schema = z.object({ const schema = z.object({
email: z.string().email(), email: z.string().email(),
fullName: z.string(), fullName: z.string(),
role: z role: z
.enum(["OWNER", "ADMIN", "FULL", "VIEWER", "AUDITOR", "EMPLOYEE"]) .enum(["OWNER", "ADMIN", "VIEWER", "AUDITOR", "EMPLOYEE"])
.default("VIEWER"), .default("VIEWER"),
}); });
type InviteUserDialogProps = PropsWithChildren<{ type InviteUserDialogProps = PropsWithChildren<{
connectionId: string; connectionId: string;
viewerMembershipFKey: InviteUserDialog_currentRoleFragment$key; fKey: MembersPage_invitationsTotalCountFragment$key;
}>; }>;
export function InviteUserDialog(props: InviteUserDialogProps) { export function InviteUserDialog(props: InviteUserDialogProps) {
const { children, connectionId, viewerMembershipFKey } = props; const { children, connectionId, fKey } = props;
const organizationId = useOrganizationId(); const organizationId = useOrganizationId();
const { __ } = useTranslate(); const { __ } = useTranslate();
const dialogRef = useDialogRef(); const dialogRef = useDialogRef();
const { viewerMembership } = const { role } = use(CurrentUser);
useFragment<InviteUserDialog_currentRoleFragment$key>( const [inviteUser, isInviting] =
currentRoleFragment, useMutationWithToasts<InviteUserDialogMutation>(inviteMutation, {
viewerMembershipFKey, successMessage: __("Invitation sent successfully"),
); errorMessage: __("Failed to send invitation"),
const [inviteUser, isInviting] = useMutationWithToasts(inviteMutation, { });
successMessage: __("Invitation sent successfully"),
errorMessage: __("Failed to send invitation"),
});
const assignableRoles = getAssignableRoles(viewerMembership.role); const assignableRoles = getAssignableRoles(role);
const { register, handleSubmit, formState, reset, control } = const { register, handleSubmit, formState, reset, control } =
useFormWithSchema(schema, { useFormWithSchema(schema, {
@@ -102,6 +100,17 @@ export function InviteUserDialog(props: InviteUserDialogProps) {
reset(); reset();
dialogRef.current?.close(); dialogRef.current?.close();
}, },
updater: (store) => {
const { updatableData } =
store.readUpdatableFragment<MembersPage_invitationsTotalCountFragment$key>(
invitationCountFragment,
fKey,
);
if (typeof updatableData.totalCount === "number") {
updatableData.totalCount += 1;
}
},
}); });
}); });

View File

@@ -1225,10 +1225,13 @@ func (r *organizationResolver) Invitations(ctx context.Context, obj *types.Organ
return nil, nil return nil, nil
} }
filters := coredata.NewInvitationFilter(nil)
if gqlutils.OnlyTotalCountSelected(ctx) { if gqlutils.OnlyTotalCountSelected(ctx) {
return &types.InvitationConnection{ return &types.InvitationConnection{
Resolver: r, Resolver: r,
ParentID: obj.ID, ParentID: obj.ID,
Filters: filters,
}, nil }, nil
} }
@@ -1243,7 +1246,6 @@ func (r *organizationResolver) Invitations(ctx context.Context, obj *types.Organ
} }
} }
filters := coredata.NewInvitationFilter(nil)
if status != nil { if status != nil {
filters = coredata.NewInvitationFilter([]coredata.InvitationStatus{*status}) filters = coredata.NewInvitationFilter([]coredata.InvitationStatus{*status})
} }