@shipfox/client-integrations 5.0.0 → 6.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +84 -0
- package/dist/application/complete-integration-callback.d.ts +13 -0
- package/dist/application/complete-integration-callback.d.ts.map +1 -0
- package/dist/application/complete-integration-callback.js +26 -0
- package/dist/application/complete-integration-callback.js.map +1 -0
- package/dist/components/connection-picker.d.ts +2 -2
- package/dist/components/connection-picker.d.ts.map +1 -1
- package/dist/components/connection-picker.js +4 -4
- package/dist/components/connection-picker.js.map +1 -1
- package/dist/components/installed-integrations-section.d.ts +8 -6
- package/dist/components/installed-integrations-section.d.ts.map +1 -1
- package/dist/components/installed-integrations-section.js +22 -15
- package/dist/components/installed-integrations-section.js.map +1 -1
- package/dist/components/integration-gallery-for-workspace.d.ts +2 -2
- package/dist/components/integration-gallery-for-workspace.d.ts.map +1 -1
- package/dist/components/integration-gallery-for-workspace.js +14 -7
- package/dist/components/integration-gallery-for-workspace.js.map +1 -1
- package/dist/components/integration-gallery.d.ts +2 -2
- package/dist/components/integration-gallery.d.ts.map +1 -1
- package/dist/components/integration-gallery.js.map +1 -1
- package/dist/components/integration-usage-events.d.ts +1 -3
- package/dist/components/integration-usage-events.d.ts.map +1 -1
- package/dist/components/integration-usage-events.js +1 -125
- package/dist/components/integration-usage-events.js.map +1 -1
- package/dist/components/integration-usage-modal.d.ts +2 -2
- package/dist/components/integration-usage-modal.d.ts.map +1 -1
- package/dist/components/integration-usage-modal.js +2 -2
- package/dist/components/integration-usage-modal.js.map +1 -1
- package/dist/components/provider-grid.d.ts +7 -4
- package/dist/components/provider-grid.d.ts.map +1 -1
- package/dist/components/provider-grid.js +15 -10
- package/dist/components/provider-grid.js.map +1 -1
- package/dist/components/redirect-install-page.d.ts +2 -3
- package/dist/components/redirect-install-page.d.ts.map +1 -1
- package/dist/components/redirect-install-page.js +1 -1
- package/dist/components/redirect-install-page.js.map +1 -1
- package/dist/components/repository-picker.d.ts +2 -2
- package/dist/components/repository-picker.d.ts.map +1 -1
- package/dist/components/repository-picker.js +4 -4
- package/dist/components/repository-picker.js.map +1 -1
- package/dist/components/webhook/webhook-create-modal.d.ts +2 -2
- package/dist/components/webhook/webhook-create-modal.d.ts.map +1 -1
- package/dist/components/webhook/webhook-create-modal.js +8 -8
- package/dist/components/webhook/webhook-create-modal.js.map +1 -1
- package/dist/components/webhook/webhook-modals.stories.d.ts.map +1 -1
- package/dist/components/webhook/webhook-modals.stories.js +7 -7
- package/dist/components/webhook/webhook-modals.stories.js.map +1 -1
- package/dist/components/webhook/webhook-usage-details.d.ts.map +1 -1
- package/dist/components/webhook/webhook-usage-details.js +2 -2
- package/dist/components/webhook/webhook-usage-details.js.map +1 -1
- package/dist/connection-status-badge.d.ts +2 -2
- package/dist/connection-status-badge.d.ts.map +1 -1
- package/dist/connection-status-badge.js +11 -15
- package/dist/connection-status-badge.js.map +1 -1
- package/dist/core/models.d.ts +66 -0
- package/dist/core/models.d.ts.map +1 -0
- package/dist/core/models.js +156 -0
- package/dist/core/models.js.map +1 -0
- package/dist/feature.d.ts +7 -0
- package/dist/feature.d.ts.map +1 -1
- package/dist/feature.js +10 -9
- package/dist/feature.js.map +1 -1
- package/dist/hooks/api/integration-mapper.d.ts +11 -0
- package/dist/hooks/api/integration-mapper.d.ts.map +1 -0
- package/dist/hooks/api/integration-mapper.js +54 -0
- package/dist/hooks/api/integration-mapper.js.map +1 -0
- package/dist/hooks/api/integrations.d.ts +45 -240
- package/dist/hooks/api/integrations.d.ts.map +1 -1
- package/dist/hooks/api/integrations.js +78 -31
- package/dist/hooks/api/integrations.js.map +1 -1
- package/dist/hooks/api/webhook-connections.d.ts +12 -64
- package/dist/hooks/api/webhook-connections.d.ts.map +1 -1
- package/dist/hooks/api/webhook-connections.js +17 -9
- package/dist/hooks/api/webhook-connections.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/linear-callback.d.ts +2 -1
- package/dist/linear-callback.d.ts.map +1 -1
- package/dist/linear-callback.js +17 -15
- package/dist/linear-callback.js.map +1 -1
- package/dist/pages/gitea-install-page.d.ts.map +1 -1
- package/dist/pages/gitea-install-page.js +1 -10
- package/dist/pages/gitea-install-page.js.map +1 -1
- package/dist/pages/linear-callback-page.d.ts.map +1 -1
- package/dist/pages/linear-callback-page.js +19 -32
- package/dist/pages/linear-callback-page.js.map +1 -1
- package/dist/pages/linear-install-page.d.ts.map +1 -1
- package/dist/pages/linear-install-page.js +2 -1
- package/dist/pages/linear-install-page.js.map +1 -1
- package/dist/pages/sentry-callback-page.d.ts.map +1 -1
- package/dist/pages/sentry-callback-page.js +22 -25
- package/dist/pages/sentry-callback-page.js.map +1 -1
- package/dist/pages/sentry-install-page.d.ts.map +1 -1
- package/dist/pages/sentry-install-page.js +2 -1
- package/dist/pages/sentry-install-page.js.map +1 -1
- package/dist/pages/slack-callback-page.d.ts.map +1 -1
- package/dist/pages/slack-callback-page.js +21 -28
- package/dist/pages/slack-callback-page.js.map +1 -1
- package/dist/pages/slack-install-page.d.ts.map +1 -1
- package/dist/pages/slack-install-page.js +2 -1
- package/dist/pages/slack-install-page.js.map +1 -1
- package/dist/pages/source-control-onboarding-page.d.ts.map +1 -1
- package/dist/pages/source-control-onboarding-page.js +5 -1
- package/dist/pages/source-control-onboarding-page.js.map +1 -1
- package/dist/provider-catalog.d.ts.map +1 -1
- package/dist/provider-catalog.js +7 -6
- package/dist/provider-catalog.js.map +1 -1
- package/dist/routes/github-callback.d.ts +16 -0
- package/dist/routes/github-callback.d.ts.map +1 -1
- package/dist/routes/github-callback.js +43 -21
- package/dist/routes/github-callback.js.map +1 -1
- package/dist/routes/linear-callback.d.ts +2 -0
- package/dist/routes/linear-callback.d.ts.map +1 -1
- package/dist/routes/linear-callback.js +2 -0
- package/dist/routes/linear-callback.js.map +1 -1
- package/dist/routes/sentry-callback.d.ts +2 -0
- package/dist/routes/sentry-callback.d.ts.map +1 -1
- package/dist/routes/sentry-callback.js +2 -0
- package/dist/routes/sentry-callback.js.map +1 -1
- package/dist/routes/slack-callback.d.ts +2 -0
- package/dist/routes/slack-callback.d.ts.map +1 -1
- package/dist/routes/slack-callback.js +2 -0
- package/dist/routes/slack-callback.js.map +1 -1
- package/dist/sentry-callback.d.ts +2 -1
- package/dist/sentry-callback.d.ts.map +1 -1
- package/dist/sentry-callback.js +18 -19
- package/dist/sentry-callback.js.map +1 -1
- package/dist/slack-callback.d.ts +2 -1
- package/dist/slack-callback.d.ts.map +1 -1
- package/dist/slack-callback.js +17 -15
- package/dist/slack-callback.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +17 -17
- package/src/application/complete-integration-callback.test.ts +41 -0
- package/src/application/complete-integration-callback.ts +39 -0
- package/src/components/connection-picker.tsx +7 -7
- package/src/components/installed-integrations-section.tsx +29 -24
- package/src/components/integration-gallery-for-workspace.tsx +23 -16
- package/src/components/integration-gallery.tsx +3 -3
- package/src/components/integration-usage-events.ts +1 -116
- package/src/components/integration-usage-modal.tsx +4 -4
- package/src/components/provider-grid.tsx +30 -18
- package/src/components/redirect-install-page.test.tsx +2 -6
- package/src/components/redirect-install-page.tsx +3 -2
- package/src/components/repository-picker.tsx +6 -6
- package/src/components/webhook/webhook-create-modal.tsx +12 -11
- package/src/components/webhook/webhook-modals.stories.tsx +10 -10
- package/src/components/webhook/webhook-usage-details.tsx +2 -4
- package/src/connection-status-badge.tsx +8 -14
- package/src/core/models.ts +200 -0
- package/src/feature.ts +12 -10
- package/src/hooks/api/integration-mapper.ts +64 -0
- package/src/hooks/api/integrations.test.ts +44 -22
- package/src/hooks/api/integrations.ts +229 -84
- package/src/hooks/api/webhook-connections.ts +58 -17
- package/src/index.ts +2 -1
- package/src/linear-callback.ts +24 -16
- package/src/pages/gitea-install-page.tsx +1 -10
- package/src/pages/linear-callback-page.tsx +18 -30
- package/src/pages/linear-install-page.tsx +2 -1
- package/src/pages/sentry-callback-page.test.tsx +5 -1
- package/src/pages/sentry-callback-page.tsx +28 -25
- package/src/pages/sentry-install-page.tsx +2 -1
- package/src/pages/slack-callback-page.tsx +20 -26
- package/src/pages/slack-install-page.tsx +2 -1
- package/src/pages/source-control-onboarding-page.tsx +5 -1
- package/src/provider-catalog.ts +7 -6
- package/src/routes/github-callback.test.ts +35 -1
- package/src/routes/github-callback.tsx +47 -21
- package/src/routes/linear-callback.tsx +5 -1
- package/src/routes/sentry-callback.tsx +5 -1
- package/src/routes/slack-callback.tsx +6 -1
- package/src/sentry-callback.test.ts +2 -1
- package/src/sentry-callback.ts +30 -20
- package/src/slack-callback.ts +24 -16
- package/tsconfig.build.tsbuildinfo +1 -1
- package/vercel.json +5 -0
- package/dist/integration-icon.d.ts +0 -17
- package/dist/integration-icon.d.ts.map +0 -1
- package/dist/integration-icon.js +0 -22
- package/dist/integration-icon.js.map +0 -1
- package/src/integration-icon.react.test.tsx +0 -40
- package/src/integration-icon.test.ts +0 -19
- package/src/integration-icon.tsx +0 -26
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
$ shipfox-swc
|
|
2
|
-
Successfully compiled:
|
|
2
|
+
Successfully compiled: 51 files with swc (83.75ms)
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,89 @@
|
|
|
1
1
|
# @shipfox/client-integrations
|
|
2
2
|
|
|
3
|
+
## 6.0.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 102c5f4: Isolates private browser state and React Query data across authenticated principal transitions.
|
|
8
|
+
- Updated dependencies [4b85404]
|
|
9
|
+
- Updated dependencies [102c5f4]
|
|
10
|
+
- @shipfox/api-integration-core-dto@9.0.2
|
|
11
|
+
- @shipfox/api-integration-gitea-dto@9.0.2
|
|
12
|
+
- @shipfox/api-integration-github-dto@9.0.2
|
|
13
|
+
- @shipfox/api-integration-linear-dto@9.0.2
|
|
14
|
+
- @shipfox/api-integration-sentry-dto@9.0.2
|
|
15
|
+
- @shipfox/api-integration-slack-dto@9.0.2
|
|
16
|
+
- @shipfox/api-integration-webhook-dto@9.0.2
|
|
17
|
+
- @shipfox/react-ui@0.3.7
|
|
18
|
+
- @shipfox/client-ui@6.0.2
|
|
19
|
+
- @shipfox/client-shell@6.0.2
|
|
20
|
+
- @shipfox/client-auth@6.0.2
|
|
21
|
+
- @shipfox/integration-icons@0.2.2
|
|
22
|
+
|
|
23
|
+
## 6.0.1
|
|
24
|
+
|
|
25
|
+
### Patch Changes
|
|
26
|
+
|
|
27
|
+
- 475ce59: Republishes all public packages after restoring release authorization.
|
|
28
|
+
- 3f8f1cb: Enforces typed route-input and browser-storage boundaries across client features.
|
|
29
|
+
- Updated dependencies [475ce59]
|
|
30
|
+
- Updated dependencies [3f8f1cb]
|
|
31
|
+
- @shipfox/api-integration-core-dto@9.0.1
|
|
32
|
+
- @shipfox/api-integration-gitea-dto@9.0.1
|
|
33
|
+
- @shipfox/api-integration-github-dto@9.0.1
|
|
34
|
+
- @shipfox/api-integration-linear-dto@9.0.1
|
|
35
|
+
- @shipfox/api-integration-sentry-dto@9.0.1
|
|
36
|
+
- @shipfox/api-integration-slack-dto@9.0.1
|
|
37
|
+
- @shipfox/api-integration-webhook-dto@9.0.1
|
|
38
|
+
- @shipfox/client-api@6.0.1
|
|
39
|
+
- @shipfox/client-auth@6.0.1
|
|
40
|
+
- @shipfox/client-shell@6.0.1
|
|
41
|
+
- @shipfox/client-ui@6.0.1
|
|
42
|
+
- @shipfox/integration-icons@0.2.1
|
|
43
|
+
- @shipfox/react-ui@0.3.6
|
|
44
|
+
|
|
45
|
+
## 6.0.0
|
|
46
|
+
|
|
47
|
+
### Major Changes
|
|
48
|
+
|
|
49
|
+
- 24be269: Makes checked API adapters the only public business-response boundary and returns package-owned domain models from Agent, Integrations, and Workflows adapters.
|
|
50
|
+
- c02ac42: Converges the integrations client on a package-owned domain model (camelCase, schema-validated) instead of exposing raw snake_case API DTOs, changing the shape of `useSourceConnectionsQuery`, `useIntegrationConnectionsQuery`, `useIntegrationProvidersQuery`, `useRepositoriesInfiniteQuery`, and the `ConnectionPicker`/`ProviderGrid`/`RepositoryPicker` props. Adds `emptyResponseSchema` to `@shipfox/client-api` for schema-validated DELETE requests with no response body.
|
|
51
|
+
|
|
52
|
+
### Minor Changes
|
|
53
|
+
|
|
54
|
+
- 401b583: Exposes typed feature-owned navigation and settings contributions and enforces coordinator-owned client composition.
|
|
55
|
+
|
|
56
|
+
### Patch Changes
|
|
57
|
+
|
|
58
|
+
- d784a07: Enforces checked client API responses and removes stale transport compatibility helpers.
|
|
59
|
+
- f2d50a8: Extracts shared integration provider icons into a leaf package so client features can render them without depending on integration routing code.
|
|
60
|
+
- cd90c19: Enforces package-owned query policies and explicit cache-operation ownership across client resources.
|
|
61
|
+
- 9d8f510: Converges integration callback flows on domain-owned models and safe cache refreshes.
|
|
62
|
+
- Updated dependencies [401b583]
|
|
63
|
+
- Updated dependencies [d784a07]
|
|
64
|
+
- Updated dependencies [891e469]
|
|
65
|
+
- Updated dependencies [82eda45]
|
|
66
|
+
- Updated dependencies [f2d50a8]
|
|
67
|
+
- Updated dependencies [cd90c19]
|
|
68
|
+
- Updated dependencies [24be269]
|
|
69
|
+
- Updated dependencies [c56c124]
|
|
70
|
+
- Updated dependencies [02974d6]
|
|
71
|
+
- Updated dependencies [4a6d124]
|
|
72
|
+
- Updated dependencies [c02ac42]
|
|
73
|
+
- @shipfox/client-shell@6.0.0
|
|
74
|
+
- @shipfox/client-auth@6.0.0
|
|
75
|
+
- @shipfox/integration-icons@0.2.0
|
|
76
|
+
- @shipfox/client-api@6.0.0
|
|
77
|
+
- @shipfox/api-integration-core-dto@9.0.0
|
|
78
|
+
- @shipfox/api-integration-github-dto@9.0.0
|
|
79
|
+
- @shipfox/api-integration-gitea-dto@9.0.0
|
|
80
|
+
- @shipfox/api-integration-linear-dto@9.0.0
|
|
81
|
+
- @shipfox/api-integration-sentry-dto@9.0.0
|
|
82
|
+
- @shipfox/api-integration-slack-dto@9.0.0
|
|
83
|
+
- @shipfox/api-integration-webhook-dto@9.0.0
|
|
84
|
+
- @shipfox/client-ui@6.0.0
|
|
85
|
+
- @shipfox/react-ui@0.3.5
|
|
86
|
+
|
|
3
87
|
## 5.0.0
|
|
4
88
|
|
|
5
89
|
### Minor Changes
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type QueryClient } from '@tanstack/react-query';
|
|
2
|
+
import type { IntegrationConnection } from '#core/models.js';
|
|
3
|
+
export interface CompleteIntegrationCallbackOptions<TInput> {
|
|
4
|
+
input: TInput;
|
|
5
|
+
refreshAuth: () => Promise<{
|
|
6
|
+
accessToken: string;
|
|
7
|
+
}>;
|
|
8
|
+
complete: (input: TInput, accessToken: string) => Promise<IntegrationConnection>;
|
|
9
|
+
queryClient: QueryClient;
|
|
10
|
+
}
|
|
11
|
+
export declare function completeIntegrationCallback<TInput>({ input, refreshAuth, complete, queryClient, }: CompleteIntegrationCallbackOptions<TInput>): Promise<IntegrationConnection>;
|
|
12
|
+
export declare function useCompleteIntegrationCallback(): <TInput>(options: Omit<CompleteIntegrationCallbackOptions<TInput>, "queryClient">) => Promise<IntegrationConnection>;
|
|
13
|
+
//# sourceMappingURL=complete-integration-callback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"complete-integration-callback.d.ts","sourceRoot":"","sources":["../../src/application/complete-integration-callback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,WAAW,EAAiB,MAAM,uBAAuB,CAAC;AAEvE,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,iBAAiB,CAAC;AAG3D,MAAM,WAAW,kCAAkC,CAAC,MAAM;IACxD,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,OAAO,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;IAClD,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,qBAAqB,CAAC,CAAC;IACjF,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED,wBAAsB,2BAA2B,CAAC,MAAM,EAAE,EACxD,KAAK,EACL,WAAW,EACX,QAAQ,EACR,WAAW,GACZ,EAAE,kCAAkC,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAW7E;AAED,wBAAgB,8BAA8B,KAGnC,MAAM,WACF,IAAI,CAAC,kCAAkC,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC,KACvE,OAAO,CAAC,qBAAqB,CAAC,CAGpC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useQueryClient } from '@tanstack/react-query';
|
|
2
|
+
import { useCallback } from 'react';
|
|
3
|
+
import { integrationsQueryKeys } from '#hooks/api/integrations.js';
|
|
4
|
+
export async function completeIntegrationCallback({ input, refreshAuth, complete, queryClient }) {
|
|
5
|
+
const session = await refreshAuth();
|
|
6
|
+
const connection = await complete(input, session.accessToken);
|
|
7
|
+
try {
|
|
8
|
+
await queryClient.invalidateQueries({
|
|
9
|
+
queryKey: integrationsQueryKeys.connectionsByWorkspace(connection.workspaceId)
|
|
10
|
+
});
|
|
11
|
+
} catch {
|
|
12
|
+
// Cache refresh is best effort: the successful callback is already committed server-side.
|
|
13
|
+
}
|
|
14
|
+
return connection;
|
|
15
|
+
}
|
|
16
|
+
export function useCompleteIntegrationCallback() {
|
|
17
|
+
const queryClient = useQueryClient();
|
|
18
|
+
return useCallback(async (options)=>completeIntegrationCallback({
|
|
19
|
+
...options,
|
|
20
|
+
queryClient
|
|
21
|
+
}), [
|
|
22
|
+
queryClient
|
|
23
|
+
]);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
//# sourceMappingURL=complete-integration-callback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/application/complete-integration-callback.ts"],"sourcesContent":["import {type QueryClient, useQueryClient} from '@tanstack/react-query';\nimport {useCallback} from 'react';\nimport type {IntegrationConnection} from '#core/models.js';\nimport {integrationsQueryKeys} from '#hooks/api/integrations.js';\n\nexport interface CompleteIntegrationCallbackOptions<TInput> {\n input: TInput;\n refreshAuth: () => Promise<{accessToken: string}>;\n complete: (input: TInput, accessToken: string) => Promise<IntegrationConnection>;\n queryClient: QueryClient;\n}\n\nexport async function completeIntegrationCallback<TInput>({\n input,\n refreshAuth,\n complete,\n queryClient,\n}: CompleteIntegrationCallbackOptions<TInput>): Promise<IntegrationConnection> {\n const session = await refreshAuth();\n const connection = await complete(input, session.accessToken);\n try {\n await queryClient.invalidateQueries({\n queryKey: integrationsQueryKeys.connectionsByWorkspace(connection.workspaceId),\n });\n } catch {\n // Cache refresh is best effort: the successful callback is already committed server-side.\n }\n return connection;\n}\n\nexport function useCompleteIntegrationCallback() {\n const queryClient = useQueryClient();\n return useCallback(\n async <TInput>(\n options: Omit<CompleteIntegrationCallbackOptions<TInput>, 'queryClient'>,\n ): Promise<IntegrationConnection> => completeIntegrationCallback({...options, queryClient}),\n [queryClient],\n );\n}\n"],"names":["useQueryClient","useCallback","integrationsQueryKeys","completeIntegrationCallback","input","refreshAuth","complete","queryClient","session","connection","accessToken","invalidateQueries","queryKey","connectionsByWorkspace","workspaceId","useCompleteIntegrationCallback","options"],"mappings":"AAAA,SAA0BA,cAAc,QAAO,wBAAwB;AACvE,SAAQC,WAAW,QAAO,QAAQ;AAElC,SAAQC,qBAAqB,QAAO,6BAA6B;AASjE,OAAO,eAAeC,4BAAoC,EACxDC,KAAK,EACLC,WAAW,EACXC,QAAQ,EACRC,WAAW,EACgC;IAC3C,MAAMC,UAAU,MAAMH;IACtB,MAAMI,aAAa,MAAMH,SAASF,OAAOI,QAAQE,WAAW;IAC5D,IAAI;QACF,MAAMH,YAAYI,iBAAiB,CAAC;YAClCC,UAAUV,sBAAsBW,sBAAsB,CAACJ,WAAWK,WAAW;QAC/E;IACF,EAAE,OAAM;IACN,0FAA0F;IAC5F;IACA,OAAOL;AACT;AAEA,OAAO,SAASM;IACd,MAAMR,cAAcP;IACpB,OAAOC,YACL,OACEe,UACmCb,4BAA4B;YAAC,GAAGa,OAAO;YAAET;QAAW,IACzF;QAACA;KAAY;AAEjB"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { IntegrationConnection } from '#core/models.js';
|
|
2
2
|
export declare function ConnectionPicker({ connections, selectedConnectionId, onSelect, }: {
|
|
3
|
-
connections:
|
|
3
|
+
connections: IntegrationConnection[];
|
|
4
4
|
selectedConnectionId: string | undefined;
|
|
5
5
|
onSelect: (connectionId: string) => void;
|
|
6
6
|
}): import("react").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection-picker.d.ts","sourceRoot":"","sources":["../../src/components/connection-picker.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"connection-picker.d.ts","sourceRoot":"","sources":["../../src/components/connection-picker.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,iBAAiB,CAAC;AAE3D,wBAAgB,gBAAgB,CAAC,EAC/B,WAAW,EACX,oBAAoB,EACpB,QAAQ,GACT,EAAE;IACD,WAAW,EAAE,qBAAqB,EAAE,CAAC;IACrC,oBAAoB,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1C,+BAsBA"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { IntegrationIcon } from '@shipfox/integration-icons';
|
|
2
3
|
import { useIsTextTruncated } from '@shipfox/react-ui/hooks';
|
|
3
4
|
import { Label } from '@shipfox/react-ui/label';
|
|
4
5
|
import { RadioGroup, RadioGroupItem } from '@shipfox/react-ui/radio-group';
|
|
5
6
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@shipfox/react-ui/tooltip';
|
|
6
7
|
import { Text } from '@shipfox/react-ui/typography';
|
|
7
8
|
import { useId } from 'react';
|
|
8
|
-
import { IntegrationIcon } from '#integration-icon.js';
|
|
9
9
|
export function ConnectionPicker({ connections, selectedConnectionId, onSelect }) {
|
|
10
10
|
const labelId = useId();
|
|
11
11
|
return /*#__PURE__*/ _jsxs("div", {
|
|
@@ -33,7 +33,7 @@ export function ConnectionPicker({ connections, selectedConnectionId, onSelect }
|
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
35
|
function ConnectionOption({ connection }) {
|
|
36
|
-
const { ref: nameRef, isTruncated } = useIsTextTruncated(connection.
|
|
36
|
+
const { ref: nameRef, isTruncated } = useIsTextTruncated(connection.displayName);
|
|
37
37
|
return /*#__PURE__*/ _jsxs("span", {
|
|
38
38
|
className: "flex min-w-0 items-center gap-10",
|
|
39
39
|
children: [
|
|
@@ -66,12 +66,12 @@ function ConnectionOption({ connection }) {
|
|
|
66
66
|
as: "span",
|
|
67
67
|
size: "sm",
|
|
68
68
|
bold: true,
|
|
69
|
-
children: connection.
|
|
69
|
+
children: connection.displayName
|
|
70
70
|
})
|
|
71
71
|
})
|
|
72
72
|
}),
|
|
73
73
|
isTruncated ? /*#__PURE__*/ _jsx(TooltipContent, {
|
|
74
|
-
children: connection.
|
|
74
|
+
children: connection.displayName
|
|
75
75
|
}) : null
|
|
76
76
|
]
|
|
77
77
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/connection-picker.tsx"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"sources":["../../src/components/connection-picker.tsx"],"sourcesContent":["import {IntegrationIcon} from '@shipfox/integration-icons';\nimport {useIsTextTruncated} from '@shipfox/react-ui/hooks';\nimport {Label} from '@shipfox/react-ui/label';\nimport {RadioGroup, RadioGroupItem} from '@shipfox/react-ui/radio-group';\nimport {Tooltip, TooltipContent, TooltipTrigger} from '@shipfox/react-ui/tooltip';\nimport {Text} from '@shipfox/react-ui/typography';\nimport {useId} from 'react';\nimport type {IntegrationConnection} from '#core/models.js';\n\nexport function ConnectionPicker({\n connections,\n selectedConnectionId,\n onSelect,\n}: {\n connections: IntegrationConnection[];\n selectedConnectionId: string | undefined;\n onSelect: (connectionId: string) => void;\n}) {\n const labelId = useId();\n\n return (\n <div className=\"flex flex-col gap-10\">\n <Label id={labelId} className=\"sr-only\">\n Source integration\n </Label>\n <RadioGroup\n aria-labelledby={labelId}\n value={selectedConnectionId ?? ''}\n onValueChange={onSelect}\n className=\"grid grid-cols-2 gap-8 min-[1200px]:grid-cols-3 max-[760px]:grid-cols-1\"\n >\n {connections.map((connection) => (\n <RadioGroupItem key={connection.id} value={connection.id} className=\"p-12\">\n <ConnectionOption connection={connection} />\n </RadioGroupItem>\n ))}\n </RadioGroup>\n </div>\n );\n}\n\nfunction ConnectionOption({connection}: {connection: IntegrationConnection}) {\n const {ref: nameRef, isTruncated} = useIsTextTruncated<HTMLSpanElement>(connection.displayName);\n\n return (\n <span className=\"flex min-w-0 items-center gap-10\">\n <Tooltip>\n <TooltipTrigger asChild>\n <span className=\"shrink-0\">\n <IntegrationIcon\n source={connection.provider}\n aria-hidden\n className=\"size-20 text-foreground-neutral-base\"\n />\n </span>\n </TooltipTrigger>\n <TooltipContent>{integrationName(connection.provider)}</TooltipContent>\n </Tooltip>\n\n <Tooltip>\n <TooltipTrigger asChild>\n <span ref={nameRef} className=\"min-w-0 truncate\">\n <Text as=\"span\" size=\"sm\" bold>\n {connection.displayName}\n </Text>\n </span>\n </TooltipTrigger>\n {isTruncated ? <TooltipContent>{connection.displayName}</TooltipContent> : null}\n </Tooltip>\n </span>\n );\n}\n\nfunction integrationName(provider: string): string {\n switch (provider) {\n case 'github':\n return 'GitHub';\n case 'gitea':\n return 'Gitea';\n case 'sentry':\n return 'Sentry';\n case 'webhook':\n return 'Webhook';\n case 'debug':\n return 'Debug';\n default:\n return provider;\n }\n}\n"],"names":["IntegrationIcon","useIsTextTruncated","Label","RadioGroup","RadioGroupItem","Tooltip","TooltipContent","TooltipTrigger","Text","useId","ConnectionPicker","connections","selectedConnectionId","onSelect","labelId","div","className","id","aria-labelledby","value","onValueChange","map","connection","ConnectionOption","ref","nameRef","isTruncated","displayName","span","asChild","source","provider","aria-hidden","integrationName","as","size","bold"],"mappings":";AAAA,SAAQA,eAAe,QAAO,6BAA6B;AAC3D,SAAQC,kBAAkB,QAAO,0BAA0B;AAC3D,SAAQC,KAAK,QAAO,0BAA0B;AAC9C,SAAQC,UAAU,EAAEC,cAAc,QAAO,gCAAgC;AACzE,SAAQC,OAAO,EAAEC,cAAc,EAAEC,cAAc,QAAO,4BAA4B;AAClF,SAAQC,IAAI,QAAO,+BAA+B;AAClD,SAAQC,KAAK,QAAO,QAAQ;AAG5B,OAAO,SAASC,iBAAiB,EAC/BC,WAAW,EACXC,oBAAoB,EACpBC,QAAQ,EAKT;IACC,MAAMC,UAAUL;IAEhB,qBACE,MAACM;QAAIC,WAAU;;0BACb,KAACd;gBAAMe,IAAIH;gBAASE,WAAU;0BAAU;;0BAGxC,KAACb;gBACCe,mBAAiBJ;gBACjBK,OAAOP,wBAAwB;gBAC/BQ,eAAeP;gBACfG,WAAU;0BAETL,YAAYU,GAAG,CAAC,CAACC,2BAChB,KAAClB;wBAAmCe,OAAOG,WAAWL,EAAE;wBAAED,WAAU;kCAClE,cAAA,KAACO;4BAAiBD,YAAYA;;uBADXA,WAAWL,EAAE;;;;AAO5C;AAEA,SAASM,iBAAiB,EAACD,UAAU,EAAsC;IACzE,MAAM,EAACE,KAAKC,OAAO,EAAEC,WAAW,EAAC,GAAGzB,mBAAoCqB,WAAWK,WAAW;IAE9F,qBACE,MAACC;QAAKZ,WAAU;;0BACd,MAACX;;kCACC,KAACE;wBAAesB,OAAO;kCACrB,cAAA,KAACD;4BAAKZ,WAAU;sCACd,cAAA,KAAChB;gCACC8B,QAAQR,WAAWS,QAAQ;gCAC3BC,aAAW;gCACXhB,WAAU;;;;kCAIhB,KAACV;kCAAgB2B,gBAAgBX,WAAWS,QAAQ;;;;0BAGtD,MAAC1B;;kCACC,KAACE;wBAAesB,OAAO;kCACrB,cAAA,KAACD;4BAAKJ,KAAKC;4BAAST,WAAU;sCAC5B,cAAA,KAACR;gCAAK0B,IAAG;gCAAOC,MAAK;gCAAKC,IAAI;0CAC3Bd,WAAWK,WAAW;;;;oBAI5BD,4BAAc,KAACpB;kCAAgBgB,WAAWK,WAAW;yBAAqB;;;;;AAInF;AAEA,SAASM,gBAAgBF,QAAgB;IACvC,OAAQA;QACN,KAAK;YACH,OAAO;QACT,KAAK;YACH,OAAO;QACT,KAAK;YACH,OAAO;QACT,KAAK;YACH,OAAO;QACT,KAAK;YACH,OAAO;QACT;YACE,OAAOA;IACX;AACF"}
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type { UseQueryResult } from '@tanstack/react-query';
|
|
1
|
+
import { type IntegrationConnection } from '#core/models.js';
|
|
3
2
|
interface InstalledIntegrationsSectionProps {
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
connections: IntegrationConnection[];
|
|
4
|
+
isPending: boolean;
|
|
5
|
+
isFetching: boolean;
|
|
6
|
+
error?: Error | null | undefined;
|
|
7
|
+
onRetry: () => void;
|
|
6
8
|
isMutating: boolean;
|
|
7
9
|
onUse: (connectionId: string) => void;
|
|
8
|
-
onSetActive: (connection:
|
|
10
|
+
onSetActive: (connection: IntegrationConnection, active: boolean) => void;
|
|
9
11
|
onDelete: (connectionId: string) => void;
|
|
10
12
|
providerDisplayName: (provider: string) => string | undefined;
|
|
11
13
|
}
|
|
12
|
-
export declare function InstalledIntegrationsSection({
|
|
14
|
+
export declare function InstalledIntegrationsSection({ connections, isPending, isFetching, error, onRetry, isMutating, onUse, onSetActive, onDelete, providerDisplayName, }: InstalledIntegrationsSectionProps): import("react").JSX.Element;
|
|
13
15
|
export {};
|
|
14
16
|
//# sourceMappingURL=installed-integrations-section.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"installed-integrations-section.d.ts","sourceRoot":"","sources":["../../src/components/installed-integrations-section.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"installed-integrations-section.d.ts","sourceRoot":"","sources":["../../src/components/installed-integrations-section.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAAC,KAAK,qBAAqB,EAAqB,MAAM,iBAAiB,CAAC;AAG/E,UAAU,iCAAiC;IACzC,WAAW,EAAE,qBAAqB,EAAE,CAAC;IACrC,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,GAAG,SAAS,CAAC;IACjC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,WAAW,EAAE,CAAC,UAAU,EAAE,qBAAqB,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1E,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,mBAAmB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CAC/D;AAKD,wBAAgB,4BAA4B,CAAC,EAC3C,WAAW,EACX,SAAS,EACT,UAAU,EACV,KAAK,EACL,OAAO,EACP,UAAU,EACV,KAAK,EACL,WAAW,EACX,QAAQ,EACR,mBAAmB,GACpB,EAAE,iCAAiC,+BAgDnC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { QueryLoadError } from '@shipfox/client-ui';
|
|
3
|
+
import { IntegrationIcon } from '@shipfox/integration-icons';
|
|
3
4
|
import { IconButton } from '@shipfox/react-ui/button';
|
|
4
5
|
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from '@shipfox/react-ui/dropdown-menu';
|
|
5
6
|
import { EmptyState } from '@shipfox/react-ui/empty-state';
|
|
@@ -8,10 +9,10 @@ import { Header, Text } from '@shipfox/react-ui/typography';
|
|
|
8
9
|
import { cn, formatDate } from '@shipfox/react-ui/utils';
|
|
9
10
|
import { Link } from '@tanstack/react-router';
|
|
10
11
|
import { ConnectionStatusBadge } from '#connection-status-badge.js';
|
|
11
|
-
import {
|
|
12
|
+
import { isUsableConnection } from '#core/models.js';
|
|
12
13
|
import { usageEventsForConnection } from './integration-usage-events.js';
|
|
13
14
|
const INSTALLED_SURFACE_CLASS = 'overflow-hidden rounded-8 border border-border-neutral-base bg-background-neutral-base';
|
|
14
|
-
export function InstalledIntegrationsSection({
|
|
15
|
+
export function InstalledIntegrationsSection({ connections, isPending, isFetching, error, onRetry, isMutating, onUse, onSetActive, onDelete, providerDisplayName }) {
|
|
15
16
|
return /*#__PURE__*/ _jsxs("section", {
|
|
16
17
|
className: "flex flex-col gap-16",
|
|
17
18
|
"aria-label": "Installed integrations",
|
|
@@ -30,17 +31,23 @@ export function InstalledIntegrationsSection({ connectionsQuery, connections, is
|
|
|
30
31
|
})
|
|
31
32
|
]
|
|
32
33
|
}),
|
|
33
|
-
|
|
34
|
+
isPending ? /*#__PURE__*/ _jsx(InstalledSkeleton, {
|
|
34
35
|
label: "Loading integrations"
|
|
35
36
|
}) : null,
|
|
36
|
-
|
|
37
|
+
error ? /*#__PURE__*/ _jsx("div", {
|
|
37
38
|
className: cn(INSTALLED_SURFACE_CLASS, 'px-16'),
|
|
38
39
|
children: /*#__PURE__*/ _jsx(QueryLoadError, {
|
|
39
|
-
query:
|
|
40
|
+
query: {
|
|
41
|
+
isError: true,
|
|
42
|
+
isFetching,
|
|
43
|
+
data: undefined,
|
|
44
|
+
error,
|
|
45
|
+
refetch: onRetry
|
|
46
|
+
},
|
|
40
47
|
subject: "integrations"
|
|
41
48
|
})
|
|
42
49
|
}) : null,
|
|
43
|
-
|
|
50
|
+
!isPending && !error && connections.length === 0 ? /*#__PURE__*/ _jsx("div", {
|
|
44
51
|
className: cn(INSTALLED_SURFACE_CLASS, 'px-16'),
|
|
45
52
|
children: /*#__PURE__*/ _jsx(EmptyState, {
|
|
46
53
|
icon: "componentLine",
|
|
@@ -63,8 +70,8 @@ export function InstalledIntegrationsSection({ connectionsQuery, connections, is
|
|
|
63
70
|
});
|
|
64
71
|
}
|
|
65
72
|
function InstalledRow({ connection, isMutating, onUse, onSetActive, onDelete, providerDisplayName }) {
|
|
66
|
-
const muted = connection.
|
|
67
|
-
const active = connection
|
|
73
|
+
const muted = connection.lifecycleStatus === 'disabled';
|
|
74
|
+
const active = isUsableConnection(connection);
|
|
68
75
|
const recentEventsEvent = usageEventsForConnection(connection)[0]?.value ?? 'received';
|
|
69
76
|
const providerName = providerDisplayName(connection.provider);
|
|
70
77
|
return /*#__PURE__*/ _jsxs("li", {
|
|
@@ -85,10 +92,10 @@ function InstalledRow({ connection, isMutating, onUse, onSetActive, onDelete, pr
|
|
|
85
92
|
size: "md",
|
|
86
93
|
bold: true,
|
|
87
94
|
className: cn('truncate', muted ? 'text-foreground-neutral-disabled' : undefined),
|
|
88
|
-
children: connection.
|
|
95
|
+
children: connection.displayName
|
|
89
96
|
}),
|
|
90
97
|
/*#__PURE__*/ _jsx(ConnectionStatusBadge, {
|
|
91
|
-
status: connection.
|
|
98
|
+
status: connection.lifecycleStatus,
|
|
92
99
|
className: "shrink-0"
|
|
93
100
|
})
|
|
94
101
|
]
|
|
@@ -98,7 +105,7 @@ function InstalledRow({ connection, isMutating, onUse, onSetActive, onDelete, pr
|
|
|
98
105
|
className: "truncate text-foreground-neutral-muted",
|
|
99
106
|
children: [
|
|
100
107
|
"Added ",
|
|
101
|
-
formatDate(connection.
|
|
108
|
+
formatDate(connection.createdAt)
|
|
102
109
|
]
|
|
103
110
|
})
|
|
104
111
|
]
|
|
@@ -111,16 +118,16 @@ function InstalledRow({ connection, isMutating, onUse, onSetActive, onDelete, pr
|
|
|
111
118
|
size: "sm",
|
|
112
119
|
variant: "transparent",
|
|
113
120
|
icon: "more2Line",
|
|
114
|
-
"aria-label": `Open ${connection.
|
|
121
|
+
"aria-label": `Open ${connection.displayName} integration actions`
|
|
115
122
|
})
|
|
116
123
|
}),
|
|
117
124
|
/*#__PURE__*/ _jsxs(DropdownMenuContent, {
|
|
118
125
|
align: "end",
|
|
119
126
|
children: [
|
|
120
|
-
connection.
|
|
127
|
+
connection.externalUrl ? /*#__PURE__*/ _jsx(DropdownMenuItem, {
|
|
121
128
|
asChild: true,
|
|
122
129
|
children: /*#__PURE__*/ _jsx("a", {
|
|
123
|
-
href: connection.
|
|
130
|
+
href: connection.externalUrl,
|
|
124
131
|
target: "_blank",
|
|
125
132
|
rel: "noreferrer noopener",
|
|
126
133
|
children: providerName ? `Open in ${providerName}` : 'Open provider settings'
|
|
@@ -135,7 +142,7 @@ function InstalledRow({ connection, isMutating, onUse, onSetActive, onDelete, pr
|
|
|
135
142
|
children: /*#__PURE__*/ _jsx(Link, {
|
|
136
143
|
to: "/workspaces/$wid/settings/events",
|
|
137
144
|
params: {
|
|
138
|
-
wid: connection.
|
|
145
|
+
wid: connection.workspaceId
|
|
139
146
|
},
|
|
140
147
|
search: {
|
|
141
148
|
source: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/installed-integrations-section.tsx"],"sourcesContent":["import type {\n IntegrationConnectionDto,\n ListIntegrationConnectionsResponseDto,\n} from '@shipfox/api-integration-core-dto';\nimport {QueryLoadError} from '@shipfox/client-ui';\nimport {IconButton} from '@shipfox/react-ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '@shipfox/react-ui/dropdown-menu';\nimport {EmptyState} from '@shipfox/react-ui/empty-state';\nimport {Skeleton} from '@shipfox/react-ui/skeleton';\nimport {Header, Text} from '@shipfox/react-ui/typography';\nimport {cn, formatDate} from '@shipfox/react-ui/utils';\nimport type {UseQueryResult} from '@tanstack/react-query';\nimport {Link} from '@tanstack/react-router';\nimport {ConnectionStatusBadge} from '#connection-status-badge.js';\nimport {IntegrationIcon} from '#integration-icon.js';\nimport {usageEventsForConnection} from './integration-usage-events.js';\n\ninterface InstalledIntegrationsSectionProps {\n connectionsQuery: UseQueryResult<ListIntegrationConnectionsResponseDto, Error>;\n connections: IntegrationConnectionDto[];\n isMutating: boolean;\n onUse: (connectionId: string) => void;\n onSetActive: (connection: IntegrationConnectionDto, active: boolean) => void;\n onDelete: (connectionId: string) => void;\n providerDisplayName: (provider: string) => string | undefined;\n}\n\nconst INSTALLED_SURFACE_CLASS =\n 'overflow-hidden rounded-8 border border-border-neutral-base bg-background-neutral-base';\n\nexport function InstalledIntegrationsSection({\n connectionsQuery,\n connections,\n isMutating,\n onUse,\n onSetActive,\n onDelete,\n providerDisplayName,\n}: InstalledIntegrationsSectionProps) {\n return (\n <section className=\"flex flex-col gap-16\" aria-label=\"Installed integrations\">\n <div className=\"flex flex-col gap-4\">\n <Header variant=\"h3\">Installed integrations</Header>\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\">\n Provider accounts installed in this workspace.\n </Text>\n </div>\n\n {connectionsQuery.isPending ? <InstalledSkeleton label=\"Loading integrations\" /> : null}\n\n {connectionsQuery.isError && connectionsQuery.data === undefined ? (\n <div className={cn(INSTALLED_SURFACE_CLASS, 'px-16')}>\n <QueryLoadError query={connectionsQuery} subject=\"integrations\" />\n </div>\n ) : null}\n\n {connectionsQuery.data !== undefined && connections.length === 0 ? (\n <div className={cn(INSTALLED_SURFACE_CLASS, 'px-16')}>\n <EmptyState\n icon=\"componentLine\"\n title=\"No integrations installed yet\"\n description=\"Install a provider below to get started.\"\n />\n </div>\n ) : null}\n\n {connections.length > 0 ? (\n <ul className={cn('divide-y divide-border-neutral-base', INSTALLED_SURFACE_CLASS)}>\n {connections.map((connection) => (\n <InstalledRow\n key={connection.id}\n connection={connection}\n isMutating={isMutating}\n onUse={onUse}\n onSetActive={(nextActive) => onSetActive(connection, nextActive)}\n onDelete={onDelete}\n providerDisplayName={providerDisplayName}\n />\n ))}\n </ul>\n ) : null}\n </section>\n );\n}\n\nfunction InstalledRow({\n connection,\n isMutating,\n onUse,\n onSetActive,\n onDelete,\n providerDisplayName,\n}: {\n connection: IntegrationConnectionDto;\n isMutating: boolean;\n onUse: (connectionId: string) => void;\n onSetActive: (active: boolean) => void;\n onDelete: (connectionId: string) => void;\n providerDisplayName: (provider: string) => string | undefined;\n}) {\n const muted = connection.lifecycle_status === 'disabled';\n const active = connection.lifecycle_status === 'active';\n const recentEventsEvent = usageEventsForConnection(connection)[0]?.value ?? 'received';\n const providerName = providerDisplayName(connection.provider);\n\n return (\n <li className=\"flex items-center gap-12 px-16 py-12 transition-colors hover:bg-background-components-hover\">\n <IntegrationIcon\n source={connection.provider}\n aria-hidden\n className={cn(\n 'size-24 shrink-0',\n muted ? 'text-foreground-neutral-disabled' : 'text-foreground-neutral-base',\n )}\n />\n <div className=\"flex min-w-0 flex-1 flex-col gap-2\">\n <div className=\"flex min-w-0 items-center gap-8\">\n <Text\n size=\"md\"\n bold\n className={cn('truncate', muted ? 'text-foreground-neutral-disabled' : undefined)}\n >\n {connection.display_name}\n </Text>\n <ConnectionStatusBadge status={connection.lifecycle_status} className=\"shrink-0\" />\n </div>\n <Text size=\"sm\" className=\"truncate text-foreground-neutral-muted\">\n Added {formatDate(connection.created_at)}\n </Text>\n </div>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <IconButton\n size=\"sm\"\n variant=\"transparent\"\n icon=\"more2Line\"\n aria-label={`Open ${connection.display_name} integration actions`}\n />\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n {connection.external_url ? (\n <DropdownMenuItem asChild>\n <a href={connection.external_url} target=\"_blank\" rel=\"noreferrer noopener\">\n {providerName ? `Open in ${providerName}` : 'Open provider settings'}\n </a>\n </DropdownMenuItem>\n ) : null}\n <DropdownMenuItem onSelect={() => onUse(connection.id)}>\n Use this integration\n </DropdownMenuItem>\n <DropdownMenuItem asChild>\n <Link\n to=\"/workspaces/$wid/settings/events\"\n params={{wid: connection.workspace_id}}\n search={{source: [connection.slug], event: [recentEventsEvent]}}\n >\n View recent events\n </Link>\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem disabled={isMutating} onSelect={() => onSetActive(!active)}>\n {active ? 'Disable integration' : 'Enable integration'}\n </DropdownMenuItem>\n <DropdownMenuItem disabled={isMutating} onSelect={() => onDelete(connection.id)}>\n Delete integration\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </li>\n );\n}\n\nfunction InstalledSkeleton({label}: {label: string}) {\n return (\n <ul\n role=\"status\"\n aria-label={label}\n className={cn('divide-y divide-border-neutral-base', INSTALLED_SURFACE_CLASS)}\n >\n {[0, 1, 2].map((row) => (\n <li key={row} className=\"flex items-center gap-12 px-16 py-12\">\n <Skeleton className=\"size-24 shrink-0\" />\n <div className=\"flex min-w-0 flex-1 flex-col gap-2\">\n <Skeleton className=\"h-16 w-120\" />\n <Skeleton className=\"h-12 w-80\" />\n </div>\n <Skeleton className=\"h-20 w-72 shrink-0\" />\n </li>\n ))}\n </ul>\n );\n}\n"],"names":["QueryLoadError","IconButton","DropdownMenu","DropdownMenuContent","DropdownMenuItem","DropdownMenuSeparator","DropdownMenuTrigger","EmptyState","Skeleton","Header","Text","cn","formatDate","Link","ConnectionStatusBadge","IntegrationIcon","usageEventsForConnection","INSTALLED_SURFACE_CLASS","InstalledIntegrationsSection","connectionsQuery","connections","isMutating","onUse","onSetActive","onDelete","providerDisplayName","section","className","aria-label","div","variant","size","isPending","InstalledSkeleton","label","isError","data","undefined","query","subject","length","icon","title","description","ul","map","connection","InstalledRow","nextActive","id","muted","lifecycle_status","active","recentEventsEvent","value","providerName","provider","li","source","aria-hidden","bold","display_name","status","created_at","asChild","align","external_url","a","href","target","rel","onSelect","to","params","wid","workspace_id","search","slug","event","disabled","role","row"],"mappings":";AAIA,SAAQA,cAAc,QAAO,qBAAqB;AAClD,SAAQC,UAAU,QAAO,2BAA2B;AACpD,SACEC,YAAY,EACZC,mBAAmB,EACnBC,gBAAgB,EAChBC,qBAAqB,EACrBC,mBAAmB,QACd,kCAAkC;AACzC,SAAQC,UAAU,QAAO,gCAAgC;AACzD,SAAQC,QAAQ,QAAO,6BAA6B;AACpD,SAAQC,MAAM,EAAEC,IAAI,QAAO,+BAA+B;AAC1D,SAAQC,EAAE,EAAEC,UAAU,QAAO,0BAA0B;AAEvD,SAAQC,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,qBAAqB,QAAO,8BAA8B;AAClE,SAAQC,eAAe,QAAO,uBAAuB;AACrD,SAAQC,wBAAwB,QAAO,gCAAgC;AAYvE,MAAMC,0BACJ;AAEF,OAAO,SAASC,6BAA6B,EAC3CC,gBAAgB,EAChBC,WAAW,EACXC,UAAU,EACVC,KAAK,EACLC,WAAW,EACXC,QAAQ,EACRC,mBAAmB,EACe;IAClC,qBACE,MAACC;QAAQC,WAAU;QAAuBC,cAAW;;0BACnD,MAACC;gBAAIF,WAAU;;kCACb,KAAClB;wBAAOqB,SAAQ;kCAAK;;kCACrB,KAACpB;wBAAKqB,MAAK;wBAAKJ,WAAU;kCAAgC;;;;YAK3DR,iBAAiBa,SAAS,iBAAG,KAACC;gBAAkBC,OAAM;iBAA4B;YAElFf,iBAAiBgB,OAAO,IAAIhB,iBAAiBiB,IAAI,KAAKC,0BACrD,KAACR;gBAAIF,WAAWhB,GAAGM,yBAAyB;0BAC1C,cAAA,KAACjB;oBAAesC,OAAOnB;oBAAkBoB,SAAQ;;iBAEjD;YAEHpB,iBAAiBiB,IAAI,KAAKC,aAAajB,YAAYoB,MAAM,KAAK,kBAC7D,KAACX;gBAAIF,WAAWhB,GAAGM,yBAAyB;0BAC1C,cAAA,KAACV;oBACCkC,MAAK;oBACLC,OAAM;oBACNC,aAAY;;iBAGd;YAEHvB,YAAYoB,MAAM,GAAG,kBACpB,KAACI;gBAAGjB,WAAWhB,GAAG,uCAAuCM;0BACtDG,YAAYyB,GAAG,CAAC,CAACC,2BAChB,KAACC;wBAECD,YAAYA;wBACZzB,YAAYA;wBACZC,OAAOA;wBACPC,aAAa,CAACyB,aAAezB,YAAYuB,YAAYE;wBACrDxB,UAAUA;wBACVC,qBAAqBA;uBANhBqB,WAAWG,EAAE;iBAUtB;;;AAGV;AAEA,SAASF,aAAa,EACpBD,UAAU,EACVzB,UAAU,EACVC,KAAK,EACLC,WAAW,EACXC,QAAQ,EACRC,mBAAmB,EAQpB;IACC,MAAMyB,QAAQJ,WAAWK,gBAAgB,KAAK;IAC9C,MAAMC,SAASN,WAAWK,gBAAgB,KAAK;IAC/C,MAAME,oBAAoBrC,yBAAyB8B,WAAW,CAAC,EAAE,EAAEQ,SAAS;IAC5E,MAAMC,eAAe9B,oBAAoBqB,WAAWU,QAAQ;IAE5D,qBACE,MAACC;QAAG9B,WAAU;;0BACZ,KAACZ;gBACC2C,QAAQZ,WAAWU,QAAQ;gBAC3BG,aAAW;gBACXhC,WAAWhB,GACT,oBACAuC,QAAQ,qCAAqC;;0BAGjD,MAACrB;gBAAIF,WAAU;;kCACb,MAACE;wBAAIF,WAAU;;0CACb,KAACjB;gCACCqB,MAAK;gCACL6B,IAAI;gCACJjC,WAAWhB,GAAG,YAAYuC,QAAQ,qCAAqCb;0CAEtES,WAAWe,YAAY;;0CAE1B,KAAC/C;gCAAsBgD,QAAQhB,WAAWK,gBAAgB;gCAAExB,WAAU;;;;kCAExE,MAACjB;wBAAKqB,MAAK;wBAAKJ,WAAU;;4BAAyC;4BAC1Df,WAAWkC,WAAWiB,UAAU;;;;;0BAG3C,MAAC7D;;kCACC,KAACI;wBAAoB0D,OAAO;kCAC1B,cAAA,KAAC/D;4BACC8B,MAAK;4BACLD,SAAQ;4BACRW,MAAK;4BACLb,cAAY,CAAC,KAAK,EAAEkB,WAAWe,YAAY,CAAC,oBAAoB,CAAC;;;kCAGrE,MAAC1D;wBAAoB8D,OAAM;;4BACxBnB,WAAWoB,YAAY,iBACtB,KAAC9D;gCAAiB4D,OAAO;0CACvB,cAAA,KAACG;oCAAEC,MAAMtB,WAAWoB,YAAY;oCAAEG,QAAO;oCAASC,KAAI;8CACnDf,eAAe,CAAC,QAAQ,EAAEA,cAAc,GAAG;;iCAG9C;0CACJ,KAACnD;gCAAiBmE,UAAU,IAAMjD,MAAMwB,WAAWG,EAAE;0CAAG;;0CAGxD,KAAC7C;gCAAiB4D,OAAO;0CACvB,cAAA,KAACnD;oCACC2D,IAAG;oCACHC,QAAQ;wCAACC,KAAK5B,WAAW6B,YAAY;oCAAA;oCACrCC,QAAQ;wCAAClB,QAAQ;4CAACZ,WAAW+B,IAAI;yCAAC;wCAAEC,OAAO;4CAACzB;yCAAkB;oCAAA;8CAC/D;;;0CAIH,KAAChD;0CACD,KAACD;gCAAiB2E,UAAU1D;gCAAYkD,UAAU,IAAMhD,YAAY,CAAC6B;0CAClEA,SAAS,wBAAwB;;0CAEpC,KAAChD;gCAAiB2E,UAAU1D;gCAAYkD,UAAU,IAAM/C,SAASsB,WAAWG,EAAE;0CAAG;;;;;;;;AAO3F;AAEA,SAAShB,kBAAkB,EAACC,KAAK,EAAkB;IACjD,qBACE,KAACU;QACCoC,MAAK;QACLpD,cAAYM;QACZP,WAAWhB,GAAG,uCAAuCM;kBAEpD;YAAC;YAAG;YAAG;SAAE,CAAC4B,GAAG,CAAC,CAACoC,oBACd,MAACxB;gBAAa9B,WAAU;;kCACtB,KAACnB;wBAASmB,WAAU;;kCACpB,MAACE;wBAAIF,WAAU;;0CACb,KAACnB;gCAASmB,WAAU;;0CACpB,KAACnB;gCAASmB,WAAU;;;;kCAEtB,KAACnB;wBAASmB,WAAU;;;eANbsD;;AAWjB"}
|
|
1
|
+
{"version":3,"sources":["../../src/components/installed-integrations-section.tsx"],"sourcesContent":["import {QueryLoadError} from '@shipfox/client-ui';\nimport {IntegrationIcon} from '@shipfox/integration-icons';\nimport {IconButton} from '@shipfox/react-ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '@shipfox/react-ui/dropdown-menu';\nimport {EmptyState} from '@shipfox/react-ui/empty-state';\nimport {Skeleton} from '@shipfox/react-ui/skeleton';\nimport {Header, Text} from '@shipfox/react-ui/typography';\nimport {cn, formatDate} from '@shipfox/react-ui/utils';\nimport {Link} from '@tanstack/react-router';\nimport {ConnectionStatusBadge} from '#connection-status-badge.js';\nimport {type IntegrationConnection, isUsableConnection} from '#core/models.js';\nimport {usageEventsForConnection} from './integration-usage-events.js';\n\ninterface InstalledIntegrationsSectionProps {\n connections: IntegrationConnection[];\n isPending: boolean;\n isFetching: boolean;\n error?: Error | null | undefined;\n onRetry: () => void;\n isMutating: boolean;\n onUse: (connectionId: string) => void;\n onSetActive: (connection: IntegrationConnection, active: boolean) => void;\n onDelete: (connectionId: string) => void;\n providerDisplayName: (provider: string) => string | undefined;\n}\n\nconst INSTALLED_SURFACE_CLASS =\n 'overflow-hidden rounded-8 border border-border-neutral-base bg-background-neutral-base';\n\nexport function InstalledIntegrationsSection({\n connections,\n isPending,\n isFetching,\n error,\n onRetry,\n isMutating,\n onUse,\n onSetActive,\n onDelete,\n providerDisplayName,\n}: InstalledIntegrationsSectionProps) {\n return (\n <section className=\"flex flex-col gap-16\" aria-label=\"Installed integrations\">\n <div className=\"flex flex-col gap-4\">\n <Header variant=\"h3\">Installed integrations</Header>\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\">\n Provider accounts installed in this workspace.\n </Text>\n </div>\n\n {isPending ? <InstalledSkeleton label=\"Loading integrations\" /> : null}\n\n {error ? (\n <div className={cn(INSTALLED_SURFACE_CLASS, 'px-16')}>\n <QueryLoadError\n query={{isError: true, isFetching, data: undefined, error, refetch: onRetry}}\n subject=\"integrations\"\n />\n </div>\n ) : null}\n\n {!isPending && !error && connections.length === 0 ? (\n <div className={cn(INSTALLED_SURFACE_CLASS, 'px-16')}>\n <EmptyState\n icon=\"componentLine\"\n title=\"No integrations installed yet\"\n description=\"Install a provider below to get started.\"\n />\n </div>\n ) : null}\n\n {connections.length > 0 ? (\n <ul className={cn('divide-y divide-border-neutral-base', INSTALLED_SURFACE_CLASS)}>\n {connections.map((connection) => (\n <InstalledRow\n key={connection.id}\n connection={connection}\n isMutating={isMutating}\n onUse={onUse}\n onSetActive={(nextActive) => onSetActive(connection, nextActive)}\n onDelete={onDelete}\n providerDisplayName={providerDisplayName}\n />\n ))}\n </ul>\n ) : null}\n </section>\n );\n}\n\nfunction InstalledRow({\n connection,\n isMutating,\n onUse,\n onSetActive,\n onDelete,\n providerDisplayName,\n}: {\n connection: IntegrationConnection;\n isMutating: boolean;\n onUse: (connectionId: string) => void;\n onSetActive: (active: boolean) => void;\n onDelete: (connectionId: string) => void;\n providerDisplayName: (provider: string) => string | undefined;\n}) {\n const muted = connection.lifecycleStatus === 'disabled';\n const active = isUsableConnection(connection);\n const recentEventsEvent = usageEventsForConnection(connection)[0]?.value ?? 'received';\n const providerName = providerDisplayName(connection.provider);\n\n return (\n <li className=\"flex items-center gap-12 px-16 py-12 transition-colors hover:bg-background-components-hover\">\n <IntegrationIcon\n source={connection.provider}\n aria-hidden\n className={cn(\n 'size-24 shrink-0',\n muted ? 'text-foreground-neutral-disabled' : 'text-foreground-neutral-base',\n )}\n />\n <div className=\"flex min-w-0 flex-1 flex-col gap-2\">\n <div className=\"flex min-w-0 items-center gap-8\">\n <Text\n size=\"md\"\n bold\n className={cn('truncate', muted ? 'text-foreground-neutral-disabled' : undefined)}\n >\n {connection.displayName}\n </Text>\n <ConnectionStatusBadge status={connection.lifecycleStatus} className=\"shrink-0\" />\n </div>\n <Text size=\"sm\" className=\"truncate text-foreground-neutral-muted\">\n Added {formatDate(connection.createdAt)}\n </Text>\n </div>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <IconButton\n size=\"sm\"\n variant=\"transparent\"\n icon=\"more2Line\"\n aria-label={`Open ${connection.displayName} integration actions`}\n />\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n {connection.externalUrl ? (\n <DropdownMenuItem asChild>\n <a href={connection.externalUrl} target=\"_blank\" rel=\"noreferrer noopener\">\n {providerName ? `Open in ${providerName}` : 'Open provider settings'}\n </a>\n </DropdownMenuItem>\n ) : null}\n <DropdownMenuItem onSelect={() => onUse(connection.id)}>\n Use this integration\n </DropdownMenuItem>\n <DropdownMenuItem asChild>\n <Link\n to=\"/workspaces/$wid/settings/events\"\n params={{wid: connection.workspaceId}}\n search={{source: [connection.slug], event: [recentEventsEvent]}}\n >\n View recent events\n </Link>\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem disabled={isMutating} onSelect={() => onSetActive(!active)}>\n {active ? 'Disable integration' : 'Enable integration'}\n </DropdownMenuItem>\n <DropdownMenuItem disabled={isMutating} onSelect={() => onDelete(connection.id)}>\n Delete integration\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </li>\n );\n}\n\nfunction InstalledSkeleton({label}: {label: string}) {\n return (\n <ul\n role=\"status\"\n aria-label={label}\n className={cn('divide-y divide-border-neutral-base', INSTALLED_SURFACE_CLASS)}\n >\n {[0, 1, 2].map((row) => (\n <li key={row} className=\"flex items-center gap-12 px-16 py-12\">\n <Skeleton className=\"size-24 shrink-0\" />\n <div className=\"flex min-w-0 flex-1 flex-col gap-2\">\n <Skeleton className=\"h-16 w-120\" />\n <Skeleton className=\"h-12 w-80\" />\n </div>\n <Skeleton className=\"h-20 w-72 shrink-0\" />\n </li>\n ))}\n </ul>\n );\n}\n"],"names":["QueryLoadError","IntegrationIcon","IconButton","DropdownMenu","DropdownMenuContent","DropdownMenuItem","DropdownMenuSeparator","DropdownMenuTrigger","EmptyState","Skeleton","Header","Text","cn","formatDate","Link","ConnectionStatusBadge","isUsableConnection","usageEventsForConnection","INSTALLED_SURFACE_CLASS","InstalledIntegrationsSection","connections","isPending","isFetching","error","onRetry","isMutating","onUse","onSetActive","onDelete","providerDisplayName","section","className","aria-label","div","variant","size","InstalledSkeleton","label","query","isError","data","undefined","refetch","subject","length","icon","title","description","ul","map","connection","InstalledRow","nextActive","id","muted","lifecycleStatus","active","recentEventsEvent","value","providerName","provider","li","source","aria-hidden","bold","displayName","status","createdAt","asChild","align","externalUrl","a","href","target","rel","onSelect","to","params","wid","workspaceId","search","slug","event","disabled","role","row"],"mappings":";AAAA,SAAQA,cAAc,QAAO,qBAAqB;AAClD,SAAQC,eAAe,QAAO,6BAA6B;AAC3D,SAAQC,UAAU,QAAO,2BAA2B;AACpD,SACEC,YAAY,EACZC,mBAAmB,EACnBC,gBAAgB,EAChBC,qBAAqB,EACrBC,mBAAmB,QACd,kCAAkC;AACzC,SAAQC,UAAU,QAAO,gCAAgC;AACzD,SAAQC,QAAQ,QAAO,6BAA6B;AACpD,SAAQC,MAAM,EAAEC,IAAI,QAAO,+BAA+B;AAC1D,SAAQC,EAAE,EAAEC,UAAU,QAAO,0BAA0B;AACvD,SAAQC,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,qBAAqB,QAAO,8BAA8B;AAClE,SAAoCC,kBAAkB,QAAO,kBAAkB;AAC/E,SAAQC,wBAAwB,QAAO,gCAAgC;AAevE,MAAMC,0BACJ;AAEF,OAAO,SAASC,6BAA6B,EAC3CC,WAAW,EACXC,SAAS,EACTC,UAAU,EACVC,KAAK,EACLC,OAAO,EACPC,UAAU,EACVC,KAAK,EACLC,WAAW,EACXC,QAAQ,EACRC,mBAAmB,EACe;IAClC,qBACE,MAACC;QAAQC,WAAU;QAAuBC,cAAW;;0BACnD,MAACC;gBAAIF,WAAU;;kCACb,KAACrB;wBAAOwB,SAAQ;kCAAK;;kCACrB,KAACvB;wBAAKwB,MAAK;wBAAKJ,WAAU;kCAAgC;;;;YAK3DV,0BAAY,KAACe;gBAAkBC,OAAM;iBAA4B;YAEjEd,sBACC,KAACU;gBAAIF,WAAWnB,GAAGM,yBAAyB;0BAC1C,cAAA,KAAClB;oBACCsC,OAAO;wBAACC,SAAS;wBAAMjB;wBAAYkB,MAAMC;wBAAWlB;wBAAOmB,SAASlB;oBAAO;oBAC3EmB,SAAQ;;iBAGV;YAEH,CAACtB,aAAa,CAACE,SAASH,YAAYwB,MAAM,KAAK,kBAC9C,KAACX;gBAAIF,WAAWnB,GAAGM,yBAAyB;0BAC1C,cAAA,KAACV;oBACCqC,MAAK;oBACLC,OAAM;oBACNC,aAAY;;iBAGd;YAEH3B,YAAYwB,MAAM,GAAG,kBACpB,KAACI;gBAAGjB,WAAWnB,GAAG,uCAAuCM;0BACtDE,YAAY6B,GAAG,CAAC,CAACC,2BAChB,KAACC;wBAECD,YAAYA;wBACZzB,YAAYA;wBACZC,OAAOA;wBACPC,aAAa,CAACyB,aAAezB,YAAYuB,YAAYE;wBACrDxB,UAAUA;wBACVC,qBAAqBA;uBANhBqB,WAAWG,EAAE;iBAUtB;;;AAGV;AAEA,SAASF,aAAa,EACpBD,UAAU,EACVzB,UAAU,EACVC,KAAK,EACLC,WAAW,EACXC,QAAQ,EACRC,mBAAmB,EAQpB;IACC,MAAMyB,QAAQJ,WAAWK,eAAe,KAAK;IAC7C,MAAMC,SAASxC,mBAAmBkC;IAClC,MAAMO,oBAAoBxC,yBAAyBiC,WAAW,CAAC,EAAE,EAAEQ,SAAS;IAC5E,MAAMC,eAAe9B,oBAAoBqB,WAAWU,QAAQ;IAE5D,qBACE,MAACC;QAAG9B,WAAU;;0BACZ,KAAC9B;gBACC6D,QAAQZ,WAAWU,QAAQ;gBAC3BG,aAAW;gBACXhC,WAAWnB,GACT,oBACA0C,QAAQ,qCAAqC;;0BAGjD,MAACrB;gBAAIF,WAAU;;kCACb,MAACE;wBAAIF,WAAU;;0CACb,KAACpB;gCACCwB,MAAK;gCACL6B,IAAI;gCACJjC,WAAWnB,GAAG,YAAY0C,QAAQ,qCAAqCb;0CAEtES,WAAWe,WAAW;;0CAEzB,KAAClD;gCAAsBmD,QAAQhB,WAAWK,eAAe;gCAAExB,WAAU;;;;kCAEvE,MAACpB;wBAAKwB,MAAK;wBAAKJ,WAAU;;4BAAyC;4BAC1DlB,WAAWqC,WAAWiB,SAAS;;;;;0BAG1C,MAAChE;;kCACC,KAACI;wBAAoB6D,OAAO;kCAC1B,cAAA,KAAClE;4BACCiC,MAAK;4BACLD,SAAQ;4BACRW,MAAK;4BACLb,cAAY,CAAC,KAAK,EAAEkB,WAAWe,WAAW,CAAC,oBAAoB,CAAC;;;kCAGpE,MAAC7D;wBAAoBiE,OAAM;;4BACxBnB,WAAWoB,WAAW,iBACrB,KAACjE;gCAAiB+D,OAAO;0CACvB,cAAA,KAACG;oCAAEC,MAAMtB,WAAWoB,WAAW;oCAAEG,QAAO;oCAASC,KAAI;8CAClDf,eAAe,CAAC,QAAQ,EAAEA,cAAc,GAAG;;iCAG9C;0CACJ,KAACtD;gCAAiBsE,UAAU,IAAMjD,MAAMwB,WAAWG,EAAE;0CAAG;;0CAGxD,KAAChD;gCAAiB+D,OAAO;0CACvB,cAAA,KAACtD;oCACC8D,IAAG;oCACHC,QAAQ;wCAACC,KAAK5B,WAAW6B,WAAW;oCAAA;oCACpCC,QAAQ;wCAAClB,QAAQ;4CAACZ,WAAW+B,IAAI;yCAAC;wCAAEC,OAAO;4CAACzB;yCAAkB;oCAAA;8CAC/D;;;0CAIH,KAACnD;0CACD,KAACD;gCAAiB8E,UAAU1D;gCAAYkD,UAAU,IAAMhD,YAAY,CAAC6B;0CAClEA,SAAS,wBAAwB;;0CAEpC,KAACnD;gCAAiB8E,UAAU1D;gCAAYkD,UAAU,IAAM/C,SAASsB,WAAWG,EAAE;0CAAG;;;;;;;;AAO3F;AAEA,SAASjB,kBAAkB,EAACC,KAAK,EAAkB;IACjD,qBACE,KAACW;QACCoC,MAAK;QACLpD,cAAYK;QACZN,WAAWnB,GAAG,uCAAuCM;kBAEpD;YAAC;YAAG;YAAG;SAAE,CAAC+B,GAAG,CAAC,CAACoC,oBACd,MAACxB;gBAAa9B,WAAU;;kCACtB,KAACtB;wBAASsB,WAAU;;kCACpB,MAACE;wBAAIF,WAAU;;0CACb,KAACtB;gCAASsB,WAAU;;0CACpB,KAACtB;gCAASsB,WAAU;;;;kCAEtB,KAACtB;wBAASsB,WAAU;;;eANbsD;;AAWjB"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { IntegrationCapability } from '#core/models.js';
|
|
2
2
|
interface IntegrationGalleryForWorkspaceProps {
|
|
3
|
-
capability:
|
|
3
|
+
capability: IntegrationCapability | undefined;
|
|
4
4
|
emptyProvidersMessage: string;
|
|
5
5
|
workspaceId: string;
|
|
6
6
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integration-gallery-for-workspace.d.ts","sourceRoot":"","sources":["../../src/components/integration-gallery-for-workspace.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"integration-gallery-for-workspace.d.ts","sourceRoot":"","sources":["../../src/components/integration-gallery-for-workspace.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,qBAAqB,EAGtB,MAAM,iBAAiB,CAAC;AAmBzB,UAAU,mCAAmC;IAC3C,UAAU,EAAE,qBAAqB,GAAG,SAAS,CAAC;IAC9C,qBAAqB,EAAE,MAAM,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,8BAA8B,CAAC,EAC7C,UAAU,EACV,qBAAqB,EACrB,WAAW,GACZ,EAAE,mCAAmC,+BAmKrC"}
|
|
@@ -24,24 +24,24 @@ export function IntegrationGalleryForWorkspace({ capability, emptyProvidersMessa
|
|
|
24
24
|
const deleteConnection = useDeleteIntegrationConnectionMutation();
|
|
25
25
|
const updateWebhookConnection = useUpdateWebhookConnectionMutation();
|
|
26
26
|
const deleteWebhookConnection = useDeleteWebhookConnectionMutation();
|
|
27
|
-
const providers = providersQuery.data
|
|
27
|
+
const providers = providersQuery.data ?? [];
|
|
28
28
|
const providersMap = new Map(providers.map((provider)=>[
|
|
29
29
|
provider.provider,
|
|
30
30
|
provider
|
|
31
31
|
]));
|
|
32
|
-
const allConnections = connectionsQuery.data
|
|
32
|
+
const allConnections = connectionsQuery.data ?? [];
|
|
33
33
|
// Filter in memory so the all-status cache key stays shared; passing capability
|
|
34
34
|
// into the hook would collide with the active-only `source_control` key used
|
|
35
35
|
// elsewhere.
|
|
36
36
|
const connections = capability ? allConnections.filter((connection)=>connection.capabilities.includes(capability)) : allConnections;
|
|
37
|
-
const providerDisplayName = (provider)=>providersMap.get(provider)?.
|
|
37
|
+
const providerDisplayName = (provider)=>providersMap.get(provider)?.displayName;
|
|
38
38
|
const providerLabel = (provider)=>providerDisplayName(provider) ?? provider;
|
|
39
39
|
const sortedConnections = [
|
|
40
40
|
...connections
|
|
41
41
|
].sort((a, b)=>{
|
|
42
42
|
const byProvider = providerLabel(a.provider).localeCompare(providerLabel(b.provider));
|
|
43
43
|
if (byProvider !== 0) return byProvider;
|
|
44
|
-
return a.
|
|
44
|
+
return a.createdAt.localeCompare(b.createdAt);
|
|
45
45
|
});
|
|
46
46
|
const usageConnection = sortedConnections.find((connection)=>connection.id === usageConnectionId) ?? (createdUsageConnection?.id === usageConnectionId ? createdUsageConnection : null) ?? null;
|
|
47
47
|
const deleteConnectionTarget = sortedConnections.find((connection)=>connection.id === deleteConnectionId);
|
|
@@ -91,8 +91,11 @@ export function IntegrationGalleryForWorkspace({ capability, emptyProvidersMessa
|
|
|
91
91
|
className: "flex flex-col gap-24",
|
|
92
92
|
children: [
|
|
93
93
|
/*#__PURE__*/ _jsx(InstalledIntegrationsSection, {
|
|
94
|
-
connectionsQuery: connectionsQuery,
|
|
95
94
|
connections: sortedConnections,
|
|
95
|
+
isPending: connectionsQuery.isPending,
|
|
96
|
+
isFetching: connectionsQuery.isFetching,
|
|
97
|
+
error: connectionsQuery.isError ? connectionsQuery.error : undefined,
|
|
98
|
+
onRetry: ()=>void connectionsQuery.refetch(),
|
|
96
99
|
isMutating: updateConnection.isPending || deleteConnection.isPending || updateWebhookConnection.isPending || deleteWebhookConnection.isPending,
|
|
97
100
|
onUse: setUsageConnectionId,
|
|
98
101
|
onSetActive: (connection, active)=>{
|
|
@@ -120,7 +123,11 @@ export function IntegrationGalleryForWorkspace({ capability, emptyProvidersMessa
|
|
|
120
123
|
]
|
|
121
124
|
}),
|
|
122
125
|
/*#__PURE__*/ _jsx(ProviderGrid, {
|
|
123
|
-
|
|
126
|
+
providers: providers,
|
|
127
|
+
isPending: providersQuery.isPending,
|
|
128
|
+
isFetching: providersQuery.isFetching,
|
|
129
|
+
error: providersQuery.isError ? providersQuery.error : undefined,
|
|
130
|
+
onRetry: ()=>void providersQuery.refetch(),
|
|
124
131
|
workspaceId: workspaceId,
|
|
125
132
|
emptyMessage: emptyProvidersMessage,
|
|
126
133
|
onOpenProvider: setCreateProvider
|
|
@@ -152,7 +159,7 @@ export function IntegrationGalleryForWorkspace({ capability, emptyProvidersMessa
|
|
|
152
159
|
}) : null
|
|
153
160
|
}),
|
|
154
161
|
/*#__PURE__*/ _jsx(IntegrationDeleteConfirmModal, {
|
|
155
|
-
connectionName: deleteConnectionTarget?.
|
|
162
|
+
connectionName: deleteConnectionTarget?.displayName,
|
|
156
163
|
open: deleteConnectionId !== undefined,
|
|
157
164
|
isPending: deleteConnection.isPending || deleteWebhookConnection.isPending,
|
|
158
165
|
onOpenChange: (open)=>{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/integration-gallery-for-workspace.tsx"],"sourcesContent":["import type {\n IntegrationCapabilityDto,\n IntegrationConnectionDto,\n IntegrationProviderDto,\n} from '@shipfox/api-integration-core-dto';\nimport {toast} from '@shipfox/react-ui/toast';\nimport {Header, Text} from '@shipfox/react-ui/typography';\nimport {useState} from 'react';\nimport {\n useDeleteIntegrationConnectionMutation,\n useIntegrationConnectionsQuery,\n useIntegrationProvidersQuery,\n useUpdateIntegrationConnectionMutation,\n} from '#hooks/api/integrations.js';\nimport {\n useDeleteWebhookConnectionMutation,\n useUpdateWebhookConnectionMutation,\n} from '#hooks/api/webhook-connections.js';\nimport {InstalledIntegrationsSection} from './installed-integrations-section.js';\nimport {IntegrationDeleteConfirmModal} from './integration-delete-confirm-modal.js';\nimport {usageEventsForConnection} from './integration-usage-events.js';\nimport {IntegrationUsageModal} from './integration-usage-modal.js';\nimport {ProviderGrid} from './provider-grid.js';\nimport {WebhookCreateModal} from './webhook/webhook-create-modal.js';\nimport {WebhookUsageDetails} from './webhook/webhook-usage-details.js';\n\ninterface IntegrationGalleryForWorkspaceProps {\n capability: IntegrationCapabilityDto | undefined;\n emptyProvidersMessage: string;\n workspaceId: string;\n}\n\nexport function IntegrationGalleryForWorkspace({\n capability,\n emptyProvidersMessage,\n workspaceId,\n}: IntegrationGalleryForWorkspaceProps) {\n const [createProvider, setCreateProvider] = useState<string | undefined>();\n const [usageConnectionId, setUsageConnectionId] = useState<string | undefined>();\n const [createdUsageConnection, setCreatedUsageConnection] = useState<\n IntegrationConnectionDto | undefined\n >();\n const [deleteConnectionId, setDeleteConnectionId] = useState<string | undefined>();\n const providersQuery = useIntegrationProvidersQuery(capability ? {capability} : undefined);\n const connectionsQuery = useIntegrationConnectionsQuery(workspaceId);\n const updateConnection = useUpdateIntegrationConnectionMutation();\n const deleteConnection = useDeleteIntegrationConnectionMutation();\n const updateWebhookConnection = useUpdateWebhookConnectionMutation();\n const deleteWebhookConnection = useDeleteWebhookConnectionMutation();\n\n const providers = providersQuery.data?.providers ?? [];\n const providersMap = new Map<string, IntegrationProviderDto>(\n providers.map((provider) => [provider.provider, provider]),\n );\n\n const allConnections = connectionsQuery.data?.connections ?? [];\n // Filter in memory so the all-status cache key stays shared; passing capability\n // into the hook would collide with the active-only `source_control` key used\n // elsewhere.\n const connections = capability\n ? allConnections.filter((connection) => connection.capabilities.includes(capability))\n : allConnections;\n\n const providerDisplayName = (provider: string) => providersMap.get(provider)?.display_name;\n const providerLabel = (provider: string) => providerDisplayName(provider) ?? provider;\n\n const sortedConnections = [...connections].sort((a, b) => {\n const byProvider = providerLabel(a.provider).localeCompare(providerLabel(b.provider));\n if (byProvider !== 0) return byProvider;\n return a.created_at.localeCompare(b.created_at);\n });\n const usageConnection =\n sortedConnections.find((connection) => connection.id === usageConnectionId) ??\n (createdUsageConnection?.id === usageConnectionId ? createdUsageConnection : null) ??\n null;\n const deleteConnectionTarget = sortedConnections.find(\n (connection) => connection.id === deleteConnectionId,\n );\n\n async function setConnectionActive(connection: IntegrationConnectionDto, active: boolean) {\n try {\n const body = {lifecycle_status: active ? 'active' : 'disabled'} as const;\n if (connection.provider === 'webhook') {\n await updateWebhookConnection.mutateAsync({\n workspaceId,\n connectionId: connection.id,\n body,\n });\n } else {\n await updateConnection.mutateAsync({\n connectionId: connection.id,\n body,\n });\n }\n toast.success(active ? 'Integration enabled.' : 'Integration disabled.');\n } catch (error) {\n toast.error(error instanceof Error ? error.message : 'Could not update integration.');\n }\n }\n\n async function confirmDeleteConnection() {\n if (!deleteConnectionTarget) return;\n try {\n if (deleteConnectionTarget.provider === 'webhook') {\n await deleteWebhookConnection.mutateAsync({\n workspaceId,\n connectionId: deleteConnectionTarget.id,\n });\n } else {\n await deleteConnection.mutateAsync({\n workspaceId,\n connectionId: deleteConnectionTarget.id,\n });\n }\n toast.success('Integration deleted.');\n setDeleteConnectionId(undefined);\n } catch (error) {\n toast.error(error instanceof Error ? error.message : 'Could not delete integration.');\n }\n }\n\n return (\n <div className=\"flex flex-col gap-24\">\n <InstalledIntegrationsSection\n connectionsQuery={connectionsQuery}\n connections={sortedConnections}\n isMutating={\n updateConnection.isPending ||\n deleteConnection.isPending ||\n updateWebhookConnection.isPending ||\n deleteWebhookConnection.isPending\n }\n onUse={setUsageConnectionId}\n onSetActive={(connection, active) => {\n void setConnectionActive(connection, active);\n }}\n onDelete={setDeleteConnectionId}\n providerDisplayName={providerDisplayName}\n />\n\n <section className=\"flex flex-col gap-16\" aria-label=\"Available integrations\">\n <div className=\"flex flex-col gap-4\">\n <Header variant=\"h3\">Available integrations</Header>\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\">\n Providers available to install in this workspace.\n </Text>\n </div>\n\n <ProviderGrid\n providersQuery={providersQuery}\n workspaceId={workspaceId}\n emptyMessage={emptyProvidersMessage}\n onOpenProvider={setCreateProvider}\n />\n </section>\n <WebhookCreateModal\n workspaceId={workspaceId}\n open={createProvider === 'webhook'}\n onOpenChange={(open) => setCreateProvider(open ? 'webhook' : undefined)}\n onCreated={(connection) => {\n setCreatedUsageConnection(connection);\n setUsageConnectionId(connection.id);\n }}\n />\n <IntegrationUsageModal\n connection={usageConnection}\n events={usageConnection ? usageEventsForConnection(usageConnection) : []}\n open={usageConnection !== null}\n onOpenChange={(open) => {\n if (!open) {\n setUsageConnectionId(undefined);\n setCreatedUsageConnection(undefined);\n }\n }}\n >\n {usageConnection?.provider === 'webhook' ? (\n <WebhookUsageDetails workspaceId={workspaceId} connectionId={usageConnection.id} />\n ) : null}\n </IntegrationUsageModal>\n <IntegrationDeleteConfirmModal\n connectionName={deleteConnectionTarget?.display_name}\n open={deleteConnectionId !== undefined}\n isPending={deleteConnection.isPending || deleteWebhookConnection.isPending}\n onOpenChange={(open) => {\n if (!open) setDeleteConnectionId(undefined);\n }}\n onConfirm={() => {\n void confirmDeleteConnection();\n }}\n />\n </div>\n );\n}\n"],"names":["toast","Header","Text","useState","useDeleteIntegrationConnectionMutation","useIntegrationConnectionsQuery","useIntegrationProvidersQuery","useUpdateIntegrationConnectionMutation","useDeleteWebhookConnectionMutation","useUpdateWebhookConnectionMutation","InstalledIntegrationsSection","IntegrationDeleteConfirmModal","usageEventsForConnection","IntegrationUsageModal","ProviderGrid","WebhookCreateModal","WebhookUsageDetails","IntegrationGalleryForWorkspace","capability","emptyProvidersMessage","workspaceId","createProvider","setCreateProvider","usageConnectionId","setUsageConnectionId","createdUsageConnection","setCreatedUsageConnection","deleteConnectionId","setDeleteConnectionId","providersQuery","undefined","connectionsQuery","updateConnection","deleteConnection","updateWebhookConnection","deleteWebhookConnection","providers","data","providersMap","Map","map","provider","allConnections","connections","filter","connection","capabilities","includes","providerDisplayName","get","display_name","providerLabel","sortedConnections","sort","a","b","byProvider","localeCompare","created_at","usageConnection","find","id","deleteConnectionTarget","setConnectionActive","active","body","lifecycle_status","mutateAsync","connectionId","success","error","Error","message","confirmDeleteConnection","div","className","isMutating","isPending","onUse","onSetActive","onDelete","section","aria-label","variant","size","emptyMessage","onOpenProvider","open","onOpenChange","onCreated","events","connectionName","onConfirm"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/components/integration-gallery-for-workspace.tsx"],"sourcesContent":["import {toast} from '@shipfox/react-ui/toast';\nimport {Header, Text} from '@shipfox/react-ui/typography';\nimport {useState} from 'react';\nimport type {\n IntegrationCapability,\n IntegrationConnection,\n IntegrationProvider,\n} from '#core/models.js';\nimport {\n useDeleteIntegrationConnectionMutation,\n useIntegrationConnectionsQuery,\n useIntegrationProvidersQuery,\n useUpdateIntegrationConnectionMutation,\n} from '#hooks/api/integrations.js';\nimport {\n useDeleteWebhookConnectionMutation,\n useUpdateWebhookConnectionMutation,\n} from '#hooks/api/webhook-connections.js';\nimport {InstalledIntegrationsSection} from './installed-integrations-section.js';\nimport {IntegrationDeleteConfirmModal} from './integration-delete-confirm-modal.js';\nimport {usageEventsForConnection} from './integration-usage-events.js';\nimport {IntegrationUsageModal} from './integration-usage-modal.js';\nimport {ProviderGrid} from './provider-grid.js';\nimport {WebhookCreateModal} from './webhook/webhook-create-modal.js';\nimport {WebhookUsageDetails} from './webhook/webhook-usage-details.js';\n\ninterface IntegrationGalleryForWorkspaceProps {\n capability: IntegrationCapability | undefined;\n emptyProvidersMessage: string;\n workspaceId: string;\n}\n\nexport function IntegrationGalleryForWorkspace({\n capability,\n emptyProvidersMessage,\n workspaceId,\n}: IntegrationGalleryForWorkspaceProps) {\n const [createProvider, setCreateProvider] = useState<string | undefined>();\n const [usageConnectionId, setUsageConnectionId] = useState<string | undefined>();\n const [createdUsageConnection, setCreatedUsageConnection] = useState<\n IntegrationConnection | undefined\n >();\n const [deleteConnectionId, setDeleteConnectionId] = useState<string | undefined>();\n const providersQuery = useIntegrationProvidersQuery(capability ? {capability} : undefined);\n const connectionsQuery = useIntegrationConnectionsQuery(workspaceId);\n const updateConnection = useUpdateIntegrationConnectionMutation();\n const deleteConnection = useDeleteIntegrationConnectionMutation();\n const updateWebhookConnection = useUpdateWebhookConnectionMutation();\n const deleteWebhookConnection = useDeleteWebhookConnectionMutation();\n\n const providers = providersQuery.data ?? [];\n const providersMap = new Map<string, IntegrationProvider>(\n providers.map((provider) => [provider.provider, provider]),\n );\n\n const allConnections = connectionsQuery.data ?? [];\n // Filter in memory so the all-status cache key stays shared; passing capability\n // into the hook would collide with the active-only `source_control` key used\n // elsewhere.\n const connections = capability\n ? allConnections.filter((connection) => connection.capabilities.includes(capability))\n : allConnections;\n\n const providerDisplayName = (provider: string) => providersMap.get(provider)?.displayName;\n const providerLabel = (provider: string) => providerDisplayName(provider) ?? provider;\n\n const sortedConnections = [...connections].sort((a, b) => {\n const byProvider = providerLabel(a.provider).localeCompare(providerLabel(b.provider));\n if (byProvider !== 0) return byProvider;\n return a.createdAt.localeCompare(b.createdAt);\n });\n const usageConnection =\n sortedConnections.find((connection) => connection.id === usageConnectionId) ??\n (createdUsageConnection?.id === usageConnectionId ? createdUsageConnection : null) ??\n null;\n const deleteConnectionTarget = sortedConnections.find(\n (connection) => connection.id === deleteConnectionId,\n );\n\n async function setConnectionActive(connection: IntegrationConnection, active: boolean) {\n try {\n const body = {lifecycle_status: active ? 'active' : 'disabled'} as const;\n if (connection.provider === 'webhook') {\n await updateWebhookConnection.mutateAsync({\n workspaceId,\n connectionId: connection.id,\n body,\n });\n } else {\n await updateConnection.mutateAsync({\n connectionId: connection.id,\n body,\n });\n }\n toast.success(active ? 'Integration enabled.' : 'Integration disabled.');\n } catch (error) {\n toast.error(error instanceof Error ? error.message : 'Could not update integration.');\n }\n }\n\n async function confirmDeleteConnection() {\n if (!deleteConnectionTarget) return;\n try {\n if (deleteConnectionTarget.provider === 'webhook') {\n await deleteWebhookConnection.mutateAsync({\n workspaceId,\n connectionId: deleteConnectionTarget.id,\n });\n } else {\n await deleteConnection.mutateAsync({\n workspaceId,\n connectionId: deleteConnectionTarget.id,\n });\n }\n toast.success('Integration deleted.');\n setDeleteConnectionId(undefined);\n } catch (error) {\n toast.error(error instanceof Error ? error.message : 'Could not delete integration.');\n }\n }\n\n return (\n <div className=\"flex flex-col gap-24\">\n <InstalledIntegrationsSection\n connections={sortedConnections}\n isPending={connectionsQuery.isPending}\n isFetching={connectionsQuery.isFetching}\n error={connectionsQuery.isError ? connectionsQuery.error : undefined}\n onRetry={() => void connectionsQuery.refetch()}\n isMutating={\n updateConnection.isPending ||\n deleteConnection.isPending ||\n updateWebhookConnection.isPending ||\n deleteWebhookConnection.isPending\n }\n onUse={setUsageConnectionId}\n onSetActive={(connection, active) => {\n void setConnectionActive(connection, active);\n }}\n onDelete={setDeleteConnectionId}\n providerDisplayName={providerDisplayName}\n />\n\n <section className=\"flex flex-col gap-16\" aria-label=\"Available integrations\">\n <div className=\"flex flex-col gap-4\">\n <Header variant=\"h3\">Available integrations</Header>\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\">\n Providers available to install in this workspace.\n </Text>\n </div>\n\n <ProviderGrid\n providers={providers}\n isPending={providersQuery.isPending}\n isFetching={providersQuery.isFetching}\n error={providersQuery.isError ? providersQuery.error : undefined}\n onRetry={() => void providersQuery.refetch()}\n workspaceId={workspaceId}\n emptyMessage={emptyProvidersMessage}\n onOpenProvider={setCreateProvider}\n />\n </section>\n <WebhookCreateModal\n workspaceId={workspaceId}\n open={createProvider === 'webhook'}\n onOpenChange={(open) => setCreateProvider(open ? 'webhook' : undefined)}\n onCreated={(connection) => {\n setCreatedUsageConnection(connection);\n setUsageConnectionId(connection.id);\n }}\n />\n <IntegrationUsageModal\n connection={usageConnection}\n events={usageConnection ? usageEventsForConnection(usageConnection) : []}\n open={usageConnection !== null}\n onOpenChange={(open) => {\n if (!open) {\n setUsageConnectionId(undefined);\n setCreatedUsageConnection(undefined);\n }\n }}\n >\n {usageConnection?.provider === 'webhook' ? (\n <WebhookUsageDetails workspaceId={workspaceId} connectionId={usageConnection.id} />\n ) : null}\n </IntegrationUsageModal>\n <IntegrationDeleteConfirmModal\n connectionName={deleteConnectionTarget?.displayName}\n open={deleteConnectionId !== undefined}\n isPending={deleteConnection.isPending || deleteWebhookConnection.isPending}\n onOpenChange={(open) => {\n if (!open) setDeleteConnectionId(undefined);\n }}\n onConfirm={() => {\n void confirmDeleteConnection();\n }}\n />\n </div>\n );\n}\n"],"names":["toast","Header","Text","useState","useDeleteIntegrationConnectionMutation","useIntegrationConnectionsQuery","useIntegrationProvidersQuery","useUpdateIntegrationConnectionMutation","useDeleteWebhookConnectionMutation","useUpdateWebhookConnectionMutation","InstalledIntegrationsSection","IntegrationDeleteConfirmModal","usageEventsForConnection","IntegrationUsageModal","ProviderGrid","WebhookCreateModal","WebhookUsageDetails","IntegrationGalleryForWorkspace","capability","emptyProvidersMessage","workspaceId","createProvider","setCreateProvider","usageConnectionId","setUsageConnectionId","createdUsageConnection","setCreatedUsageConnection","deleteConnectionId","setDeleteConnectionId","providersQuery","undefined","connectionsQuery","updateConnection","deleteConnection","updateWebhookConnection","deleteWebhookConnection","providers","data","providersMap","Map","map","provider","allConnections","connections","filter","connection","capabilities","includes","providerDisplayName","get","displayName","providerLabel","sortedConnections","sort","a","b","byProvider","localeCompare","createdAt","usageConnection","find","id","deleteConnectionTarget","setConnectionActive","active","body","lifecycle_status","mutateAsync","connectionId","success","error","Error","message","confirmDeleteConnection","div","className","isPending","isFetching","isError","onRetry","refetch","isMutating","onUse","onSetActive","onDelete","section","aria-label","variant","size","emptyMessage","onOpenProvider","open","onOpenChange","onCreated","events","connectionName","onConfirm"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { IntegrationCapability } from '#core/models.js';
|
|
2
2
|
export interface IntegrationGalleryProps {
|
|
3
|
-
capability?:
|
|
3
|
+
capability?: IntegrationCapability;
|
|
4
4
|
emptyProvidersMessage?: string;
|
|
5
5
|
workspaceId?: string;
|
|
6
6
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integration-gallery.d.ts","sourceRoot":"","sources":["../../src/components/integration-gallery.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"integration-gallery.d.ts","sourceRoot":"","sources":["../../src/components/integration-gallery.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,iBAAiB,CAAC;AAG3D,MAAM,WAAW,uBAAuB;IACtC,UAAU,CAAC,EAAE,qBAAqB,CAAC;IACnC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,EACjC,UAAU,EACV,qBAAmF,EACnF,WAAW,GACZ,EAAE,uBAAuB,+BAiBzB"}
|