@shipfox/client-integrations 12.0.1 → 13.0.0
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 +41 -0
- package/dist/components/callback-status-shell.d.ts +4 -3
- package/dist/components/callback-status-shell.d.ts.map +1 -1
- package/dist/components/callback-status-shell.js +11 -11
- package/dist/components/callback-status-shell.js.map +1 -1
- package/dist/components/installed-integrations-section.d.ts +2 -1
- package/dist/components/installed-integrations-section.d.ts.map +1 -1
- package/dist/components/installed-integrations-section.js +7 -6
- package/dist/components/installed-integrations-section.js.map +1 -1
- package/dist/components/integration-gallery-for-workspace.d.ts.map +1 -1
- package/dist/components/integration-gallery-for-workspace.js +11 -2
- package/dist/components/integration-gallery-for-workspace.js.map +1 -1
- package/dist/components/integration-gallery.stories.js +10 -9
- package/dist/components/integration-gallery.stories.js.map +1 -1
- package/dist/components/provider-grid.d.ts +2 -2
- package/dist/components/provider-grid.d.ts.map +1 -1
- package/dist/components/provider-grid.js +4 -4
- package/dist/components/provider-grid.js.map +1 -1
- package/dist/components/redirect-install-page.d.ts +1 -1
- package/dist/components/redirect-install-page.js +2 -2
- package/dist/components/redirect-install-page.js.map +1 -1
- package/dist/components/webhook/webhook-modals.stories.js +2 -2
- package/dist/components/webhook/webhook-modals.stories.js.map +1 -1
- package/dist/feature.d.ts +7 -7
- package/dist/feature.js +7 -7
- package/dist/feature.js.map +1 -1
- package/dist/hooks/api/integrations.js +1 -1
- package/dist/hooks/api/integrations.js.map +1 -1
- package/dist/pages/gitea-install-page.js +4 -4
- 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 +58 -12
- package/dist/pages/linear-callback-page.js.map +1 -1
- package/dist/pages/sentry-callback-page.d.ts.map +1 -1
- package/dist/pages/sentry-callback-page.js +22 -9
- package/dist/pages/sentry-callback-page.js.map +1 -1
- package/dist/pages/slack-callback-page.d.ts.map +1 -1
- package/dist/pages/slack-callback-page.js +50 -18
- package/dist/pages/slack-callback-page.js.map +1 -1
- package/dist/pages/source-control-onboarding-page.js +1 -1
- package/dist/pages/source-control-onboarding-page.js.map +1 -1
- package/dist/provider-catalog.d.ts +1 -1
- package/dist/provider-catalog.d.ts.map +1 -1
- package/dist/provider-catalog.js +5 -5
- package/dist/provider-catalog.js.map +1 -1
- package/dist/sentry-callback.js +2 -2
- package/dist/sentry-callback.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/dist/workspace-navigation.d.ts +13 -0
- package/dist/workspace-navigation.d.ts.map +1 -0
- package/dist/workspace-navigation.js +17 -0
- package/dist/workspace-navigation.js.map +1 -0
- package/package.json +13 -13
- package/src/components/callback-status-shell.tsx +14 -10
- package/src/components/installed-integrations-section.tsx +16 -9
- package/src/components/integration-gallery-for-workspace.tsx +20 -10
- package/src/components/integration-gallery.stories.tsx +10 -10
- package/src/components/integration-gallery.test.tsx +30 -15
- package/src/components/provider-grid.tsx +6 -6
- package/src/components/redirect-install-page.test.tsx +3 -3
- package/src/components/redirect-install-page.tsx +2 -2
- package/src/components/webhook/webhook-modals.stories.tsx +2 -2
- package/src/feature.ts +7 -7
- package/src/hooks/api/integrations.ts +1 -1
- package/src/pages/gitea-install-page.tsx +2 -2
- package/src/pages/linear-callback-page.test.tsx +25 -12
- package/src/pages/linear-callback-page.tsx +73 -12
- package/src/pages/sentry-callback-page.test.tsx +8 -5
- package/src/pages/sentry-callback-page.tsx +32 -8
- package/src/pages/slack-callback-page.test.tsx +78 -0
- package/src/pages/slack-callback-page.tsx +56 -18
- package/src/pages/source-control-onboarding-page.test.tsx +4 -4
- package/src/pages/source-control-onboarding-page.tsx +1 -1
- package/src/provider-catalog.test.ts +4 -4
- package/src/provider-catalog.ts +10 -10
- package/src/sentry-callback.ts +2 -2
- package/src/workspace-navigation.test.ts +43 -0
- package/src/workspace-navigation.ts +38 -0
- package/test/render.tsx +2 -1
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-grid.d.ts","sourceRoot":"","sources":["../../src/components/provider-grid.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,iBAAiB,CAAC;AAGzD,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,mBAAmB,EAAE,CAAC;IACjC,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,GAAG,SAAS,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,
|
|
1
|
+
{"version":3,"file":"provider-grid.d.ts","sourceRoot":"","sources":["../../src/components/provider-grid.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,iBAAiB,CAAC;AAGzD,MAAM,WAAW,iBAAiB;IAChC,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,mBAAmB,EAAE,CAAC;IACjC,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,GAAG,SAAS,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CAC3D;AAED,eAAO,MAAM,mBAAmB,oDAAoD,CAAC;AAErF,eAAO,MAAM,sBAAsB,2FACuD,CAAC;AAE3F,wBAAgB,YAAY,CAAC,EAC3B,aAAa,EACb,SAAS,EACT,SAAS,EACT,UAAkB,EAClB,KAAK,EACL,OAAO,EACP,YAAY,EACZ,YAAkC,EAClC,YAAuC,EACvC,cAAc,GACf,EAAE,iBAAiB,+BA+CnB"}
|
|
@@ -11,7 +11,7 @@ import { Link } from '@tanstack/react-router';
|
|
|
11
11
|
import { PROVIDER_CATALOG } from '#provider-catalog.js';
|
|
12
12
|
export const PROVIDER_GRID_CLASS = 'grid grid-cols-2 gap-12 max-[760px]:grid-cols-1';
|
|
13
13
|
export const PROVIDER_SURFACE_CLASS = 'overflow-hidden rounded-8 border border-border-neutral-base bg-background-neutral-base';
|
|
14
|
-
export function ProviderGrid({ providers, isPending, isFetching = false, error, onRetry,
|
|
14
|
+
export function ProviderGrid({ workspaceSlug, providers, isPending, isFetching = false, error, onRetry, emptyMessage, loadingLabel = 'Loading providers', errorSubject = 'available integrations', onOpenProvider }) {
|
|
15
15
|
const installableProviders = providers.filter((provider)=>PROVIDER_CATALOG[provider.provider]);
|
|
16
16
|
if (isPending) return /*#__PURE__*/ _jsx(ProviderGridSkeleton, {
|
|
17
17
|
label: loadingLabel
|
|
@@ -46,13 +46,13 @@ export function ProviderGrid({ providers, isPending, isFetching = false, error,
|
|
|
46
46
|
children: installableProviders.map((provider)=>/*#__PURE__*/ _jsx("li", {
|
|
47
47
|
children: /*#__PURE__*/ _jsx(ProviderCard, {
|
|
48
48
|
provider: provider,
|
|
49
|
-
|
|
49
|
+
workspaceSlug: workspaceSlug,
|
|
50
50
|
onOpenProvider: onOpenProvider
|
|
51
51
|
})
|
|
52
52
|
}, provider.provider))
|
|
53
53
|
});
|
|
54
54
|
}
|
|
55
|
-
function ProviderCard({ provider,
|
|
55
|
+
function ProviderCard({ provider, workspaceSlug, onOpenProvider }) {
|
|
56
56
|
const catalog = PROVIDER_CATALOG[provider.provider];
|
|
57
57
|
if (!catalog) return null;
|
|
58
58
|
if (catalog.kind === 'modal-connect') {
|
|
@@ -70,7 +70,7 @@ function ProviderCard({ provider, workspaceId, onOpenProvider }) {
|
|
|
70
70
|
return /*#__PURE__*/ _jsx(Link, {
|
|
71
71
|
to: catalog.setupPath,
|
|
72
72
|
params: {
|
|
73
|
-
|
|
73
|
+
workspaceSlug
|
|
74
74
|
},
|
|
75
75
|
"aria-label": `Install ${provider.displayName}`,
|
|
76
76
|
className: "group flex h-full min-w-0 items-center justify-between gap-12 rounded-8 border border-border-neutral-base bg-background-neutral-base p-16 transition-colors hover:bg-background-components-hover focus-visible:shadow-button-neutral-focus focus-visible:outline-none",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/provider-grid.tsx"],"sourcesContent":["import {QueryLoadError} from '@shipfox/client-ui';\nimport {IntegrationIcon} from '@shipfox/integration-icons';\nimport {Card} from '@shipfox/react-ui/card';\nimport {EmptyState} from '@shipfox/react-ui/empty-state';\nimport {Icon} from '@shipfox/react-ui/icon';\nimport {Skeleton} from '@shipfox/react-ui/skeleton';\nimport {Text} from '@shipfox/react-ui/typography';\nimport {cn} from '@shipfox/react-ui/utils';\nimport {Link} from '@tanstack/react-router';\nimport type {IntegrationProvider} from '#core/models.js';\nimport {PROVIDER_CATALOG} from '#provider-catalog.js';\n\nexport interface ProviderGridProps {\n providers: IntegrationProvider[];\n isPending: boolean;\n isFetching?: boolean;\n error?: Error | null | undefined;\n onRetry?: () => void;\n
|
|
1
|
+
{"version":3,"sources":["../../src/components/provider-grid.tsx"],"sourcesContent":["import {QueryLoadError} from '@shipfox/client-ui';\nimport {IntegrationIcon} from '@shipfox/integration-icons';\nimport {Card} from '@shipfox/react-ui/card';\nimport {EmptyState} from '@shipfox/react-ui/empty-state';\nimport {Icon} from '@shipfox/react-ui/icon';\nimport {Skeleton} from '@shipfox/react-ui/skeleton';\nimport {Text} from '@shipfox/react-ui/typography';\nimport {cn} from '@shipfox/react-ui/utils';\nimport {Link} from '@tanstack/react-router';\nimport type {IntegrationProvider} from '#core/models.js';\nimport {PROVIDER_CATALOG} from '#provider-catalog.js';\n\nexport interface ProviderGridProps {\n workspaceSlug: string;\n providers: IntegrationProvider[];\n isPending: boolean;\n isFetching?: boolean;\n error?: Error | null | undefined;\n onRetry?: () => void;\n emptyMessage: string;\n loadingLabel?: string;\n errorSubject?: string;\n onOpenProvider?: ((provider: string) => void) | undefined;\n}\n\nexport const PROVIDER_GRID_CLASS = 'grid grid-cols-2 gap-12 max-[760px]:grid-cols-1';\n\nexport const PROVIDER_SURFACE_CLASS =\n 'overflow-hidden rounded-8 border border-border-neutral-base bg-background-neutral-base';\n\nexport function ProviderGrid({\n workspaceSlug,\n providers,\n isPending,\n isFetching = false,\n error,\n onRetry,\n emptyMessage,\n loadingLabel = 'Loading providers',\n errorSubject = 'available integrations',\n onOpenProvider,\n}: ProviderGridProps) {\n const installableProviders = providers.filter((provider) => PROVIDER_CATALOG[provider.provider]);\n\n if (isPending) return <ProviderGridSkeleton label={loadingLabel} />;\n\n if (error) {\n return (\n <div className={cn(PROVIDER_SURFACE_CLASS, 'px-16')}>\n <QueryLoadError\n query={{\n isError: true,\n isFetching,\n data: undefined,\n error,\n refetch: onRetry ?? (() => undefined),\n }}\n subject={errorSubject}\n />\n </div>\n );\n }\n\n if (installableProviders.length === 0) {\n return (\n <div className={cn(PROVIDER_SURFACE_CLASS, 'px-16')}>\n <EmptyState\n icon=\"componentLine\"\n title=\"No integrations available\"\n description={emptyMessage}\n />\n </div>\n );\n }\n\n return (\n <ul className={PROVIDER_GRID_CLASS}>\n {installableProviders.map((provider) => (\n <li key={provider.provider}>\n <ProviderCard\n provider={provider}\n workspaceSlug={workspaceSlug}\n onOpenProvider={onOpenProvider}\n />\n </li>\n ))}\n </ul>\n );\n}\n\nfunction ProviderCard({\n provider,\n workspaceSlug,\n onOpenProvider,\n}: {\n provider: IntegrationProvider;\n workspaceSlug: string;\n onOpenProvider?: ((provider: string) => void) | undefined;\n}) {\n const catalog = PROVIDER_CATALOG[provider.provider];\n if (!catalog) return null;\n\n if (catalog.kind === 'modal-connect') {\n return (\n <button\n type=\"button\"\n aria-label={`Add ${provider.displayName}`}\n onClick={() => onOpenProvider?.(provider.provider)}\n className=\"group flex h-full w-full min-w-0 items-center justify-between gap-12 rounded-8 border border-border-neutral-base bg-background-neutral-base p-16 text-left transition-colors hover:bg-background-components-hover focus-visible:shadow-button-neutral-focus focus-visible:outline-none\"\n >\n <ProviderCardContent provider={provider} action=\"Add\" />\n </button>\n );\n }\n\n return (\n <Link\n to={catalog.setupPath}\n params={{workspaceSlug}}\n aria-label={`Install ${provider.displayName}`}\n className=\"group flex h-full min-w-0 items-center justify-between gap-12 rounded-8 border border-border-neutral-base bg-background-neutral-base p-16 transition-colors hover:bg-background-components-hover focus-visible:shadow-button-neutral-focus focus-visible:outline-none\"\n >\n <ProviderCardContent provider={provider} action=\"Install\" />\n </Link>\n );\n}\n\nfunction ProviderCardContent({\n provider,\n action,\n}: {\n provider: IntegrationProvider;\n action: 'Add' | 'Install';\n}) {\n return (\n <>\n <span className=\"flex min-w-0 items-center gap-12\">\n <IntegrationIcon\n source={provider.provider}\n aria-hidden\n className=\"size-24 shrink-0 text-foreground-neutral-base\"\n />\n <Text as=\"span\" size=\"md\" bold className=\"truncate\">\n {provider.displayName}\n </Text>\n </span>\n <span className=\"flex shrink-0 items-center gap-4 text-foreground-neutral-muted transition-colors group-hover:text-foreground-highlight-interactive\">\n <Text as=\"span\" size=\"sm\">\n {action}\n </Text>\n <Icon name=\"chevronRight\" className=\"size-16\" />\n </span>\n </>\n );\n}\n\nfunction ProviderGridSkeleton({label}: {label: string}) {\n return (\n <ul role=\"status\" aria-label={label} className={PROVIDER_GRID_CLASS}>\n {[0, 1, 2, 3].map((tile) => (\n <li key={tile}>\n <Card className=\"h-full p-16\">\n <div className=\"flex items-center justify-between gap-12\">\n <div className=\"flex min-w-0 items-center gap-12\">\n <Skeleton className=\"size-24 shrink-0\" />\n <Skeleton className=\"h-16 w-100\" />\n </div>\n <Skeleton className=\"h-16 w-64 shrink-0\" />\n </div>\n </Card>\n </li>\n ))}\n </ul>\n );\n}\n"],"names":["QueryLoadError","IntegrationIcon","Card","EmptyState","Icon","Skeleton","Text","cn","Link","PROVIDER_CATALOG","PROVIDER_GRID_CLASS","PROVIDER_SURFACE_CLASS","ProviderGrid","workspaceSlug","providers","isPending","isFetching","error","onRetry","emptyMessage","loadingLabel","errorSubject","onOpenProvider","installableProviders","filter","provider","ProviderGridSkeleton","label","div","className","query","isError","data","undefined","refetch","subject","length","icon","title","description","ul","map","li","ProviderCard","catalog","kind","button","type","aria-label","displayName","onClick","ProviderCardContent","action","to","setupPath","params","span","source","aria-hidden","as","size","bold","name","role","tile"],"mappings":"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"}
|
|
@@ -7,7 +7,7 @@ interface RedirectInstallPageProps {
|
|
|
7
7
|
loadingLabel?: string;
|
|
8
8
|
/**
|
|
9
9
|
* Runs before leaving the app (e.g. to persist the workspace id for a
|
|
10
|
-
* state-less provider callback
|
|
10
|
+
* state-less provider callback. It must not throw. A failed side effect
|
|
11
11
|
* should never block the redirect.
|
|
12
12
|
*/
|
|
13
13
|
beforeRedirect?: (workspaceId: string) => void;
|
|
@@ -52,9 +52,9 @@ export function RedirectInstallPage({ installRequest, errorFallbackMessage, load
|
|
|
52
52
|
variant: "muted",
|
|
53
53
|
className: "w-fit",
|
|
54
54
|
children: /*#__PURE__*/ _jsx(Link, {
|
|
55
|
-
to: "/
|
|
55
|
+
to: "/w/$workspaceSlug/integrations",
|
|
56
56
|
params: {
|
|
57
|
-
|
|
57
|
+
workspaceSlug: workspace.slug
|
|
58
58
|
},
|
|
59
59
|
children: "Back to integrations"
|
|
60
60
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/redirect-install-page.tsx"],"sourcesContent":["import {ApiError} from '@shipfox/client-api';\nimport {useActiveWorkspace} from '@shipfox/client-auth';\nimport {ButtonLink} from '@shipfox/react-ui/button';\nimport {Callout} from '@shipfox/react-ui/callout';\nimport {FullPageLoader} from '@shipfox/react-ui/loader';\nimport {Text} from '@shipfox/react-ui/typography';\nimport {Link} from '@tanstack/react-router';\nimport {useEffect, useRef, useState} from 'react';\nimport type {InstallRedirect} from '#core/models.js';\n\ninterface RedirectInstallPageProps {\n installRequest: (body: {workspace_id: string}) => Promise<InstallRedirect>;\n errorFallbackMessage: string;\n loadingLabel?: string;\n /**\n * Runs before leaving the app (e.g. to persist the workspace id for a\n * state-less provider callback
|
|
1
|
+
{"version":3,"sources":["../../src/components/redirect-install-page.tsx"],"sourcesContent":["import {ApiError} from '@shipfox/client-api';\nimport {useActiveWorkspace} from '@shipfox/client-auth';\nimport {ButtonLink} from '@shipfox/react-ui/button';\nimport {Callout} from '@shipfox/react-ui/callout';\nimport {FullPageLoader} from '@shipfox/react-ui/loader';\nimport {Text} from '@shipfox/react-ui/typography';\nimport {Link} from '@tanstack/react-router';\nimport {useEffect, useRef, useState} from 'react';\nimport type {InstallRedirect} from '#core/models.js';\n\ninterface RedirectInstallPageProps {\n installRequest: (body: {workspace_id: string}) => Promise<InstallRedirect>;\n errorFallbackMessage: string;\n loadingLabel?: string;\n /**\n * Runs before leaving the app (e.g. to persist the workspace id for a\n * state-less provider callback. It must not throw. A failed side effect\n * should never block the redirect.\n */\n beforeRedirect?: (workspaceId: string) => void;\n /** Injectable for tests: jsdom's window.location cannot be stubbed. */\n assignLocation?: (url: string) => void;\n}\n\nexport function RedirectInstallPage({\n installRequest,\n errorFallbackMessage,\n loadingLabel = 'Starting installation',\n beforeRedirect,\n assignLocation = (url) => window.location.assign(url),\n}: RedirectInstallPageProps) {\n const workspace = useActiveWorkspace();\n const startedRef = useRef(false);\n const [errorMessage, setErrorMessage] = useState<string | undefined>();\n\n useEffect(() => {\n if (startedRef.current) return;\n startedRef.current = true;\n // The side effect is best-effort persistence; a throw here must never\n // block the install redirect, so swallow it and continue.\n try {\n beforeRedirect?.(workspace.id);\n } catch {\n // ignore\n }\n installRequest({workspace_id: workspace.id})\n .then((response) => {\n assignLocation(response.installUrl);\n })\n .catch((error: unknown) => {\n setErrorMessage(error instanceof ApiError ? error.message : errorFallbackMessage);\n });\n }, [workspace, installRequest, beforeRedirect, errorFallbackMessage, assignLocation]);\n\n if (errorMessage) {\n return (\n <div className=\"mx-auto flex w-full max-w-[480px] flex-col gap-16\">\n <Callout role=\"alert\" type=\"error\">\n <Text size=\"sm\">{errorMessage}</Text>\n </Callout>\n <ButtonLink asChild variant=\"muted\" className=\"w-fit\">\n <Link to=\"/w/$workspaceSlug/integrations\" params={{workspaceSlug: workspace.slug}}>\n Back to integrations\n </Link>\n </ButtonLink>\n </div>\n );\n }\n\n return <FullPageLoader aria-label={loadingLabel} />;\n}\n"],"names":["ApiError","useActiveWorkspace","ButtonLink","Callout","FullPageLoader","Text","Link","useEffect","useRef","useState","RedirectInstallPage","installRequest","errorFallbackMessage","loadingLabel","beforeRedirect","assignLocation","url","window","location","assign","workspace","startedRef","errorMessage","setErrorMessage","current","id","workspace_id","then","response","installUrl","catch","error","message","div","className","role","type","size","asChild","variant","to","params","workspaceSlug","slug","aria-label"],"mappings":";AAAA,SAAQA,QAAQ,QAAO,sBAAsB;AAC7C,SAAQC,kBAAkB,QAAO,uBAAuB;AACxD,SAAQC,UAAU,QAAO,2BAA2B;AACpD,SAAQC,OAAO,QAAO,4BAA4B;AAClD,SAAQC,cAAc,QAAO,2BAA2B;AACxD,SAAQC,IAAI,QAAO,+BAA+B;AAClD,SAAQC,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,SAAS,EAAEC,MAAM,EAAEC,QAAQ,QAAO,QAAQ;AAiBlD,OAAO,SAASC,oBAAoB,EAClCC,cAAc,EACdC,oBAAoB,EACpBC,eAAe,uBAAuB,EACtCC,cAAc,EACdC,iBAAiB,CAACC,MAAQC,OAAOC,QAAQ,CAACC,MAAM,CAACH,IAAI,EAC5B;IACzB,MAAMI,YAAYnB;IAClB,MAAMoB,aAAab,OAAO;IAC1B,MAAM,CAACc,cAAcC,gBAAgB,GAAGd;IAExCF,UAAU;QACR,IAAIc,WAAWG,OAAO,EAAE;QACxBH,WAAWG,OAAO,GAAG;QACrB,sEAAsE;QACtE,0DAA0D;QAC1D,IAAI;YACFV,iBAAiBM,UAAUK,EAAE;QAC/B,EAAE,OAAM;QACN,SAAS;QACX;QACAd,eAAe;YAACe,cAAcN,UAAUK,EAAE;QAAA,GACvCE,IAAI,CAAC,CAACC;YACLb,eAAea,SAASC,UAAU;QACpC,GACCC,KAAK,CAAC,CAACC;YACNR,gBAAgBQ,iBAAiB/B,WAAW+B,MAAMC,OAAO,GAAGpB;QAC9D;IACJ,GAAG;QAACQ;QAAWT;QAAgBG;QAAgBF;QAAsBG;KAAe;IAEpF,IAAIO,cAAc;QAChB,qBACE,MAACW;YAAIC,WAAU;;8BACb,KAAC/B;oBAAQgC,MAAK;oBAAQC,MAAK;8BACzB,cAAA,KAAC/B;wBAAKgC,MAAK;kCAAMf;;;8BAEnB,KAACpB;oBAAWoC,OAAO;oBAACC,SAAQ;oBAAQL,WAAU;8BAC5C,cAAA,KAAC5B;wBAAKkC,IAAG;wBAAiCC,QAAQ;4BAACC,eAAetB,UAAUuB,IAAI;wBAAA;kCAAG;;;;;IAM3F;IAEA,qBAAO,KAACvC;QAAewC,cAAY/B;;AACrC"}
|
|
@@ -160,7 +160,7 @@ function createStoryRouter(scenario) {
|
|
|
160
160
|
});
|
|
161
161
|
const workspaceRoute = createRoute({
|
|
162
162
|
getParentRoute: ()=>rootRoute,
|
|
163
|
-
path: '/
|
|
163
|
+
path: '/w/$workspaceSlug',
|
|
164
164
|
component: Outlet
|
|
165
165
|
});
|
|
166
166
|
const integrationsRoute = createRoute({
|
|
@@ -178,7 +178,7 @@ function createStoryRouter(scenario) {
|
|
|
178
178
|
return createRouter({
|
|
179
179
|
history: createMemoryHistory({
|
|
180
180
|
initialEntries: [
|
|
181
|
-
|
|
181
|
+
'/w/acme/settings/integrations'
|
|
182
182
|
]
|
|
183
183
|
}),
|
|
184
184
|
routeTree: rootRoute.addChildren([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/webhook/webhook-modals.stories.tsx"],"sourcesContent":["import type {WebhookConnectionDto} from '@shipfox/api-integration-webhook-dto';\nimport {WEBHOOK_RECEIVED_EVENT} from '@shipfox/api-integration-webhook-dto';\nimport {configureApiClient} from '@shipfox/client-api';\nimport {Toaster} from '@shipfox/react-ui/toast';\nimport type {Meta, StoryObj} from '@storybook/react';\nimport {QueryClient, QueryClientProvider} from '@tanstack/react-query';\nimport {\n createMemoryHistory,\n createRootRoute,\n createRoute,\n createRouter,\n Outlet,\n RouterProvider,\n} from '@tanstack/react-router';\nimport {useMemo} from 'react';\nimport type {IntegrationConnection} from '#core/models.js';\nimport {IntegrationDeleteConfirmModal} from '../integration-delete-confirm-modal.js';\nimport {IntegrationUsageModal} from '../integration-usage-modal.js';\nimport {CopyableValue} from './copyable-value.js';\nimport {WebhookCreateModal} from './webhook-create-modal.js';\nimport {WebhookPublicEndpointAlert} from './webhook-public-endpoint-alert.js';\nimport {WebhookUsageDetails} from './webhook-usage-details.js';\n\nconst WORKSPACE_ID = '11111111-1111-4111-8111-111111111111';\nconst CONNECTION_ID = '77777777-7777-4777-8777-777777777777';\n\ntype Scenario =\n | 'create-form'\n | 'create-success'\n | 'usage-active'\n | 'usage-disabled'\n | 'delete-confirm'\n | 'copyable-value';\n\ninterface WebhookModalStoryProps {\n scenario: Scenario;\n}\n\nconst activeConnection: WebhookConnectionDto = {\n id: CONNECTION_ID,\n workspace_id: WORKSPACE_ID,\n name: 'Stripe production',\n slug: 'stripe-prod',\n lifecycle_status: 'active',\n inbound_url: 'https://api.example.test/webhook/77777777-7777-4777-8777-777777777777',\n created_at: '2026-04-12T00:00:00.000Z',\n updated_at: '2026-04-12T00:00:00.000Z',\n};\n\nconst disabledConnection: WebhookConnectionDto = {\n ...activeConnection,\n lifecycle_status: 'disabled',\n};\n\nconst activeIntegrationConnection: IntegrationConnection = {\n id: CONNECTION_ID,\n workspaceId: WORKSPACE_ID,\n provider: 'webhook',\n externalAccountId: activeConnection.slug,\n slug: activeConnection.slug,\n displayName: activeConnection.name,\n lifecycleStatus: activeConnection.lifecycle_status,\n capabilities: [],\n createdAt: activeConnection.created_at,\n updatedAt: activeConnection.updated_at,\n};\n\nconst disabledIntegrationConnection: IntegrationConnection = {\n ...activeIntegrationConnection,\n lifecycleStatus: 'disabled',\n};\n\nfunction WebhookModalStory({scenario}: WebhookModalStoryProps) {\n const connection = scenario === 'usage-disabled' ? disabledConnection : activeConnection;\n\n configureApiClient({\n baseUrl: 'https://api.example.test',\n fetchImpl: fetchForConnection(connection),\n });\n\n const queryClient = useMemo(\n () => new QueryClient({defaultOptions: {queries: {retry: false}}}),\n [],\n );\n const router = useMemo(() => createStoryRouter(scenario), [scenario]);\n\n return (\n <QueryClientProvider client={queryClient}>\n <RouterProvider router={router} />\n <Toaster />\n </QueryClientProvider>\n );\n}\n\nconst meta = {\n title: 'Integrations/WebhookModals',\n component: WebhookModalStory,\n parameters: {layout: 'fullscreen'},\n args: {scenario: 'create-form'},\n} satisfies Meta<typeof WebhookModalStory>;\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const Playground: Story = {};\n\nexport const CreateSuccess: Story = {\n args: {scenario: 'create-success'},\n};\n\nexport const UsageActive: Story = {\n args: {scenario: 'usage-active'},\n};\n\nexport const UsageDisabled: Story = {\n args: {scenario: 'usage-disabled'},\n};\n\nexport const DeleteConfirm: Story = {\n args: {scenario: 'delete-confirm'},\n};\n\nexport const CopyableValueState: Story = {\n args: {scenario: 'copyable-value'},\n};\n\nfunction StorySurface({scenario}: {scenario: Scenario}) {\n return (\n <div className=\"min-h-screen bg-background-neutral-background p-24\">\n {scenario === 'create-form' ? (\n <WebhookCreateModal\n workspaceId={WORKSPACE_ID}\n open\n onOpenChange={() => undefined}\n onCreated={() => undefined}\n />\n ) : null}\n {scenario === 'create-success' ||\n scenario === 'usage-active' ||\n scenario === 'usage-disabled' ? (\n <IntegrationUsageModal\n connection={\n scenario === 'usage-disabled'\n ? disabledIntegrationConnection\n : activeIntegrationConnection\n }\n events={[{value: WEBHOOK_RECEIVED_EVENT, label: WEBHOOK_RECEIVED_EVENT}]}\n open\n onOpenChange={() => undefined}\n >\n <WebhookUsageDetails workspaceId={WORKSPACE_ID} connectionId={CONNECTION_ID} />\n </IntegrationUsageModal>\n ) : null}\n {scenario === 'delete-confirm' ? (\n <IntegrationDeleteConfirmModal\n connectionName={activeConnection.name}\n open\n isPending={false}\n onOpenChange={() => undefined}\n onConfirm={() => undefined}\n />\n ) : null}\n {scenario === 'copyable-value' ? (\n <div className=\"mx-auto max-w-[560px] rounded-8 border border-border-neutral-base bg-background-neutral-base p-24\">\n <div className=\"flex flex-col gap-12\">\n <CopyableValue label=\"inbound URL\" value={activeConnection.inbound_url} />\n <WebhookPublicEndpointAlert />\n </div>\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction createStoryRouter(scenario: Scenario) {\n const rootRoute = createRootRoute({component: Outlet});\n const workspaceRoute = createRoute({\n getParentRoute: () => rootRoute,\n path: '/workspaces/$wid',\n component: Outlet,\n });\n const integrationsRoute = createRoute({\n getParentRoute: () => workspaceRoute,\n path: 'settings/integrations',\n component: () => <StorySurface scenario={scenario} />,\n });\n const eventsRoute = createRoute({\n getParentRoute: () => workspaceRoute,\n path: 'settings/events',\n component: () => <div />,\n });\n\n return createRouter({\n history: createMemoryHistory({\n initialEntries: [`/workspaces/${WORKSPACE_ID}/settings/integrations`],\n }),\n routeTree: rootRoute.addChildren([\n workspaceRoute.addChildren([integrationsRoute, eventsRoute]),\n ]),\n });\n}\n\nfunction fetchForConnection(connection: WebhookConnectionDto): typeof fetch {\n return (input) => {\n const url = requestUrl(input);\n if (url.pathname === '/integrations/webhook/connections') {\n return Promise.resolve(jsonResponse({connections: [connection]}));\n }\n return Promise.resolve(jsonResponse({}, {status: 404}));\n };\n}\n\nfunction requestUrl(input: RequestInfo | URL): URL {\n if (typeof input === 'string') return new URL(input);\n if (input instanceof URL) return input;\n return new URL(input.url);\n}\n\nfunction jsonResponse(body: unknown, init: ResponseInit = {}) {\n return new Response(JSON.stringify(body), {\n status: 200,\n headers: {'content-type': 'application/json'},\n ...init,\n });\n}\n"],"names":["WEBHOOK_RECEIVED_EVENT","configureApiClient","Toaster","QueryClient","QueryClientProvider","createMemoryHistory","createRootRoute","createRoute","createRouter","Outlet","RouterProvider","useMemo","IntegrationDeleteConfirmModal","IntegrationUsageModal","CopyableValue","WebhookCreateModal","WebhookPublicEndpointAlert","WebhookUsageDetails","WORKSPACE_ID","CONNECTION_ID","activeConnection","id","workspace_id","name","slug","lifecycle_status","inbound_url","created_at","updated_at","disabledConnection","activeIntegrationConnection","workspaceId","provider","externalAccountId","displayName","lifecycleStatus","capabilities","createdAt","updatedAt","disabledIntegrationConnection","WebhookModalStory","scenario","connection","baseUrl","fetchImpl","fetchForConnection","queryClient","defaultOptions","queries","retry","router","createStoryRouter","client","meta","title","component","parameters","layout","args","Playground","CreateSuccess","UsageActive","UsageDisabled","DeleteConfirm","CopyableValueState","StorySurface","div","className","open","onOpenChange","undefined","onCreated","events","value","label","connectionId","connectionName","isPending","onConfirm","rootRoute","workspaceRoute","getParentRoute","path","integrationsRoute","eventsRoute","history","initialEntries","routeTree","addChildren","input","url","requestUrl","pathname","Promise","resolve","jsonResponse","connections","status","URL","body","init","Response","JSON","stringify","headers"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/webhook/webhook-modals.stories.tsx"],"sourcesContent":["import type {WebhookConnectionDto} from '@shipfox/api-integration-webhook-dto';\nimport {WEBHOOK_RECEIVED_EVENT} from '@shipfox/api-integration-webhook-dto';\nimport {configureApiClient} from '@shipfox/client-api';\nimport {Toaster} from '@shipfox/react-ui/toast';\nimport type {Meta, StoryObj} from '@storybook/react';\nimport {QueryClient, QueryClientProvider} from '@tanstack/react-query';\nimport {\n createMemoryHistory,\n createRootRoute,\n createRoute,\n createRouter,\n Outlet,\n RouterProvider,\n} from '@tanstack/react-router';\nimport {useMemo} from 'react';\nimport type {IntegrationConnection} from '#core/models.js';\nimport {IntegrationDeleteConfirmModal} from '../integration-delete-confirm-modal.js';\nimport {IntegrationUsageModal} from '../integration-usage-modal.js';\nimport {CopyableValue} from './copyable-value.js';\nimport {WebhookCreateModal} from './webhook-create-modal.js';\nimport {WebhookPublicEndpointAlert} from './webhook-public-endpoint-alert.js';\nimport {WebhookUsageDetails} from './webhook-usage-details.js';\n\nconst WORKSPACE_ID = '11111111-1111-4111-8111-111111111111';\nconst CONNECTION_ID = '77777777-7777-4777-8777-777777777777';\n\ntype Scenario =\n | 'create-form'\n | 'create-success'\n | 'usage-active'\n | 'usage-disabled'\n | 'delete-confirm'\n | 'copyable-value';\n\ninterface WebhookModalStoryProps {\n scenario: Scenario;\n}\n\nconst activeConnection: WebhookConnectionDto = {\n id: CONNECTION_ID,\n workspace_id: WORKSPACE_ID,\n name: 'Stripe production',\n slug: 'stripe-prod',\n lifecycle_status: 'active',\n inbound_url: 'https://api.example.test/webhook/77777777-7777-4777-8777-777777777777',\n created_at: '2026-04-12T00:00:00.000Z',\n updated_at: '2026-04-12T00:00:00.000Z',\n};\n\nconst disabledConnection: WebhookConnectionDto = {\n ...activeConnection,\n lifecycle_status: 'disabled',\n};\n\nconst activeIntegrationConnection: IntegrationConnection = {\n id: CONNECTION_ID,\n workspaceId: WORKSPACE_ID,\n provider: 'webhook',\n externalAccountId: activeConnection.slug,\n slug: activeConnection.slug,\n displayName: activeConnection.name,\n lifecycleStatus: activeConnection.lifecycle_status,\n capabilities: [],\n createdAt: activeConnection.created_at,\n updatedAt: activeConnection.updated_at,\n};\n\nconst disabledIntegrationConnection: IntegrationConnection = {\n ...activeIntegrationConnection,\n lifecycleStatus: 'disabled',\n};\n\nfunction WebhookModalStory({scenario}: WebhookModalStoryProps) {\n const connection = scenario === 'usage-disabled' ? disabledConnection : activeConnection;\n\n configureApiClient({\n baseUrl: 'https://api.example.test',\n fetchImpl: fetchForConnection(connection),\n });\n\n const queryClient = useMemo(\n () => new QueryClient({defaultOptions: {queries: {retry: false}}}),\n [],\n );\n const router = useMemo(() => createStoryRouter(scenario), [scenario]);\n\n return (\n <QueryClientProvider client={queryClient}>\n <RouterProvider router={router} />\n <Toaster />\n </QueryClientProvider>\n );\n}\n\nconst meta = {\n title: 'Integrations/WebhookModals',\n component: WebhookModalStory,\n parameters: {layout: 'fullscreen'},\n args: {scenario: 'create-form'},\n} satisfies Meta<typeof WebhookModalStory>;\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const Playground: Story = {};\n\nexport const CreateSuccess: Story = {\n args: {scenario: 'create-success'},\n};\n\nexport const UsageActive: Story = {\n args: {scenario: 'usage-active'},\n};\n\nexport const UsageDisabled: Story = {\n args: {scenario: 'usage-disabled'},\n};\n\nexport const DeleteConfirm: Story = {\n args: {scenario: 'delete-confirm'},\n};\n\nexport const CopyableValueState: Story = {\n args: {scenario: 'copyable-value'},\n};\n\nfunction StorySurface({scenario}: {scenario: Scenario}) {\n return (\n <div className=\"min-h-screen bg-background-neutral-background p-24\">\n {scenario === 'create-form' ? (\n <WebhookCreateModal\n workspaceId={WORKSPACE_ID}\n open\n onOpenChange={() => undefined}\n onCreated={() => undefined}\n />\n ) : null}\n {scenario === 'create-success' ||\n scenario === 'usage-active' ||\n scenario === 'usage-disabled' ? (\n <IntegrationUsageModal\n connection={\n scenario === 'usage-disabled'\n ? disabledIntegrationConnection\n : activeIntegrationConnection\n }\n events={[{value: WEBHOOK_RECEIVED_EVENT, label: WEBHOOK_RECEIVED_EVENT}]}\n open\n onOpenChange={() => undefined}\n >\n <WebhookUsageDetails workspaceId={WORKSPACE_ID} connectionId={CONNECTION_ID} />\n </IntegrationUsageModal>\n ) : null}\n {scenario === 'delete-confirm' ? (\n <IntegrationDeleteConfirmModal\n connectionName={activeConnection.name}\n open\n isPending={false}\n onOpenChange={() => undefined}\n onConfirm={() => undefined}\n />\n ) : null}\n {scenario === 'copyable-value' ? (\n <div className=\"mx-auto max-w-[560px] rounded-8 border border-border-neutral-base bg-background-neutral-base p-24\">\n <div className=\"flex flex-col gap-12\">\n <CopyableValue label=\"inbound URL\" value={activeConnection.inbound_url} />\n <WebhookPublicEndpointAlert />\n </div>\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction createStoryRouter(scenario: Scenario) {\n const rootRoute = createRootRoute({component: Outlet});\n const workspaceRoute = createRoute({\n getParentRoute: () => rootRoute,\n path: '/w/$workspaceSlug',\n component: Outlet,\n });\n const integrationsRoute = createRoute({\n getParentRoute: () => workspaceRoute,\n path: 'settings/integrations',\n component: () => <StorySurface scenario={scenario} />,\n });\n const eventsRoute = createRoute({\n getParentRoute: () => workspaceRoute,\n path: 'settings/events',\n component: () => <div />,\n });\n\n return createRouter({\n history: createMemoryHistory({\n initialEntries: ['/w/acme/settings/integrations'],\n }),\n routeTree: rootRoute.addChildren([\n workspaceRoute.addChildren([integrationsRoute, eventsRoute]),\n ]),\n });\n}\n\nfunction fetchForConnection(connection: WebhookConnectionDto): typeof fetch {\n return (input) => {\n const url = requestUrl(input);\n if (url.pathname === '/integrations/webhook/connections') {\n return Promise.resolve(jsonResponse({connections: [connection]}));\n }\n return Promise.resolve(jsonResponse({}, {status: 404}));\n };\n}\n\nfunction requestUrl(input: RequestInfo | URL): URL {\n if (typeof input === 'string') return new URL(input);\n if (input instanceof URL) return input;\n return new URL(input.url);\n}\n\nfunction jsonResponse(body: unknown, init: ResponseInit = {}) {\n return new Response(JSON.stringify(body), {\n status: 200,\n headers: {'content-type': 'application/json'},\n ...init,\n });\n}\n"],"names":["WEBHOOK_RECEIVED_EVENT","configureApiClient","Toaster","QueryClient","QueryClientProvider","createMemoryHistory","createRootRoute","createRoute","createRouter","Outlet","RouterProvider","useMemo","IntegrationDeleteConfirmModal","IntegrationUsageModal","CopyableValue","WebhookCreateModal","WebhookPublicEndpointAlert","WebhookUsageDetails","WORKSPACE_ID","CONNECTION_ID","activeConnection","id","workspace_id","name","slug","lifecycle_status","inbound_url","created_at","updated_at","disabledConnection","activeIntegrationConnection","workspaceId","provider","externalAccountId","displayName","lifecycleStatus","capabilities","createdAt","updatedAt","disabledIntegrationConnection","WebhookModalStory","scenario","connection","baseUrl","fetchImpl","fetchForConnection","queryClient","defaultOptions","queries","retry","router","createStoryRouter","client","meta","title","component","parameters","layout","args","Playground","CreateSuccess","UsageActive","UsageDisabled","DeleteConfirm","CopyableValueState","StorySurface","div","className","open","onOpenChange","undefined","onCreated","events","value","label","connectionId","connectionName","isPending","onConfirm","rootRoute","workspaceRoute","getParentRoute","path","integrationsRoute","eventsRoute","history","initialEntries","routeTree","addChildren","input","url","requestUrl","pathname","Promise","resolve","jsonResponse","connections","status","URL","body","init","Response","JSON","stringify","headers"],"mappings":"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"}
|
package/dist/feature.d.ts
CHANGED
|
@@ -24,31 +24,31 @@ export declare const integrationsFeature: {
|
|
|
24
24
|
readonly parent: "root";
|
|
25
25
|
readonly impl: "@shipfox/client-integrations/routes/slack-callback";
|
|
26
26
|
}, {
|
|
27
|
-
readonly path: "/
|
|
27
|
+
readonly path: "/w/$workspaceSlug/integrations";
|
|
28
28
|
readonly parent: "workspaceLayout";
|
|
29
29
|
readonly impl: "@shipfox/client-integrations/routes/integrations";
|
|
30
30
|
}, {
|
|
31
|
-
readonly path: "/
|
|
31
|
+
readonly path: "/w/$workspaceSlug/integrations/gitea";
|
|
32
32
|
readonly parent: "workspaceLayout";
|
|
33
33
|
readonly impl: "@shipfox/client-integrations/routes/gitea";
|
|
34
34
|
}, {
|
|
35
|
-
readonly path: "/
|
|
35
|
+
readonly path: "/w/$workspaceSlug/integrations/github";
|
|
36
36
|
readonly parent: "workspaceLayout";
|
|
37
37
|
readonly impl: "@shipfox/client-integrations/routes/github";
|
|
38
38
|
}, {
|
|
39
|
-
readonly path: "/
|
|
39
|
+
readonly path: "/w/$workspaceSlug/integrations/linear";
|
|
40
40
|
readonly parent: "workspaceLayout";
|
|
41
41
|
readonly impl: "@shipfox/client-integrations/routes/linear";
|
|
42
42
|
}, {
|
|
43
|
-
readonly path: "/
|
|
43
|
+
readonly path: "/w/$workspaceSlug/integrations/sentry";
|
|
44
44
|
readonly parent: "workspaceLayout";
|
|
45
45
|
readonly impl: "@shipfox/client-integrations/routes/sentry";
|
|
46
46
|
}, {
|
|
47
|
-
readonly path: "/
|
|
47
|
+
readonly path: "/w/$workspaceSlug/integrations/slack";
|
|
48
48
|
readonly parent: "workspaceLayout";
|
|
49
49
|
readonly impl: "@shipfox/client-integrations/routes/slack";
|
|
50
50
|
}, {
|
|
51
|
-
readonly path: "/
|
|
51
|
+
readonly path: "/w/$workspaceSlug/settings/integrations";
|
|
52
52
|
readonly parent: "workspaceSettings";
|
|
53
53
|
readonly impl: "@shipfox/client-integrations/routes/integrations-settings";
|
|
54
54
|
}];
|
package/dist/feature.js
CHANGED
|
@@ -32,37 +32,37 @@ export const integrationsFeature = defineClientFeature({
|
|
|
32
32
|
impl: '@shipfox/client-integrations/routes/slack-callback'
|
|
33
33
|
},
|
|
34
34
|
{
|
|
35
|
-
path: '/
|
|
35
|
+
path: '/w/$workspaceSlug/integrations',
|
|
36
36
|
parent: 'workspaceLayout',
|
|
37
37
|
impl: '@shipfox/client-integrations/routes/integrations'
|
|
38
38
|
},
|
|
39
39
|
{
|
|
40
|
-
path: '/
|
|
40
|
+
path: '/w/$workspaceSlug/integrations/gitea',
|
|
41
41
|
parent: 'workspaceLayout',
|
|
42
42
|
impl: '@shipfox/client-integrations/routes/gitea'
|
|
43
43
|
},
|
|
44
44
|
{
|
|
45
|
-
path: '/
|
|
45
|
+
path: '/w/$workspaceSlug/integrations/github',
|
|
46
46
|
parent: 'workspaceLayout',
|
|
47
47
|
impl: '@shipfox/client-integrations/routes/github'
|
|
48
48
|
},
|
|
49
49
|
{
|
|
50
|
-
path: '/
|
|
50
|
+
path: '/w/$workspaceSlug/integrations/linear',
|
|
51
51
|
parent: 'workspaceLayout',
|
|
52
52
|
impl: '@shipfox/client-integrations/routes/linear'
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
|
-
path: '/
|
|
55
|
+
path: '/w/$workspaceSlug/integrations/sentry',
|
|
56
56
|
parent: 'workspaceLayout',
|
|
57
57
|
impl: '@shipfox/client-integrations/routes/sentry'
|
|
58
58
|
},
|
|
59
59
|
{
|
|
60
|
-
path: '/
|
|
60
|
+
path: '/w/$workspaceSlug/integrations/slack',
|
|
61
61
|
parent: 'workspaceLayout',
|
|
62
62
|
impl: '@shipfox/client-integrations/routes/slack'
|
|
63
63
|
},
|
|
64
64
|
{
|
|
65
|
-
path: '/
|
|
65
|
+
path: '/w/$workspaceSlug/settings/integrations',
|
|
66
66
|
parent: 'workspaceSettings',
|
|
67
67
|
impl: '@shipfox/client-integrations/routes/integrations-settings'
|
|
68
68
|
}
|
package/dist/feature.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/feature.ts"],"sourcesContent":["import {defineClientFeature, type SettingsSectionEntry} from '@shipfox/client-shell';\n\nexport const integrationsSettingsSections = [\n {\n id: 'settings.integrations',\n pathSegment: 'integrations',\n label: 'Integrations',\n icon: 'plugLine',\n order: 700,\n },\n] as const satisfies readonly SettingsSectionEntry[];\n\nexport const integrationsFeature = defineClientFeature({\n id: 'shipfox.integrations',\n routes: [\n {\n path: '/integrations/github/callback',\n parent: 'root',\n impl: '@shipfox/client-integrations/routes/github-callback',\n },\n {\n path: '/integrations/linear/callback',\n parent: 'root',\n impl: '@shipfox/client-integrations/routes/linear-callback',\n },\n {\n path: '/integrations/sentry/callback',\n parent: 'root',\n impl: '@shipfox/client-integrations/routes/sentry-callback',\n },\n {\n path: '/integrations/slack/callback',\n parent: 'root',\n impl: '@shipfox/client-integrations/routes/slack-callback',\n },\n {\n path: '/
|
|
1
|
+
{"version":3,"sources":["../src/feature.ts"],"sourcesContent":["import {defineClientFeature, type SettingsSectionEntry} from '@shipfox/client-shell';\n\nexport const integrationsSettingsSections = [\n {\n id: 'settings.integrations',\n pathSegment: 'integrations',\n label: 'Integrations',\n icon: 'plugLine',\n order: 700,\n },\n] as const satisfies readonly SettingsSectionEntry[];\n\nexport const integrationsFeature = defineClientFeature({\n id: 'shipfox.integrations',\n routes: [\n {\n path: '/integrations/github/callback',\n parent: 'root',\n impl: '@shipfox/client-integrations/routes/github-callback',\n },\n {\n path: '/integrations/linear/callback',\n parent: 'root',\n impl: '@shipfox/client-integrations/routes/linear-callback',\n },\n {\n path: '/integrations/sentry/callback',\n parent: 'root',\n impl: '@shipfox/client-integrations/routes/sentry-callback',\n },\n {\n path: '/integrations/slack/callback',\n parent: 'root',\n impl: '@shipfox/client-integrations/routes/slack-callback',\n },\n {\n path: '/w/$workspaceSlug/integrations',\n parent: 'workspaceLayout',\n impl: '@shipfox/client-integrations/routes/integrations',\n },\n {\n path: '/w/$workspaceSlug/integrations/gitea',\n parent: 'workspaceLayout',\n impl: '@shipfox/client-integrations/routes/gitea',\n },\n {\n path: '/w/$workspaceSlug/integrations/github',\n parent: 'workspaceLayout',\n impl: '@shipfox/client-integrations/routes/github',\n },\n {\n path: '/w/$workspaceSlug/integrations/linear',\n parent: 'workspaceLayout',\n impl: '@shipfox/client-integrations/routes/linear',\n },\n {\n path: '/w/$workspaceSlug/integrations/sentry',\n parent: 'workspaceLayout',\n impl: '@shipfox/client-integrations/routes/sentry',\n },\n {\n path: '/w/$workspaceSlug/integrations/slack',\n parent: 'workspaceLayout',\n impl: '@shipfox/client-integrations/routes/slack',\n },\n {\n path: '/w/$workspaceSlug/settings/integrations',\n parent: 'workspaceSettings',\n impl: '@shipfox/client-integrations/routes/integrations-settings',\n },\n ],\n settingsSections: integrationsSettingsSections,\n});\n"],"names":["defineClientFeature","integrationsSettingsSections","id","pathSegment","label","icon","order","integrationsFeature","routes","path","parent","impl","settingsSections"],"mappings":"AAAA,SAAQA,mBAAmB,QAAkC,wBAAwB;AAErF,OAAO,MAAMC,+BAA+B;IAC1C;QACEC,IAAI;QACJC,aAAa;QACbC,OAAO;QACPC,MAAM;QACNC,OAAO;IACT;CACD,CAAoD;AAErD,OAAO,MAAMC,sBAAsBP,oBAAoB;IACrDE,IAAI;IACJM,QAAQ;QACN;YACEC,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;QACA;YACEF,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;QACA;YACEF,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;QACA;YACEF,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;QACA;YACEF,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;QACA;YACEF,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;QACA;YACEF,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;QACA;YACEF,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;QACA;YACEF,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;QACA;YACEF,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;QACA;YACEF,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;KACD;IACDC,kBAAkBX;AACpB,GAAG"}
|
|
@@ -69,7 +69,7 @@ export async function listSourceConnections({ workspaceId, signal }) {
|
|
|
69
69
|
});
|
|
70
70
|
// The endpoint returns every lifecycle status (the settings hub needs that),
|
|
71
71
|
// but source-control consumers (onboarding redirect, project creation) only
|
|
72
|
-
// act on usable connections
|
|
72
|
+
// act on usable connections. A disabled/error one must read as "not there".
|
|
73
73
|
return connections.filter(isUsableConnection);
|
|
74
74
|
}
|
|
75
75
|
export function sourceConnectionsQueryOptions(workspaceId) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/hooks/api/integrations.ts"],"sourcesContent":["import type {\n IntegrationCapabilityDto,\n UpdateIntegrationConnectionBodyDto,\n} from '@shipfox/api-integration-core-dto';\nimport {\n integrationConnectionDtoSchema,\n listIntegrationConnectionsResponseSchema,\n listIntegrationProvidersResponseSchema,\n listRepositoriesResponseSchema,\n} from '@shipfox/api-integration-core-dto';\nimport type {CreateGiteaConnectionBodyDto} from '@shipfox/api-integration-gitea-dto';\nimport {createGiteaConnectionResponseSchema} from '@shipfox/api-integration-gitea-dto';\nimport type {CreateGithubInstallBodyDto} from '@shipfox/api-integration-github-dto';\nimport {\n createGithubInstallResponseSchema,\n githubCallbackResponseSchema,\n} from '@shipfox/api-integration-github-dto';\nimport type {\n CreateLinearInstallBodyDto,\n LinearCallbackQueryDto,\n} from '@shipfox/api-integration-linear-dto';\nimport {\n createLinearInstallResponseSchema,\n linearCallbackResponseSchema,\n} from '@shipfox/api-integration-linear-dto';\nimport type {\n CreateSentryInstallBodyDto,\n SentryConnectBodyDto,\n} from '@shipfox/api-integration-sentry-dto';\nimport {\n createSentryInstallResponseSchema,\n sentryConnectResponseSchema,\n} from '@shipfox/api-integration-sentry-dto';\nimport type {\n CreateSlackInstallBodyDto,\n SlackCallbackQueryDto,\n} from '@shipfox/api-integration-slack-dto';\nimport {\n createSlackInstallResponseSchema,\n slackCallbackResponseSchema,\n} from '@shipfox/api-integration-slack-dto';\nimport {checkedApiRequest, emptyResponseSchema} from '@shipfox/client-api';\nimport {\n type FetchQueryOptions,\n type InfiniteData,\n infiniteQueryOptions,\n queryOptions,\n type UseInfiniteQueryOptions,\n useInfiniteQuery,\n useMutation,\n useQuery,\n useQueryClient,\n} from '@tanstack/react-query';\nimport {\n type InstallRedirect,\n type IntegrationConnection,\n type IntegrationProvider,\n isUsableConnection,\n type RepositoryPage,\n} from '#core/models.js';\nimport {serializeLinearCallbackQuery} from '#linear-callback.js';\nimport {serializeSlackCallbackQuery} from '#slack-callback.js';\nimport {\n toInstallRedirect,\n toIntegrationConnection,\n toIntegrationProvider,\n toRepository,\n} from './integration-mapper.js';\n\nexport const integrationsQueryKeys = {\n all: ['integrations'] as const,\n providers: (capability: IntegrationCapabilityDto | 'all') =>\n [...integrationsQueryKeys.all, 'providers', capability] as const,\n connections: (workspaceId: string, capability: IntegrationCapabilityDto | 'all') =>\n [...integrationsQueryKeys.all, 'connections', workspaceId, capability] as const,\n // Prefix matching every per-capability connections query for a workspace, so\n // a mutation can refresh all connection views without touching providers or\n // repositories.\n connectionsByWorkspace: (workspaceId: string) =>\n [...integrationsQueryKeys.all, 'connections', workspaceId] as const,\n sourceConnections: (workspaceId: string) =>\n integrationsQueryKeys.connections(workspaceId, 'source_control'),\n repositories: (connectionId: string, search: string) =>\n [...integrationsQueryKeys.all, 'repositories', connectionId, search] as const,\n};\n\ntype SourceConnectionsQueryKey =\n | ReturnType<typeof integrationsQueryKeys.sourceConnections>\n | readonly ['integrations', 'source-connections'];\n\ntype SourceConnectionsQueryOptions = FetchQueryOptions<\n IntegrationConnection[],\n Error,\n IntegrationConnection[],\n SourceConnectionsQueryKey\n>;\n\ntype ProvidersQueryKey = ReturnType<typeof integrationsQueryKeys.providers>;\n\ntype ProvidersQueryOptions = FetchQueryOptions<\n IntegrationProvider[],\n Error,\n IntegrationProvider[],\n ProvidersQueryKey\n>;\n\ntype ConnectionsQueryKey =\n | ReturnType<typeof integrationsQueryKeys.connections>\n | readonly ['integrations', 'connections'];\n\ntype ConnectionsQueryOptions = FetchQueryOptions<\n IntegrationConnection[],\n Error,\n IntegrationConnection[],\n ConnectionsQueryKey\n>;\n\ntype RepositoriesQueryKey =\n | ReturnType<typeof integrationsQueryKeys.repositories>\n | readonly ['integrations', 'repositories'];\n\ntype RepositoriesInfiniteQueryOptions = UseInfiniteQueryOptions<\n RepositoryPage,\n Error,\n InfiniteData<RepositoryPage, string | undefined>,\n RepositoriesQueryKey,\n string | undefined\n>;\n\nexport async function listIntegrationProviders({\n capability,\n signal,\n}: {\n capability?: IntegrationCapabilityDto;\n signal?: AbortSignal;\n}): Promise<IntegrationProvider[]> {\n const search = new URLSearchParams();\n if (capability) search.set('capability', capability);\n const query = search.toString();\n const path = query ? `/integration-providers?${query}` : '/integration-providers';\n const response = await checkedApiRequest(listIntegrationProvidersResponseSchema, path, {signal});\n return response.providers.map(toIntegrationProvider);\n}\n\nexport async function listIntegrationConnections({\n workspaceId,\n capability,\n signal,\n}: {\n workspaceId: string;\n capability?: IntegrationCapabilityDto | undefined;\n signal?: AbortSignal | undefined;\n}): Promise<IntegrationConnection[]> {\n const search = new URLSearchParams({workspace_id: workspaceId});\n if (capability) search.set('capability', capability);\n const response = await checkedApiRequest(\n listIntegrationConnectionsResponseSchema,\n `/integration-connections?${search.toString()}`,\n {signal},\n );\n return response.connections.map(toIntegrationConnection);\n}\n\nexport async function listSourceConnections({\n workspaceId,\n signal,\n}: {\n workspaceId: string;\n signal?: AbortSignal;\n}): Promise<IntegrationConnection[]> {\n const connections = await listIntegrationConnections({\n workspaceId,\n capability: 'source_control',\n signal,\n });\n // The endpoint returns every lifecycle status (the settings hub needs that),\n // but source-control consumers (onboarding redirect, project creation) only\n // act on usable connections — a disabled/error one must read as \"not there\".\n return connections.filter(isUsableConnection);\n}\n\nexport function sourceConnectionsQueryOptions(\n workspaceId: string | undefined,\n): SourceConnectionsQueryOptions {\n return queryOptions({\n queryKey: workspaceId\n ? integrationsQueryKeys.sourceConnections(workspaceId)\n : ([...integrationsQueryKeys.all, 'source-connections'] as const),\n enabled: Boolean(workspaceId),\n queryFn: ({signal}) => listSourceConnections({workspaceId: workspaceId ?? '', signal}),\n });\n}\n\nexport async function createGiteaConnection(\n body: CreateGiteaConnectionBodyDto,\n): Promise<IntegrationConnection> {\n const response = await checkedApiRequest(\n createGiteaConnectionResponseSchema,\n '/integrations/gitea/connections',\n {\n method: 'POST',\n body,\n },\n );\n return toIntegrationConnection(response);\n}\n\nexport async function createGithubInstall(\n body: CreateGithubInstallBodyDto,\n): Promise<InstallRedirect> {\n return toInstallRedirect(\n await checkedApiRequest(createGithubInstallResponseSchema, '/integrations/github/install', {\n method: 'POST',\n body,\n }),\n );\n}\n\nexport async function completeGithubCallback({\n code,\n installationId,\n state,\n setupAction,\n token,\n}: {\n code: string;\n installationId: number;\n state: string;\n setupAction?: string;\n token: string;\n}): Promise<IntegrationConnection> {\n const query = new URLSearchParams({code, installation_id: String(installationId), state});\n if (setupAction) query.set('setup_action', setupAction);\n const response = await checkedApiRequest(\n githubCallbackResponseSchema,\n `/integrations/github/callback/api?${query.toString()}`,\n {headers: {authorization: `Bearer ${token}`}},\n );\n return toIntegrationConnection(response);\n}\n\nexport async function createSentryInstall(\n body: CreateSentryInstallBodyDto,\n): Promise<InstallRedirect> {\n return toInstallRedirect(\n await checkedApiRequest(createSentryInstallResponseSchema, '/integrations/sentry/install', {\n method: 'POST',\n body,\n }),\n );\n}\n\nexport async function createLinearInstall(\n body: CreateLinearInstallBodyDto,\n): Promise<InstallRedirect> {\n return toInstallRedirect(\n await checkedApiRequest(createLinearInstallResponseSchema, '/integrations/linear/install', {\n method: 'POST',\n body,\n }),\n );\n}\n\nexport async function createSlackInstall(\n body: CreateSlackInstallBodyDto,\n): Promise<InstallRedirect> {\n return toInstallRedirect(\n await checkedApiRequest(createSlackInstallResponseSchema, '/integrations/slack/install', {\n method: 'POST',\n body,\n }),\n );\n}\n\nexport async function completeLinearCallback({\n query,\n token,\n}: {\n query: LinearCallbackQueryDto;\n token: string;\n}): Promise<IntegrationConnection> {\n const response = await checkedApiRequest(\n linearCallbackResponseSchema,\n `/integrations/linear/callback/api?${serializeLinearCallbackQuery(query)}`,\n {headers: {authorization: `Bearer ${token}`}},\n );\n return toIntegrationConnection(response);\n}\n\nexport async function completeSlackCallback({\n query,\n token,\n}: {\n query: SlackCallbackQueryDto;\n token: string;\n}): Promise<IntegrationConnection> {\n const response = await checkedApiRequest(\n slackCallbackResponseSchema,\n `/integrations/slack/callback/api?${serializeSlackCallbackQuery(query)}`,\n {headers: {authorization: `Bearer ${token}`}},\n );\n return toIntegrationConnection(response);\n}\n\n// Called from the callback route with an explicit bearer (same as the GitHub\n// callback): the route refreshes auth itself before forwarding the grant code.\nexport async function connectSentry({body, token}: {body: SentryConnectBodyDto; token: string}) {\n const response = await checkedApiRequest(\n sentryConnectResponseSchema,\n '/integrations/sentry/connect',\n {\n method: 'POST',\n body,\n headers: {authorization: `Bearer ${token}`},\n },\n );\n return toIntegrationConnection(response);\n}\n\nexport async function listRepositories({\n connectionId,\n cursor,\n search,\n signal,\n}: {\n connectionId: string;\n cursor?: string;\n search?: string;\n signal?: AbortSignal;\n}): Promise<RepositoryPage> {\n const params = new URLSearchParams();\n if (cursor) params.set('cursor', cursor);\n if (search) params.set('search', search);\n const query = params.toString();\n const path = query\n ? `/integration-connections/${connectionId}/repositories?${query}`\n : `/integration-connections/${connectionId}/repositories`;\n const response = await checkedApiRequest(listRepositoriesResponseSchema, path, {signal});\n return {\n repositories: response.repositories.map(toRepository),\n ...(response.next_cursor == null ? {} : {nextCursor: response.next_cursor}),\n };\n}\n\nexport async function updateIntegrationConnection({\n connectionId,\n body,\n}: {\n connectionId: string;\n body: UpdateIntegrationConnectionBodyDto;\n}): Promise<IntegrationConnection> {\n const response = await checkedApiRequest(\n integrationConnectionDtoSchema,\n `/integration-connections/${encodeURIComponent(connectionId)}`,\n {method: 'PATCH', body},\n );\n return toIntegrationConnection(response);\n}\n\nexport async function deleteIntegrationConnection({connectionId}: {connectionId: string}) {\n await checkedApiRequest(\n emptyResponseSchema,\n `/integration-connections/${encodeURIComponent(connectionId)}`,\n {\n method: 'DELETE',\n },\n );\n}\n\nexport function useIntegrationProvidersQuery(params?: {capability?: IntegrationCapabilityDto}) {\n return useQuery(integrationProvidersQueryOptions(params?.capability));\n}\n\nexport function integrationProvidersQueryOptions(\n capability?: IntegrationCapabilityDto,\n): ProvidersQueryOptions {\n return queryOptions({\n queryKey: integrationsQueryKeys.providers(capability ?? 'all'),\n queryFn: ({signal}) => listIntegrationProviders(capability ? {capability, signal} : {signal}),\n });\n}\n\nexport function useSourceConnectionsQuery(workspaceId: string | undefined) {\n return useQuery(sourceConnectionsQueryOptions(workspaceId));\n}\n\nexport function useIntegrationConnectionsQuery(workspaceId: string | undefined) {\n return useQuery(integrationConnectionsQueryOptions(workspaceId));\n}\n\nexport function integrationConnectionsQueryOptions(\n workspaceId: string | undefined,\n): ConnectionsQueryOptions {\n return queryOptions({\n queryKey: workspaceId\n ? integrationsQueryKeys.connections(workspaceId, 'all')\n : ([...integrationsQueryKeys.all, 'connections'] as const),\n enabled: Boolean(workspaceId),\n queryFn: ({signal}) => listIntegrationConnections({workspaceId: workspaceId ?? '', signal}),\n });\n}\n\nexport function repositoriesInfiniteQueryOptions(\n connectionId: string | undefined,\n options?: {search?: string},\n): RepositoriesInfiniteQueryOptions {\n const trimmedSearch = options?.search?.trim() ?? '';\n return infiniteQueryOptions({\n queryKey: connectionId\n ? integrationsQueryKeys.repositories(connectionId, trimmedSearch)\n : ([...integrationsQueryKeys.all, 'repositories'] as const),\n enabled: Boolean(connectionId),\n initialPageParam: undefined as string | undefined,\n queryFn: ({pageParam, signal}) => {\n const args: {connectionId: string; cursor?: string; search?: string; signal: AbortSignal} = {\n connectionId: connectionId ?? '',\n signal,\n };\n if (pageParam) args.cursor = pageParam;\n if (trimmedSearch) args.search = trimmedSearch;\n return listRepositories(args);\n },\n getNextPageParam: (lastPage) => lastPage.nextCursor,\n });\n}\n\nexport function useRepositoriesInfiniteQuery(\n connectionId: string | undefined,\n options?: {search?: string},\n) {\n return useInfiniteQuery(repositoriesInfiniteQueryOptions(connectionId, options));\n}\n\nexport function useCreateGiteaConnectionMutation() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: createGiteaConnection,\n onSuccess: async (connection) => {\n await queryClient.invalidateQueries({\n queryKey: integrationsQueryKeys.connectionsByWorkspace(connection.workspaceId),\n refetchType: 'all',\n });\n },\n });\n}\n\nexport function useCreateLinearInstallMutation() {\n return useMutation({mutationFn: createLinearInstall});\n}\n\nexport function useCreateSlackInstallMutation() {\n return useMutation({mutationFn: createSlackInstall});\n}\n\nexport function useCompleteLinearCallbackMutation() {\n return useMutation({mutationFn: completeLinearCallback});\n}\n\nexport function useCompleteSlackCallbackMutation() {\n return useMutation({mutationFn: completeSlackCallback});\n}\n\nexport function useUpdateIntegrationConnectionMutation() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: updateIntegrationConnection,\n onSuccess: async (connection) => {\n await queryClient.invalidateQueries({\n queryKey: integrationsQueryKeys.connectionsByWorkspace(connection.workspaceId),\n });\n },\n });\n}\n\nexport function useDeleteIntegrationConnectionMutation() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: ({\n workspaceId: _workspaceId,\n connectionId,\n }: {\n workspaceId: string;\n connectionId: string;\n }) => deleteIntegrationConnection({connectionId}),\n onSuccess: async (_result, variables) => {\n await queryClient.invalidateQueries({\n queryKey: integrationsQueryKeys.connectionsByWorkspace(variables.workspaceId),\n });\n },\n });\n}\n"],"names":["integrationConnectionDtoSchema","listIntegrationConnectionsResponseSchema","listIntegrationProvidersResponseSchema","listRepositoriesResponseSchema","createGiteaConnectionResponseSchema","createGithubInstallResponseSchema","githubCallbackResponseSchema","createLinearInstallResponseSchema","linearCallbackResponseSchema","createSentryInstallResponseSchema","sentryConnectResponseSchema","createSlackInstallResponseSchema","slackCallbackResponseSchema","checkedApiRequest","emptyResponseSchema","infiniteQueryOptions","queryOptions","useInfiniteQuery","useMutation","useQuery","useQueryClient","isUsableConnection","serializeLinearCallbackQuery","serializeSlackCallbackQuery","toInstallRedirect","toIntegrationConnection","toIntegrationProvider","toRepository","integrationsQueryKeys","all","providers","capability","connections","workspaceId","connectionsByWorkspace","sourceConnections","repositories","connectionId","search","listIntegrationProviders","signal","URLSearchParams","set","query","toString","path","response","map","listIntegrationConnections","workspace_id","listSourceConnections","filter","sourceConnectionsQueryOptions","queryKey","enabled","Boolean","queryFn","createGiteaConnection","body","method","createGithubInstall","completeGithubCallback","code","installationId","state","setupAction","token","installation_id","String","headers","authorization","createSentryInstall","createLinearInstall","createSlackInstall","completeLinearCallback","completeSlackCallback","connectSentry","listRepositories","cursor","params","next_cursor","nextCursor","updateIntegrationConnection","encodeURIComponent","deleteIntegrationConnection","useIntegrationProvidersQuery","integrationProvidersQueryOptions","useSourceConnectionsQuery","useIntegrationConnectionsQuery","integrationConnectionsQueryOptions","repositoriesInfiniteQueryOptions","options","trimmedSearch","trim","initialPageParam","undefined","pageParam","args","getNextPageParam","lastPage","useRepositoriesInfiniteQuery","useCreateGiteaConnectionMutation","queryClient","mutationFn","onSuccess","connection","invalidateQueries","refetchType","useCreateLinearInstallMutation","useCreateSlackInstallMutation","useCompleteLinearCallbackMutation","useCompleteSlackCallbackMutation","useUpdateIntegrationConnectionMutation","useDeleteIntegrationConnectionMutation","_workspaceId","_result","variables"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/hooks/api/integrations.ts"],"sourcesContent":["import type {\n IntegrationCapabilityDto,\n UpdateIntegrationConnectionBodyDto,\n} from '@shipfox/api-integration-core-dto';\nimport {\n integrationConnectionDtoSchema,\n listIntegrationConnectionsResponseSchema,\n listIntegrationProvidersResponseSchema,\n listRepositoriesResponseSchema,\n} from '@shipfox/api-integration-core-dto';\nimport type {CreateGiteaConnectionBodyDto} from '@shipfox/api-integration-gitea-dto';\nimport {createGiteaConnectionResponseSchema} from '@shipfox/api-integration-gitea-dto';\nimport type {CreateGithubInstallBodyDto} from '@shipfox/api-integration-github-dto';\nimport {\n createGithubInstallResponseSchema,\n githubCallbackResponseSchema,\n} from '@shipfox/api-integration-github-dto';\nimport type {\n CreateLinearInstallBodyDto,\n LinearCallbackQueryDto,\n} from '@shipfox/api-integration-linear-dto';\nimport {\n createLinearInstallResponseSchema,\n linearCallbackResponseSchema,\n} from '@shipfox/api-integration-linear-dto';\nimport type {\n CreateSentryInstallBodyDto,\n SentryConnectBodyDto,\n} from '@shipfox/api-integration-sentry-dto';\nimport {\n createSentryInstallResponseSchema,\n sentryConnectResponseSchema,\n} from '@shipfox/api-integration-sentry-dto';\nimport type {\n CreateSlackInstallBodyDto,\n SlackCallbackQueryDto,\n} from '@shipfox/api-integration-slack-dto';\nimport {\n createSlackInstallResponseSchema,\n slackCallbackResponseSchema,\n} from '@shipfox/api-integration-slack-dto';\nimport {checkedApiRequest, emptyResponseSchema} from '@shipfox/client-api';\nimport {\n type FetchQueryOptions,\n type InfiniteData,\n infiniteQueryOptions,\n queryOptions,\n type UseInfiniteQueryOptions,\n useInfiniteQuery,\n useMutation,\n useQuery,\n useQueryClient,\n} from '@tanstack/react-query';\nimport {\n type InstallRedirect,\n type IntegrationConnection,\n type IntegrationProvider,\n isUsableConnection,\n type RepositoryPage,\n} from '#core/models.js';\nimport {serializeLinearCallbackQuery} from '#linear-callback.js';\nimport {serializeSlackCallbackQuery} from '#slack-callback.js';\nimport {\n toInstallRedirect,\n toIntegrationConnection,\n toIntegrationProvider,\n toRepository,\n} from './integration-mapper.js';\n\nexport const integrationsQueryKeys = {\n all: ['integrations'] as const,\n providers: (capability: IntegrationCapabilityDto | 'all') =>\n [...integrationsQueryKeys.all, 'providers', capability] as const,\n connections: (workspaceId: string, capability: IntegrationCapabilityDto | 'all') =>\n [...integrationsQueryKeys.all, 'connections', workspaceId, capability] as const,\n // Prefix matching every per-capability connections query for a workspace, so\n // a mutation can refresh all connection views without touching providers or\n // repositories.\n connectionsByWorkspace: (workspaceId: string) =>\n [...integrationsQueryKeys.all, 'connections', workspaceId] as const,\n sourceConnections: (workspaceId: string) =>\n integrationsQueryKeys.connections(workspaceId, 'source_control'),\n repositories: (connectionId: string, search: string) =>\n [...integrationsQueryKeys.all, 'repositories', connectionId, search] as const,\n};\n\ntype SourceConnectionsQueryKey =\n | ReturnType<typeof integrationsQueryKeys.sourceConnections>\n | readonly ['integrations', 'source-connections'];\n\ntype SourceConnectionsQueryOptions = FetchQueryOptions<\n IntegrationConnection[],\n Error,\n IntegrationConnection[],\n SourceConnectionsQueryKey\n>;\n\ntype ProvidersQueryKey = ReturnType<typeof integrationsQueryKeys.providers>;\n\ntype ProvidersQueryOptions = FetchQueryOptions<\n IntegrationProvider[],\n Error,\n IntegrationProvider[],\n ProvidersQueryKey\n>;\n\ntype ConnectionsQueryKey =\n | ReturnType<typeof integrationsQueryKeys.connections>\n | readonly ['integrations', 'connections'];\n\ntype ConnectionsQueryOptions = FetchQueryOptions<\n IntegrationConnection[],\n Error,\n IntegrationConnection[],\n ConnectionsQueryKey\n>;\n\ntype RepositoriesQueryKey =\n | ReturnType<typeof integrationsQueryKeys.repositories>\n | readonly ['integrations', 'repositories'];\n\ntype RepositoriesInfiniteQueryOptions = UseInfiniteQueryOptions<\n RepositoryPage,\n Error,\n InfiniteData<RepositoryPage, string | undefined>,\n RepositoriesQueryKey,\n string | undefined\n>;\n\nexport async function listIntegrationProviders({\n capability,\n signal,\n}: {\n capability?: IntegrationCapabilityDto;\n signal?: AbortSignal;\n}): Promise<IntegrationProvider[]> {\n const search = new URLSearchParams();\n if (capability) search.set('capability', capability);\n const query = search.toString();\n const path = query ? `/integration-providers?${query}` : '/integration-providers';\n const response = await checkedApiRequest(listIntegrationProvidersResponseSchema, path, {signal});\n return response.providers.map(toIntegrationProvider);\n}\n\nexport async function listIntegrationConnections({\n workspaceId,\n capability,\n signal,\n}: {\n workspaceId: string;\n capability?: IntegrationCapabilityDto | undefined;\n signal?: AbortSignal | undefined;\n}): Promise<IntegrationConnection[]> {\n const search = new URLSearchParams({workspace_id: workspaceId});\n if (capability) search.set('capability', capability);\n const response = await checkedApiRequest(\n listIntegrationConnectionsResponseSchema,\n `/integration-connections?${search.toString()}`,\n {signal},\n );\n return response.connections.map(toIntegrationConnection);\n}\n\nexport async function listSourceConnections({\n workspaceId,\n signal,\n}: {\n workspaceId: string;\n signal?: AbortSignal;\n}): Promise<IntegrationConnection[]> {\n const connections = await listIntegrationConnections({\n workspaceId,\n capability: 'source_control',\n signal,\n });\n // The endpoint returns every lifecycle status (the settings hub needs that),\n // but source-control consumers (onboarding redirect, project creation) only\n // act on usable connections. A disabled/error one must read as \"not there\".\n return connections.filter(isUsableConnection);\n}\n\nexport function sourceConnectionsQueryOptions(\n workspaceId: string | undefined,\n): SourceConnectionsQueryOptions {\n return queryOptions({\n queryKey: workspaceId\n ? integrationsQueryKeys.sourceConnections(workspaceId)\n : ([...integrationsQueryKeys.all, 'source-connections'] as const),\n enabled: Boolean(workspaceId),\n queryFn: ({signal}) => listSourceConnections({workspaceId: workspaceId ?? '', signal}),\n });\n}\n\nexport async function createGiteaConnection(\n body: CreateGiteaConnectionBodyDto,\n): Promise<IntegrationConnection> {\n const response = await checkedApiRequest(\n createGiteaConnectionResponseSchema,\n '/integrations/gitea/connections',\n {\n method: 'POST',\n body,\n },\n );\n return toIntegrationConnection(response);\n}\n\nexport async function createGithubInstall(\n body: CreateGithubInstallBodyDto,\n): Promise<InstallRedirect> {\n return toInstallRedirect(\n await checkedApiRequest(createGithubInstallResponseSchema, '/integrations/github/install', {\n method: 'POST',\n body,\n }),\n );\n}\n\nexport async function completeGithubCallback({\n code,\n installationId,\n state,\n setupAction,\n token,\n}: {\n code: string;\n installationId: number;\n state: string;\n setupAction?: string;\n token: string;\n}): Promise<IntegrationConnection> {\n const query = new URLSearchParams({code, installation_id: String(installationId), state});\n if (setupAction) query.set('setup_action', setupAction);\n const response = await checkedApiRequest(\n githubCallbackResponseSchema,\n `/integrations/github/callback/api?${query.toString()}`,\n {headers: {authorization: `Bearer ${token}`}},\n );\n return toIntegrationConnection(response);\n}\n\nexport async function createSentryInstall(\n body: CreateSentryInstallBodyDto,\n): Promise<InstallRedirect> {\n return toInstallRedirect(\n await checkedApiRequest(createSentryInstallResponseSchema, '/integrations/sentry/install', {\n method: 'POST',\n body,\n }),\n );\n}\n\nexport async function createLinearInstall(\n body: CreateLinearInstallBodyDto,\n): Promise<InstallRedirect> {\n return toInstallRedirect(\n await checkedApiRequest(createLinearInstallResponseSchema, '/integrations/linear/install', {\n method: 'POST',\n body,\n }),\n );\n}\n\nexport async function createSlackInstall(\n body: CreateSlackInstallBodyDto,\n): Promise<InstallRedirect> {\n return toInstallRedirect(\n await checkedApiRequest(createSlackInstallResponseSchema, '/integrations/slack/install', {\n method: 'POST',\n body,\n }),\n );\n}\n\nexport async function completeLinearCallback({\n query,\n token,\n}: {\n query: LinearCallbackQueryDto;\n token: string;\n}): Promise<IntegrationConnection> {\n const response = await checkedApiRequest(\n linearCallbackResponseSchema,\n `/integrations/linear/callback/api?${serializeLinearCallbackQuery(query)}`,\n {headers: {authorization: `Bearer ${token}`}},\n );\n return toIntegrationConnection(response);\n}\n\nexport async function completeSlackCallback({\n query,\n token,\n}: {\n query: SlackCallbackQueryDto;\n token: string;\n}): Promise<IntegrationConnection> {\n const response = await checkedApiRequest(\n slackCallbackResponseSchema,\n `/integrations/slack/callback/api?${serializeSlackCallbackQuery(query)}`,\n {headers: {authorization: `Bearer ${token}`}},\n );\n return toIntegrationConnection(response);\n}\n\n// Called from the callback route with an explicit bearer (same as the GitHub\n// callback): the route refreshes auth itself before forwarding the grant code.\nexport async function connectSentry({body, token}: {body: SentryConnectBodyDto; token: string}) {\n const response = await checkedApiRequest(\n sentryConnectResponseSchema,\n '/integrations/sentry/connect',\n {\n method: 'POST',\n body,\n headers: {authorization: `Bearer ${token}`},\n },\n );\n return toIntegrationConnection(response);\n}\n\nexport async function listRepositories({\n connectionId,\n cursor,\n search,\n signal,\n}: {\n connectionId: string;\n cursor?: string;\n search?: string;\n signal?: AbortSignal;\n}): Promise<RepositoryPage> {\n const params = new URLSearchParams();\n if (cursor) params.set('cursor', cursor);\n if (search) params.set('search', search);\n const query = params.toString();\n const path = query\n ? `/integration-connections/${connectionId}/repositories?${query}`\n : `/integration-connections/${connectionId}/repositories`;\n const response = await checkedApiRequest(listRepositoriesResponseSchema, path, {signal});\n return {\n repositories: response.repositories.map(toRepository),\n ...(response.next_cursor == null ? {} : {nextCursor: response.next_cursor}),\n };\n}\n\nexport async function updateIntegrationConnection({\n connectionId,\n body,\n}: {\n connectionId: string;\n body: UpdateIntegrationConnectionBodyDto;\n}): Promise<IntegrationConnection> {\n const response = await checkedApiRequest(\n integrationConnectionDtoSchema,\n `/integration-connections/${encodeURIComponent(connectionId)}`,\n {method: 'PATCH', body},\n );\n return toIntegrationConnection(response);\n}\n\nexport async function deleteIntegrationConnection({connectionId}: {connectionId: string}) {\n await checkedApiRequest(\n emptyResponseSchema,\n `/integration-connections/${encodeURIComponent(connectionId)}`,\n {\n method: 'DELETE',\n },\n );\n}\n\nexport function useIntegrationProvidersQuery(params?: {capability?: IntegrationCapabilityDto}) {\n return useQuery(integrationProvidersQueryOptions(params?.capability));\n}\n\nexport function integrationProvidersQueryOptions(\n capability?: IntegrationCapabilityDto,\n): ProvidersQueryOptions {\n return queryOptions({\n queryKey: integrationsQueryKeys.providers(capability ?? 'all'),\n queryFn: ({signal}) => listIntegrationProviders(capability ? {capability, signal} : {signal}),\n });\n}\n\nexport function useSourceConnectionsQuery(workspaceId: string | undefined) {\n return useQuery(sourceConnectionsQueryOptions(workspaceId));\n}\n\nexport function useIntegrationConnectionsQuery(workspaceId: string | undefined) {\n return useQuery(integrationConnectionsQueryOptions(workspaceId));\n}\n\nexport function integrationConnectionsQueryOptions(\n workspaceId: string | undefined,\n): ConnectionsQueryOptions {\n return queryOptions({\n queryKey: workspaceId\n ? integrationsQueryKeys.connections(workspaceId, 'all')\n : ([...integrationsQueryKeys.all, 'connections'] as const),\n enabled: Boolean(workspaceId),\n queryFn: ({signal}) => listIntegrationConnections({workspaceId: workspaceId ?? '', signal}),\n });\n}\n\nexport function repositoriesInfiniteQueryOptions(\n connectionId: string | undefined,\n options?: {search?: string},\n): RepositoriesInfiniteQueryOptions {\n const trimmedSearch = options?.search?.trim() ?? '';\n return infiniteQueryOptions({\n queryKey: connectionId\n ? integrationsQueryKeys.repositories(connectionId, trimmedSearch)\n : ([...integrationsQueryKeys.all, 'repositories'] as const),\n enabled: Boolean(connectionId),\n initialPageParam: undefined as string | undefined,\n queryFn: ({pageParam, signal}) => {\n const args: {connectionId: string; cursor?: string; search?: string; signal: AbortSignal} = {\n connectionId: connectionId ?? '',\n signal,\n };\n if (pageParam) args.cursor = pageParam;\n if (trimmedSearch) args.search = trimmedSearch;\n return listRepositories(args);\n },\n getNextPageParam: (lastPage) => lastPage.nextCursor,\n });\n}\n\nexport function useRepositoriesInfiniteQuery(\n connectionId: string | undefined,\n options?: {search?: string},\n) {\n return useInfiniteQuery(repositoriesInfiniteQueryOptions(connectionId, options));\n}\n\nexport function useCreateGiteaConnectionMutation() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: createGiteaConnection,\n onSuccess: async (connection) => {\n await queryClient.invalidateQueries({\n queryKey: integrationsQueryKeys.connectionsByWorkspace(connection.workspaceId),\n refetchType: 'all',\n });\n },\n });\n}\n\nexport function useCreateLinearInstallMutation() {\n return useMutation({mutationFn: createLinearInstall});\n}\n\nexport function useCreateSlackInstallMutation() {\n return useMutation({mutationFn: createSlackInstall});\n}\n\nexport function useCompleteLinearCallbackMutation() {\n return useMutation({mutationFn: completeLinearCallback});\n}\n\nexport function useCompleteSlackCallbackMutation() {\n return useMutation({mutationFn: completeSlackCallback});\n}\n\nexport function useUpdateIntegrationConnectionMutation() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: updateIntegrationConnection,\n onSuccess: async (connection) => {\n await queryClient.invalidateQueries({\n queryKey: integrationsQueryKeys.connectionsByWorkspace(connection.workspaceId),\n });\n },\n });\n}\n\nexport function useDeleteIntegrationConnectionMutation() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: ({\n workspaceId: _workspaceId,\n connectionId,\n }: {\n workspaceId: string;\n connectionId: string;\n }) => deleteIntegrationConnection({connectionId}),\n onSuccess: async (_result, variables) => {\n await queryClient.invalidateQueries({\n queryKey: integrationsQueryKeys.connectionsByWorkspace(variables.workspaceId),\n });\n },\n });\n}\n"],"names":["integrationConnectionDtoSchema","listIntegrationConnectionsResponseSchema","listIntegrationProvidersResponseSchema","listRepositoriesResponseSchema","createGiteaConnectionResponseSchema","createGithubInstallResponseSchema","githubCallbackResponseSchema","createLinearInstallResponseSchema","linearCallbackResponseSchema","createSentryInstallResponseSchema","sentryConnectResponseSchema","createSlackInstallResponseSchema","slackCallbackResponseSchema","checkedApiRequest","emptyResponseSchema","infiniteQueryOptions","queryOptions","useInfiniteQuery","useMutation","useQuery","useQueryClient","isUsableConnection","serializeLinearCallbackQuery","serializeSlackCallbackQuery","toInstallRedirect","toIntegrationConnection","toIntegrationProvider","toRepository","integrationsQueryKeys","all","providers","capability","connections","workspaceId","connectionsByWorkspace","sourceConnections","repositories","connectionId","search","listIntegrationProviders","signal","URLSearchParams","set","query","toString","path","response","map","listIntegrationConnections","workspace_id","listSourceConnections","filter","sourceConnectionsQueryOptions","queryKey","enabled","Boolean","queryFn","createGiteaConnection","body","method","createGithubInstall","completeGithubCallback","code","installationId","state","setupAction","token","installation_id","String","headers","authorization","createSentryInstall","createLinearInstall","createSlackInstall","completeLinearCallback","completeSlackCallback","connectSentry","listRepositories","cursor","params","next_cursor","nextCursor","updateIntegrationConnection","encodeURIComponent","deleteIntegrationConnection","useIntegrationProvidersQuery","integrationProvidersQueryOptions","useSourceConnectionsQuery","useIntegrationConnectionsQuery","integrationConnectionsQueryOptions","repositoriesInfiniteQueryOptions","options","trimmedSearch","trim","initialPageParam","undefined","pageParam","args","getNextPageParam","lastPage","useRepositoriesInfiniteQuery","useCreateGiteaConnectionMutation","queryClient","mutationFn","onSuccess","connection","invalidateQueries","refetchType","useCreateLinearInstallMutation","useCreateSlackInstallMutation","useCompleteLinearCallbackMutation","useCompleteSlackCallbackMutation","useUpdateIntegrationConnectionMutation","useDeleteIntegrationConnectionMutation","_workspaceId","_result","variables"],"mappings":"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"}
|
|
@@ -29,9 +29,9 @@ export function GiteaInstallPage() {
|
|
|
29
29
|
});
|
|
30
30
|
toast.success('Gitea organization installed.');
|
|
31
31
|
await navigate({
|
|
32
|
-
to: '/
|
|
32
|
+
to: '/w/$workspaceSlug',
|
|
33
33
|
params: {
|
|
34
|
-
|
|
34
|
+
workspaceSlug: workspace.slug
|
|
35
35
|
}
|
|
36
36
|
});
|
|
37
37
|
} catch (error) {
|
|
@@ -112,9 +112,9 @@ export function GiteaInstallPage() {
|
|
|
112
112
|
asChild: true,
|
|
113
113
|
variant: "muted",
|
|
114
114
|
children: /*#__PURE__*/ _jsx(Link, {
|
|
115
|
-
to: "/
|
|
115
|
+
to: "/w/$workspaceSlug/integrations",
|
|
116
116
|
params: {
|
|
117
|
-
|
|
117
|
+
workspaceSlug: workspace.slug
|
|
118
118
|
},
|
|
119
119
|
children: "Cancel"
|
|
120
120
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/pages/gitea-install-page.tsx"],"sourcesContent":["import {useActiveWorkspace} from '@shipfox/client-auth';\nimport {Button, ButtonLink} from '@shipfox/react-ui/button';\nimport {Callout} from '@shipfox/react-ui/callout';\nimport {FormField, FormFieldInput, fieldError} from '@shipfox/react-ui/form-field';\nimport {toast} from '@shipfox/react-ui/toast';\nimport {Header, Text} from '@shipfox/react-ui/typography';\nimport {useForm} from '@tanstack/react-form';\nimport {Link, useNavigate} from '@tanstack/react-router';\nimport {useState} from 'react';\nimport {useCreateGiteaConnectionMutation} from '#hooks/api/integrations.js';\nimport {giteaConnectErrorToFormError} from './gitea-form-errors.js';\n\nexport function GiteaInstallPage() {\n const workspace = useActiveWorkspace();\n const connect = useCreateGiteaConnectionMutation();\n const navigate = useNavigate();\n const [formError, setFormError] = useState<string | undefined>();\n\n const form = useForm({\n defaultValues: {org: ''},\n onSubmit: async ({value}) => {\n setFormError(undefined);\n const workspaceId = workspace.id;\n try {\n await connect.mutateAsync({workspace_id: workspaceId, org: value.org.trim()});\n toast.success('Gitea organization installed.');\n await navigate({to: '/
|
|
1
|
+
{"version":3,"sources":["../../src/pages/gitea-install-page.tsx"],"sourcesContent":["import {useActiveWorkspace} from '@shipfox/client-auth';\nimport {Button, ButtonLink} from '@shipfox/react-ui/button';\nimport {Callout} from '@shipfox/react-ui/callout';\nimport {FormField, FormFieldInput, fieldError} from '@shipfox/react-ui/form-field';\nimport {toast} from '@shipfox/react-ui/toast';\nimport {Header, Text} from '@shipfox/react-ui/typography';\nimport {useForm} from '@tanstack/react-form';\nimport {Link, useNavigate} from '@tanstack/react-router';\nimport {useState} from 'react';\nimport {useCreateGiteaConnectionMutation} from '#hooks/api/integrations.js';\nimport {giteaConnectErrorToFormError} from './gitea-form-errors.js';\n\nexport function GiteaInstallPage() {\n const workspace = useActiveWorkspace();\n const connect = useCreateGiteaConnectionMutation();\n const navigate = useNavigate();\n const [formError, setFormError] = useState<string | undefined>();\n\n const form = useForm({\n defaultValues: {org: ''},\n onSubmit: async ({value}) => {\n setFormError(undefined);\n const workspaceId = workspace.id;\n try {\n await connect.mutateAsync({workspace_id: workspaceId, org: value.org.trim()});\n toast.success('Gitea organization installed.');\n await navigate({to: '/w/$workspaceSlug', params: {workspaceSlug: workspace.slug}});\n } catch (error) {\n const mapped = giteaConnectErrorToFormError(error);\n if (mapped.kind === 'field') {\n form.setFieldMeta(mapped.field, (prev) => ({\n ...prev,\n errorMap: {...prev.errorMap, onServer: mapped.message},\n }));\n } else {\n setFormError(mapped.message);\n }\n }\n },\n });\n\n return (\n <div className=\"mx-auto flex w-full max-w-[480px] flex-col gap-20\">\n <header className=\"flex flex-col gap-8\">\n <Header variant=\"h1\">Install Gitea</Header>\n <Text size=\"md\" className=\"text-foreground-neutral-muted\">\n Enter the Gitea organization to install in this workspace.\n </Text>\n </header>\n\n <form\n className=\"flex flex-col gap-18\"\n noValidate\n onSubmit={(event) => {\n event.preventDefault();\n event.stopPropagation();\n void form.handleSubmit();\n }}\n >\n {formError ? (\n <Callout role=\"alert\" type=\"error\">\n {formError}\n </Callout>\n ) : null}\n <form.Field\n name=\"org\"\n validators={{\n onBlur: ({value}) =>\n value.trim().length > 0 ? undefined : 'Enter your Gitea organization.',\n onSubmit: ({value}) =>\n value.trim().length > 0 ? undefined : 'Enter your Gitea organization.',\n }}\n >\n {(field) => (\n <FormField label=\"Organization\" id=\"gitea-org\" error={fieldError(field)}>\n <FormFieldInput\n placeholder=\"my-org\"\n autoComplete=\"off\"\n value={field.state.value}\n onChange={(event) => field.handleChange(event.target.value)}\n onBlur={field.handleBlur}\n />\n </FormField>\n )}\n </form.Field>\n <div className=\"flex items-center gap-12\">\n <Button type=\"submit\" isLoading={connect.isPending}>\n Install\n </Button>\n <ButtonLink asChild variant=\"muted\">\n <Link to=\"/w/$workspaceSlug/integrations\" params={{workspaceSlug: workspace.slug}}>\n Cancel\n </Link>\n </ButtonLink>\n </div>\n </form>\n </div>\n );\n}\n"],"names":["useActiveWorkspace","Button","ButtonLink","Callout","FormField","FormFieldInput","fieldError","toast","Header","Text","useForm","Link","useNavigate","useState","useCreateGiteaConnectionMutation","giteaConnectErrorToFormError","GiteaInstallPage","workspace","connect","navigate","formError","setFormError","form","defaultValues","org","onSubmit","value","undefined","workspaceId","id","mutateAsync","workspace_id","trim","success","to","params","workspaceSlug","slug","error","mapped","kind","setFieldMeta","field","prev","errorMap","onServer","message","div","className","header","variant","size","noValidate","event","preventDefault","stopPropagation","handleSubmit","role","type","Field","name","validators","onBlur","length","label","placeholder","autoComplete","state","onChange","handleChange","target","handleBlur","isLoading","isPending","asChild"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"linear-callback-page.d.ts","sourceRoot":"","sources":["../../src/pages/linear-callback-page.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"linear-callback-page.d.ts","sourceRoot":"","sources":["../../src/pages/linear-callback-page.tsx"],"names":[],"mappings":"AAgCA,wBAAgB,kBAAkB,gCAoIjC"}
|