@shipfox/client-integrations 14.0.0 → 14.0.1
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 +14 -0
- package/dist/components/callback-status-shell.js +3 -3
- package/dist/components/callback-status-shell.js.map +1 -1
- package/dist/components/connection-picker.js +3 -3
- package/dist/components/connection-picker.js.map +1 -1
- package/dist/components/installed-integrations-section.js +9 -9
- package/dist/components/installed-integrations-section.js.map +1 -1
- package/dist/components/integration-delete-confirm-modal.js +1 -1
- package/dist/components/integration-delete-confirm-modal.js.map +1 -1
- package/dist/components/integration-gallery-for-workspace.js +3 -3
- package/dist/components/integration-gallery-for-workspace.js.map +1 -1
- package/dist/components/integration-usage-modal.js +6 -6
- package/dist/components/integration-usage-modal.js.map +1 -1
- package/dist/components/provider-grid.d.ts +1 -1
- package/dist/components/provider-grid.d.ts.map +1 -1
- package/dist/components/provider-grid.js +10 -10
- package/dist/components/provider-grid.js.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.js +4 -4
- package/dist/components/repository-picker.js.map +1 -1
- package/dist/components/webhook/copyable-value.js +3 -3
- package/dist/components/webhook/copyable-value.js.map +1 -1
- package/dist/components/webhook/webhook-create-modal.js +1 -1
- package/dist/components/webhook/webhook-create-modal.js.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/pages/gitea-install-page.js +4 -4
- package/dist/pages/gitea-install-page.js.map +1 -1
- package/dist/pages/jira-callback-page.js +7 -7
- package/dist/pages/jira-callback-page.js.map +1 -1
- package/dist/pages/sentry-callback-page.js +7 -7
- package/dist/pages/sentry-callback-page.js.map +1 -1
- package/dist/pages/source-control-onboarding-page.js +2 -2
- package/dist/pages/source-control-onboarding-page.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +6 -6
- package/src/components/callback-status-shell.tsx +3 -3
- package/src/components/connection-picker.tsx +3 -3
- package/src/components/installed-integrations-section.tsx +9 -9
- package/src/components/integration-delete-confirm-modal.tsx +1 -1
- package/src/components/integration-gallery-for-workspace.tsx +3 -3
- package/src/components/integration-usage-modal.tsx +6 -6
- package/src/components/provider-grid.tsx +10 -10
- package/src/components/redirect-install-page.tsx +1 -1
- package/src/components/repository-picker.test.tsx +2 -2
- package/src/components/repository-picker.tsx +6 -4
- package/src/components/webhook/copyable-value.tsx +3 -3
- package/src/components/webhook/webhook-create-modal.tsx +1 -1
- package/src/components/webhook/webhook-usage-details.tsx +2 -2
- package/src/pages/gitea-install-page.tsx +4 -4
- package/src/pages/jira-callback-page.tsx +7 -7
- package/src/pages/sentry-callback-page.tsx +7 -7
- package/src/pages/source-control-onboarding-page.tsx +2 -2
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -152,7 +152,7 @@ export function SentryCallbackPage() {
|
|
|
152
152
|
return /*#__PURE__*/ _jsxs(CallbackColumn, {
|
|
153
153
|
children: [
|
|
154
154
|
/*#__PURE__*/ _jsxs("header", {
|
|
155
|
-
className: "flex flex-col gap-
|
|
155
|
+
className: "flex flex-col gap-inline",
|
|
156
156
|
children: [
|
|
157
157
|
/*#__PURE__*/ _jsx(Header, {
|
|
158
158
|
variant: "h2",
|
|
@@ -169,7 +169,7 @@ export function SentryCallbackPage() {
|
|
|
169
169
|
role: "alert",
|
|
170
170
|
type: "error",
|
|
171
171
|
children: /*#__PURE__*/ _jsxs("div", {
|
|
172
|
-
className: "flex flex-col gap-
|
|
172
|
+
className: "flex flex-col gap-inline",
|
|
173
173
|
children: [
|
|
174
174
|
/*#__PURE__*/ _jsx(Text, {
|
|
175
175
|
size: "sm",
|
|
@@ -200,12 +200,12 @@ export function SentryCallbackPage() {
|
|
|
200
200
|
})
|
|
201
201
|
}) : null,
|
|
202
202
|
/*#__PURE__*/ _jsx("section", {
|
|
203
|
-
className: "flex flex-col gap-
|
|
203
|
+
className: "flex flex-col gap-inline",
|
|
204
204
|
"aria-label": "Choose a workspace",
|
|
205
205
|
children: orderedWorkspaces.map((workspace)=>/*#__PURE__*/ _jsx(Card, {
|
|
206
|
-
className: "p-
|
|
206
|
+
className: "p-panel-compact",
|
|
207
207
|
children: /*#__PURE__*/ _jsxs("div", {
|
|
208
|
-
className: "flex items-center justify-between gap-
|
|
208
|
+
className: "flex items-center justify-between gap-cluster",
|
|
209
209
|
children: [
|
|
210
210
|
/*#__PURE__*/ _jsx(Text, {
|
|
211
211
|
size: "md",
|
|
@@ -241,9 +241,9 @@ export function SentryCallbackPage() {
|
|
|
241
241
|
}
|
|
242
242
|
function CallbackColumn({ children }) {
|
|
243
243
|
return /*#__PURE__*/ _jsx("main", {
|
|
244
|
-
className: "flex min-h-screen bg-background-subtle-base px-
|
|
244
|
+
className: "flex min-h-screen bg-background-subtle-base px-row py-frame",
|
|
245
245
|
children: /*#__PURE__*/ _jsx("div", {
|
|
246
|
-
className: "mx-auto flex w-full max-w-[480px] flex-col justify-center gap-
|
|
246
|
+
className: "mx-auto flex w-full max-w-[480px] flex-col justify-center gap-section",
|
|
247
247
|
children: children
|
|
248
248
|
})
|
|
249
249
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/pages/sentry-callback-page.tsx"],"sourcesContent":["import {useAuthState, useRefreshAuth} from '@shipfox/client-auth';\nimport {useRouteSearch} from '@shipfox/client-shell/runtime';\nimport {createSingleFlight, sessionStorageOrUndefined} from '@shipfox/client-ui';\nimport {Button, ButtonLink} from '@shipfox/react-ui/button';\nimport {Callout} from '@shipfox/react-ui/callout';\nimport {Card} from '@shipfox/react-ui/card';\nimport {FullPageLoader} from '@shipfox/react-ui/loader';\nimport {toast} from '@shipfox/react-ui/toast';\nimport {Header, Text} from '@shipfox/react-ui/typography';\nimport {useQueryClient} from '@tanstack/react-query';\nimport {Link, useNavigate} from '@tanstack/react-router';\nimport {useEffect, useMemo, useRef, useState} from 'react';\nimport {useCompleteIntegrationCallback} from '#application/complete-integration-callback.js';\nimport type {IntegrationConnection} from '#core/models.js';\nimport {connectSentry} from '#hooks/api/integrations.js';\nimport {\n classifySentryConnectError,\n clearSentryInstallWorkspace,\n parseSentryCallbackParams,\n preselectSentryWorkspace,\n readSentryInstallWorkspace,\n type SentryConnectFailure,\n} from '#sentry-callback.js';\nimport {resolveWorkspaceSlug} from '#workspace-navigation.js';\n\nconst connectRequests = createSingleFlight<string, IntegrationConnection>();\n\nexport function SentryCallbackPage() {\n const navigate = useNavigate();\n const queryClient = useQueryClient();\n const refreshAuth = useRefreshAuth();\n const {workspaces, isLoading} = useAuthState();\n const completeIntegrationCallback = useCompleteIntegrationCallback();\n\n const params = useRouteSearch(parseSentryCallbackParams);\n const storedWorkspaceId = useMemo(\n () => readSentryInstallWorkspace(sessionStorageOrUndefined()),\n [],\n );\n const preselection = preselectSentryWorkspace(storedWorkspaceId, workspaces);\n const preselectedId = preselection.kind === 'pick' ? preselection.preselectedId : undefined;\n\n const [connectingId, setConnectingId] = useState<string | undefined>();\n const [failure, setFailure] = useState<\n {workspaceId: string; failure: SentryConnectFailure} | undefined\n >();\n const [retryLocked, setRetryLocked] = useState(false);\n const disposedRef = useRef(false);\n\n useEffect(() => {\n disposedRef.current = false;\n return () => {\n disposedRef.current = true;\n };\n }, []);\n\n // Wait for auth before treating an empty workspace list as \"no workspace\": on\n // a cold return from Sentry, `workspaces` is [] until the session refresh\n // resolves, and bouncing to `/` then would discard the one-shot grant code.\n const noWorkspace = !isLoading && preselection.kind === 'none';\n useEffect(() => {\n if (!noWorkspace) return;\n toast.error('You need a workspace before installing Sentry.');\n navigate({to: '/', replace: true});\n }, [noWorkspace, navigate]);\n\n const retryAfterSeconds =\n failure?.failure.kind === 'retryable' ? failure.failure.retryAfterSeconds : undefined;\n useEffect(() => {\n // No backoff window (any non-rate-limited failure) re-enables Retry, so a\n // prior rate-limit lock can never strand the button in a disabled state.\n if (!retryAfterSeconds) {\n setRetryLocked(false);\n return;\n }\n setRetryLocked(true);\n const timer = setTimeout(() => setRetryLocked(false), retryAfterSeconds * 1000);\n return () => clearTimeout(timer);\n }, [retryAfterSeconds]);\n\n if (!params) {\n return (\n <CallbackColumn>\n <Callout role=\"alert\" type=\"error\">\n <Text size=\"sm\">\n This Sentry link is missing required parameters. Start the install again from your\n workspace settings.\n </Text>\n </Callout>\n <ButtonLink asChild variant=\"muted\" className=\"w-fit\">\n <Link to=\"/\">Back to Shipfox</Link>\n </ButtonLink>\n </CallbackColumn>\n );\n }\n\n // Hold the loader until auth resolves; the workspace list and the\n // noWorkspace redirect both depend on a settled `workspaces`.\n if (isLoading) return <FullPageLoader />;\n\n if (noWorkspace) return null;\n\n const connect = (workspaceId: string) => {\n setConnectingId(workspaceId);\n setFailure(undefined);\n const key = `${params.installationId}|${workspaceId}|${params.code}`;\n const request = connectRequests.run(\n key,\n async () =>\n await completeIntegrationCallback({\n input: workspaceId,\n refreshAuth,\n complete: async (selectedWorkspaceId, token) =>\n await connectSentry({\n body: {\n workspace_id: selectedWorkspaceId,\n code: params.code,\n installation_id: params.installationId,\n },\n token,\n }),\n }),\n );\n\n request\n .then(async () => {\n clearSentryInstallWorkspace(sessionStorageOrUndefined());\n if (disposedRef.current) return;\n toast.success('Sentry installed.');\n const workspaceSlug = await resolveWorkspaceSlug({\n workspaceId,\n fallbackWorkspaces: workspaces,\n queryClient,\n });\n if (disposedRef.current) return;\n await navigate(\n workspaceSlug\n ? {\n to: '/w/$workspaceSlug/settings/integrations',\n params: {workspaceSlug},\n replace: true,\n }\n : {to: '/', replace: true},\n );\n })\n .catch((error: unknown) => {\n if (disposedRef.current) return;\n const classified = classifySentryConnectError(error);\n if (classified.kind === 'terminal') {\n // Only a fresh install (new grant code) can recover; the stored\n // handoff has served its purpose either way.\n clearSentryInstallWorkspace(sessionStorageOrUndefined());\n }\n setConnectingId(undefined);\n setFailure({workspaceId, failure: classified});\n });\n };\n\n const orderedWorkspaces = preselectedId\n ? [\n ...workspaces.filter((workspace) => workspace.id === preselectedId),\n ...workspaces.filter((workspace) => workspace.id !== preselectedId),\n ]\n : workspaces;\n\n const failureWorkspaceId = failure?.workspaceId ?? preselectedId ?? workspaces[0]?.id;\n const failureWorkspace = failureWorkspaceId\n ? workspaces.find(({id}) => id === failureWorkspaceId)\n : undefined;\n\n return (\n <CallbackColumn>\n <header className=\"flex flex-col gap-8\">\n <Header variant=\"h2\">Install Sentry</Header>\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\">\n {params.orgSlug\n ? `Install the Sentry org \"${params.orgSlug}\" in a workspace.`\n : 'Install this Sentry integration in a workspace.'}\n </Text>\n </header>\n\n {failure ? (\n <Callout role=\"alert\" type=\"error\">\n <div className=\"flex flex-col gap-8\">\n <Text size=\"sm\">{failure.failure.message}</Text>\n {failure.failure.kind === 'retryable' ? (\n <Button\n size=\"sm\"\n variant=\"secondary\"\n className=\"w-fit\"\n disabled={retryLocked || connectingId !== undefined}\n onClick={() => connect(failure.workspaceId)}\n >\n Retry\n </Button>\n ) : null}\n {failure.failure.kind === 'terminal' &&\n failure.failure.startOver &&\n failureWorkspace ? (\n <Button asChild size=\"sm\" variant=\"secondary\" className=\"w-fit\">\n <Link\n to=\"/w/$workspaceSlug/integrations/sentry\"\n params={{workspaceSlug: failureWorkspace.slug}}\n >\n Start over\n </Link>\n </Button>\n ) : null}\n </div>\n </Callout>\n ) : null}\n\n <section className=\"flex flex-col gap-8\" aria-label=\"Choose a workspace\">\n {orderedWorkspaces.map((workspace) => (\n <Card key={workspace.id} className=\"p-16\">\n <div className=\"flex items-center justify-between gap-12\">\n <Text size=\"md\" bold className=\"truncate\">\n {workspace.name}\n </Text>\n <Button\n variant=\"secondary\"\n disabled={connectingId !== undefined}\n isLoading={connectingId === workspace.id}\n onClick={() => connect(workspace.id)}\n >\n Install\n </Button>\n </div>\n </Card>\n ))}\n </section>\n\n {failureWorkspace ? (\n <ButtonLink asChild variant=\"muted\" className=\"w-fit\">\n <Link\n to=\"/w/$workspaceSlug/settings/integrations\"\n params={{workspaceSlug: failureWorkspace.slug}}\n >\n Back to settings\n </Link>\n </ButtonLink>\n ) : null}\n </CallbackColumn>\n );\n}\n\nfunction CallbackColumn({children}: {children: React.ReactNode}) {\n return (\n <main className=\"flex min-h-screen bg-background-subtle-base px-16 py-32\">\n <div className=\"mx-auto flex w-full max-w-[480px] flex-col justify-center gap-20\">\n {children}\n </div>\n </main>\n );\n}\n"],"names":["useAuthState","useRefreshAuth","useRouteSearch","createSingleFlight","sessionStorageOrUndefined","Button","ButtonLink","Callout","Card","FullPageLoader","toast","Header","Text","useQueryClient","Link","useNavigate","useEffect","useMemo","useRef","useState","useCompleteIntegrationCallback","connectSentry","classifySentryConnectError","clearSentryInstallWorkspace","parseSentryCallbackParams","preselectSentryWorkspace","readSentryInstallWorkspace","resolveWorkspaceSlug","connectRequests","SentryCallbackPage","navigate","queryClient","refreshAuth","workspaces","isLoading","completeIntegrationCallback","params","storedWorkspaceId","preselection","preselectedId","kind","undefined","connectingId","setConnectingId","failure","setFailure","retryLocked","setRetryLocked","disposedRef","current","noWorkspace","error","to","replace","retryAfterSeconds","timer","setTimeout","clearTimeout","CallbackColumn","role","type","size","asChild","variant","className","connect","workspaceId","key","installationId","code","request","run","input","complete","selectedWorkspaceId","token","body","workspace_id","installation_id","then","success","workspaceSlug","fallbackWorkspaces","catch","classified","orderedWorkspaces","filter","workspace","id","failureWorkspaceId","failureWorkspace","find","header","orgSlug","div","message","disabled","onClick","startOver","slug","section","aria-label","map","bold","name","children","main"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/pages/sentry-callback-page.tsx"],"sourcesContent":["import {useAuthState, useRefreshAuth} from '@shipfox/client-auth';\nimport {useRouteSearch} from '@shipfox/client-shell/runtime';\nimport {createSingleFlight, sessionStorageOrUndefined} from '@shipfox/client-ui';\nimport {Button, ButtonLink} from '@shipfox/react-ui/button';\nimport {Callout} from '@shipfox/react-ui/callout';\nimport {Card} from '@shipfox/react-ui/card';\nimport {FullPageLoader} from '@shipfox/react-ui/loader';\nimport {toast} from '@shipfox/react-ui/toast';\nimport {Header, Text} from '@shipfox/react-ui/typography';\nimport {useQueryClient} from '@tanstack/react-query';\nimport {Link, useNavigate} from '@tanstack/react-router';\nimport {useEffect, useMemo, useRef, useState} from 'react';\nimport {useCompleteIntegrationCallback} from '#application/complete-integration-callback.js';\nimport type {IntegrationConnection} from '#core/models.js';\nimport {connectSentry} from '#hooks/api/integrations.js';\nimport {\n classifySentryConnectError,\n clearSentryInstallWorkspace,\n parseSentryCallbackParams,\n preselectSentryWorkspace,\n readSentryInstallWorkspace,\n type SentryConnectFailure,\n} from '#sentry-callback.js';\nimport {resolveWorkspaceSlug} from '#workspace-navigation.js';\n\nconst connectRequests = createSingleFlight<string, IntegrationConnection>();\n\nexport function SentryCallbackPage() {\n const navigate = useNavigate();\n const queryClient = useQueryClient();\n const refreshAuth = useRefreshAuth();\n const {workspaces, isLoading} = useAuthState();\n const completeIntegrationCallback = useCompleteIntegrationCallback();\n\n const params = useRouteSearch(parseSentryCallbackParams);\n const storedWorkspaceId = useMemo(\n () => readSentryInstallWorkspace(sessionStorageOrUndefined()),\n [],\n );\n const preselection = preselectSentryWorkspace(storedWorkspaceId, workspaces);\n const preselectedId = preselection.kind === 'pick' ? preselection.preselectedId : undefined;\n\n const [connectingId, setConnectingId] = useState<string | undefined>();\n const [failure, setFailure] = useState<\n {workspaceId: string; failure: SentryConnectFailure} | undefined\n >();\n const [retryLocked, setRetryLocked] = useState(false);\n const disposedRef = useRef(false);\n\n useEffect(() => {\n disposedRef.current = false;\n return () => {\n disposedRef.current = true;\n };\n }, []);\n\n // Wait for auth before treating an empty workspace list as \"no workspace\": on\n // a cold return from Sentry, `workspaces` is [] until the session refresh\n // resolves, and bouncing to `/` then would discard the one-shot grant code.\n const noWorkspace = !isLoading && preselection.kind === 'none';\n useEffect(() => {\n if (!noWorkspace) return;\n toast.error('You need a workspace before installing Sentry.');\n navigate({to: '/', replace: true});\n }, [noWorkspace, navigate]);\n\n const retryAfterSeconds =\n failure?.failure.kind === 'retryable' ? failure.failure.retryAfterSeconds : undefined;\n useEffect(() => {\n // No backoff window (any non-rate-limited failure) re-enables Retry, so a\n // prior rate-limit lock can never strand the button in a disabled state.\n if (!retryAfterSeconds) {\n setRetryLocked(false);\n return;\n }\n setRetryLocked(true);\n const timer = setTimeout(() => setRetryLocked(false), retryAfterSeconds * 1000);\n return () => clearTimeout(timer);\n }, [retryAfterSeconds]);\n\n if (!params) {\n return (\n <CallbackColumn>\n <Callout role=\"alert\" type=\"error\">\n <Text size=\"sm\">\n This Sentry link is missing required parameters. Start the install again from your\n workspace settings.\n </Text>\n </Callout>\n <ButtonLink asChild variant=\"muted\" className=\"w-fit\">\n <Link to=\"/\">Back to Shipfox</Link>\n </ButtonLink>\n </CallbackColumn>\n );\n }\n\n // Hold the loader until auth resolves; the workspace list and the\n // noWorkspace redirect both depend on a settled `workspaces`.\n if (isLoading) return <FullPageLoader />;\n\n if (noWorkspace) return null;\n\n const connect = (workspaceId: string) => {\n setConnectingId(workspaceId);\n setFailure(undefined);\n const key = `${params.installationId}|${workspaceId}|${params.code}`;\n const request = connectRequests.run(\n key,\n async () =>\n await completeIntegrationCallback({\n input: workspaceId,\n refreshAuth,\n complete: async (selectedWorkspaceId, token) =>\n await connectSentry({\n body: {\n workspace_id: selectedWorkspaceId,\n code: params.code,\n installation_id: params.installationId,\n },\n token,\n }),\n }),\n );\n\n request\n .then(async () => {\n clearSentryInstallWorkspace(sessionStorageOrUndefined());\n if (disposedRef.current) return;\n toast.success('Sentry installed.');\n const workspaceSlug = await resolveWorkspaceSlug({\n workspaceId,\n fallbackWorkspaces: workspaces,\n queryClient,\n });\n if (disposedRef.current) return;\n await navigate(\n workspaceSlug\n ? {\n to: '/w/$workspaceSlug/settings/integrations',\n params: {workspaceSlug},\n replace: true,\n }\n : {to: '/', replace: true},\n );\n })\n .catch((error: unknown) => {\n if (disposedRef.current) return;\n const classified = classifySentryConnectError(error);\n if (classified.kind === 'terminal') {\n // Only a fresh install (new grant code) can recover; the stored\n // handoff has served its purpose either way.\n clearSentryInstallWorkspace(sessionStorageOrUndefined());\n }\n setConnectingId(undefined);\n setFailure({workspaceId, failure: classified});\n });\n };\n\n const orderedWorkspaces = preselectedId\n ? [\n ...workspaces.filter((workspace) => workspace.id === preselectedId),\n ...workspaces.filter((workspace) => workspace.id !== preselectedId),\n ]\n : workspaces;\n\n const failureWorkspaceId = failure?.workspaceId ?? preselectedId ?? workspaces[0]?.id;\n const failureWorkspace = failureWorkspaceId\n ? workspaces.find(({id}) => id === failureWorkspaceId)\n : undefined;\n\n return (\n <CallbackColumn>\n <header className=\"flex flex-col gap-inline\">\n <Header variant=\"h2\">Install Sentry</Header>\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\">\n {params.orgSlug\n ? `Install the Sentry org \"${params.orgSlug}\" in a workspace.`\n : 'Install this Sentry integration in a workspace.'}\n </Text>\n </header>\n\n {failure ? (\n <Callout role=\"alert\" type=\"error\">\n <div className=\"flex flex-col gap-inline\">\n <Text size=\"sm\">{failure.failure.message}</Text>\n {failure.failure.kind === 'retryable' ? (\n <Button\n size=\"sm\"\n variant=\"secondary\"\n className=\"w-fit\"\n disabled={retryLocked || connectingId !== undefined}\n onClick={() => connect(failure.workspaceId)}\n >\n Retry\n </Button>\n ) : null}\n {failure.failure.kind === 'terminal' &&\n failure.failure.startOver &&\n failureWorkspace ? (\n <Button asChild size=\"sm\" variant=\"secondary\" className=\"w-fit\">\n <Link\n to=\"/w/$workspaceSlug/integrations/sentry\"\n params={{workspaceSlug: failureWorkspace.slug}}\n >\n Start over\n </Link>\n </Button>\n ) : null}\n </div>\n </Callout>\n ) : null}\n\n <section className=\"flex flex-col gap-inline\" aria-label=\"Choose a workspace\">\n {orderedWorkspaces.map((workspace) => (\n <Card key={workspace.id} className=\"p-panel-compact\">\n <div className=\"flex items-center justify-between gap-cluster\">\n <Text size=\"md\" bold className=\"truncate\">\n {workspace.name}\n </Text>\n <Button\n variant=\"secondary\"\n disabled={connectingId !== undefined}\n isLoading={connectingId === workspace.id}\n onClick={() => connect(workspace.id)}\n >\n Install\n </Button>\n </div>\n </Card>\n ))}\n </section>\n\n {failureWorkspace ? (\n <ButtonLink asChild variant=\"muted\" className=\"w-fit\">\n <Link\n to=\"/w/$workspaceSlug/settings/integrations\"\n params={{workspaceSlug: failureWorkspace.slug}}\n >\n Back to settings\n </Link>\n </ButtonLink>\n ) : null}\n </CallbackColumn>\n );\n}\n\nfunction CallbackColumn({children}: {children: React.ReactNode}) {\n return (\n <main className=\"flex min-h-screen bg-background-subtle-base px-row py-frame\">\n <div className=\"mx-auto flex w-full max-w-[480px] flex-col justify-center gap-section\">\n {children}\n </div>\n </main>\n );\n}\n"],"names":["useAuthState","useRefreshAuth","useRouteSearch","createSingleFlight","sessionStorageOrUndefined","Button","ButtonLink","Callout","Card","FullPageLoader","toast","Header","Text","useQueryClient","Link","useNavigate","useEffect","useMemo","useRef","useState","useCompleteIntegrationCallback","connectSentry","classifySentryConnectError","clearSentryInstallWorkspace","parseSentryCallbackParams","preselectSentryWorkspace","readSentryInstallWorkspace","resolveWorkspaceSlug","connectRequests","SentryCallbackPage","navigate","queryClient","refreshAuth","workspaces","isLoading","completeIntegrationCallback","params","storedWorkspaceId","preselection","preselectedId","kind","undefined","connectingId","setConnectingId","failure","setFailure","retryLocked","setRetryLocked","disposedRef","current","noWorkspace","error","to","replace","retryAfterSeconds","timer","setTimeout","clearTimeout","CallbackColumn","role","type","size","asChild","variant","className","connect","workspaceId","key","installationId","code","request","run","input","complete","selectedWorkspaceId","token","body","workspace_id","installation_id","then","success","workspaceSlug","fallbackWorkspaces","catch","classified","orderedWorkspaces","filter","workspace","id","failureWorkspaceId","failureWorkspace","find","header","orgSlug","div","message","disabled","onClick","startOver","slug","section","aria-label","map","bold","name","children","main"],"mappings":"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"}
|
|
@@ -9,10 +9,10 @@ export function SourceControlOnboardingPage() {
|
|
|
9
9
|
capability: 'source_control'
|
|
10
10
|
});
|
|
11
11
|
return /*#__PURE__*/ _jsxs("div", {
|
|
12
|
-
className: "mx-auto flex w-full max-w-[640px] flex-col gap-
|
|
12
|
+
className: "mx-auto flex w-full max-w-[640px] flex-col gap-section",
|
|
13
13
|
children: [
|
|
14
14
|
/*#__PURE__*/ _jsxs("header", {
|
|
15
|
-
className: "flex flex-col gap-
|
|
15
|
+
className: "flex flex-col gap-inline",
|
|
16
16
|
children: [
|
|
17
17
|
/*#__PURE__*/ _jsx(Header, {
|
|
18
18
|
variant: "h1",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/pages/source-control-onboarding-page.tsx"],"sourcesContent":["import {useActiveWorkspace} from '@shipfox/client-auth';\nimport {Header, Text} from '@shipfox/react-ui/typography';\nimport {ProviderGrid} from '#components/provider-grid.js';\nimport {useIntegrationProvidersQuery} from '#hooks/api/integrations.js';\n\nexport function SourceControlOnboardingPage() {\n const workspace = useActiveWorkspace();\n const providersQuery = useIntegrationProvidersQuery({capability: 'source_control'});\n\n return (\n <div className=\"mx-auto flex w-full max-w-[640px] flex-col gap-
|
|
1
|
+
{"version":3,"sources":["../../src/pages/source-control-onboarding-page.tsx"],"sourcesContent":["import {useActiveWorkspace} from '@shipfox/client-auth';\nimport {Header, Text} from '@shipfox/react-ui/typography';\nimport {ProviderGrid} from '#components/provider-grid.js';\nimport {useIntegrationProvidersQuery} from '#hooks/api/integrations.js';\n\nexport function SourceControlOnboardingPage() {\n const workspace = useActiveWorkspace();\n const providersQuery = useIntegrationProvidersQuery({capability: 'source_control'});\n\n return (\n <div className=\"mx-auto flex w-full max-w-[640px] flex-col gap-section\">\n <header className=\"flex flex-col gap-inline\">\n <Header variant=\"h1\">Install source control</Header>\n <Text size=\"md\" className=\"text-foreground-neutral-muted\">\n Shipfox needs a source control integration to import your repositories.\n </Text>\n </header>\n\n <ProviderGrid\n workspaceSlug={workspace.slug}\n providers={providersQuery.data ?? []}\n isPending={providersQuery.isPending}\n isFetching={providersQuery.isFetching}\n error={providersQuery.isError ? providersQuery.error : undefined}\n onRetry={() => void providersQuery.refetch()}\n emptyMessage=\"Enable at least one source-control provider in the application settings.\"\n />\n </div>\n );\n}\n"],"names":["useActiveWorkspace","Header","Text","ProviderGrid","useIntegrationProvidersQuery","SourceControlOnboardingPage","workspace","providersQuery","capability","div","className","header","variant","size","workspaceSlug","slug","providers","data","isPending","isFetching","error","isError","undefined","onRetry","refetch","emptyMessage"],"mappings":";AAAA,SAAQA,kBAAkB,QAAO,uBAAuB;AACxD,SAAQC,MAAM,EAAEC,IAAI,QAAO,+BAA+B;AAC1D,SAAQC,YAAY,QAAO,+BAA+B;AAC1D,SAAQC,4BAA4B,QAAO,6BAA6B;AAExE,OAAO,SAASC;IACd,MAAMC,YAAYN;IAClB,MAAMO,iBAAiBH,6BAA6B;QAACI,YAAY;IAAgB;IAEjF,qBACE,MAACC;QAAIC,WAAU;;0BACb,MAACC;gBAAOD,WAAU;;kCAChB,KAACT;wBAAOW,SAAQ;kCAAK;;kCACrB,KAACV;wBAAKW,MAAK;wBAAKH,WAAU;kCAAgC;;;;0BAK5D,KAACP;gBACCW,eAAeR,UAAUS,IAAI;gBAC7BC,WAAWT,eAAeU,IAAI,IAAI,EAAE;gBACpCC,WAAWX,eAAeW,SAAS;gBACnCC,YAAYZ,eAAeY,UAAU;gBACrCC,OAAOb,eAAec,OAAO,GAAGd,eAAea,KAAK,GAAGE;gBACvDC,SAAS,IAAM,KAAKhB,eAAeiB,OAAO;gBAC1CC,cAAa;;;;AAIrB"}
|