@shipfox/client-integrations 13.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 +32 -0
- package/dist/application/complete-integration-callback.d.ts +11 -0
- package/dist/application/complete-integration-callback.d.ts.map +1 -1
- package/dist/application/complete-integration-callback.js +38 -8
- package/dist/application/complete-integration-callback.js.map +1 -1
- package/dist/components/callback-status-shell.d.ts +1 -1
- package/dist/components/callback-status-shell.d.ts.map +1 -1
- 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/core/models.d.ts +6 -0
- package/dist/core/models.d.ts.map +1 -1
- package/dist/core/models.js +12 -0
- package/dist/core/models.js.map +1 -1
- package/dist/feature.d.ts +8 -0
- package/dist/feature.d.ts.map +1 -1
- package/dist/feature.js +10 -0
- package/dist/feature.js.map +1 -1
- package/dist/hooks/api/integration-mapper.d.ts +3 -1
- package/dist/hooks/api/integration-mapper.d.ts.map +1 -1
- package/dist/hooks/api/integration-mapper.js +8 -0
- package/dist/hooks/api/integration-mapper.js.map +1 -1
- package/dist/hooks/api/integrations.d.ts +25 -1
- package/dist/hooks/api/integrations.d.ts.map +1 -1
- package/dist/hooks/api/integrations.js +44 -1
- package/dist/hooks/api/integrations.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/jira-callback-state.d.ts +9 -0
- package/dist/jira-callback-state.d.ts.map +1 -0
- package/dist/jira-callback-state.js +16 -0
- package/dist/jira-callback-state.js.map +1 -0
- package/dist/jira-callback.d.ts +11 -0
- package/dist/jira-callback.d.ts.map +1 -0
- package/dist/jira-callback.js +59 -0
- package/dist/jira-callback.js.map +1 -0
- package/dist/jira-form-errors.d.ts +8 -0
- package/dist/jira-form-errors.d.ts.map +1 -0
- package/dist/jira-form-errors.js +55 -0
- package/dist/jira-form-errors.js.map +1 -0
- 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.d.ts +2 -0
- package/dist/pages/jira-callback-page.d.ts.map +1 -0
- package/dist/pages/jira-callback-page.js +341 -0
- package/dist/pages/jira-callback-page.js.map +1 -0
- package/dist/pages/jira-install-page.d.ts +2 -0
- package/dist/pages/jira-install-page.d.ts.map +1 -0
- package/dist/pages/jira-install-page.js +26 -0
- package/dist/pages/jira-install-page.js.map +1 -0
- 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/provider-catalog.d.ts +1 -1
- package/dist/provider-catalog.d.ts.map +1 -1
- package/dist/provider-catalog.js +5 -0
- package/dist/provider-catalog.js.map +1 -1
- package/dist/routes/jira-callback.d.ts +8 -0
- package/dist/routes/jira-callback.d.ts.map +1 -0
- package/dist/routes/jira-callback.js +9 -0
- package/dist/routes/jira-callback.js.map +1 -0
- package/dist/routes/jira.d.ts +6 -0
- package/dist/routes/jira.d.ts.map +1 -0
- package/dist/routes/jira.js +7 -0
- package/dist/routes/jira.js.map +1 -0
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +9 -8
- package/src/application/complete-integration-callback.test.ts +44 -1
- package/src/application/complete-integration-callback.ts +61 -8
- package/src/components/callback-status-shell.tsx +7 -4
- 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-events.test.ts +13 -0
- 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/core/models.ts +18 -0
- package/src/feature.ts +10 -0
- package/src/hooks/api/integration-mapper.ts +6 -0
- package/src/hooks/api/integrations.test.ts +92 -0
- package/src/hooks/api/integrations.ts +71 -0
- package/src/index.ts +4 -0
- package/src/jira-callback-state.ts +19 -0
- package/src/jira-callback.test.ts +76 -0
- package/src/jira-callback.ts +67 -0
- package/src/jira-form-errors.test.ts +57 -0
- package/src/jira-form-errors.ts +94 -0
- package/src/pages/gitea-install-page.tsx +4 -4
- package/src/pages/jira-callback-page.test.tsx +250 -0
- package/src/pages/jira-callback-page.tsx +366 -0
- package/src/pages/jira-install-page.tsx +28 -0
- package/src/pages/sentry-callback-page.tsx +7 -7
- package/src/pages/source-control-onboarding-page.tsx +2 -2
- package/src/provider-catalog.test.ts +6 -0
- package/src/provider-catalog.ts +7 -1
- package/src/routes/jira-callback.tsx +8 -0
- package/src/routes/jira.tsx +4 -0
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { createTypedBrowserStorage } from '@shipfox/client-ui';
|
|
2
|
+
export const JIRA_INSTALL_WORKSPACE_KEY = 'shipfox.jira-install.workspace-id';
|
|
3
|
+
const jiraInstallWorkspaceStorageKey = {
|
|
4
|
+
key: JIRA_INSTALL_WORKSPACE_KEY,
|
|
5
|
+
lifetime: 'session',
|
|
6
|
+
// This is a one-shot navigation hint, not private workspace state. It must
|
|
7
|
+
// remain readable on an OAuth callback before workspace hydration completes;
|
|
8
|
+
// the signed callback state and returned connection are authoritative.
|
|
9
|
+
principalScope: 'global',
|
|
10
|
+
serialize: (workspaceId)=>workspaceId,
|
|
11
|
+
parse: (value)=>value || undefined
|
|
12
|
+
};
|
|
13
|
+
export function saveJiraInstallWorkspace(storage, workspaceId) {
|
|
14
|
+
installWorkspaceStorage(storage).write(workspaceId);
|
|
15
|
+
}
|
|
16
|
+
export function readJiraInstallWorkspace(storage) {
|
|
17
|
+
return installWorkspaceStorage(storage).read();
|
|
18
|
+
}
|
|
19
|
+
export function clearJiraInstallWorkspace(storage) {
|
|
20
|
+
installWorkspaceStorage(storage).remove();
|
|
21
|
+
}
|
|
22
|
+
function installWorkspaceStorage(storage) {
|
|
23
|
+
return createTypedBrowserStorage(()=>storage, jiraInstallWorkspaceStorageKey);
|
|
24
|
+
}
|
|
25
|
+
export function parseJiraCallbackQuery(search) {
|
|
26
|
+
const state = stringParam(search.state);
|
|
27
|
+
if (!state) return undefined;
|
|
28
|
+
const code = stringParam(search.code);
|
|
29
|
+
if (code) return {
|
|
30
|
+
code,
|
|
31
|
+
state
|
|
32
|
+
};
|
|
33
|
+
const error = stringParam(search.error);
|
|
34
|
+
if (!error) return undefined;
|
|
35
|
+
const errorDescription = stringParam(search.error_description);
|
|
36
|
+
return errorDescription ? {
|
|
37
|
+
error,
|
|
38
|
+
error_description: errorDescription,
|
|
39
|
+
state
|
|
40
|
+
} : {
|
|
41
|
+
error,
|
|
42
|
+
state
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export function serializeJiraCallbackQuery(query) {
|
|
46
|
+
const params = new URLSearchParams();
|
|
47
|
+
if ('code' in query) params.set('code', query.code);
|
|
48
|
+
else {
|
|
49
|
+
params.set('error', query.error);
|
|
50
|
+
if (query.error_description) params.set('error_description', query.error_description);
|
|
51
|
+
}
|
|
52
|
+
params.set('state', query.state);
|
|
53
|
+
return params.toString();
|
|
54
|
+
}
|
|
55
|
+
function stringParam(value) {
|
|
56
|
+
return typeof value === 'string' && value.length > 0 ? value : undefined;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
//# sourceMappingURL=jira-callback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/jira-callback.ts"],"sourcesContent":["import type {JiraCallbackQueryDto} from '@shipfox/api-integration-jira-dto';\nimport {\n type BrowserStorage,\n type BrowserStorageKey,\n createTypedBrowserStorage,\n} from '@shipfox/client-ui';\n\nexport const JIRA_INSTALL_WORKSPACE_KEY = 'shipfox.jira-install.workspace-id';\n\ntype WorkspaceStorage = BrowserStorage | undefined;\n\nconst jiraInstallWorkspaceStorageKey = {\n key: JIRA_INSTALL_WORKSPACE_KEY,\n lifetime: 'session',\n // This is a one-shot navigation hint, not private workspace state. It must\n // remain readable on an OAuth callback before workspace hydration completes;\n // the signed callback state and returned connection are authoritative.\n principalScope: 'global',\n serialize: (workspaceId: string) => workspaceId,\n parse: (value: string) => value || undefined,\n} satisfies BrowserStorageKey<string>;\n\nexport function saveJiraInstallWorkspace(storage: WorkspaceStorage, workspaceId: string): void {\n installWorkspaceStorage(storage).write(workspaceId);\n}\n\nexport function readJiraInstallWorkspace(storage: WorkspaceStorage): string | undefined {\n return installWorkspaceStorage(storage).read();\n}\n\nexport function clearJiraInstallWorkspace(storage: WorkspaceStorage): void {\n installWorkspaceStorage(storage).remove();\n}\n\nfunction installWorkspaceStorage(storage: WorkspaceStorage) {\n return createTypedBrowserStorage(() => storage, jiraInstallWorkspaceStorageKey);\n}\n\nexport function parseJiraCallbackQuery(\n search: Record<string, unknown>,\n): JiraCallbackQueryDto | undefined {\n const state = stringParam(search.state);\n if (!state) return undefined;\n\n const code = stringParam(search.code);\n if (code) return {code, state};\n\n const error = stringParam(search.error);\n if (!error) return undefined;\n const errorDescription = stringParam(search.error_description);\n return errorDescription ? {error, error_description: errorDescription, state} : {error, state};\n}\n\nexport function serializeJiraCallbackQuery(query: JiraCallbackQueryDto): string {\n const params = new URLSearchParams();\n if ('code' in query) params.set('code', query.code);\n else {\n params.set('error', query.error);\n if (query.error_description) params.set('error_description', query.error_description);\n }\n params.set('state', query.state);\n return params.toString();\n}\n\nfunction stringParam(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n"],"names":["createTypedBrowserStorage","JIRA_INSTALL_WORKSPACE_KEY","jiraInstallWorkspaceStorageKey","key","lifetime","principalScope","serialize","workspaceId","parse","value","undefined","saveJiraInstallWorkspace","storage","installWorkspaceStorage","write","readJiraInstallWorkspace","read","clearJiraInstallWorkspace","remove","parseJiraCallbackQuery","search","state","stringParam","code","error","errorDescription","error_description","serializeJiraCallbackQuery","query","params","URLSearchParams","set","toString","length"],"mappings":"AACA,SAGEA,yBAAyB,QACpB,qBAAqB;AAE5B,OAAO,MAAMC,6BAA6B,oCAAoC;AAI9E,MAAMC,iCAAiC;IACrCC,KAAKF;IACLG,UAAU;IACV,2EAA2E;IAC3E,6EAA6E;IAC7E,uEAAuE;IACvEC,gBAAgB;IAChBC,WAAW,CAACC,cAAwBA;IACpCC,OAAO,CAACC,QAAkBA,SAASC;AACrC;AAEA,OAAO,SAASC,yBAAyBC,OAAyB,EAAEL,WAAmB;IACrFM,wBAAwBD,SAASE,KAAK,CAACP;AACzC;AAEA,OAAO,SAASQ,yBAAyBH,OAAyB;IAChE,OAAOC,wBAAwBD,SAASI,IAAI;AAC9C;AAEA,OAAO,SAASC,0BAA0BL,OAAyB;IACjEC,wBAAwBD,SAASM,MAAM;AACzC;AAEA,SAASL,wBAAwBD,OAAyB;IACxD,OAAOZ,0BAA0B,IAAMY,SAASV;AAClD;AAEA,OAAO,SAASiB,uBACdC,MAA+B;IAE/B,MAAMC,QAAQC,YAAYF,OAAOC,KAAK;IACtC,IAAI,CAACA,OAAO,OAAOX;IAEnB,MAAMa,OAAOD,YAAYF,OAAOG,IAAI;IACpC,IAAIA,MAAM,OAAO;QAACA;QAAMF;IAAK;IAE7B,MAAMG,QAAQF,YAAYF,OAAOI,KAAK;IACtC,IAAI,CAACA,OAAO,OAAOd;IACnB,MAAMe,mBAAmBH,YAAYF,OAAOM,iBAAiB;IAC7D,OAAOD,mBAAmB;QAACD;QAAOE,mBAAmBD;QAAkBJ;IAAK,IAAI;QAACG;QAAOH;IAAK;AAC/F;AAEA,OAAO,SAASM,2BAA2BC,KAA2B;IACpE,MAAMC,SAAS,IAAIC;IACnB,IAAI,UAAUF,OAAOC,OAAOE,GAAG,CAAC,QAAQH,MAAML,IAAI;SAC7C;QACHM,OAAOE,GAAG,CAAC,SAASH,MAAMJ,KAAK;QAC/B,IAAII,MAAMF,iBAAiB,EAAEG,OAAOE,GAAG,CAAC,qBAAqBH,MAAMF,iBAAiB;IACtF;IACAG,OAAOE,GAAG,CAAC,SAASH,MAAMP,KAAK;IAC/B,OAAOQ,OAAOG,QAAQ;AACxB;AAEA,SAASV,YAAYb,KAAc;IACjC,OAAO,OAAOA,UAAU,YAAYA,MAAMwB,MAAM,GAAG,IAAIxB,QAAQC;AACjE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jira-form-errors.d.ts","sourceRoot":"","sources":["../src/jira-form-errors.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,mBAAmB,CAwE7E"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { ApiError } from '@shipfox/client-api';
|
|
2
|
+
export function classifyJiraCallbackError(error) {
|
|
3
|
+
if (error instanceof ApiError) {
|
|
4
|
+
switch(error.code){
|
|
5
|
+
case 'invalid-jira-install-state':
|
|
6
|
+
return failure('Jira install link expired', 'Jira install link expired. Start again from workspace settings.', true);
|
|
7
|
+
case 'jira-install-state-actor-mismatch':
|
|
8
|
+
case 'unauthorized':
|
|
9
|
+
return {
|
|
10
|
+
...failure('Different Shipfox account', 'Different Shipfox account. Sign in with the account that started this install.', true),
|
|
11
|
+
signIn: true
|
|
12
|
+
};
|
|
13
|
+
case 'not-found':
|
|
14
|
+
case 'forbidden':
|
|
15
|
+
case 'workspace-inactive':
|
|
16
|
+
return failure('Workspace access changed', 'You no longer have access to this workspace. Return to Shipfox to continue.', false);
|
|
17
|
+
case 'jira-installation-already-linked':
|
|
18
|
+
case 'jira-connection-already-linked':
|
|
19
|
+
return failure('Jira already linked', 'This Jira site is already linked to another workspace.', false);
|
|
20
|
+
case 'jira-authorization-scope-mismatch':
|
|
21
|
+
case 'jira-offline-access-not-granted':
|
|
22
|
+
case 'jira-oauth-callback-error':
|
|
23
|
+
case 'access-denied':
|
|
24
|
+
return failure('Jira permissions needed', 'Jira did not authorize the permissions Shipfox needs. Review the consent and start again.', true);
|
|
25
|
+
case 'jira-site-selection-mismatch':
|
|
26
|
+
case 'jira-pending-selection-not-found':
|
|
27
|
+
return failure('Jira site selection expired', 'This Jira site selection is no longer valid. Start the install again from workspace settings.', true);
|
|
28
|
+
case 'network-error':
|
|
29
|
+
return failure('Could not reach Shipfox', 'Check your connection and start again.', true);
|
|
30
|
+
case 'rate-limited':
|
|
31
|
+
case 'timeout':
|
|
32
|
+
case 'provider-unavailable':
|
|
33
|
+
case 'malformed-provider-response':
|
|
34
|
+
return failure('Jira is temporarily unavailable', 'Start a new install when Jira is available.', true);
|
|
35
|
+
case 'slug-conflict':
|
|
36
|
+
return failure('Jira install could not be completed', 'Could not complete the Jira install. Start again from workspace settings.', true);
|
|
37
|
+
default:
|
|
38
|
+
return fallback();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return fallback();
|
|
42
|
+
}
|
|
43
|
+
function failure(title, message, startOver) {
|
|
44
|
+
return {
|
|
45
|
+
title,
|
|
46
|
+
message,
|
|
47
|
+
startOver,
|
|
48
|
+
signIn: false
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function fallback() {
|
|
52
|
+
return failure('Jira install could not be completed', 'Could not complete the Jira install. Start again from workspace settings.', true);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
//# sourceMappingURL=jira-form-errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/jira-form-errors.ts"],"sourcesContent":["import {ApiError} from '@shipfox/client-api';\n\nexport interface JiraCallbackFailure {\n title: string;\n message: string;\n startOver: boolean;\n signIn: boolean;\n}\n\nexport function classifyJiraCallbackError(error: unknown): JiraCallbackFailure {\n if (error instanceof ApiError) {\n switch (error.code) {\n case 'invalid-jira-install-state':\n return failure(\n 'Jira install link expired',\n 'Jira install link expired. Start again from workspace settings.',\n true,\n );\n case 'jira-install-state-actor-mismatch':\n case 'unauthorized':\n return {\n ...failure(\n 'Different Shipfox account',\n 'Different Shipfox account. Sign in with the account that started this install.',\n true,\n ),\n signIn: true,\n };\n case 'not-found':\n case 'forbidden':\n case 'workspace-inactive':\n return failure(\n 'Workspace access changed',\n 'You no longer have access to this workspace. Return to Shipfox to continue.',\n false,\n );\n case 'jira-installation-already-linked':\n case 'jira-connection-already-linked':\n return failure(\n 'Jira already linked',\n 'This Jira site is already linked to another workspace.',\n false,\n );\n case 'jira-authorization-scope-mismatch':\n case 'jira-offline-access-not-granted':\n case 'jira-oauth-callback-error':\n case 'access-denied':\n return failure(\n 'Jira permissions needed',\n 'Jira did not authorize the permissions Shipfox needs. Review the consent and start again.',\n true,\n );\n case 'jira-site-selection-mismatch':\n case 'jira-pending-selection-not-found':\n return failure(\n 'Jira site selection expired',\n 'This Jira site selection is no longer valid. Start the install again from workspace settings.',\n true,\n );\n case 'network-error':\n return failure('Could not reach Shipfox', 'Check your connection and start again.', true);\n case 'rate-limited':\n case 'timeout':\n case 'provider-unavailable':\n case 'malformed-provider-response':\n return failure(\n 'Jira is temporarily unavailable',\n 'Start a new install when Jira is available.',\n true,\n );\n case 'slug-conflict':\n return failure(\n 'Jira install could not be completed',\n 'Could not complete the Jira install. Start again from workspace settings.',\n true,\n );\n default:\n return fallback();\n }\n }\n return fallback();\n}\n\nfunction failure(title: string, message: string, startOver: boolean): JiraCallbackFailure {\n return {title, message, startOver, signIn: false};\n}\n\nfunction fallback(): JiraCallbackFailure {\n return failure(\n 'Jira install could not be completed',\n 'Could not complete the Jira install. Start again from workspace settings.',\n true,\n );\n}\n"],"names":["ApiError","classifyJiraCallbackError","error","code","failure","signIn","fallback","title","message","startOver"],"mappings":"AAAA,SAAQA,QAAQ,QAAO,sBAAsB;AAS7C,OAAO,SAASC,0BAA0BC,KAAc;IACtD,IAAIA,iBAAiBF,UAAU;QAC7B,OAAQE,MAAMC,IAAI;YAChB,KAAK;gBACH,OAAOC,QACL,6BACA,mEACA;YAEJ,KAAK;YACL,KAAK;gBACH,OAAO;oBACL,GAAGA,QACD,6BACA,kFACA,KACD;oBACDC,QAAQ;gBACV;YACF,KAAK;YACL,KAAK;YACL,KAAK;gBACH,OAAOD,QACL,4BACA,+EACA;YAEJ,KAAK;YACL,KAAK;gBACH,OAAOA,QACL,uBACA,0DACA;YAEJ,KAAK;YACL,KAAK;YACL,KAAK;YACL,KAAK;gBACH,OAAOA,QACL,2BACA,6FACA;YAEJ,KAAK;YACL,KAAK;gBACH,OAAOA,QACL,+BACA,iGACA;YAEJ,KAAK;gBACH,OAAOA,QAAQ,2BAA2B,0CAA0C;YACtF,KAAK;YACL,KAAK;YACL,KAAK;YACL,KAAK;gBACH,OAAOA,QACL,mCACA,+CACA;YAEJ,KAAK;gBACH,OAAOA,QACL,uCACA,6EACA;YAEJ;gBACE,OAAOE;QACX;IACF;IACA,OAAOA;AACT;AAEA,SAASF,QAAQG,KAAa,EAAEC,OAAe,EAAEC,SAAkB;IACjE,OAAO;QAACF;QAAOC;QAASC;QAAWJ,QAAQ;IAAK;AAClD;AAEA,SAASC;IACP,OAAOF,QACL,uCACA,6EACA;AAEJ"}
|
|
@@ -51,10 +51,10 @@ export function GiteaInstallPage() {
|
|
|
51
51
|
}
|
|
52
52
|
});
|
|
53
53
|
return /*#__PURE__*/ _jsxs("div", {
|
|
54
|
-
className: "mx-auto flex w-full max-w-[480px] flex-col gap-
|
|
54
|
+
className: "mx-auto flex w-full max-w-[480px] flex-col gap-section",
|
|
55
55
|
children: [
|
|
56
56
|
/*#__PURE__*/ _jsxs("header", {
|
|
57
|
-
className: "flex flex-col gap-
|
|
57
|
+
className: "flex flex-col gap-inline",
|
|
58
58
|
children: [
|
|
59
59
|
/*#__PURE__*/ _jsx(Header, {
|
|
60
60
|
variant: "h1",
|
|
@@ -68,7 +68,7 @@ export function GiteaInstallPage() {
|
|
|
68
68
|
]
|
|
69
69
|
}),
|
|
70
70
|
/*#__PURE__*/ _jsxs("form", {
|
|
71
|
-
className: "flex flex-col gap-
|
|
71
|
+
className: "flex flex-col gap-group",
|
|
72
72
|
noValidate: true,
|
|
73
73
|
onSubmit: (event)=>{
|
|
74
74
|
event.preventDefault();
|
|
@@ -101,7 +101,7 @@ export function GiteaInstallPage() {
|
|
|
101
101
|
})
|
|
102
102
|
}),
|
|
103
103
|
/*#__PURE__*/ _jsxs("div", {
|
|
104
|
-
className: "flex items-center gap-
|
|
104
|
+
className: "flex items-center gap-cluster",
|
|
105
105
|
children: [
|
|
106
106
|
/*#__PURE__*/ _jsx(Button, {
|
|
107
107
|
type: "submit",
|
|
@@ -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: '/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-
|
|
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-section\">\n <header className=\"flex flex-col gap-inline\">\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-group\"\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-cluster\">\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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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jira-callback-page.d.ts","sourceRoot":"","sources":["../../src/pages/jira-callback-page.tsx"],"names":[],"mappings":"AAsCA,wBAAgB,gBAAgB,gCA2N/B"}
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useAuthState, useRefreshAuth } from '@shipfox/client-auth';
|
|
3
|
+
import { useRouteSearch } from '@shipfox/client-shell/runtime';
|
|
4
|
+
import { sessionStorageOrUndefined } from '@shipfox/client-ui';
|
|
5
|
+
import { Button, ButtonLink } from '@shipfox/react-ui/button';
|
|
6
|
+
import { Callout } from '@shipfox/react-ui/callout';
|
|
7
|
+
import { Card } from '@shipfox/react-ui/card';
|
|
8
|
+
import { FullPageLoader } from '@shipfox/react-ui/loader';
|
|
9
|
+
import { toast } from '@shipfox/react-ui/toast';
|
|
10
|
+
import { Header, Text } from '@shipfox/react-ui/typography';
|
|
11
|
+
import { useQueryClient } from '@tanstack/react-query';
|
|
12
|
+
import { Link, useNavigate } from '@tanstack/react-router';
|
|
13
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
14
|
+
import { useCompleteIntegrationCallback, useCompleteIntegrationCallbackResult } from '#application/complete-integration-callback.js';
|
|
15
|
+
import { CallbackStatusShell } from '#components/callback-status-shell.js';
|
|
16
|
+
import { useCompleteJiraCallbackMutation, useCompleteJiraSiteSelectionMutation } from '#hooks/api/integrations.js';
|
|
17
|
+
import { clearJiraInstallWorkspace, parseJiraCallbackQuery, readJiraInstallWorkspace, serializeJiraCallbackQuery } from '#jira-callback.js';
|
|
18
|
+
import { JIRA_CALLBACK_CACHE_SIZE, jiraCallbackRequests, jiraCompletedConnections, jiraSiteSelectionRequests, jiraToastedCallbacks } from '#jira-callback-state.js';
|
|
19
|
+
import { classifyJiraCallbackError } from '#jira-form-errors.js';
|
|
20
|
+
import { rememberCallbackKey, resolveWorkspaceSlug } from '#workspace-navigation.js';
|
|
21
|
+
export function JiraCallbackPage() {
|
|
22
|
+
const navigate = useNavigate();
|
|
23
|
+
const queryClient = useQueryClient();
|
|
24
|
+
const refreshAuth = useRefreshAuth();
|
|
25
|
+
const { workspaces, isLoading } = useAuthState();
|
|
26
|
+
const completeIntegrationCallback = useCompleteIntegrationCallback();
|
|
27
|
+
const completeIntegrationCallbackResult = useCompleteIntegrationCallbackResult();
|
|
28
|
+
const { mutateAsync: completeJiraCallback } = useCompleteJiraCallbackMutation();
|
|
29
|
+
const { mutateAsync: completeJiraSiteSelection } = useCompleteJiraSiteSelectionMutation();
|
|
30
|
+
const params = useRouteSearch(parseJiraCallbackQuery);
|
|
31
|
+
const callbackKey = params ? serializeJiraCallbackQuery(params) : undefined;
|
|
32
|
+
const workspaceId = useMemo(()=>readJiraInstallWorkspace(sessionStorageOrUndefined()), []);
|
|
33
|
+
const [sites, setSites] = useState();
|
|
34
|
+
const [failure, setFailure] = useState();
|
|
35
|
+
const [selectedCloudId, setSelectedCloudId] = useState();
|
|
36
|
+
const [completedWorkspace, setCompletedWorkspace] = useState();
|
|
37
|
+
const disposedRef = useRef(false);
|
|
38
|
+
const callbackKeyRef = useRef(callbackKey);
|
|
39
|
+
callbackKeyRef.current = callbackKey;
|
|
40
|
+
const [callbackStateKey, setCallbackStateKey] = useState(callbackKey);
|
|
41
|
+
useEffect(()=>{
|
|
42
|
+
disposedRef.current = false;
|
|
43
|
+
return ()=>{
|
|
44
|
+
disposedRef.current = true;
|
|
45
|
+
};
|
|
46
|
+
}, []);
|
|
47
|
+
const completeConnection = useCallback(async (connection, callbackKey, isActive = ()=>true)=>{
|
|
48
|
+
if (disposedRef.current || !isActive()) return;
|
|
49
|
+
const completedConnection = jiraCompletedConnections.get(callbackKey);
|
|
50
|
+
if (completedConnection) {
|
|
51
|
+
const workspaceSlug = await resolveWorkspaceSlug({
|
|
52
|
+
workspaceId: completedConnection.workspaceId,
|
|
53
|
+
fallbackWorkspaces: workspaces,
|
|
54
|
+
queryClient
|
|
55
|
+
});
|
|
56
|
+
if (!disposedRef.current && isActive()) setCompletedWorkspace(workspaceSlug ? {
|
|
57
|
+
slug: workspaceSlug
|
|
58
|
+
} : {});
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
rememberCompletedConnection(callbackKey, connection);
|
|
62
|
+
try {
|
|
63
|
+
clearJiraInstallWorkspace(sessionStorageOrUndefined());
|
|
64
|
+
} catch {
|
|
65
|
+
// The successful API response remains the source of truth for navigation.
|
|
66
|
+
}
|
|
67
|
+
if (disposedRef.current || !isActive()) return;
|
|
68
|
+
if (!jiraToastedCallbacks.has(callbackKey)) {
|
|
69
|
+
rememberCallbackKey(jiraToastedCallbacks, callbackKey);
|
|
70
|
+
toast.success('Jira installed.');
|
|
71
|
+
}
|
|
72
|
+
let workspaceSlug;
|
|
73
|
+
try {
|
|
74
|
+
workspaceSlug = await resolveWorkspaceSlug({
|
|
75
|
+
workspaceId: connection.workspaceId,
|
|
76
|
+
fallbackWorkspaces: workspaces,
|
|
77
|
+
queryClient
|
|
78
|
+
});
|
|
79
|
+
if (disposedRef.current || !isActive()) return;
|
|
80
|
+
if (!workspaceSlug) {
|
|
81
|
+
setCompletedWorkspace({});
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
setCompletedWorkspace({
|
|
85
|
+
slug: workspaceSlug
|
|
86
|
+
});
|
|
87
|
+
await navigate({
|
|
88
|
+
to: '/w/$workspaceSlug/settings/integrations',
|
|
89
|
+
params: {
|
|
90
|
+
workspaceSlug
|
|
91
|
+
},
|
|
92
|
+
replace: true
|
|
93
|
+
});
|
|
94
|
+
} catch {
|
|
95
|
+
if (!disposedRef.current && isActive()) setCompletedWorkspace({
|
|
96
|
+
slug: workspaceSlug
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}, [
|
|
100
|
+
navigate,
|
|
101
|
+
queryClient,
|
|
102
|
+
workspaces
|
|
103
|
+
]);
|
|
104
|
+
useEffect(()=>{
|
|
105
|
+
if (callbackKey === undefined) return;
|
|
106
|
+
setCallbackStateKey(callbackKey);
|
|
107
|
+
setSites(undefined);
|
|
108
|
+
setSelectedCloudId(undefined);
|
|
109
|
+
setFailure(undefined);
|
|
110
|
+
setCompletedWorkspace(undefined);
|
|
111
|
+
}, [
|
|
112
|
+
callbackKey
|
|
113
|
+
]);
|
|
114
|
+
useEffect(()=>{
|
|
115
|
+
if (!params || !callbackKey || isLoading) return;
|
|
116
|
+
let active = true;
|
|
117
|
+
const completedConnection = jiraCompletedConnections.get(callbackKey);
|
|
118
|
+
if (completedConnection) {
|
|
119
|
+
void completeConnection(completedConnection, callbackKey, ()=>active);
|
|
120
|
+
return ()=>{
|
|
121
|
+
active = false;
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
const request = jiraCallbackRequests.run(callbackKey, async ()=>{
|
|
125
|
+
return await completeIntegrationCallbackResult({
|
|
126
|
+
input: params,
|
|
127
|
+
refreshAuth,
|
|
128
|
+
complete: async (query, token)=>await completeJiraCallback({
|
|
129
|
+
query,
|
|
130
|
+
token
|
|
131
|
+
}),
|
|
132
|
+
getConnection: (result)=>'sites' in result ? undefined : result
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
request.then(async (result)=>{
|
|
136
|
+
if (disposedRef.current || !active) return;
|
|
137
|
+
if ('sites' in result) {
|
|
138
|
+
setFailure(undefined);
|
|
139
|
+
setSites(result.sites);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
await completeConnection(result, callbackKey, ()=>active);
|
|
143
|
+
}, (error)=>{
|
|
144
|
+
if (!disposedRef.current && active) setFailure(classifyJiraCallbackError(error));
|
|
145
|
+
});
|
|
146
|
+
return ()=>{
|
|
147
|
+
active = false;
|
|
148
|
+
};
|
|
149
|
+
}, [
|
|
150
|
+
callbackKey,
|
|
151
|
+
completeIntegrationCallbackResult,
|
|
152
|
+
completeJiraCallback,
|
|
153
|
+
completeConnection,
|
|
154
|
+
isLoading,
|
|
155
|
+
params,
|
|
156
|
+
refreshAuth
|
|
157
|
+
]);
|
|
158
|
+
function selectSite(site) {
|
|
159
|
+
if (!params || !callbackKey || selectedCloudId) return;
|
|
160
|
+
setSelectedCloudId(site.cloudId);
|
|
161
|
+
setFailure(undefined);
|
|
162
|
+
const selectionKey = callbackKey;
|
|
163
|
+
const request = jiraSiteSelectionRequests.run(params.state, async ()=>{
|
|
164
|
+
return await completeIntegrationCallback({
|
|
165
|
+
input: {
|
|
166
|
+
cloud_id: site.cloudId,
|
|
167
|
+
state: params.state
|
|
168
|
+
},
|
|
169
|
+
refreshAuth,
|
|
170
|
+
complete: async (body, token)=>await completeJiraSiteSelection({
|
|
171
|
+
body,
|
|
172
|
+
token
|
|
173
|
+
})
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
request.then(async (connection)=>{
|
|
177
|
+
if (disposedRef.current || callbackKeyRef.current !== selectionKey) return;
|
|
178
|
+
jiraCallbackRequests.clear(selectionKey);
|
|
179
|
+
await completeConnection(connection, selectionKey, ()=>callbackKeyRef.current === selectionKey);
|
|
180
|
+
}, (error)=>{
|
|
181
|
+
if (disposedRef.current || callbackKeyRef.current !== selectionKey) return;
|
|
182
|
+
setSelectedCloudId(undefined);
|
|
183
|
+
setFailure(classifyJiraCallbackError(error));
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
if (!params) {
|
|
187
|
+
return /*#__PURE__*/ _jsx(JiraCallbackFailurePage, {
|
|
188
|
+
failure: classifyJiraCallbackError(new Error('invalid callback')),
|
|
189
|
+
workspaceSlug: workspaces.find(({ id })=>id === workspaceId)?.slug
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
if (isLoading) return /*#__PURE__*/ _jsx(FullPageLoader, {
|
|
193
|
+
"aria-label": "Connecting Jira"
|
|
194
|
+
});
|
|
195
|
+
if (callbackStateKey === callbackKey && completedWorkspace) return /*#__PURE__*/ _jsx(CallbackStatusShell, {
|
|
196
|
+
title: "Jira connected",
|
|
197
|
+
status: "success",
|
|
198
|
+
message: completedWorkspace.slug ? 'Jira is connected. Continue in integrations settings.' : 'Jira is connected. Return to Shipfox to continue.',
|
|
199
|
+
workspaceSlug: completedWorkspace.slug,
|
|
200
|
+
installPath: "/w/$workspaceSlug/integrations/jira"
|
|
201
|
+
});
|
|
202
|
+
if (callbackStateKey === callbackKey && sites) return /*#__PURE__*/ _jsx(JiraSiteSelectionPage, {
|
|
203
|
+
sites: sites,
|
|
204
|
+
selectedCloudId: selectedCloudId,
|
|
205
|
+
failure: failure,
|
|
206
|
+
workspaceSlug: workspaces.find(({ id })=>id === workspaceId)?.slug,
|
|
207
|
+
onSelect: selectSite
|
|
208
|
+
});
|
|
209
|
+
if (callbackStateKey === callbackKey && failure) return /*#__PURE__*/ _jsx(JiraCallbackFailurePage, {
|
|
210
|
+
failure: failure,
|
|
211
|
+
workspaceSlug: workspaces.find(({ id })=>id === workspaceId)?.slug
|
|
212
|
+
});
|
|
213
|
+
return /*#__PURE__*/ _jsx(FullPageLoader, {
|
|
214
|
+
"aria-label": "Connecting Jira"
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
function rememberCompletedConnection(key, connection) {
|
|
218
|
+
jiraCompletedConnections.delete(key);
|
|
219
|
+
jiraCompletedConnections.set(key, connection);
|
|
220
|
+
while(jiraCompletedConnections.size > JIRA_CALLBACK_CACHE_SIZE){
|
|
221
|
+
const oldestKey = jiraCompletedConnections.keys().next().value;
|
|
222
|
+
if (oldestKey === undefined) return;
|
|
223
|
+
jiraCompletedConnections.delete(oldestKey);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
function JiraCallbackFailurePage({ failure, workspaceSlug }) {
|
|
227
|
+
return /*#__PURE__*/ _jsx(CallbackStatusShell, {
|
|
228
|
+
title: failure.title,
|
|
229
|
+
message: failure.message,
|
|
230
|
+
startOver: failure.startOver,
|
|
231
|
+
switchAccount: failure.signIn,
|
|
232
|
+
workspaceSlug: workspaceSlug,
|
|
233
|
+
installPath: "/w/$workspaceSlug/integrations/jira"
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
function JiraSiteSelectionPage({ sites, selectedCloudId, failure, workspaceSlug, onSelect }) {
|
|
237
|
+
return /*#__PURE__*/ _jsx("main", {
|
|
238
|
+
className: "flex min-h-screen bg-background-subtle-base px-row py-frame",
|
|
239
|
+
children: /*#__PURE__*/ _jsxs("div", {
|
|
240
|
+
className: "mx-auto flex w-full max-w-[480px] flex-col justify-center gap-section",
|
|
241
|
+
children: [
|
|
242
|
+
/*#__PURE__*/ _jsxs("header", {
|
|
243
|
+
className: "flex flex-col gap-inline",
|
|
244
|
+
children: [
|
|
245
|
+
/*#__PURE__*/ _jsx(Header, {
|
|
246
|
+
variant: "h2",
|
|
247
|
+
children: "Choose a Jira site"
|
|
248
|
+
}),
|
|
249
|
+
/*#__PURE__*/ _jsx(Text, {
|
|
250
|
+
size: "sm",
|
|
251
|
+
className: "text-foreground-neutral-muted",
|
|
252
|
+
children: "Select the Jira site to connect to this Shipfox workspace."
|
|
253
|
+
})
|
|
254
|
+
]
|
|
255
|
+
}),
|
|
256
|
+
failure ? /*#__PURE__*/ _jsx(Callout, {
|
|
257
|
+
role: "alert",
|
|
258
|
+
type: "error",
|
|
259
|
+
children: /*#__PURE__*/ _jsx(Text, {
|
|
260
|
+
size: "sm",
|
|
261
|
+
children: failure.message
|
|
262
|
+
})
|
|
263
|
+
}) : null,
|
|
264
|
+
/*#__PURE__*/ _jsx("section", {
|
|
265
|
+
className: "flex flex-col gap-inline",
|
|
266
|
+
"aria-label": "Choose a Jira site",
|
|
267
|
+
children: sites.map((site)=>/*#__PURE__*/ _jsx(Card, {
|
|
268
|
+
className: "p-panel-compact",
|
|
269
|
+
children: /*#__PURE__*/ _jsxs("div", {
|
|
270
|
+
className: "flex items-center justify-between gap-cluster",
|
|
271
|
+
children: [
|
|
272
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
273
|
+
className: "min-w-0",
|
|
274
|
+
children: [
|
|
275
|
+
/*#__PURE__*/ _jsx(Text, {
|
|
276
|
+
size: "md",
|
|
277
|
+
bold: true,
|
|
278
|
+
className: "truncate",
|
|
279
|
+
children: site.name
|
|
280
|
+
}),
|
|
281
|
+
/*#__PURE__*/ _jsx(Text, {
|
|
282
|
+
size: "sm",
|
|
283
|
+
className: "truncate text-foreground-neutral-muted",
|
|
284
|
+
children: site.url
|
|
285
|
+
})
|
|
286
|
+
]
|
|
287
|
+
}),
|
|
288
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
289
|
+
variant: "secondary",
|
|
290
|
+
disabled: selectedCloudId !== undefined,
|
|
291
|
+
isLoading: selectedCloudId === site.cloudId,
|
|
292
|
+
onClick: ()=>onSelect(site),
|
|
293
|
+
children: "Connect"
|
|
294
|
+
})
|
|
295
|
+
]
|
|
296
|
+
})
|
|
297
|
+
}, site.cloudId))
|
|
298
|
+
}),
|
|
299
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
300
|
+
className: "flex flex-col gap-inline sm:flex-row sm:items-center",
|
|
301
|
+
children: [
|
|
302
|
+
failure?.startOver && workspaceSlug ? /*#__PURE__*/ _jsx(ButtonLink, {
|
|
303
|
+
asChild: true,
|
|
304
|
+
variant: "muted",
|
|
305
|
+
className: "min-h-44 w-full sm:w-fit",
|
|
306
|
+
children: /*#__PURE__*/ _jsx(Link, {
|
|
307
|
+
to: "/w/$workspaceSlug/integrations/jira",
|
|
308
|
+
params: {
|
|
309
|
+
workspaceSlug
|
|
310
|
+
},
|
|
311
|
+
children: "Start over"
|
|
312
|
+
})
|
|
313
|
+
}) : null,
|
|
314
|
+
workspaceSlug ? /*#__PURE__*/ _jsx(ButtonLink, {
|
|
315
|
+
asChild: true,
|
|
316
|
+
variant: "muted",
|
|
317
|
+
className: "min-h-44 w-full sm:w-fit",
|
|
318
|
+
children: /*#__PURE__*/ _jsx(Link, {
|
|
319
|
+
to: "/w/$workspaceSlug/settings/integrations",
|
|
320
|
+
params: {
|
|
321
|
+
workspaceSlug
|
|
322
|
+
},
|
|
323
|
+
children: "Back to integrations"
|
|
324
|
+
})
|
|
325
|
+
}) : /*#__PURE__*/ _jsx(ButtonLink, {
|
|
326
|
+
asChild: true,
|
|
327
|
+
variant: "muted",
|
|
328
|
+
className: "min-h-44 w-full sm:w-fit",
|
|
329
|
+
children: /*#__PURE__*/ _jsx(Link, {
|
|
330
|
+
to: "/",
|
|
331
|
+
children: "Back to Shipfox"
|
|
332
|
+
})
|
|
333
|
+
})
|
|
334
|
+
]
|
|
335
|
+
})
|
|
336
|
+
]
|
|
337
|
+
})
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
//# sourceMappingURL=jira-callback-page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/pages/jira-callback-page.tsx"],"sourcesContent":["import {useAuthState, useRefreshAuth} from '@shipfox/client-auth';\nimport {useRouteSearch} from '@shipfox/client-shell/runtime';\nimport {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 {useCallback, useEffect, useMemo, useRef, useState} from 'react';\nimport {\n useCompleteIntegrationCallback,\n useCompleteIntegrationCallbackResult,\n} from '#application/complete-integration-callback.js';\nimport {CallbackStatusShell} from '#components/callback-status-shell.js';\nimport type {IntegrationConnection, JiraSite} from '#core/models.js';\nimport {\n useCompleteJiraCallbackMutation,\n useCompleteJiraSiteSelectionMutation,\n} from '#hooks/api/integrations.js';\nimport {\n clearJiraInstallWorkspace,\n parseJiraCallbackQuery,\n readJiraInstallWorkspace,\n serializeJiraCallbackQuery,\n} from '#jira-callback.js';\nimport {\n JIRA_CALLBACK_CACHE_SIZE,\n jiraCallbackRequests,\n jiraCompletedConnections,\n jiraSiteSelectionRequests,\n jiraToastedCallbacks,\n} from '#jira-callback-state.js';\nimport {classifyJiraCallbackError, type JiraCallbackFailure} from '#jira-form-errors.js';\nimport {rememberCallbackKey, resolveWorkspaceSlug} from '#workspace-navigation.js';\n\nexport function JiraCallbackPage() {\n const navigate = useNavigate();\n const queryClient = useQueryClient();\n const refreshAuth = useRefreshAuth();\n const {workspaces, isLoading} = useAuthState();\n const completeIntegrationCallback = useCompleteIntegrationCallback();\n const completeIntegrationCallbackResult = useCompleteIntegrationCallbackResult();\n const {mutateAsync: completeJiraCallback} = useCompleteJiraCallbackMutation();\n const {mutateAsync: completeJiraSiteSelection} = useCompleteJiraSiteSelectionMutation();\n const params = useRouteSearch(parseJiraCallbackQuery);\n const callbackKey = params ? serializeJiraCallbackQuery(params) : undefined;\n const workspaceId = useMemo(() => readJiraInstallWorkspace(sessionStorageOrUndefined()), []);\n const [sites, setSites] = useState<JiraSite[] | undefined>();\n const [failure, setFailure] = useState<JiraCallbackFailure | undefined>();\n const [selectedCloudId, setSelectedCloudId] = useState<string | undefined>();\n const [completedWorkspace, setCompletedWorkspace] = useState<{\n slug?: string | undefined;\n }>();\n const disposedRef = useRef(false);\n const callbackKeyRef = useRef(callbackKey);\n callbackKeyRef.current = callbackKey;\n const [callbackStateKey, setCallbackStateKey] = useState(callbackKey);\n\n useEffect(() => {\n disposedRef.current = false;\n return () => {\n disposedRef.current = true;\n };\n }, []);\n\n const completeConnection = useCallback(\n async (\n connection: IntegrationConnection,\n callbackKey: string,\n isActive: () => boolean = () => true,\n ) => {\n if (disposedRef.current || !isActive()) return;\n const completedConnection = jiraCompletedConnections.get(callbackKey);\n if (completedConnection) {\n const workspaceSlug = await resolveWorkspaceSlug({\n workspaceId: completedConnection.workspaceId,\n fallbackWorkspaces: workspaces,\n queryClient,\n });\n if (!disposedRef.current && isActive())\n setCompletedWorkspace(workspaceSlug ? {slug: workspaceSlug} : {});\n return;\n }\n rememberCompletedConnection(callbackKey, connection);\n try {\n clearJiraInstallWorkspace(sessionStorageOrUndefined());\n } catch {\n // The successful API response remains the source of truth for navigation.\n }\n if (disposedRef.current || !isActive()) return;\n if (!jiraToastedCallbacks.has(callbackKey)) {\n rememberCallbackKey(jiraToastedCallbacks, callbackKey);\n toast.success('Jira installed.');\n }\n let workspaceSlug: string | undefined;\n try {\n workspaceSlug = await resolveWorkspaceSlug({\n workspaceId: connection.workspaceId,\n fallbackWorkspaces: workspaces,\n queryClient,\n });\n if (disposedRef.current || !isActive()) return;\n if (!workspaceSlug) {\n setCompletedWorkspace({});\n return;\n }\n setCompletedWorkspace({slug: workspaceSlug});\n await navigate({\n to: '/w/$workspaceSlug/settings/integrations',\n params: {workspaceSlug},\n replace: true,\n });\n } catch {\n if (!disposedRef.current && isActive()) setCompletedWorkspace({slug: workspaceSlug});\n }\n },\n [navigate, queryClient, workspaces],\n );\n\n useEffect(() => {\n if (callbackKey === undefined) return;\n setCallbackStateKey(callbackKey);\n setSites(undefined);\n setSelectedCloudId(undefined);\n setFailure(undefined);\n setCompletedWorkspace(undefined);\n }, [callbackKey]);\n\n useEffect(() => {\n if (!params || !callbackKey || isLoading) return;\n\n let active = true;\n\n const completedConnection = jiraCompletedConnections.get(callbackKey);\n if (completedConnection) {\n void completeConnection(completedConnection, callbackKey, () => active);\n return () => {\n active = false;\n };\n }\n\n const request = jiraCallbackRequests.run(callbackKey, async () => {\n return await completeIntegrationCallbackResult({\n input: params,\n refreshAuth,\n complete: async (query, token) => await completeJiraCallback({query, token}),\n getConnection: (result) => ('sites' in result ? undefined : result),\n });\n });\n\n request.then(\n async (result) => {\n if (disposedRef.current || !active) return;\n if ('sites' in result) {\n setFailure(undefined);\n setSites(result.sites);\n return;\n }\n await completeConnection(result, callbackKey, () => active);\n },\n (error: unknown) => {\n if (!disposedRef.current && active) setFailure(classifyJiraCallbackError(error));\n },\n );\n\n return () => {\n active = false;\n };\n }, [\n callbackKey,\n completeIntegrationCallbackResult,\n completeJiraCallback,\n completeConnection,\n isLoading,\n params,\n refreshAuth,\n ]);\n\n function selectSite(site: JiraSite) {\n if (!params || !callbackKey || selectedCloudId) return;\n setSelectedCloudId(site.cloudId);\n setFailure(undefined);\n const selectionKey = callbackKey;\n const request = jiraSiteSelectionRequests.run(params.state, async () => {\n return await completeIntegrationCallback({\n input: {cloud_id: site.cloudId, state: params.state},\n refreshAuth,\n complete: async (body, token) => await completeJiraSiteSelection({body, token}),\n });\n });\n request.then(\n async (connection) => {\n if (disposedRef.current || callbackKeyRef.current !== selectionKey) return;\n jiraCallbackRequests.clear(selectionKey);\n await completeConnection(\n connection,\n selectionKey,\n () => callbackKeyRef.current === selectionKey,\n );\n },\n (error: unknown) => {\n if (disposedRef.current || callbackKeyRef.current !== selectionKey) return;\n setSelectedCloudId(undefined);\n setFailure(classifyJiraCallbackError(error));\n },\n );\n }\n\n if (!params) {\n return (\n <JiraCallbackFailurePage\n failure={classifyJiraCallbackError(new Error('invalid callback'))}\n workspaceSlug={workspaces.find(({id}) => id === workspaceId)?.slug}\n />\n );\n }\n\n if (isLoading) return <FullPageLoader aria-label=\"Connecting Jira\" />;\n\n if (callbackStateKey === callbackKey && completedWorkspace)\n return (\n <CallbackStatusShell\n title=\"Jira connected\"\n status=\"success\"\n message={\n completedWorkspace.slug\n ? 'Jira is connected. Continue in integrations settings.'\n : 'Jira is connected. Return to Shipfox to continue.'\n }\n workspaceSlug={completedWorkspace.slug}\n installPath=\"/w/$workspaceSlug/integrations/jira\"\n />\n );\n\n if (callbackStateKey === callbackKey && sites)\n return (\n <JiraSiteSelectionPage\n sites={sites}\n selectedCloudId={selectedCloudId}\n failure={failure}\n workspaceSlug={workspaces.find(({id}) => id === workspaceId)?.slug}\n onSelect={selectSite}\n />\n );\n\n if (callbackStateKey === callbackKey && failure)\n return (\n <JiraCallbackFailurePage\n failure={failure}\n workspaceSlug={workspaces.find(({id}) => id === workspaceId)?.slug}\n />\n );\n\n return <FullPageLoader aria-label=\"Connecting Jira\" />;\n}\n\nfunction rememberCompletedConnection(key: string, connection: IntegrationConnection): void {\n jiraCompletedConnections.delete(key);\n jiraCompletedConnections.set(key, connection);\n while (jiraCompletedConnections.size > JIRA_CALLBACK_CACHE_SIZE) {\n const oldestKey = jiraCompletedConnections.keys().next().value;\n if (oldestKey === undefined) return;\n jiraCompletedConnections.delete(oldestKey);\n }\n}\n\nfunction JiraCallbackFailurePage({\n failure,\n workspaceSlug,\n}: {\n failure: JiraCallbackFailure;\n workspaceSlug: string | undefined;\n}) {\n return (\n <CallbackStatusShell\n title={failure.title}\n message={failure.message}\n startOver={failure.startOver}\n switchAccount={failure.signIn}\n workspaceSlug={workspaceSlug}\n installPath=\"/w/$workspaceSlug/integrations/jira\"\n />\n );\n}\n\nfunction JiraSiteSelectionPage({\n sites,\n selectedCloudId,\n failure,\n workspaceSlug,\n onSelect,\n}: {\n sites: JiraSite[];\n selectedCloudId: string | undefined;\n failure: JiraCallbackFailure | undefined;\n workspaceSlug: string | undefined;\n onSelect: (site: JiraSite) => void;\n}) {\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 <header className=\"flex flex-col gap-inline\">\n <Header variant=\"h2\">Choose a Jira site</Header>\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\">\n Select the Jira site to connect to this Shipfox workspace.\n </Text>\n </header>\n\n {failure ? (\n <Callout role=\"alert\" type=\"error\">\n <Text size=\"sm\">{failure.message}</Text>\n </Callout>\n ) : null}\n\n <section className=\"flex flex-col gap-inline\" aria-label=\"Choose a Jira site\">\n {sites.map((site) => (\n <Card key={site.cloudId} className=\"p-panel-compact\">\n <div className=\"flex items-center justify-between gap-cluster\">\n <div className=\"min-w-0\">\n <Text size=\"md\" bold className=\"truncate\">\n {site.name}\n </Text>\n <Text size=\"sm\" className=\"truncate text-foreground-neutral-muted\">\n {site.url}\n </Text>\n </div>\n <Button\n variant=\"secondary\"\n disabled={selectedCloudId !== undefined}\n isLoading={selectedCloudId === site.cloudId}\n onClick={() => onSelect(site)}\n >\n Connect\n </Button>\n </div>\n </Card>\n ))}\n </section>\n\n <div className=\"flex flex-col gap-inline sm:flex-row sm:items-center\">\n {failure?.startOver && workspaceSlug ? (\n <ButtonLink asChild variant=\"muted\" className=\"min-h-44 w-full sm:w-fit\">\n <Link to=\"/w/$workspaceSlug/integrations/jira\" params={{workspaceSlug}}>\n Start over\n </Link>\n </ButtonLink>\n ) : null}\n {workspaceSlug ? (\n <ButtonLink asChild variant=\"muted\" className=\"min-h-44 w-full sm:w-fit\">\n <Link to=\"/w/$workspaceSlug/settings/integrations\" params={{workspaceSlug}}>\n Back to integrations\n </Link>\n </ButtonLink>\n ) : (\n <ButtonLink asChild variant=\"muted\" className=\"min-h-44 w-full sm:w-fit\">\n <Link to=\"/\">Back to Shipfox</Link>\n </ButtonLink>\n )}\n </div>\n </div>\n </main>\n );\n}\n"],"names":["useAuthState","useRefreshAuth","useRouteSearch","sessionStorageOrUndefined","Button","ButtonLink","Callout","Card","FullPageLoader","toast","Header","Text","useQueryClient","Link","useNavigate","useCallback","useEffect","useMemo","useRef","useState","useCompleteIntegrationCallback","useCompleteIntegrationCallbackResult","CallbackStatusShell","useCompleteJiraCallbackMutation","useCompleteJiraSiteSelectionMutation","clearJiraInstallWorkspace","parseJiraCallbackQuery","readJiraInstallWorkspace","serializeJiraCallbackQuery","JIRA_CALLBACK_CACHE_SIZE","jiraCallbackRequests","jiraCompletedConnections","jiraSiteSelectionRequests","jiraToastedCallbacks","classifyJiraCallbackError","rememberCallbackKey","resolveWorkspaceSlug","JiraCallbackPage","navigate","queryClient","refreshAuth","workspaces","isLoading","completeIntegrationCallback","completeIntegrationCallbackResult","mutateAsync","completeJiraCallback","completeJiraSiteSelection","params","callbackKey","undefined","workspaceId","sites","setSites","failure","setFailure","selectedCloudId","setSelectedCloudId","completedWorkspace","setCompletedWorkspace","disposedRef","callbackKeyRef","current","callbackStateKey","setCallbackStateKey","completeConnection","connection","isActive","completedConnection","get","workspaceSlug","fallbackWorkspaces","slug","rememberCompletedConnection","has","success","to","replace","active","request","run","input","complete","query","token","getConnection","result","then","error","selectSite","site","cloudId","selectionKey","state","cloud_id","body","clear","JiraCallbackFailurePage","Error","find","id","aria-label","title","status","message","installPath","JiraSiteSelectionPage","onSelect","key","delete","set","size","oldestKey","keys","next","value","startOver","switchAccount","signIn","main","className","div","header","variant","role","type","section","map","bold","name","url","disabled","onClick","asChild"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jira-install-page.d.ts","sourceRoot":"","sources":["../../src/pages/jira-install-page.tsx"],"names":[],"mappings":"AAMA,wBAAgB,eAAe,gCAqB9B"}
|