Change webhook table names

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
Sacha Al Himdani
2026-02-13 12:16:15 +01:00
parent 5a8c60a5aa
commit a1e726ec49
19 changed files with 1444 additions and 1436 deletions

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<cc57c5db0d6374e4941bb0d4f1fb73c2>>
* @generated SignedSource<<18c0948adc229a75b1d980e64730b423>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -20,10 +20,10 @@ export type WebhooksSettingsPageQuery$data = {
readonly webhookConfigurations: {
readonly edges: ReadonlyArray<{
readonly node: {
readonly calls: {
readonly endpointUrl: string;
readonly events: {
readonly totalCount: number;
};
readonly endpointUrl: string;
readonly id: string;
readonly selectedEvents: ReadonlyArray<WebhookEventType>;
};
@@ -110,9 +110,9 @@ v4 = [
"value": 0
}
],
"concreteType": "WebhookCallConnection",
"concreteType": "WebhookEventConnection",
"kind": "LinkedField",
"name": "calls",
"name": "events",
"plural": false,
"selections": [
{
@@ -123,7 +123,7 @@ v4 = [
"storageKey": null
}
],
"storageKey": "calls(first:0)"
"storageKey": "events(first:0)"
},
(v2/*: any*/)
],
@@ -265,7 +265,7 @@ return {
]
},
"params": {
"cacheID": "97b7c454586fe958e456fa7929b46686",
"cacheID": "b5ca3cf4d05d2cb81c744e760433cb94",
"id": null,
"metadata": {
"connection": [
@@ -282,11 +282,11 @@ return {
},
"name": "WebhooksSettingsPageQuery",
"operationKind": "query",
"text": "query WebhooksSettingsPageQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n id\n webhookConfigurations(first: 50) {\n edges {\n node {\n id\n endpointUrl\n selectedEvents\n calls(first: 0) {\n totalCount\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n id\n }\n}\n"
"text": "query WebhooksSettingsPageQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n id\n webhookConfigurations(first: 50) {\n edges {\n node {\n id\n endpointUrl\n selectedEvents\n events(first: 0) {\n totalCount\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n id\n }\n}\n"
}
};
})();
(node as any).hash = "58012f55644dae31fe5e18c2c1e193a7";
(node as any).hash = "bac1812903d6f495d15bb0e70ce5ed48";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<c53381e72c0d17cff70568af0bbbb6e5>>
* @generated SignedSource<<70389123cd52ffd010e2b8f0109aedcd>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,22 +9,22 @@
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type WebhookCallStatus = "FAILED" | "SUCCEEDED";
export type WebhooksSettingsPage_callsQuery$variables = {
export type WebhookEventStatus = "FAILED" | "SUCCEEDED";
export type WebhooksSettingsPage_eventsQuery$variables = {
after?: string | null | undefined;
first?: number | null | undefined;
webhookConfigurationId: string;
};
export type WebhooksSettingsPage_callsQuery$data = {
export type WebhooksSettingsPage_eventsQuery$data = {
readonly node: {
readonly calls?: {
readonly events?: {
readonly edges: ReadonlyArray<{
readonly node: {
readonly createdAt: string;
readonly endpointUrl: string;
readonly id: string;
readonly response: string | null | undefined;
readonly status: WebhookCallStatus;
readonly status: WebhookEventStatus;
};
}>;
readonly pageInfo: {
@@ -35,9 +35,9 @@ export type WebhooksSettingsPage_callsQuery$data = {
};
};
};
export type WebhooksSettingsPage_callsQuery = {
response: WebhooksSettingsPage_callsQuery$data;
variables: WebhooksSettingsPage_callsQuery$variables;
export type WebhooksSettingsPage_eventsQuery = {
response: WebhooksSettingsPage_eventsQuery$data;
variables: WebhooksSettingsPage_eventsQuery$variables;
};
const node: ConcreteRequest = (function(){
@@ -87,9 +87,9 @@ v5 = {
"variableName": "first"
}
],
"concreteType": "WebhookCallConnection",
"concreteType": "WebhookEventConnection",
"kind": "LinkedField",
"name": "calls",
"name": "events",
"plural": false,
"selections": [
{
@@ -127,7 +127,7 @@ v5 = {
{
"alias": null,
"args": null,
"concreteType": "WebhookCallEdge",
"concreteType": "WebhookEventEdge",
"kind": "LinkedField",
"name": "edges",
"plural": true,
@@ -135,7 +135,7 @@ v5 = {
{
"alias": null,
"args": null,
"concreteType": "WebhookCall",
"concreteType": "WebhookEvent",
"kind": "LinkedField",
"name": "node",
"plural": false,
@@ -191,7 +191,7 @@ return {
],
"kind": "Fragment",
"metadata": null,
"name": "WebhooksSettingsPage_callsQuery",
"name": "WebhooksSettingsPage_eventsQuery",
"selections": [
{
"alias": null,
@@ -217,7 +217,7 @@ return {
(v0/*: any*/)
],
"kind": "Operation",
"name": "WebhooksSettingsPage_callsQuery",
"name": "WebhooksSettingsPage_eventsQuery",
"selections": [
{
"alias": null,
@@ -242,16 +242,16 @@ return {
]
},
"params": {
"cacheID": "9371a8918daebbb2a660b02649ba0241",
"cacheID": "507b568e987ce78e58b171810a60bce8",
"id": null,
"metadata": {},
"name": "WebhooksSettingsPage_callsQuery",
"name": "WebhooksSettingsPage_eventsQuery",
"operationKind": "query",
"text": "query WebhooksSettingsPage_callsQuery(\n $webhookConfigurationId: ID!\n $first: Int\n $after: CursorKey\n) {\n node(id: $webhookConfigurationId) {\n __typename\n ... on WebhookConfiguration {\n calls(first: $first, after: $after) {\n totalCount\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n node {\n id\n status\n endpointUrl\n createdAt\n response\n }\n }\n }\n }\n id\n }\n}\n"
"text": "query WebhooksSettingsPage_eventsQuery(\n $webhookConfigurationId: ID!\n $first: Int\n $after: CursorKey\n) {\n node(id: $webhookConfigurationId) {\n __typename\n ... on WebhookConfiguration {\n events(first: $first, after: $after) {\n totalCount\n pageInfo {\n hasNextPage\n endCursor\n }\n edges {\n node {\n id\n status\n endpointUrl\n createdAt\n response\n }\n }\n }\n }\n id\n }\n}\n"
}
};
})();
(node as any).hash = "de18874117b6272fdf2e22871adc4a5d";
(node as any).hash = "2e528e16c34c33138858f92215af2ab4";
export default node;

View File

@@ -23,9 +23,9 @@ import { type PreloadedQuery, usePreloadedQuery, useRelayEnvironment } from "rea
import { ConnectionHandler, fetchQuery, graphql } from "relay-runtime";
import { z } from "zod";
import type { WebhooksSettingsPage_callsQuery } from "#/__generated__/core/WebhooksSettingsPage_callsQuery.graphql";
import type { WebhooksSettingsPage_createMutation } from "#/__generated__/core/WebhooksSettingsPage_createMutation.graphql";
import type { WebhooksSettingsPage_deleteMutation } from "#/__generated__/core/WebhooksSettingsPage_deleteMutation.graphql";
import type { WebhooksSettingsPage_eventsQuery } from "#/__generated__/core/WebhooksSettingsPage_eventsQuery.graphql";
import type { WebhooksSettingsPage_signingSecretQuery } from "#/__generated__/core/WebhooksSettingsPage_signingSecretQuery.graphql";
import type { WebhooksSettingsPage_updateMutation } from "#/__generated__/core/WebhooksSettingsPage_updateMutation.graphql";
import type { WebhooksSettingsPageQuery } from "#/__generated__/core/WebhooksSettingsPageQuery.graphql";
@@ -45,7 +45,7 @@ export const webhooksSettingsPageQuery = graphql`
id
endpointUrl
selectedEvents
calls(first: 0) {
events(first: 0) {
totalCount
}
}
@@ -98,15 +98,15 @@ const signingSecretQuery = graphql`
}
`;
const webhookCallsQuery = graphql`
query WebhooksSettingsPage_callsQuery(
const webhookEventsQuery = graphql`
query WebhooksSettingsPage_eventsQuery(
$webhookConfigurationId: ID!
$first: Int
$after: CursorKey
) {
node(id: $webhookConfigurationId) {
... on WebhookConfiguration {
calls(first: $first, after: $after) {
events(first: $first, after: $after) {
totalCount
pageInfo {
hasNextPage
@@ -285,7 +285,7 @@ function WebhookFormDialog({
);
}
function CallStatusBadge({ status }: { status: string }) {
function EventStatusBadge({ status }: { status: string }) {
const { __ } = useTranslate();
if (status === "SUCCEEDED") {
return <Badge variant="success" size="sm">{__("Succeeded")}</Badge>;
@@ -297,7 +297,7 @@ function formatDate(iso: string) {
return new Date(iso).toLocaleString();
}
function WebhookCallsDialog({
function WebhookEventsDialog({
webhookConfigurationId,
endpointUrl,
onClose,
@@ -307,10 +307,11 @@ function WebhookCallsDialog({
onClose: () => void;
}) {
const { __ } = useTranslate();
const { toast } = useToast();
const environment = useRelayEnvironment();
const dialogRef = useDialogRef();
type CallNode = NonNullable<WebhooksSettingsPage_callsQuery["response"]["node"]["calls"]>["edges"][number]["node"];
const [calls, setCalls] = useState<CallNode[]>([]);
type EventNode = NonNullable<WebhooksSettingsPage_eventsQuery["response"]["node"]["events"]>["edges"][number]["node"];
const [events, setEvents] = useState<EventNode[]>([]);
const [loading, setLoading] = useState(true);
const [hasNextPage, setHasNextPage] = useState(false);
const [endCursor, setEndCursor] = useState<string | null>(null);
@@ -318,13 +319,13 @@ function WebhookCallsDialog({
const PAGE_SIZE = 20;
const loadCalls = useCallback(
const loadEvents = useCallback(
async (after?: string | null) => {
setLoading(true);
try {
const data = await fetchQuery<WebhooksSettingsPage_callsQuery>(
const data = await fetchQuery<WebhooksSettingsPage_eventsQuery>(
environment,
webhookCallsQuery,
webhookEventsQuery,
{
webhookConfigurationId,
first: PAGE_SIZE,
@@ -332,30 +333,36 @@ function WebhookCallsDialog({
},
).toPromise();
const connection = data?.node?.calls;
const connection = data?.node?.events;
if (connection) {
const newCalls = connection.edges.map(e => e.node);
setCalls(prev => after ? [...prev, ...newCalls] : newCalls);
const newEvents = connection.edges.map(e => e.node);
setEvents(prev => after ? [...prev, ...newEvents] : newEvents);
setHasNextPage(connection.pageInfo.hasNextPage);
setEndCursor(connection.pageInfo.endCursor ?? null);
setTotalCount(connection.totalCount);
}
} catch {
toast({
title: __("Error"),
description: __("Failed to load webhook events."),
variant: "error",
});
} finally {
setLoading(false);
}
},
[environment, webhookConfigurationId],
[environment, webhookConfigurationId, toast, __],
);
useEffect(() => {
void loadCalls();
void loadEvents();
dialogRef.current?.open();
}, []); // eslint-disable-line react-hooks/exhaustive-deps
}, [loadEvents]);
return (
<Dialog
ref={dialogRef}
title={__("Webhook Calls")}
title={__("Webhook Events")}
className="max-w-2xl"
onClose={onClose}
>
@@ -368,29 +375,29 @@ function WebhookCallsDialog({
</span>
)}
</p>
{calls.length === 0 && !loading
{events.length === 0 && !loading
? (
<p className="text-sm text-txt-tertiary text-center py-8">
{__("No webhook calls recorded yet.")}
{__("No webhook events recorded yet.")}
</p>
)
: (
<div className="space-y-2">
{calls.map(call => (
{events.map(event => (
<div
key={call.id}
key={event.id}
className="border border-border-solid rounded-md p-3 space-y-1"
>
<div className="flex items-center justify-between">
<CallStatusBadge status={call.status} />
<EventStatusBadge status={event.status} />
<span className="text-xs text-txt-tertiary">
{formatDate(call.createdAt)}
{formatDate(event.createdAt)}
</span>
</div>
<p className="text-xs font-mono text-txt-secondary truncate">
{call.endpointUrl}
{event.endpointUrl}
</p>
{call.response && (
{event.response && (
<details className="text-xs">
<summary className="cursor-pointer text-txt-link hover:underline">
{__("Response")}
@@ -398,9 +405,9 @@ function WebhookCallsDialog({
<pre className="mt-1 bg-subtle p-2 rounded text-xs overflow-auto max-h-48 whitespace-pre-wrap break-all">
{(() => {
try {
return JSON.stringify(JSON.parse(call.response), null, 2);
return JSON.stringify(JSON.parse(event.response), null, 2);
} catch {
return call.response;
return event.response;
}
})()}
</pre>
@@ -420,7 +427,7 @@ function WebhookCallsDialog({
<DialogFooter>
<Button
variant="secondary"
onClick={() => void loadCalls(endCursor)}
onClick={() => void loadEvents(endCursor)}
>
{__("Load more")}
</Button>
@@ -441,7 +448,7 @@ export function WebhooksSettingsPage(props: {
const [deletingId, setDeletingId] = useState<string | null>(null);
const [revealedSecrets, setRevealedSecrets] = useState<Record<string, string>>({});
const [loadingSecrets, setLoadingSecrets] = useState<Set<string>>(new Set());
const [viewingCallsId, setViewingCallsId] = useState<string | null>(null);
const [viewingEventsId, setViewingEventsId] = useState<string | null>(null);
const fetchSigningSecret = useCallback(
async (webhookConfigurationId: string): Promise<string | null> => {
@@ -543,6 +550,9 @@ export function WebhooksSettingsPage(props: {
);
const webhooks = organization.webhookConfigurations?.edges ?? [];
const viewingEventsWebhook = viewingEventsId
? webhooks.find(e => e.node.id === viewingEventsId)?.node ?? null
: null;
const connectionId = ConnectionHandler.getConnectionID(
organization.id,
@@ -683,9 +693,9 @@ export function WebhooksSettingsPage(props: {
<div className="flex items-center gap-1 shrink-0">
<Button
variant="secondary"
onClick={() => setViewingCallsId(webhook.id)}
onClick={() => setViewingEventsId(webhook.id)}
>
{`${__("Calls")} (${webhook.calls.totalCount})`}
{`${__("Events")} (${webhook.events.totalCount})`}
</Button>
<WebhookFormDialog
mode="edit"
@@ -740,26 +750,22 @@ export function WebhooksSettingsPage(props: {
variant="danger"
onClick={() => deletingId && handleDelete(deletingId)}
disabled={isDeleting}
icon={isDeleting ? Spinner : IconTrashCan}
icon={isDeleting ? undefined : IconTrashCan}
>
{isDeleting
? __("Deleting...")
? <><Spinner size={16} /> {__("Deleting...")}</>
: __("Delete")}
</Button>
</DialogFooter>
</Dialog>
{viewingCallsId && (() => {
const webhook = webhooks.find(e => e.node.id === viewingCallsId);
if (!webhook) return null;
return (
<WebhookCallsDialog
webhookConfigurationId={viewingCallsId}
endpointUrl={webhook.node.endpointUrl}
onClose={() => setViewingCallsId(null)}
/>
);
})()}
{viewingEventsWebhook && viewingEventsId && (
<WebhookEventsDialog
webhookConfigurationId={viewingEventsId}
endpointUrl={viewingEventsWebhook.endpointUrl}
onClose={() => setViewingEventsId(null)}
/>
)}
</div>
);
}