@workos-inc/widgets 1.8.2 → 1.9.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/CHANGELOG.md +11 -0
- package/dist/cjs/admin-portal-domain-verification.client.cjs.map +1 -1
- package/dist/cjs/admin-portal-sso-connection.client.cjs +4 -7
- package/dist/cjs/admin-portal-sso-connection.client.cjs.map +1 -1
- package/dist/cjs/api/api-provider.cjs.map +1 -1
- package/dist/cjs/api/api-provider.d.cts +1 -1
- package/dist/cjs/api/endpoint.cjs +741 -771
- package/dist/cjs/api/endpoint.cjs.map +1 -1
- package/dist/cjs/api/endpoint.d.cts +860 -813
- package/dist/cjs/directory-sync.client.cjs +156 -0
- package/dist/cjs/directory-sync.client.cjs.map +1 -0
- package/dist/cjs/directory-sync.client.d.cts +26 -0
- package/dist/cjs/experimental/api/fetch.cjs +327 -411
- package/dist/cjs/experimental/api/fetch.cjs.map +1 -1
- package/dist/cjs/experimental/api/fetch.d.cts +832 -798
- package/dist/cjs/experimental/api/react-query.cjs +747 -777
- package/dist/cjs/experimental/api/react-query.cjs.map +1 -1
- package/dist/cjs/experimental/api/react-query.d.cts +1378 -1263
- package/dist/cjs/experimental/api/swr.cjs +720 -742
- package/dist/cjs/experimental/api/swr.cjs.map +1 -1
- package/dist/cjs/experimental/api/swr.d.cts +1218 -1175
- package/dist/cjs/index.cjs +5 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +2 -0
- package/dist/cjs/lib/add-mfa-dialog.cjs +18 -16
- package/dist/cjs/lib/add-mfa-dialog.cjs.map +1 -1
- package/dist/cjs/lib/admin-portal-sso-connection.cjs +0 -8
- package/dist/cjs/lib/admin-portal-sso-connection.cjs.map +1 -1
- package/dist/cjs/lib/admin-portal-sso-connection.d.cts +1 -2
- package/dist/cjs/lib/api-keys/api-keys-context.cjs +1 -1
- package/dist/cjs/lib/api-keys/api-keys-context.cjs.map +1 -1
- package/dist/cjs/lib/api-keys/api-keys-table.cjs +7 -5
- package/dist/cjs/lib/api-keys/api-keys-table.cjs.map +1 -1
- package/dist/cjs/lib/directory-sync.cjs +288 -0
- package/dist/cjs/lib/directory-sync.cjs.map +1 -0
- package/dist/cjs/lib/directory-sync.d.cts +72 -0
- package/dist/cjs/lib/identity-providers.cjs +57 -1
- package/dist/cjs/lib/identity-providers.cjs.map +1 -1
- package/dist/cjs/lib/identity-providers.d.cts +5 -3
- package/dist/cjs/lib/pipes.cjs +9 -9
- package/dist/cjs/lib/pipes.cjs.map +1 -1
- package/dist/cjs/lib/provider-icon.cjs.map +1 -1
- package/dist/cjs/lib/provider-icon.d.cts +2 -2
- package/dist/cjs/lib/reset-mfa-dialog.cjs +2 -1
- package/dist/cjs/lib/reset-mfa-dialog.cjs.map +1 -1
- package/dist/cjs/lib/use-permissions.cjs.map +1 -1
- package/dist/cjs/lib/use-permissions.d.cts +1 -1
- package/dist/cjs/lib/users-management-context.cjs +1 -1
- package/dist/cjs/lib/users-management-context.cjs.map +1 -1
- package/dist/cjs/lib/users-management.cjs +3 -3
- package/dist/cjs/lib/users-management.cjs.map +1 -1
- package/dist/cjs/lib/utils.cjs +9 -0
- package/dist/cjs/lib/utils.cjs.map +1 -1
- package/dist/cjs/lib/utils.d.cts +16 -2
- package/dist/cjs/workos-widgets.client.cjs +13 -1
- package/dist/cjs/workos-widgets.client.cjs.map +1 -1
- package/dist/esm/admin-portal-domain-verification.client.js +2 -2
- package/dist/esm/admin-portal-domain-verification.client.js.map +1 -1
- package/dist/esm/admin-portal-sso-connection.client.js +6 -9
- package/dist/esm/admin-portal-sso-connection.client.js.map +1 -1
- package/dist/esm/api/api-provider.d.ts +1 -1
- package/dist/esm/api/api-provider.js.map +1 -1
- package/dist/esm/api/endpoint.d.ts +860 -813
- package/dist/esm/api/endpoint.js +727 -751
- package/dist/esm/api/endpoint.js.map +1 -1
- package/dist/esm/directory-sync.client.d.ts +26 -0
- package/dist/esm/directory-sync.client.js +134 -0
- package/dist/esm/directory-sync.client.js.map +1 -0
- package/dist/esm/experimental/api/fetch.d.ts +832 -798
- package/dist/esm/experimental/api/fetch.js +319 -391
- package/dist/esm/experimental/api/fetch.js.map +1 -1
- package/dist/esm/experimental/api/react-query.d.ts +1378 -1263
- package/dist/esm/experimental/api/react-query.js +730 -757
- package/dist/esm/experimental/api/react-query.js.map +1 -1
- package/dist/esm/experimental/api/swr.d.ts +1218 -1175
- package/dist/esm/experimental/api/swr.js +706 -722
- package/dist/esm/experimental/api/swr.js.map +1 -1
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +6 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lib/add-mfa-dialog.js +18 -16
- package/dist/esm/lib/add-mfa-dialog.js.map +1 -1
- package/dist/esm/lib/admin-portal-sso-connection.d.ts +1 -2
- package/dist/esm/lib/admin-portal-sso-connection.js +0 -8
- package/dist/esm/lib/admin-portal-sso-connection.js.map +1 -1
- package/dist/esm/lib/api-keys/api-keys-context.js +1 -1
- package/dist/esm/lib/api-keys/api-keys-context.js.map +1 -1
- package/dist/esm/lib/api-keys/api-keys-table.js +7 -5
- package/dist/esm/lib/api-keys/api-keys-table.js.map +1 -1
- package/dist/esm/lib/directory-sync.d.ts +72 -0
- package/dist/esm/lib/directory-sync.js +259 -0
- package/dist/esm/lib/directory-sync.js.map +1 -0
- package/dist/esm/lib/identity-providers.d.ts +5 -3
- package/dist/esm/lib/identity-providers.js +55 -1
- package/dist/esm/lib/identity-providers.js.map +1 -1
- package/dist/esm/lib/pipes.js +9 -10
- package/dist/esm/lib/pipes.js.map +1 -1
- package/dist/esm/lib/provider-icon.d.ts +2 -2
- package/dist/esm/lib/provider-icon.js.map +1 -1
- package/dist/esm/lib/reset-mfa-dialog.js +2 -1
- package/dist/esm/lib/reset-mfa-dialog.js.map +1 -1
- package/dist/esm/lib/use-permissions.d.ts +1 -1
- package/dist/esm/lib/use-permissions.js.map +1 -1
- package/dist/esm/lib/users-management-context.js +1 -1
- package/dist/esm/lib/users-management-context.js.map +1 -1
- package/dist/esm/lib/users-management.js +5 -4
- package/dist/esm/lib/users-management.js.map +1 -1
- package/dist/esm/lib/utils.d.ts +16 -2
- package/dist/esm/lib/utils.js +8 -0
- package/dist/esm/lib/utils.js.map +1 -1
- package/dist/esm/workos-widgets.client.js +13 -1
- package/dist/esm/workos-widgets.client.js.map +1 -1
- package/package.json +2 -2
package/dist/esm/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export { UsersManagement, UsersManagementProps } from './users-management.client
|
|
|
8
8
|
export { AdminPortalDomainVerification, AdminPortalDomainVerificationProps } from './admin-portal-domain-verification.client.js';
|
|
9
9
|
export { ApiKeys, ApiKeysProps } from './api-keys.client.js';
|
|
10
10
|
export { Pipes, PipesProps } from './pipes.client.js';
|
|
11
|
+
export { DirectorySync, DirectorySyncProps } from './directory-sync.client.js';
|
|
11
12
|
export { IntlContext as internal_IntlContext } from './lib/i18n/intl-context.js';
|
|
12
13
|
export { OrganizationSwitcherLoading } from './lib/organization-switcher.js';
|
|
13
14
|
export { AdminPortalSsoConnectionLoading } from './lib/admin-portal-sso-connection.js';
|
|
@@ -18,6 +19,7 @@ export { UsersManagementLoading } from './lib/users-management.js';
|
|
|
18
19
|
export { AdminPortalDomainVerificationLoading } from './lib/admin-portal-domain-verification.js';
|
|
19
20
|
export { ApiKeysLoading } from './lib/api-keys/api-keys.js';
|
|
20
21
|
export { PipesLoading } from './lib/pipes.js';
|
|
22
|
+
export { DirectorySyncLoading } from './lib/directory-sync.js';
|
|
21
23
|
import '@radix-ui/themes/props';
|
|
22
24
|
import '@tanstack/react-query';
|
|
23
25
|
import 'react';
|
package/dist/esm/index.js
CHANGED
|
@@ -34,6 +34,10 @@ import {
|
|
|
34
34
|
ApiKeysLoading
|
|
35
35
|
} from "./api-keys.client.js";
|
|
36
36
|
import { Pipes, PipesLoading } from "./pipes.client.js";
|
|
37
|
+
import {
|
|
38
|
+
DirectorySync,
|
|
39
|
+
DirectorySyncLoading
|
|
40
|
+
} from "./directory-sync.client.js";
|
|
37
41
|
import { IntlContext } from "./lib/i18n/intl-context.js";
|
|
38
42
|
export {
|
|
39
43
|
AdminPortalDomainVerification,
|
|
@@ -42,6 +46,8 @@ export {
|
|
|
42
46
|
AdminPortalSsoConnectionLoading,
|
|
43
47
|
ApiKeys,
|
|
44
48
|
ApiKeysLoading,
|
|
49
|
+
DirectorySync,
|
|
50
|
+
DirectorySyncLoading,
|
|
45
51
|
OrganizationSwitcher,
|
|
46
52
|
OrganizationSwitcherLoading,
|
|
47
53
|
Pipes,
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.ts"],"sourcesContent":["export {\n WorkOsWidgets,\n type WorkOsWidgetsProps,\n} from \"./workos-widgets.client.js\";\nexport {\n OrganizationSwitcher,\n OrganizationSwitcherLoading,\n type OrganizationSwitcherProps,\n} from \"./organization-switcher.client.js\";\nexport {\n AdminPortalSsoConnection,\n AdminPortalSsoConnectionLoading,\n type AdminPortalSsoConnectionProps,\n} from \"./admin-portal-sso-connection.client.js\";\nexport {\n UserProfile,\n UserProfileLoading,\n type UserProfileProps,\n} from \"./user-profile.client.js\";\nexport {\n UserSecurity,\n UserSecurityLoading,\n type UserSecurityProps,\n} from \"./user-security.client.js\";\nexport {\n UserSessions,\n UserSessionsLoading,\n type UserSessionsProps,\n} from \"./user-sessions.client.js\";\nexport {\n UsersManagement,\n UsersManagementLoading,\n type UsersManagementProps,\n} from \"./users-management.client.js\";\nexport {\n AdminPortalDomainVerification,\n AdminPortalDomainVerificationLoading,\n type AdminPortalDomainVerificationProps,\n} from \"./admin-portal-domain-verification.client.js\";\nexport {\n ApiKeys,\n ApiKeysLoading,\n type ApiKeysProps,\n} from \"./api-keys.client.js\";\nexport { Pipes, PipesLoading, type PipesProps } from \"./pipes.client.js\";\nexport { IntlContext as internal_IntlContext } from \"./lib/i18n/intl-context.js\";\n"],"mappings":"AAAA;AAAA,EACE;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP,SAAS,OAAO,oBAAqC;AACrD,SAAwB,mBAA4B;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts"],"sourcesContent":["export {\n WorkOsWidgets,\n type WorkOsWidgetsProps,\n} from \"./workos-widgets.client.js\";\nexport {\n OrganizationSwitcher,\n OrganizationSwitcherLoading,\n type OrganizationSwitcherProps,\n} from \"./organization-switcher.client.js\";\nexport {\n AdminPortalSsoConnection,\n AdminPortalSsoConnectionLoading,\n type AdminPortalSsoConnectionProps,\n} from \"./admin-portal-sso-connection.client.js\";\nexport {\n UserProfile,\n UserProfileLoading,\n type UserProfileProps,\n} from \"./user-profile.client.js\";\nexport {\n UserSecurity,\n UserSecurityLoading,\n type UserSecurityProps,\n} from \"./user-security.client.js\";\nexport {\n UserSessions,\n UserSessionsLoading,\n type UserSessionsProps,\n} from \"./user-sessions.client.js\";\nexport {\n UsersManagement,\n UsersManagementLoading,\n type UsersManagementProps,\n} from \"./users-management.client.js\";\nexport {\n AdminPortalDomainVerification,\n AdminPortalDomainVerificationLoading,\n type AdminPortalDomainVerificationProps,\n} from \"./admin-portal-domain-verification.client.js\";\nexport {\n ApiKeys,\n ApiKeysLoading,\n type ApiKeysProps,\n} from \"./api-keys.client.js\";\nexport { Pipes, PipesLoading, type PipesProps } from \"./pipes.client.js\";\nexport {\n DirectorySync,\n DirectorySyncLoading,\n type DirectorySyncProps,\n} from \"./directory-sync.client.js\";\nexport { IntlContext as internal_IntlContext } from \"./lib/i18n/intl-context.js\";\n"],"mappings":"AAAA;AAAA,EACE;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP,SAAS,OAAO,oBAAqC;AACrD;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP,SAAwB,mBAA4B;","names":[]}
|
|
@@ -79,7 +79,7 @@ function Content({ onClose, totpFactor }) {
|
|
|
79
79
|
const securitySettings = useSecuritySettings();
|
|
80
80
|
const translate = useTranslation();
|
|
81
81
|
const [customError, setCustomError] = React.useState(null);
|
|
82
|
-
const totp =
|
|
82
|
+
const totp = totpFactor?.authenticationFactor.totp != null && "qr_code" in totpFactor.authenticationFactor.totp ? totpFactor.authenticationFactor.totp : void 0;
|
|
83
83
|
const verifyTotp = useVerifyTotpFactor({
|
|
84
84
|
mutation: {
|
|
85
85
|
onSuccess: ({ success }) => {
|
|
@@ -208,7 +208,7 @@ function Content({ onClose, totpFactor }) {
|
|
|
208
208
|
background: "var(--gray-2)",
|
|
209
209
|
overflow: "hidden"
|
|
210
210
|
},
|
|
211
|
-
children: totp?.qr_code && /* @__PURE__ */ jsx(Box, { asChild: true, width: "100%", height: "auto", children: /* @__PURE__ */ jsx(
|
|
211
|
+
children: !!totp?.qr_code && /* @__PURE__ */ jsx(Box, { asChild: true, width: "100%", height: "auto", children: /* @__PURE__ */ jsx(
|
|
212
212
|
"img",
|
|
213
213
|
{
|
|
214
214
|
alt: translate({
|
|
@@ -234,22 +234,28 @@ function Content({ onClose, totpFactor }) {
|
|
|
234
234
|
description: "Question asking if user is unable to scan the QR code"
|
|
235
235
|
}
|
|
236
236
|
) }),
|
|
237
|
-
/* @__PURE__ */ jsx(
|
|
238
|
-
|
|
237
|
+
/* @__PURE__ */ jsx(
|
|
238
|
+
SecretDialog,
|
|
239
239
|
{
|
|
240
|
-
|
|
241
|
-
size: "1",
|
|
242
|
-
disabled: verifyTotp.isPending || isSuccess,
|
|
240
|
+
setupKey: totp && "secret" in totp ? totp.secret : "",
|
|
243
241
|
children: /* @__PURE__ */ jsx(
|
|
244
|
-
|
|
242
|
+
Button,
|
|
245
243
|
{
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
244
|
+
variant: "secondary",
|
|
245
|
+
size: "1",
|
|
246
|
+
disabled: verifyTotp.isPending || isSuccess,
|
|
247
|
+
children: /* @__PURE__ */ jsx(
|
|
248
|
+
Translation,
|
|
249
|
+
{
|
|
250
|
+
defaultMessage: "View setup key",
|
|
251
|
+
id: "q3eZjH",
|
|
252
|
+
description: "Button text to view the manual setup key"
|
|
253
|
+
}
|
|
254
|
+
)
|
|
249
255
|
}
|
|
250
256
|
)
|
|
251
257
|
}
|
|
252
|
-
)
|
|
258
|
+
)
|
|
253
259
|
] })
|
|
254
260
|
] })
|
|
255
261
|
] }),
|
|
@@ -383,10 +389,6 @@ function getMutationErrorMessage(error) {
|
|
|
383
389
|
}
|
|
384
390
|
return message;
|
|
385
391
|
}
|
|
386
|
-
function hasQrCode(response) {
|
|
387
|
-
const totp = response?.authenticationFactor.totp;
|
|
388
|
-
return totp != null && "qr_code" in totp;
|
|
389
|
-
}
|
|
390
392
|
export {
|
|
391
393
|
AddMfaDialog
|
|
392
394
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/add-mfa-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n Box,\n Code,\n Flex,\n Grid,\n Link,\n Separator,\n Text,\n VisuallyHidden,\n} from \"@radix-ui/themes\";\nimport * as React from \"react\";\nimport { type ReactNode } from \"react\";\nimport * as Otp from \"./otp-input.js\";\nimport { Dialog, Button } from \"./elements.js\";\nimport {\n CreateTotpFactorResponse,\n CreateTotpFactorResponseAuthenticationFactorAllOfTotpAnyOf,\n useCreateTotpFactor,\n useVerifyTotpFactor,\n} from \"../api/endpoint.js\";\nimport { useElevatedAccessToken } from \"../api/api-provider.js\";\nimport { Form } from \"radix-ui\";\nimport { Marker } from \"./marker.js\";\nimport { CopyButton } from \"./copy-button.js\";\nimport { useSecuritySettings } from \"./use-security-settings.js\";\nimport { ElevatedAccess } from \"./elevated-access.js\";\nimport { SaveButton } from \"./save-button.js\";\nimport { useDialogClose } from \"./use-dialog-close.js\";\nimport { Translation } from \"./i18n/translation.js\";\nimport { useTranslation } from \"./i18n/use-translation.js\";\n\ninterface AddMfaDialogProps extends Dialog.RootProps {\n children?: ReactNode;\n onSuccess?: () => void;\n}\n\nexport function AddMfaDialog({\n children,\n onSuccess,\n ...props\n}: AddMfaDialogProps) {\n const [open, setOpen] = React.useState(false);\n const [manuallyTriggered, setManuallyTriggered] = React.useState(false);\n const { elevatedAccess } = useElevatedAccessToken();\n const createAuthFactor = useCreateTotpFactor();\n\n const handleVerified = async () => {\n await createAuthFactor.mutateAsync(undefined);\n };\n\n const onTriggerClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n if (elevatedAccess && !createAuthFactor.data) {\n event.preventDefault();\n setManuallyTriggered(true);\n createAuthFactor.mutate(undefined, {\n onSuccess: () => {\n setOpen(true);\n },\n });\n } else {\n setManuallyTriggered(false);\n }\n };\n\n const handleClose = React.useCallback(() => {\n setOpen(false);\n }, []);\n\n return (\n <Dialog.Root\n {...props}\n open={props.open || open}\n onOpenChange={props.onOpenChange || setOpen}\n >\n <Dialog.Trigger\n onClick={onTriggerClick}\n // @ts-ignore I've to find a way to pass the loading state to the trigger\n loading={manuallyTriggered && createAuthFactor.isPending}\n >\n {children}\n </Dialog.Trigger>\n\n <Dialog.Content maxWidth=\"480px\">\n <ElevatedAccess onVerified={handleVerified}>\n <Content onClose={handleClose} totpFactor={createAuthFactor.data} />\n </ElevatedAccess>\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\ninterface ContentProps {\n totpFactor?: CreateTotpFactorResponse;\n onClose?: () => void;\n}\n\nfunction Content({ onClose, totpFactor }: ContentProps) {\n const securitySettings = useSecuritySettings();\n const translate = useTranslation();\n\n const [customError, setCustomError] = React.useState<string | null>(null);\n const totp = hasQrCode(totpFactor)\n ? totpFactor.authenticationFactor.totp\n : undefined;\n\n const verifyTotp = useVerifyTotpFactor({\n mutation: {\n onSuccess: ({ success }) => {\n if (!success) {\n setCustomError(\"Invalid passcode\");\n }\n },\n },\n });\n\n const serverError = verifyTotp.error || customError;\n const isSuccess = verifyTotp.isSuccess && !serverError;\n\n const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n setCustomError(null);\n\n const formData = new FormData(event.currentTarget);\n const otpCode = formData.get(\"otp-code\")?.toString();\n\n verifyTotp.mutate({\n data: {\n authenticationChallengeId: totpFactor?.authenticationChallenge.id ?? \"\",\n code: otpCode ?? \"\",\n },\n });\n };\n\n useDialogClose(isSuccess, () => {\n securitySettings.update(\"Mfa\", true);\n });\n\n return (\n <>\n <Dialog.Title mb=\"5\">\n <Translation\n defaultMessage=\"Set up an authenticator app\"\n id=\"Eu+kuO\"\n description=\"Title for setting up two-factor authentication\"\n />\n </Dialog.Title>\n\n <Form.Root onSubmit={handleSubmit}>\n <Grid columns=\"auto 1fr\" rows=\"repeat(4, auto)\" gapX=\"3\" gapY=\"1\">\n <Grid\n rows=\"subgrid\"\n gridRow=\"span 4\"\n style={{ placeItems: \"center\" }}\n >\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Marker>1</Marker>\n <Separator\n orientation=\"vertical\"\n size=\"4\"\n style={{ width: \"2px\" }}\n />\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Marker>2</Marker>\n <div />\n </Grid>\n\n <Grid rows=\"subgrid\" gridRow=\"span 4\">\n <Text as=\"p\" size=\"3\" weight=\"bold\">\n <Translation\n defaultMessage=\"Scan the QR code\"\n id=\"fTSp5u\"\n description=\"Heading for the QR code scanning step in MFA setup\"\n />\n </Text>\n <Flex direction=\"column\" gap=\"1\">\n <Text as=\"p\" size=\"2\">\n <Translation\n defaultMessage=\"Use an authenticator app like {onep}, {google}, {authy}, or {microsoft} to scan the QR code below.\"\n id=\"8xwdwI\"\n description=\"Instructions for scanning the QR code with authenticator apps\"\n values={{\n onep: (\n <Link\n href=\"https://1password.com/\"\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n // eslint-disable-next-line formatjs/no-literal-string-in-jsx\n >\n 1Password\n </Link>\n ),\n google: (\n <Link\n href=\"https://apps.apple.com/us/app/google-authenticator/id388497605\"\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n // eslint-disable-next-line formatjs/no-literal-string-in-jsx\n >\n Google Authenticator\n </Link>\n ),\n authy: (\n <Link\n href=\"https://authy.com/\"\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n // eslint-disable-next-line formatjs/no-literal-string-in-jsx\n >\n Authy\n </Link>\n ),\n microsoft: (\n <Link\n href=\"https://www.microsoft.com/en-gb/security/mobile-authenticator-app\"\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n // eslint-disable-next-line formatjs/no-literal-string-in-jsx\n >\n Microsoft Authenticator\n </Link>\n ),\n }}\n />\n </Text>\n <Flex align=\"center\" gap=\"5\" my=\"5\">\n <Grid\n position=\"relative\"\n width=\"160px\"\n height=\"160px\"\n p=\"2\"\n style={{\n border: \"1px solid var(--gray-7)\",\n borderRadius: \"var(--radius-4)\",\n background: \"var(--gray-2)\",\n overflow: \"hidden\",\n }}\n >\n {totp?.qr_code && (\n <Box asChild width=\"100%\" height=\"auto\">\n <img\n alt={translate({\n defaultMessage: \"Scan this QR code to enroll\",\n description: \"Alt text for QR code image\",\n id: \"wpbqFJ\",\n })}\n aria-describedby=\"secret-note\"\n height=\"160\"\n src={totp.qr_code}\n style={{ userSelect: \"none\", background: \"white\" }}\n width=\"160\"\n />\n </Box>\n )}\n </Grid>\n\n <Flex direction=\"column\" gap=\"1\" align=\"start\">\n <Text color=\"gray\" id=\"secret-note\" size=\"2\">\n <Translation\n defaultMessage=\"Can't scan the code?\"\n id=\"6/cdcS\"\n description=\"Question asking if user is unable to scan the QR code\"\n />\n </Text>\n\n <SecretDialog setupKey={totp?.secret ?? \"\"}>\n <Button\n variant=\"secondary\"\n size=\"1\"\n disabled={verifyTotp.isPending || isSuccess}\n >\n <Translation\n defaultMessage=\"View setup key\"\n id=\"q3eZjH\"\n description=\"Button text to view the manual setup key\"\n />\n </Button>\n </SecretDialog>\n </Flex>\n </Flex>\n </Flex>\n <Text as=\"p\" size=\"3\" weight=\"bold\">\n <Translation\n defaultMessage=\"Get verification passcode\"\n id=\"1kRd2b\"\n description=\"Heading for entering the verification code step\"\n />\n </Text>\n <Flex direction=\"column\" gap=\"4\">\n <Text as=\"p\" size=\"2\">\n <Translation\n defaultMessage=\"Enter the 6-digit passcode from your authenticator app.\"\n id=\"4/66bS\"\n description=\"Instructions for entering the verification passcode\"\n />\n </Text>\n\n <Flex direction=\"column\" gap=\"2\">\n <Otp.Root\n autoSubmit\n gap=\"3\"\n justify=\"start\"\n name=\"otp-code\"\n rows=\"48px\"\n columns=\"repeat(6, 48px)\"\n readOnly={verifyTotp.isPending || isSuccess}\n >\n <Otp.Input required autoFocus autoComplete=\"off\" />\n <Otp.Input required />\n <Otp.Input required />\n <Otp.Input required />\n <Otp.Input required />\n <Otp.Input required />\n </Otp.Root>\n\n {serverError && (\n <Text size=\"2\" color=\"red\">\n {getMutationErrorMessage(serverError)}\n </Text>\n )}\n </Flex>\n </Flex>\n </Grid>\n </Grid>\n\n <Flex mt=\"5\" gap=\"3\" justify=\"end\">\n <Dialog.Close>\n <Button\n variant=\"secondary\"\n disabled={verifyTotp.isPending || isSuccess}\n >\n <Translation\n defaultMessage=\"Cancel\"\n id=\"84pAvU\"\n description=\"Button text to cancel MFA setup\"\n />\n </Button>\n </Dialog.Close>\n\n <SaveButton\n type=\"submit\"\n loading={verifyTotp.isPending}\n done={isSuccess}\n onDone={onClose}\n >\n <Translation\n defaultMessage=\"Confirm\"\n id=\"WHthZi\"\n description=\"Button text to confirm MFA setup\"\n />\n </SaveButton>\n </Flex>\n </Form.Root>\n\n {/* mirror errors in a live region */}\n <VisuallyHidden asChild>\n <section aria-live=\"polite\">\n {getMutationErrorMessage(serverError)}\n </section>\n </VisuallyHidden>\n </>\n );\n}\n\ninterface SecretDialogProps extends React.PropsWithChildren {\n setupKey: string;\n}\n\nfunction SecretDialog({ children, setupKey }: SecretDialogProps) {\n return (\n <Dialog.Root>\n <Dialog.Trigger>{children}</Dialog.Trigger>\n <Dialog.Content\n maxWidth=\"90vw\"\n size={{ initial: \"3\", sm: \"4\" }}\n minWidth=\"300px\"\n width=\"fit-content\"\n >\n <Dialog.Title size=\"2\" weight=\"regular\">\n <Translation\n defaultMessage=\"Your setup key\"\n id=\"LleqNP\"\n description=\"Title for dialog showing the manual setup key\"\n />\n </Dialog.Title>\n <Dialog.Description>\n <Text size=\"6\">\n <Code variant=\"ghost\" style={{ letterSpacing: \"0.15rem\" }}>\n {setupKey}\n </Code>\n </Text>\n </Dialog.Description>\n\n <Flex align=\"center\" gap=\"3\" justify=\"end\" mt=\"5\">\n <Dialog.Close>\n <CopyButton value={setupKey}>\n <Translation\n defaultMessage=\"Copy and close\"\n id=\"EyjGir\"\n description=\"Button text to copy setup key and close dialog\"\n />\n </CopyButton>\n </Dialog.Close>\n </Flex>\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\nfunction getMutationErrorMessage(error: unknown) {\n let message = \"Something went wrong, please try again\";\n\n if (typeof error === \"string\") {\n message = error;\n }\n\n if (error instanceof Error) {\n message = error.message;\n }\n\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"message\" in error &&\n typeof error.message === \"string\"\n ) {\n message = error.message;\n }\n\n if (message === \"Invalid passcode\") {\n message = \"Invalid passcode, please try again\";\n }\n\n return message;\n}\n\nfunction hasQrCode(\n response?: CreateTotpFactorResponse,\n): response is CreateTotpFactorResponse & {\n authenticationFactor: {\n totp: NonNullable<CreateTotpFactorResponseAuthenticationFactorAllOfTotpAnyOf>;\n };\n} {\n const totp = response?.authenticationFactor.totp;\n return totp != null && \"qr_code\" in totp;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/add-mfa-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n Box,\n Code,\n Flex,\n Grid,\n Link,\n Separator,\n Text,\n VisuallyHidden,\n} from \"@radix-ui/themes\";\nimport * as React from \"react\";\nimport { type ReactNode } from \"react\";\nimport * as Otp from \"./otp-input.js\";\nimport { Dialog, Button } from \"./elements.js\";\nimport {\n CreateTotpFactorResponse,\n useCreateTotpFactor,\n useVerifyTotpFactor,\n} from \"../api/endpoint.js\";\nimport { useElevatedAccessToken } from \"../api/api-provider.js\";\nimport { Form } from \"radix-ui\";\nimport { Marker } from \"./marker.js\";\nimport { CopyButton } from \"./copy-button.js\";\nimport { useSecuritySettings } from \"./use-security-settings.js\";\nimport { ElevatedAccess } from \"./elevated-access.js\";\nimport { SaveButton } from \"./save-button.js\";\nimport { useDialogClose } from \"./use-dialog-close.js\";\nimport { Translation } from \"./i18n/translation.js\";\nimport { useTranslation } from \"./i18n/use-translation.js\";\n\ninterface AddMfaDialogProps extends Dialog.RootProps {\n children?: ReactNode;\n onSuccess?: () => void;\n}\n\nexport function AddMfaDialog({\n children,\n onSuccess,\n ...props\n}: AddMfaDialogProps) {\n const [open, setOpen] = React.useState(false);\n const [manuallyTriggered, setManuallyTriggered] = React.useState(false);\n const { elevatedAccess } = useElevatedAccessToken();\n const createAuthFactor = useCreateTotpFactor();\n\n const handleVerified = async () => {\n await createAuthFactor.mutateAsync(undefined);\n };\n\n const onTriggerClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n if (elevatedAccess && !createAuthFactor.data) {\n event.preventDefault();\n setManuallyTriggered(true);\n createAuthFactor.mutate(undefined, {\n onSuccess: () => {\n setOpen(true);\n },\n });\n } else {\n setManuallyTriggered(false);\n }\n };\n\n const handleClose = React.useCallback(() => {\n setOpen(false);\n }, []);\n\n return (\n <Dialog.Root\n {...props}\n open={props.open || open}\n onOpenChange={props.onOpenChange || setOpen}\n >\n <Dialog.Trigger\n onClick={onTriggerClick}\n // @ts-ignore I've to find a way to pass the loading state to the trigger\n loading={manuallyTriggered && createAuthFactor.isPending}\n >\n {children}\n </Dialog.Trigger>\n\n <Dialog.Content maxWidth=\"480px\">\n <ElevatedAccess onVerified={handleVerified}>\n <Content onClose={handleClose} totpFactor={createAuthFactor.data} />\n </ElevatedAccess>\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\ninterface ContentProps {\n totpFactor?: CreateTotpFactorResponse;\n onClose?: () => void;\n}\n\nfunction Content({ onClose, totpFactor }: ContentProps) {\n const securitySettings = useSecuritySettings();\n const translate = useTranslation();\n\n const [customError, setCustomError] = React.useState<string | null>(null);\n const totp =\n totpFactor?.authenticationFactor.totp != null &&\n \"qr_code\" in totpFactor.authenticationFactor.totp\n ? totpFactor.authenticationFactor.totp\n : undefined;\n\n const verifyTotp = useVerifyTotpFactor({\n mutation: {\n onSuccess: ({ success }) => {\n if (!success) {\n setCustomError(\"Invalid passcode\");\n }\n },\n },\n });\n\n const serverError = verifyTotp.error || customError;\n const isSuccess = verifyTotp.isSuccess && !serverError;\n\n const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n setCustomError(null);\n\n const formData = new FormData(event.currentTarget);\n const otpCode = formData.get(\"otp-code\")?.toString();\n\n verifyTotp.mutate({\n data: {\n authenticationChallengeId: totpFactor?.authenticationChallenge.id ?? \"\",\n code: otpCode ?? \"\",\n },\n });\n };\n\n useDialogClose(isSuccess, () => {\n securitySettings.update(\"Mfa\", true);\n });\n\n return (\n <>\n <Dialog.Title mb=\"5\">\n <Translation\n defaultMessage=\"Set up an authenticator app\"\n id=\"Eu+kuO\"\n description=\"Title for setting up two-factor authentication\"\n />\n </Dialog.Title>\n\n <Form.Root onSubmit={handleSubmit}>\n <Grid columns=\"auto 1fr\" rows=\"repeat(4, auto)\" gapX=\"3\" gapY=\"1\">\n <Grid\n rows=\"subgrid\"\n gridRow=\"span 4\"\n style={{ placeItems: \"center\" }}\n >\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Marker>1</Marker>\n <Separator\n orientation=\"vertical\"\n size=\"4\"\n style={{ width: \"2px\" }}\n />\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Marker>2</Marker>\n <div />\n </Grid>\n\n <Grid rows=\"subgrid\" gridRow=\"span 4\">\n <Text as=\"p\" size=\"3\" weight=\"bold\">\n <Translation\n defaultMessage=\"Scan the QR code\"\n id=\"fTSp5u\"\n description=\"Heading for the QR code scanning step in MFA setup\"\n />\n </Text>\n <Flex direction=\"column\" gap=\"1\">\n <Text as=\"p\" size=\"2\">\n <Translation\n defaultMessage=\"Use an authenticator app like {onep}, {google}, {authy}, or {microsoft} to scan the QR code below.\"\n id=\"8xwdwI\"\n description=\"Instructions for scanning the QR code with authenticator apps\"\n values={{\n onep: (\n <Link\n href=\"https://1password.com/\"\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n // eslint-disable-next-line formatjs/no-literal-string-in-jsx\n >\n 1Password\n </Link>\n ),\n google: (\n <Link\n href=\"https://apps.apple.com/us/app/google-authenticator/id388497605\"\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n // eslint-disable-next-line formatjs/no-literal-string-in-jsx\n >\n Google Authenticator\n </Link>\n ),\n authy: (\n <Link\n href=\"https://authy.com/\"\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n // eslint-disable-next-line formatjs/no-literal-string-in-jsx\n >\n Authy\n </Link>\n ),\n microsoft: (\n <Link\n href=\"https://www.microsoft.com/en-gb/security/mobile-authenticator-app\"\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n // eslint-disable-next-line formatjs/no-literal-string-in-jsx\n >\n Microsoft Authenticator\n </Link>\n ),\n }}\n />\n </Text>\n <Flex align=\"center\" gap=\"5\" my=\"5\">\n <Grid\n position=\"relative\"\n width=\"160px\"\n height=\"160px\"\n p=\"2\"\n style={{\n border: \"1px solid var(--gray-7)\",\n borderRadius: \"var(--radius-4)\",\n background: \"var(--gray-2)\",\n overflow: \"hidden\",\n }}\n >\n {!!totp?.qr_code && (\n <Box asChild width=\"100%\" height=\"auto\">\n <img\n alt={translate({\n defaultMessage: \"Scan this QR code to enroll\",\n description: \"Alt text for QR code image\",\n id: \"wpbqFJ\",\n })}\n aria-describedby=\"secret-note\"\n height=\"160\"\n src={totp.qr_code}\n style={{ userSelect: \"none\", background: \"white\" }}\n width=\"160\"\n />\n </Box>\n )}\n </Grid>\n\n <Flex direction=\"column\" gap=\"1\" align=\"start\">\n <Text color=\"gray\" id=\"secret-note\" size=\"2\">\n <Translation\n defaultMessage=\"Can't scan the code?\"\n id=\"6/cdcS\"\n description=\"Question asking if user is unable to scan the QR code\"\n />\n </Text>\n\n <SecretDialog\n setupKey={totp && \"secret\" in totp ? totp.secret : \"\"}\n >\n <Button\n variant=\"secondary\"\n size=\"1\"\n disabled={verifyTotp.isPending || isSuccess}\n >\n <Translation\n defaultMessage=\"View setup key\"\n id=\"q3eZjH\"\n description=\"Button text to view the manual setup key\"\n />\n </Button>\n </SecretDialog>\n </Flex>\n </Flex>\n </Flex>\n <Text as=\"p\" size=\"3\" weight=\"bold\">\n <Translation\n defaultMessage=\"Get verification passcode\"\n id=\"1kRd2b\"\n description=\"Heading for entering the verification code step\"\n />\n </Text>\n <Flex direction=\"column\" gap=\"4\">\n <Text as=\"p\" size=\"2\">\n <Translation\n defaultMessage=\"Enter the 6-digit passcode from your authenticator app.\"\n id=\"4/66bS\"\n description=\"Instructions for entering the verification passcode\"\n />\n </Text>\n\n <Flex direction=\"column\" gap=\"2\">\n <Otp.Root\n autoSubmit\n gap=\"3\"\n justify=\"start\"\n name=\"otp-code\"\n rows=\"48px\"\n columns=\"repeat(6, 48px)\"\n readOnly={verifyTotp.isPending || isSuccess}\n >\n <Otp.Input required autoFocus autoComplete=\"off\" />\n <Otp.Input required />\n <Otp.Input required />\n <Otp.Input required />\n <Otp.Input required />\n <Otp.Input required />\n </Otp.Root>\n\n {serverError && (\n <Text size=\"2\" color=\"red\">\n {getMutationErrorMessage(serverError)}\n </Text>\n )}\n </Flex>\n </Flex>\n </Grid>\n </Grid>\n\n <Flex mt=\"5\" gap=\"3\" justify=\"end\">\n <Dialog.Close>\n <Button\n variant=\"secondary\"\n disabled={verifyTotp.isPending || isSuccess}\n >\n <Translation\n defaultMessage=\"Cancel\"\n id=\"84pAvU\"\n description=\"Button text to cancel MFA setup\"\n />\n </Button>\n </Dialog.Close>\n\n <SaveButton\n type=\"submit\"\n loading={verifyTotp.isPending}\n done={isSuccess}\n onDone={onClose}\n >\n <Translation\n defaultMessage=\"Confirm\"\n id=\"WHthZi\"\n description=\"Button text to confirm MFA setup\"\n />\n </SaveButton>\n </Flex>\n </Form.Root>\n\n {/* mirror errors in a live region */}\n <VisuallyHidden asChild>\n <section aria-live=\"polite\">\n {getMutationErrorMessage(serverError)}\n </section>\n </VisuallyHidden>\n </>\n );\n}\n\ninterface SecretDialogProps extends React.PropsWithChildren {\n setupKey: string;\n}\n\nfunction SecretDialog({ children, setupKey }: SecretDialogProps) {\n return (\n <Dialog.Root>\n <Dialog.Trigger>{children}</Dialog.Trigger>\n <Dialog.Content\n maxWidth=\"90vw\"\n size={{ initial: \"3\", sm: \"4\" }}\n minWidth=\"300px\"\n width=\"fit-content\"\n >\n <Dialog.Title size=\"2\" weight=\"regular\">\n <Translation\n defaultMessage=\"Your setup key\"\n id=\"LleqNP\"\n description=\"Title for dialog showing the manual setup key\"\n />\n </Dialog.Title>\n <Dialog.Description>\n <Text size=\"6\">\n <Code variant=\"ghost\" style={{ letterSpacing: \"0.15rem\" }}>\n {setupKey}\n </Code>\n </Text>\n </Dialog.Description>\n\n <Flex align=\"center\" gap=\"3\" justify=\"end\" mt=\"5\">\n <Dialog.Close>\n <CopyButton value={setupKey}>\n <Translation\n defaultMessage=\"Copy and close\"\n id=\"EyjGir\"\n description=\"Button text to copy setup key and close dialog\"\n />\n </CopyButton>\n </Dialog.Close>\n </Flex>\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\nfunction getMutationErrorMessage(error: unknown) {\n let message = \"Something went wrong, please try again\";\n\n if (typeof error === \"string\") {\n message = error;\n }\n\n if (error instanceof Error) {\n message = error.message;\n }\n\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"message\" in error &&\n typeof error.message === \"string\"\n ) {\n message = error.message;\n }\n\n if (message === \"Invalid passcode\") {\n message = \"Invalid passcode, please try again\";\n }\n\n return message;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -44,9 +44,8 @@ type AdminPortalSsoConnectionProps = WidgetRootDomProps & AdminPortalSsoConnecti
|
|
|
44
44
|
adminPortalOpenButton: React.ReactNode;
|
|
45
45
|
};
|
|
46
46
|
declare const AdminPortalSsoConnection: React.FC<AdminPortalSsoConnectionProps>;
|
|
47
|
-
declare function AdminPortalOpenButton({ isPending,
|
|
47
|
+
declare function AdminPortalOpenButton({ isPending, initConfig, }: {
|
|
48
48
|
isPending: boolean;
|
|
49
|
-
href: string | null;
|
|
50
49
|
initConfig: () => void;
|
|
51
50
|
}): react_jsx_runtime.JSX.Element;
|
|
52
51
|
interface AdminPortalSsoConnectionLoadingProps extends WidgetRootDomProps {
|
|
@@ -206,7 +206,6 @@ function SessionInfo({
|
|
|
206
206
|
}
|
|
207
207
|
function AdminPortalOpenButton({
|
|
208
208
|
isPending,
|
|
209
|
-
href,
|
|
210
209
|
initConfig
|
|
211
210
|
}) {
|
|
212
211
|
const { connectionStatus } = useAdminPortalSsoConnectionContext();
|
|
@@ -245,13 +244,6 @@ function AdminPortalOpenButton({
|
|
|
245
244
|
return unreachable(connectionStatus);
|
|
246
245
|
}
|
|
247
246
|
})();
|
|
248
|
-
if (href) {
|
|
249
|
-
return /* @__PURE__ */ jsx(Button, { variant: "secondary", asChild: true, children: /* @__PURE__ */ jsxs("a", { href, target: "_blank", rel: "noopener noreferrer", children: [
|
|
250
|
-
label,
|
|
251
|
-
" ",
|
|
252
|
-
/* @__PURE__ */ jsx(ExternalLinkIcon, { "aria-hidden": true })
|
|
253
|
-
] }) });
|
|
254
|
-
}
|
|
255
247
|
return /* @__PURE__ */ jsxs(
|
|
256
248
|
Button,
|
|
257
249
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/admin-portal-sso-connection.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { Box, Card, Flex, Text } from \"@radix-ui/themes\";\nimport { Button, Skeleton } from \"./elements.js\";\nimport { IconPanel } from \"./icon-panel.js\";\nimport {\n ExternalLinkIcon,\n InfoCircledIcon,\n Cross2Icon,\n} from \"@radix-ui/react-icons\";\nimport * as CardList from \"./card-list.js\";\nimport { ProviderIcon } from \"./provider-icon.js\";\nimport {\n getIdentityProviderName,\n type IdentityProvider,\n} from \"./identity-providers.js\";\nimport { Status } from \"./status.js\";\nimport {\n getDomProps,\n unreachable,\n type WidgetRootState,\n type WidgetRootDomProps,\n} from \"./utils.js\";\nimport { Translation } from \"./i18n/translation.js\";\nimport { useTranslation } from \"./i18n/use-translation.js\";\nimport { getErrorMessage } from \"./generic-error.js\";\n\ninterface NotConfiguredProps {\n connectionStatus: \"NotConfigured\";\n identityProvider?: never;\n expiryDate?: never;\n}\n\ninterface InactiveProps {\n connectionStatus: \"Inactive\";\n identityProvider: IdentityProvider;\n expiryDate?: never;\n}\n\ninterface ActiveProps {\n connectionStatus: \"Active\";\n identityProvider: IdentityProvider;\n expiryDate?: never;\n}\n\ninterface RequiresActionProps {\n connectionStatus: \"Expired\" | \"Expiring\";\n identityProvider: IdentityProvider;\n expiryDate: Date | null;\n}\n\nexport type AdminPortalSsoConnectionStatusProps =\n | NotConfiguredProps\n | InactiveProps\n | ActiveProps\n | RequiresActionProps;\n\ntype AdminPortalSsoConnectionProps = WidgetRootDomProps &\n AdminPortalSsoConnectionStatusProps & {\n currentDate: Date | null;\n lastSession: Date | null;\n adminPortalOpenButton: React.ReactNode;\n };\n\ninterface AdminPortalSsoConnectionContextValue {\n connectionStatus: AdminPortalSsoConnectionStatusProps[\"connectionStatus\"];\n}\n\nconst AdminPortalSsoConnectionContext =\n React.createContext<AdminPortalSsoConnectionContextValue | null>(null);\nAdminPortalSsoConnectionContext.displayName = \"AdminPortalSsoConnectionContext\";\n\nfunction useAdminPortalSsoConnectionContext() {\n const context = React.useContext(AdminPortalSsoConnectionContext);\n if (!context) {\n throw new Error(\n \"useAdminPortalSsoConnectionContext must be used within a AdminPortalSsoConnectionContext provider\",\n );\n }\n return context;\n}\n\nconst AdminPortalSsoConnection: React.FC<AdminPortalSsoConnectionProps> = ({\n currentDate,\n connectionStatus,\n identityProvider,\n expiryDate,\n lastSession,\n adminPortalOpenButton,\n ...domProps\n}) => {\n return (\n <CardList.Root size=\"2\" {...getWidgetRootDomProps(\"resolved\", domProps)}>\n <AdminPortalSsoConnectionContext.Provider value={{ connectionStatus }}>\n <CardList.Item>\n <Flex direction=\"row\" justify=\"between\" align=\"center\" gap=\"2\">\n {(() => {\n if (connectionStatus === \"NotConfigured\") {\n return (\n <>\n <Text size=\"2\" color=\"gray\">\n <Translation\n defaultMessage=\"You haven't set up Single Sign-On yet.\"\n id=\"KDs1Ib\"\n description=\"Empty state message when SSO is not configured\"\n />\n </Text>\n {adminPortalOpenButton}\n </>\n );\n }\n\n return (\n <>\n <SessionInfo\n connectionStatus={connectionStatus}\n identityProvider={identityProvider}\n lastSession={lastSession}\n currentDate={currentDate}\n />\n <Flex gap=\"5\" align=\"center\">\n <SsoStatus status={connectionStatus} />\n {adminPortalOpenButton}\n </Flex>\n </>\n );\n })()}\n </Flex>\n </CardList.Item>\n {connectionStatus === \"Expired\" && (\n <CardList.Item>\n <Flex align=\"start\" gap=\"2\">\n <Box asChild mt=\"2px\" flexShrink=\"0\">\n <InfoCircledIcon color=\"gray\" />\n </Box>\n {(() => {\n if (connectionStatus === \"Expired\") {\n return (\n <Text size=\"2\" color=\"gray\">\n {(() => {\n if (!expiryDate) {\n return (\n <Translation\n defaultMessage=\"The SAML response signing certificate has expired. Users won't be able to sign-in to the application until the certificate is renewed.\"\n id=\"5tX19v\"\n description=\"Error message when SAML certificate has expired (no date)\"\n />\n );\n }\n\n return (\n <Translation\n defaultMessage=\"The SAML response signing certificate expired on {expiryDate}. Users won't be able to sign-in to the application until the certificate is renewed.\"\n id=\"vmTW/h\"\n description=\"Error message when SAML certificate has expired with date\"\n values={{\n expiryDate: (\n <Text weight=\"bold\" as=\"span\">\n {expiryDate?.toLocaleString(\"en-US\", {\n month: \"long\",\n day: \"numeric\",\n year: \"numeric\",\n })}\n </Text>\n ),\n }}\n />\n );\n })()}\n </Text>\n );\n }\n\n if (connectionStatus === \"Expiring\") {\n return (\n <Text size=\"2\" color=\"gray\">\n {(() => {\n if (!expiryDate) {\n return (\n <Translation\n defaultMessage=\"The SAML response signing certificate is expiring soon. When expired, users won't be able to sign-in.\"\n id=\"3dgA5f\"\n description=\"Warning message when SAML certificate is expiring soon (no date)\"\n />\n );\n }\n\n return (\n <Translation\n defaultMessage=\"The SAML response signing certificate will expire on {expiryDate}. When expired, users won't be able to sign-in.\"\n id=\"xT9Exy\"\n description=\"Warning message when SAML certificate is expiring with date\"\n values={{\n expiryDate: (\n <Text weight=\"bold\" as=\"span\">\n {expiryDate?.toLocaleString(\"en-US\", {\n month: \"long\",\n day: \"numeric\",\n year: \"numeric\",\n })}\n </Text>\n ),\n }}\n />\n );\n })()}\n </Text>\n );\n }\n })()}\n </Flex>\n </CardList.Item>\n )}\n </AdminPortalSsoConnectionContext.Provider>\n </CardList.Root>\n );\n};\n\nfunction SsoStatus({\n status,\n}: {\n status: AdminPortalSsoConnectionStatusProps[\"connectionStatus\"];\n}) {\n if (status === \"NotConfigured\") {\n return null;\n }\n\n if (status === \"Inactive\") {\n return (\n <Status state=\"waiting\">\n <Translation\n defaultMessage=\"Setup in progress\"\n id=\"MQR5mR\"\n description=\"Status label when SSO setup is incomplete\"\n />\n </Status>\n );\n }\n\n if (status === \"Expired\") {\n return (\n <Status state=\"error\">\n <Translation\n defaultMessage=\"Requires action\"\n id=\"Yo2vHC\"\n description=\"Status label when SSO requires attention\"\n />\n </Status>\n );\n }\n\n if (status === \"Active\" || status === \"Expiring\") {\n return (\n <Status state=\"success\">\n <Translation\n defaultMessage=\"Connected\"\n id=\"8S+Cyw\"\n description=\"Status label when SSO is active\"\n />\n </Status>\n );\n }\n\n return unreachable(status);\n}\n\nfunction SessionInfo({\n currentDate,\n identityProvider,\n lastSession,\n connectionStatus,\n}: {\n identityProvider: IdentityProvider;\n lastSession: Date | null;\n currentDate: Date | null;\n connectionStatus: AdminPortalSsoConnectionStatusProps[\"connectionStatus\"];\n}) {\n const relativeTimeString = React.useMemo(() => {\n if (\n !lastSession ||\n !currentDate ||\n connectionStatus === \"NotConfigured\" ||\n connectionStatus === \"Inactive\"\n ) {\n return null;\n }\n\n return getRelativeTimeString(currentDate, lastSession);\n }, [lastSession, currentDate, connectionStatus]);\n\n return (\n <Flex gap=\"4\" align=\"center\">\n <IconPanel color=\"panel\">\n <ProviderIcon provider={identityProvider} size=\"2\" />\n </IconPanel>\n {lastSession ? (\n <Flex direction=\"column\">\n <Text size=\"2\" weight=\"bold\">\n {getIdentityProviderName(identityProvider)}\n </Text>\n {relativeTimeString ? (\n <Text color=\"gray\" size=\"2\">\n <Translation\n defaultMessage=\"Last session {relativeTime}\"\n id=\"yN72Gc\"\n description=\"Label showing when the last SSO session occurred\"\n values={{ relativeTime: relativeTimeString }}\n />\n </Text>\n ) : null}\n </Flex>\n ) : (\n <Text size=\"2\" weight=\"bold\">\n {getIdentityProviderName(identityProvider)}\n </Text>\n )}\n </Flex>\n );\n}\n\nfunction AdminPortalOpenButton({\n isPending,\n href,\n initConfig,\n}: {\n isPending: boolean;\n href: string | null;\n initConfig: () => void;\n}) {\n const { connectionStatus } = useAdminPortalSsoConnectionContext();\n const label = (() => {\n switch (connectionStatus) {\n case \"NotConfigured\":\n return (\n <Translation\n defaultMessage=\"Set up SSO\"\n id=\"MtkNQO\"\n description=\"Button label to start SSO setup\"\n />\n );\n case \"Inactive\":\n return (\n <Translation\n defaultMessage=\"Continue setup\"\n id=\"HFxrbY\"\n description=\"Button label to continue incomplete SSO setup\"\n />\n );\n case \"Active\":\n case \"Expiring\":\n case \"Expired\":\n return (\n <Translation\n defaultMessage=\"Manage\"\n id=\"T1VKzP\"\n description=\"Button label to manage SSO settings\"\n />\n );\n default:\n return unreachable(connectionStatus);\n }\n })();\n\n if (href) {\n return (\n <Button variant=\"secondary\" asChild>\n <a href={href} target=\"_blank\" rel=\"noopener noreferrer\">\n {label} <ExternalLinkIcon aria-hidden />\n </a>\n </Button>\n );\n }\n\n return (\n <Button\n variant=\"secondary\"\n loading={isPending}\n disabled={isPending}\n onClick={initConfig}\n >\n {label} <ExternalLinkIcon aria-hidden />\n </Button>\n );\n}\n\ninterface AdminPortalSsoConnectionLoadingProps extends WidgetRootDomProps {}\n\nconst AdminPortalSsoConnectionLoading: React.FC<\n AdminPortalSsoConnectionLoadingProps\n> = (props) => {\n return (\n <Card size=\"2\" {...getWidgetRootDomProps(\"loading\", props)}>\n <Flex direction=\"row\" justify=\"between\" align=\"center\" gap=\"2\">\n <Flex gap=\"4\" align=\"center\">\n <Skeleton>\n <IconPanel color=\"panel\">\n <ProviderIcon provider=\"okta\" size=\"2\" />\n </IconPanel>\n </Skeleton>\n <Flex direction=\"column\" gap=\"1\" my=\"-4px\">\n <Skeleton>\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Text size=\"1\">Okta</Text>\n </Skeleton>\n <Skeleton>\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Text size=\"1\">Last session 10 minutes ago</Text>\n </Skeleton>\n </Flex>\n </Flex>\n <Flex gap=\"5\" align=\"center\">\n <Skeleton>\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Status state=\"error\">Requires action</Status>\n </Skeleton>\n <Skeleton>\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Button variant=\"secondary\">\n Manage <ExternalLinkIcon aria-hidden />\n </Button>\n </Skeleton>\n </Flex>\n </Flex>\n </Card>\n );\n};\n\ninterface AdminPortalSsoConnectionErrorProps extends WidgetRootDomProps {\n error: unknown;\n}\n\nconst AdminPortalSsoConnectionError: React.FC<\n AdminPortalSsoConnectionErrorProps\n> = ({ error, ...domProps }) => {\n const translate = useTranslation();\n React.useEffect(() => {\n console.error(error);\n }, [error]);\n\n const { heading, message } = getErrorMessage(error, translate);\n\n return (\n <Card size=\"2\" {...getWidgetRootDomProps(\"error\", domProps)}>\n <Flex direction=\"row\" justify=\"between\" align=\"center\" gap=\"2\">\n <Flex gap=\"4\" align=\"center\">\n <Flex\n align=\"center\"\n justify=\"center\"\n width=\"24px\"\n height=\"24px\"\n style={{\n borderRadius: \"9999px\",\n backgroundColor: \"var(--red-a4)\",\n color: \"var(--red-a11)\",\n flexShrink: 0,\n }}\n >\n <Cross2Icon width=\"18px\" height=\"18px\" />\n </Flex>\n <Flex direction=\"column\">\n <Text size=\"2\" weight=\"bold\">\n {heading}\n </Text>\n <Text size=\"2\" color=\"gray\">\n {message}\n </Text>\n </Flex>\n </Flex>\n </Flex>\n </Card>\n );\n};\n\nfunction getRelativeTimeString(\n currentDate: Date | null,\n lastSession: Date | null,\n) {\n if (!currentDate || !lastSession) {\n return null;\n }\n\n const rtf = new Intl.RelativeTimeFormat(\"en\", { numeric: \"auto\" });\n const diff = lastSession.getTime() - currentDate.getTime();\n\n const diffSeconds = Math.round(diff / 1000);\n const diffMinutes = Math.round(diffSeconds / 60);\n const diffHours = Math.round(diffMinutes / 60);\n const diffDays = Math.round(diffHours / 24);\n const diffMonths = Math.round(diffDays / 30);\n const diffYears = Math.round(diffMonths / 12);\n\n if (Math.abs(diffSeconds) < 60) {\n return \"now\";\n }\n\n if (Math.abs(diffMinutes) < 60) {\n return rtf.format(diffMinutes, \"minute\");\n }\n\n if (Math.abs(diffHours) < 24) {\n return rtf.format(diffHours, \"hour\");\n }\n\n if (Math.abs(diffDays) < 30) {\n return rtf.format(diffDays, \"day\");\n }\n\n if (Math.abs(diffMonths) < 12) {\n return rtf.format(diffMonths, \"month\");\n }\n\n return rtf.format(diffYears, \"year\");\n}\n\nfunction getWidgetRootDomProps(\n state: WidgetRootState,\n domProps: WidgetRootDomProps,\n) {\n return getDomProps({\n ...domProps,\n isWidgetRoot: true,\n widgetId: \"admin-portal-sso-connection\",\n widgetState: state,\n });\n}\n\nexport type {\n AdminPortalSsoConnectionProps,\n AdminPortalSsoConnectionLoadingProps,\n AdminPortalSsoConnectionErrorProps,\n};\nexport {\n AdminPortalSsoConnection,\n AdminPortalSsoConnectionLoading,\n AdminPortalSsoConnectionError,\n /** @internal */\n AdminPortalOpenButton,\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/admin-portal-sso-connection.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { Box, Card, Flex, Text } from \"@radix-ui/themes\";\nimport { Button, Skeleton } from \"./elements.js\";\nimport { IconPanel } from \"./icon-panel.js\";\nimport {\n ExternalLinkIcon,\n InfoCircledIcon,\n Cross2Icon,\n} from \"@radix-ui/react-icons\";\nimport * as CardList from \"./card-list.js\";\nimport { ProviderIcon } from \"./provider-icon.js\";\nimport {\n getIdentityProviderName,\n type IdentityProvider,\n} from \"./identity-providers.js\";\nimport { Status } from \"./status.js\";\nimport {\n getDomProps,\n unreachable,\n type WidgetRootState,\n type WidgetRootDomProps,\n} from \"./utils.js\";\nimport { Translation } from \"./i18n/translation.js\";\nimport { useTranslation } from \"./i18n/use-translation.js\";\nimport { getErrorMessage } from \"./generic-error.js\";\n\ninterface NotConfiguredProps {\n connectionStatus: \"NotConfigured\";\n identityProvider?: never;\n expiryDate?: never;\n}\n\ninterface InactiveProps {\n connectionStatus: \"Inactive\";\n identityProvider: IdentityProvider;\n expiryDate?: never;\n}\n\ninterface ActiveProps {\n connectionStatus: \"Active\";\n identityProvider: IdentityProvider;\n expiryDate?: never;\n}\n\ninterface RequiresActionProps {\n connectionStatus: \"Expired\" | \"Expiring\";\n identityProvider: IdentityProvider;\n expiryDate: Date | null;\n}\n\nexport type AdminPortalSsoConnectionStatusProps =\n | NotConfiguredProps\n | InactiveProps\n | ActiveProps\n | RequiresActionProps;\n\ntype AdminPortalSsoConnectionProps = WidgetRootDomProps &\n AdminPortalSsoConnectionStatusProps & {\n currentDate: Date | null;\n lastSession: Date | null;\n adminPortalOpenButton: React.ReactNode;\n };\n\ninterface AdminPortalSsoConnectionContextValue {\n connectionStatus: AdminPortalSsoConnectionStatusProps[\"connectionStatus\"];\n}\n\nconst AdminPortalSsoConnectionContext =\n React.createContext<AdminPortalSsoConnectionContextValue | null>(null);\nAdminPortalSsoConnectionContext.displayName = \"AdminPortalSsoConnectionContext\";\n\nfunction useAdminPortalSsoConnectionContext() {\n const context = React.useContext(AdminPortalSsoConnectionContext);\n if (!context) {\n throw new Error(\n \"useAdminPortalSsoConnectionContext must be used within a AdminPortalSsoConnectionContext provider\",\n );\n }\n return context;\n}\n\nconst AdminPortalSsoConnection: React.FC<AdminPortalSsoConnectionProps> = ({\n currentDate,\n connectionStatus,\n identityProvider,\n expiryDate,\n lastSession,\n adminPortalOpenButton,\n ...domProps\n}) => {\n return (\n <CardList.Root size=\"2\" {...getWidgetRootDomProps(\"resolved\", domProps)}>\n <AdminPortalSsoConnectionContext.Provider value={{ connectionStatus }}>\n <CardList.Item>\n <Flex direction=\"row\" justify=\"between\" align=\"center\" gap=\"2\">\n {(() => {\n if (connectionStatus === \"NotConfigured\") {\n return (\n <>\n <Text size=\"2\" color=\"gray\">\n <Translation\n defaultMessage=\"You haven't set up Single Sign-On yet.\"\n id=\"KDs1Ib\"\n description=\"Empty state message when SSO is not configured\"\n />\n </Text>\n {adminPortalOpenButton}\n </>\n );\n }\n\n return (\n <>\n <SessionInfo\n connectionStatus={connectionStatus}\n identityProvider={identityProvider}\n lastSession={lastSession}\n currentDate={currentDate}\n />\n <Flex gap=\"5\" align=\"center\">\n <SsoStatus status={connectionStatus} />\n {adminPortalOpenButton}\n </Flex>\n </>\n );\n })()}\n </Flex>\n </CardList.Item>\n {connectionStatus === \"Expired\" && (\n <CardList.Item>\n <Flex align=\"start\" gap=\"2\">\n <Box asChild mt=\"2px\" flexShrink=\"0\">\n <InfoCircledIcon color=\"gray\" />\n </Box>\n {(() => {\n if (connectionStatus === \"Expired\") {\n return (\n <Text size=\"2\" color=\"gray\">\n {(() => {\n if (!expiryDate) {\n return (\n <Translation\n defaultMessage=\"The SAML response signing certificate has expired. Users won't be able to sign-in to the application until the certificate is renewed.\"\n id=\"5tX19v\"\n description=\"Error message when SAML certificate has expired (no date)\"\n />\n );\n }\n\n return (\n <Translation\n defaultMessage=\"The SAML response signing certificate expired on {expiryDate}. Users won't be able to sign-in to the application until the certificate is renewed.\"\n id=\"vmTW/h\"\n description=\"Error message when SAML certificate has expired with date\"\n values={{\n expiryDate: (\n <Text weight=\"bold\" as=\"span\">\n {expiryDate?.toLocaleString(\"en-US\", {\n month: \"long\",\n day: \"numeric\",\n year: \"numeric\",\n })}\n </Text>\n ),\n }}\n />\n );\n })()}\n </Text>\n );\n }\n\n if (connectionStatus === \"Expiring\") {\n return (\n <Text size=\"2\" color=\"gray\">\n {(() => {\n if (!expiryDate) {\n return (\n <Translation\n defaultMessage=\"The SAML response signing certificate is expiring soon. When expired, users won't be able to sign-in.\"\n id=\"3dgA5f\"\n description=\"Warning message when SAML certificate is expiring soon (no date)\"\n />\n );\n }\n\n return (\n <Translation\n defaultMessage=\"The SAML response signing certificate will expire on {expiryDate}. When expired, users won't be able to sign-in.\"\n id=\"xT9Exy\"\n description=\"Warning message when SAML certificate is expiring with date\"\n values={{\n expiryDate: (\n <Text weight=\"bold\" as=\"span\">\n {expiryDate?.toLocaleString(\"en-US\", {\n month: \"long\",\n day: \"numeric\",\n year: \"numeric\",\n })}\n </Text>\n ),\n }}\n />\n );\n })()}\n </Text>\n );\n }\n })()}\n </Flex>\n </CardList.Item>\n )}\n </AdminPortalSsoConnectionContext.Provider>\n </CardList.Root>\n );\n};\n\nfunction SsoStatus({\n status,\n}: {\n status: AdminPortalSsoConnectionStatusProps[\"connectionStatus\"];\n}) {\n if (status === \"NotConfigured\") {\n return null;\n }\n\n if (status === \"Inactive\") {\n return (\n <Status state=\"waiting\">\n <Translation\n defaultMessage=\"Setup in progress\"\n id=\"MQR5mR\"\n description=\"Status label when SSO setup is incomplete\"\n />\n </Status>\n );\n }\n\n if (status === \"Expired\") {\n return (\n <Status state=\"error\">\n <Translation\n defaultMessage=\"Requires action\"\n id=\"Yo2vHC\"\n description=\"Status label when SSO requires attention\"\n />\n </Status>\n );\n }\n\n if (status === \"Active\" || status === \"Expiring\") {\n return (\n <Status state=\"success\">\n <Translation\n defaultMessage=\"Connected\"\n id=\"8S+Cyw\"\n description=\"Status label when SSO is active\"\n />\n </Status>\n );\n }\n\n return unreachable(status);\n}\n\nfunction SessionInfo({\n currentDate,\n identityProvider,\n lastSession,\n connectionStatus,\n}: {\n identityProvider: IdentityProvider;\n lastSession: Date | null;\n currentDate: Date | null;\n connectionStatus: AdminPortalSsoConnectionStatusProps[\"connectionStatus\"];\n}) {\n const relativeTimeString = React.useMemo(() => {\n if (\n !lastSession ||\n !currentDate ||\n connectionStatus === \"NotConfigured\" ||\n connectionStatus === \"Inactive\"\n ) {\n return null;\n }\n\n return getRelativeTimeString(currentDate, lastSession);\n }, [lastSession, currentDate, connectionStatus]);\n\n return (\n <Flex gap=\"4\" align=\"center\">\n <IconPanel color=\"panel\">\n <ProviderIcon provider={identityProvider} size=\"2\" />\n </IconPanel>\n {lastSession ? (\n <Flex direction=\"column\">\n <Text size=\"2\" weight=\"bold\">\n {getIdentityProviderName(identityProvider)}\n </Text>\n {relativeTimeString ? (\n <Text color=\"gray\" size=\"2\">\n <Translation\n defaultMessage=\"Last session {relativeTime}\"\n id=\"yN72Gc\"\n description=\"Label showing when the last SSO session occurred\"\n values={{ relativeTime: relativeTimeString }}\n />\n </Text>\n ) : null}\n </Flex>\n ) : (\n <Text size=\"2\" weight=\"bold\">\n {getIdentityProviderName(identityProvider)}\n </Text>\n )}\n </Flex>\n );\n}\n\nfunction AdminPortalOpenButton({\n isPending,\n initConfig,\n}: {\n isPending: boolean;\n initConfig: () => void;\n}) {\n const { connectionStatus } = useAdminPortalSsoConnectionContext();\n const label = (() => {\n switch (connectionStatus) {\n case \"NotConfigured\":\n return (\n <Translation\n defaultMessage=\"Set up SSO\"\n id=\"MtkNQO\"\n description=\"Button label to start SSO setup\"\n />\n );\n case \"Inactive\":\n return (\n <Translation\n defaultMessage=\"Continue setup\"\n id=\"HFxrbY\"\n description=\"Button label to continue incomplete SSO setup\"\n />\n );\n case \"Active\":\n case \"Expiring\":\n case \"Expired\":\n return (\n <Translation\n defaultMessage=\"Manage\"\n id=\"T1VKzP\"\n description=\"Button label to manage SSO settings\"\n />\n );\n default:\n return unreachable(connectionStatus);\n }\n })();\n\n return (\n <Button\n variant=\"secondary\"\n loading={isPending}\n disabled={isPending}\n onClick={initConfig}\n >\n {label} <ExternalLinkIcon aria-hidden />\n </Button>\n );\n}\n\ninterface AdminPortalSsoConnectionLoadingProps extends WidgetRootDomProps {}\n\nconst AdminPortalSsoConnectionLoading: React.FC<\n AdminPortalSsoConnectionLoadingProps\n> = (props) => {\n return (\n <Card size=\"2\" {...getWidgetRootDomProps(\"loading\", props)}>\n <Flex direction=\"row\" justify=\"between\" align=\"center\" gap=\"2\">\n <Flex gap=\"4\" align=\"center\">\n <Skeleton>\n <IconPanel color=\"panel\">\n <ProviderIcon provider=\"okta\" size=\"2\" />\n </IconPanel>\n </Skeleton>\n <Flex direction=\"column\" gap=\"1\" my=\"-4px\">\n <Skeleton>\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Text size=\"1\">Okta</Text>\n </Skeleton>\n <Skeleton>\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Text size=\"1\">Last session 10 minutes ago</Text>\n </Skeleton>\n </Flex>\n </Flex>\n <Flex gap=\"5\" align=\"center\">\n <Skeleton>\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Status state=\"error\">Requires action</Status>\n </Skeleton>\n <Skeleton>\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Button variant=\"secondary\">\n Manage <ExternalLinkIcon aria-hidden />\n </Button>\n </Skeleton>\n </Flex>\n </Flex>\n </Card>\n );\n};\n\ninterface AdminPortalSsoConnectionErrorProps extends WidgetRootDomProps {\n error: unknown;\n}\n\nconst AdminPortalSsoConnectionError: React.FC<\n AdminPortalSsoConnectionErrorProps\n> = ({ error, ...domProps }) => {\n const translate = useTranslation();\n React.useEffect(() => {\n console.error(error);\n }, [error]);\n\n const { heading, message } = getErrorMessage(error, translate);\n\n return (\n <Card size=\"2\" {...getWidgetRootDomProps(\"error\", domProps)}>\n <Flex direction=\"row\" justify=\"between\" align=\"center\" gap=\"2\">\n <Flex gap=\"4\" align=\"center\">\n <Flex\n align=\"center\"\n justify=\"center\"\n width=\"24px\"\n height=\"24px\"\n style={{\n borderRadius: \"9999px\",\n backgroundColor: \"var(--red-a4)\",\n color: \"var(--red-a11)\",\n flexShrink: 0,\n }}\n >\n <Cross2Icon width=\"18px\" height=\"18px\" />\n </Flex>\n <Flex direction=\"column\">\n <Text size=\"2\" weight=\"bold\">\n {heading}\n </Text>\n <Text size=\"2\" color=\"gray\">\n {message}\n </Text>\n </Flex>\n </Flex>\n </Flex>\n </Card>\n );\n};\n\nfunction getRelativeTimeString(\n currentDate: Date | null,\n lastSession: Date | null,\n) {\n if (!currentDate || !lastSession) {\n return null;\n }\n\n const rtf = new Intl.RelativeTimeFormat(\"en\", { numeric: \"auto\" });\n const diff = lastSession.getTime() - currentDate.getTime();\n\n const diffSeconds = Math.round(diff / 1000);\n const diffMinutes = Math.round(diffSeconds / 60);\n const diffHours = Math.round(diffMinutes / 60);\n const diffDays = Math.round(diffHours / 24);\n const diffMonths = Math.round(diffDays / 30);\n const diffYears = Math.round(diffMonths / 12);\n\n if (Math.abs(diffSeconds) < 60) {\n return \"now\";\n }\n\n if (Math.abs(diffMinutes) < 60) {\n return rtf.format(diffMinutes, \"minute\");\n }\n\n if (Math.abs(diffHours) < 24) {\n return rtf.format(diffHours, \"hour\");\n }\n\n if (Math.abs(diffDays) < 30) {\n return rtf.format(diffDays, \"day\");\n }\n\n if (Math.abs(diffMonths) < 12) {\n return rtf.format(diffMonths, \"month\");\n }\n\n return rtf.format(diffYears, \"year\");\n}\n\nfunction getWidgetRootDomProps(\n state: WidgetRootState,\n domProps: WidgetRootDomProps,\n) {\n return getDomProps({\n ...domProps,\n isWidgetRoot: true,\n widgetId: \"admin-portal-sso-connection\",\n widgetState: state,\n });\n}\n\nexport type {\n AdminPortalSsoConnectionProps,\n AdminPortalSsoConnectionLoadingProps,\n AdminPortalSsoConnectionErrorProps,\n};\nexport {\n AdminPortalSsoConnection,\n AdminPortalSsoConnectionLoading,\n AdminPortalSsoConnectionError,\n /** @internal */\n AdminPortalOpenButton,\n};\n"],"mappings":"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","names":[]}
|
|
@@ -26,7 +26,7 @@ const ApiKeysContextProvider = ({ children }) => {
|
|
|
26
26
|
return /* @__PURE__ */ jsx(ApiKeysContext.Provider, { value: context, children });
|
|
27
27
|
};
|
|
28
28
|
const NOOP = () => void 0;
|
|
29
|
-
const EMPTY_PAGINATION = {};
|
|
29
|
+
const EMPTY_PAGINATION = { before: null, after: null };
|
|
30
30
|
function useApiKeysContext(initialContext) {
|
|
31
31
|
const context = React.useContext(ApiKeysContext);
|
|
32
32
|
if (context) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/api-keys/api-keys-context.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport {\n ApiKeysAction,\n ApiKeysState,\n useApiKeysState,\n} from \"./api-keys-state.js\";\nimport { ListMetadata } from \"../../api/endpoint.js\";\n\nexport interface ApiKeysContextType {\n state: ApiKeysState;\n dispatch: React.Dispatch<ApiKeysAction>;\n}\n\nconst ApiKeysContext = React.createContext<ApiKeysContextType | undefined>(\n undefined,\n);\nApiKeysContext.displayName = \"ApiKeysContext\";\n\nconst initialState: ApiKeysState = {\n pagination: null,\n searchQuery: null,\n createDialogOpen: false,\n createdApiKey: null,\n};\n\nexport const ApiKeysContextProvider: React.FC<{\n children?: React.ReactNode;\n}> = ({ children }) => {\n const [state, dispatch] = useApiKeysState(initialState);\n\n const context = React.useMemo<ApiKeysContextType>(\n () => ({\n state,\n dispatch,\n }),\n [state, dispatch],\n );\n\n return (\n <ApiKeysContext.Provider value={context}>\n {children}\n </ApiKeysContext.Provider>\n );\n};\n\nconst NOOP = () => void 0;\nconst EMPTY_PAGINATION: ListMetadata = {};\n\n/**\n * The context may be provided if it is instantiated in the tree above the user.\n */\nexport function useApiKeysContext(\n initialContext?: ApiKeysContextType | null,\n): ApiKeysContextType {\n const context = React.useContext(ApiKeysContext);\n\n if (context) {\n return context;\n }\n\n if (initialContext) {\n return initialContext;\n }\n\n return {\n dispatch: NOOP,\n state: {\n pagination: EMPTY_PAGINATION,\n searchQuery: null,\n createDialogOpen: false,\n createdApiKey: null,\n },\n };\n}\n"],"mappings":";AAyCI;AAvCJ,YAAY,WAAW;AACvB;AAAA,EAGE;AAAA,OACK;AAQP,MAAM,iBAAiB,MAAM;AAAA,EAC3B;AACF;AACA,eAAe,cAAc;AAE7B,MAAM,eAA6B;AAAA,EACjC,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,kBAAkB;AAAA,EAClB,eAAe;AACjB;AAEO,MAAM,yBAER,CAAC,EAAE,SAAS,MAAM;AACrB,QAAM,CAAC,OAAO,QAAQ,IAAI,gBAAgB,YAAY;AAEtD,QAAM,UAAU,MAAM;AAAA,IACpB,OAAO;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,OAAO,QAAQ;AAAA,EAClB;AAEA,SACE,oBAAC,eAAe,UAAf,EAAwB,OAAO,SAC7B,UACH;AAEJ;AAEA,MAAM,OAAO,MAAM;AACnB,MAAM,mBAAiC,
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/api-keys/api-keys-context.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport {\n ApiKeysAction,\n ApiKeysState,\n useApiKeysState,\n} from \"./api-keys-state.js\";\nimport { ListMetadata } from \"../../api/endpoint.js\";\n\nexport interface ApiKeysContextType {\n state: ApiKeysState;\n dispatch: React.Dispatch<ApiKeysAction>;\n}\n\nconst ApiKeysContext = React.createContext<ApiKeysContextType | undefined>(\n undefined,\n);\nApiKeysContext.displayName = \"ApiKeysContext\";\n\nconst initialState: ApiKeysState = {\n pagination: null,\n searchQuery: null,\n createDialogOpen: false,\n createdApiKey: null,\n};\n\nexport const ApiKeysContextProvider: React.FC<{\n children?: React.ReactNode;\n}> = ({ children }) => {\n const [state, dispatch] = useApiKeysState(initialState);\n\n const context = React.useMemo<ApiKeysContextType>(\n () => ({\n state,\n dispatch,\n }),\n [state, dispatch],\n );\n\n return (\n <ApiKeysContext.Provider value={context}>\n {children}\n </ApiKeysContext.Provider>\n );\n};\n\nconst NOOP = () => void 0;\nconst EMPTY_PAGINATION: ListMetadata = { before: null, after: null };\n\n/**\n * The context may be provided if it is instantiated in the tree above the user.\n */\nexport function useApiKeysContext(\n initialContext?: ApiKeysContextType | null,\n): ApiKeysContextType {\n const context = React.useContext(ApiKeysContext);\n\n if (context) {\n return context;\n }\n\n if (initialContext) {\n return initialContext;\n }\n\n return {\n dispatch: NOOP,\n state: {\n pagination: EMPTY_PAGINATION,\n searchQuery: null,\n createDialogOpen: false,\n createdApiKey: null,\n },\n };\n}\n"],"mappings":";AAyCI;AAvCJ,YAAY,WAAW;AACvB;AAAA,EAGE;AAAA,OACK;AAQP,MAAM,iBAAiB,MAAM;AAAA,EAC3B;AACF;AACA,eAAe,cAAc;AAE7B,MAAM,eAA6B;AAAA,EACjC,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,kBAAkB;AAAA,EAClB,eAAe;AACjB;AAEO,MAAM,yBAER,CAAC,EAAE,SAAS,MAAM;AACrB,QAAM,CAAC,OAAO,QAAQ,IAAI,gBAAgB,YAAY;AAEtD,QAAM,UAAU,MAAM;AAAA,IACpB,OAAO;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,OAAO,QAAQ;AAAA,EAClB;AAEA,SACE,oBAAC,eAAe,UAAf,EAAwB,OAAO,SAC7B,UACH;AAEJ;AAEA,MAAM,OAAO,MAAM;AACnB,MAAM,mBAAiC,EAAE,QAAQ,MAAM,OAAO,KAAK;AAK5D,SAAS,kBACd,gBACoB;AACpB,QAAM,UAAU,MAAM,WAAW,cAAc;AAE/C,MAAI,SAAS;AACX,WAAO;AAAA,EACT;AAEA,MAAI,gBAAgB;AAClB,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,UAAU;AAAA,IACV,OAAO;AAAA,MACL,YAAY;AAAA,MACZ,aAAa;AAAA,MACb,kBAAkB;AAAA,MAClB,eAAe;AAAA,IACjB;AAAA,EACF;AACF;","names":[]}
|
|
@@ -14,6 +14,7 @@ import { ApiKeysSearch } from "./api-keys-search.js";
|
|
|
14
14
|
import { Translation } from "../i18n/translation.js";
|
|
15
15
|
import { useTranslation } from "../i18n/use-translation.js";
|
|
16
16
|
import { useLocale } from "../i18n/use-locale.js";
|
|
17
|
+
import { getListMetadata } from "../utils.js";
|
|
17
18
|
function NoApiKeys() {
|
|
18
19
|
const { clearSearch } = useApiKeysSearchContext();
|
|
19
20
|
return /* @__PURE__ */ jsxs(Flex, { p: "6", gap: "4", justify: "center", align: "center", direction: "column", children: [
|
|
@@ -142,9 +143,10 @@ function ApiKeysTable({
|
|
|
142
143
|
apiKeys
|
|
143
144
|
}) {
|
|
144
145
|
const { dispatch } = useApiKeysContext();
|
|
145
|
-
const
|
|
146
|
-
const
|
|
147
|
-
const
|
|
146
|
+
const pagination = getListMetadata(apiKeys);
|
|
147
|
+
const hasPagination = !!(pagination.before || pagination.after);
|
|
148
|
+
const hasPreviousPage = !!pagination.after;
|
|
149
|
+
const hasNextPage = !!pagination.before;
|
|
148
150
|
return /* @__PURE__ */ jsxs(Flex, { direction: "column", align: "stretch", gap: "3", children: [
|
|
149
151
|
/* @__PURE__ */ jsx(ApiKeysTableHeader, {}),
|
|
150
152
|
apiKeys.data.length === 0 ? /* @__PURE__ */ jsx(NoApiKeys, {}) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -195,7 +197,7 @@ function ApiKeysTable({
|
|
|
195
197
|
size: "1",
|
|
196
198
|
onClick: () => dispatch({
|
|
197
199
|
type: "SET_PAGINATION",
|
|
198
|
-
pagination
|
|
200
|
+
pagination
|
|
199
201
|
}),
|
|
200
202
|
children: /* @__PURE__ */ jsx(
|
|
201
203
|
Translation,
|
|
@@ -215,7 +217,7 @@ function ApiKeysTable({
|
|
|
215
217
|
size: "1",
|
|
216
218
|
onClick: () => dispatch({
|
|
217
219
|
type: "SET_PAGINATION",
|
|
218
|
-
pagination
|
|
220
|
+
pagination
|
|
219
221
|
}),
|
|
220
222
|
children: /* @__PURE__ */ jsx(
|
|
221
223
|
Translation,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/api-keys/api-keys-table.tsx"],"sourcesContent":["import { Flex, Text, Table, Code, Heading } from \"@radix-ui/themes\";\nimport { Button, DropdownMenu, IconButton } from \"../elements.js\";\nimport { DotsHorizontalIcon, MagnifyingGlassIcon } from \"@radix-ui/react-icons\";\nimport { useState } from \"react\";\nimport { RevokeApiKeyDialog } from \"./revoke-api-key-dialog.js\";\nimport { CreateApiKeyButton } from \"./create-api-key.js\";\nimport { ApiKeyDetailsDialog } from \"./api-key-details-dialog.js\";\nimport { useIsHydrated } from \"../use-is-hydrated.js\";\nimport { RelativeTime } from \"./relative-time.js\";\nimport {\n ListOrganizationApiKeysResponse,\n ListOrganizationApiKeysResponseData,\n} from \"../../api/endpoint.js\";\nimport { useApiKeysContext } from \"./api-keys-context.js\";\nimport { useApiKeysSearchContext } from \"./api-keys-search-provider.js\";\nimport { ApiKeysSearch } from \"./api-keys-search.js\";\nimport { Translation } from \"../i18n/translation.js\";\nimport { useTranslation } from \"../i18n/use-translation.js\";\nimport { useLocale } from \"../i18n/use-locale.js\";\n\nfunction NoApiKeys() {\n const { clearSearch } = useApiKeysSearchContext();\n return (\n <Flex p=\"6\" gap=\"4\" justify=\"center\" align=\"center\" direction=\"column\">\n <Flex direction=\"column\" gap=\"1\" maxWidth=\"420px\" align=\"center\">\n <MagnifyingGlassIcon\n style={{ color: \"var(--gray-9)\" }}\n width=\"32px\"\n height=\"32px\"\n />\n <Heading size=\"5\" mb=\"1\" wrap=\"balance\" as=\"h3\">\n <Translation\n defaultMessage=\"No API keys match your search\"\n id=\"cKitHb\"\n description=\"Empty state message when no API keys match search\"\n />\n </Heading>\n </Flex>\n\n <Button variant=\"secondary\" onClick={clearSearch}>\n <Translation\n defaultMessage=\"Clear search\"\n id=\"jTupOW\"\n description=\"Button to clear API key search filters\"\n />\n </Button>\n </Flex>\n );\n}\n\nfunction ApiKeysTableHeader() {\n return (\n <Flex justify=\"between\" align=\"center\">\n <ApiKeysSearch name=\"api-keys-widget-search\" style={{ width: \"390px\" }} />\n <CreateApiKeyButton />\n </Flex>\n );\n}\n\nfunction CreatedOn({ createdOn }: { createdOn: Date }) {\n const isHydrated = useIsHydrated();\n const locale = useLocale();\n return (\n <>\n {createdOn.toLocaleDateString(locale, {\n timeZone: isHydrated ? undefined : \"UTC\",\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n })}\n </>\n );\n}\n\ninterface ApiKeyRowProps {\n apiKey: ListOrganizationApiKeysResponseData;\n}\n\nfunction ApiKeyRow({ apiKey }: ApiKeyRowProps) {\n const [revokeDialogOpen, setRevokeDialogOpen] = useState(false);\n const [detailsOpen, setDetailsOpen] = useState(false);\n const translate = useTranslation();\n return (\n <>\n <RevokeApiKeyDialog\n // always remount the form when the dialog is opened to reset the validation errors\n key={`${revokeDialogOpen}`}\n open={revokeDialogOpen}\n onOpenChange={setRevokeDialogOpen}\n apiKey={apiKey}\n />\n <ApiKeyDetailsDialog\n open={detailsOpen}\n onOpenChange={setDetailsOpen}\n apiKey={apiKey}\n permissions={apiKey.permissions}\n />\n <Table.Row align=\"center\">\n <Table.Cell>\n <Text>{apiKey.name}</Text>\n </Table.Cell>\n <Table.Cell>\n <Code color=\"gray\">{apiKey.obfuscatedValue}</Code>\n </Table.Cell>\n <Table.Cell>\n <Text\n style={apiKey.lastUsedAt ? undefined : { color: \"var(--gray-10)\" }}\n >\n <RelativeTime\n date={apiKey.lastUsedAt ? new Date(apiKey.lastUsedAt) : undefined}\n />\n </Text>\n </Table.Cell>\n <Table.Cell>\n <Text>\n <CreatedOn createdOn={new Date(apiKey.createdAt)} />\n </Text>\n </Table.Cell>\n <Table.Cell justify=\"end\">\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>\n {(() => {\n const title = translate({\n defaultMessage: \"API key actions\",\n id: \"RIBfYe\",\n description: \"Tooltip for API key actions menu button\",\n });\n return (\n <IconButton title={title}>\n <DotsHorizontalIcon />\n </IconButton>\n );\n })()}\n </DropdownMenu.Trigger>\n <DropdownMenu.Content size=\"2\" align=\"end\">\n <DropdownMenu.Item onSelect={() => setDetailsOpen(true)}>\n <Translation\n defaultMessage=\"View details\"\n id=\"VGKbbj\"\n description=\"Menu item to view API key details\"\n />\n </DropdownMenu.Item>\n <DropdownMenu.Item\n variant=\"destructive\"\n onSelect={() => setRevokeDialogOpen(true)}\n >\n <Translation\n defaultMessage=\"Revoke key\"\n id=\"KZIJPP\"\n description=\"Menu item to revoke an API key\"\n />\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n </Table.Cell>\n </Table.Row>\n </>\n );\n}\n\nexport function ApiKeysTable({\n apiKeys,\n}: {\n apiKeys: ListOrganizationApiKeysResponse;\n}) {\n const { dispatch } = useApiKeysContext();\n const hasPagination =\n apiKeys.listMetadata.before || apiKeys.listMetadata.after;\n const hasPreviousPage = apiKeys.listMetadata.after;\n const hasNextPage = apiKeys.listMetadata.before;\n\n return (\n <Flex direction=\"column\" align=\"stretch\" gap=\"3\">\n <ApiKeysTableHeader />\n {apiKeys.data.length === 0 ? (\n <NoApiKeys />\n ) : (\n <>\n <Table.Root variant=\"ghost\" size=\"2\">\n <Table.Header>\n <Table.Row>\n <Table.ColumnHeaderCell width=\"25%\">\n <Translation\n defaultMessage=\"Name\"\n id=\"VYbVXN\"\n description=\"Table column header for API key name\"\n />\n </Table.ColumnHeaderCell>\n <Table.ColumnHeaderCell width=\"25%\">\n <Translation\n defaultMessage=\"Secret key\"\n id=\"H5k7GB\"\n description=\"Table column header for API key secret value\"\n />\n </Table.ColumnHeaderCell>\n <Table.ColumnHeaderCell width=\"25%\">\n <Translation\n defaultMessage=\"Last used\"\n id=\"E46t3O\"\n description=\"Table column header for API key last used timestamp\"\n />\n </Table.ColumnHeaderCell>\n <Table.ColumnHeaderCell width=\"25%\">\n <Translation\n defaultMessage=\"Created\"\n id=\"CXHhXd\"\n description=\"Table column header for API key creation date\"\n />\n </Table.ColumnHeaderCell>\n <Table.ColumnHeaderCell width=\"28px\" />\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {apiKeys.data.map((apiKey) => (\n <ApiKeyRow key={apiKey.id} apiKey={apiKey} />\n ))}\n </Table.Body>\n </Table.Root>\n {hasPagination && (\n <Flex gap=\"2\" justify=\"end\">\n <Button\n variant=\"secondary\"\n disabled={!hasPreviousPage}\n size=\"1\"\n onClick={() =>\n dispatch({\n type: \"SET_PAGINATION\",\n pagination: { after: apiKeys.listMetadata.after },\n })\n }\n >\n <Translation\n defaultMessage=\"Previous\"\n id=\"f7TUj0\"\n description=\"Button to navigate to previous page of API keys\"\n />\n </Button>\n <Button\n variant=\"secondary\"\n disabled={!hasNextPage}\n size=\"1\"\n onClick={() =>\n dispatch({\n type: \"SET_PAGINATION\",\n pagination: { before: apiKeys.listMetadata.before },\n })\n }\n >\n <Translation\n defaultMessage=\"Next\"\n id=\"L2EBxV\"\n description=\"Button to navigate to next page of API keys\"\n />\n </Button>\n </Flex>\n )}\n </>\n )}\n </Flex>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/api-keys/api-keys-table.tsx"],"sourcesContent":["import { Flex, Text, Table, Code, Heading } from \"@radix-ui/themes\";\nimport { Button, DropdownMenu, IconButton } from \"../elements.js\";\nimport { DotsHorizontalIcon, MagnifyingGlassIcon } from \"@radix-ui/react-icons\";\nimport { useState } from \"react\";\nimport { RevokeApiKeyDialog } from \"./revoke-api-key-dialog.js\";\nimport { CreateApiKeyButton } from \"./create-api-key.js\";\nimport { ApiKeyDetailsDialog } from \"./api-key-details-dialog.js\";\nimport { useIsHydrated } from \"../use-is-hydrated.js\";\nimport { RelativeTime } from \"./relative-time.js\";\nimport {\n ListOrganizationApiKeysResponse,\n ListOrganizationApiKeysResponseData,\n} from \"../../api/endpoint.js\";\nimport { useApiKeysContext } from \"./api-keys-context.js\";\nimport { useApiKeysSearchContext } from \"./api-keys-search-provider.js\";\nimport { ApiKeysSearch } from \"./api-keys-search.js\";\nimport { Translation } from \"../i18n/translation.js\";\nimport { useTranslation } from \"../i18n/use-translation.js\";\nimport { useLocale } from \"../i18n/use-locale.js\";\nimport { getListMetadata } from \"../utils.js\";\n\nfunction NoApiKeys() {\n const { clearSearch } = useApiKeysSearchContext();\n return (\n <Flex p=\"6\" gap=\"4\" justify=\"center\" align=\"center\" direction=\"column\">\n <Flex direction=\"column\" gap=\"1\" maxWidth=\"420px\" align=\"center\">\n <MagnifyingGlassIcon\n style={{ color: \"var(--gray-9)\" }}\n width=\"32px\"\n height=\"32px\"\n />\n <Heading size=\"5\" mb=\"1\" wrap=\"balance\" as=\"h3\">\n <Translation\n defaultMessage=\"No API keys match your search\"\n id=\"cKitHb\"\n description=\"Empty state message when no API keys match search\"\n />\n </Heading>\n </Flex>\n\n <Button variant=\"secondary\" onClick={clearSearch}>\n <Translation\n defaultMessage=\"Clear search\"\n id=\"jTupOW\"\n description=\"Button to clear API key search filters\"\n />\n </Button>\n </Flex>\n );\n}\n\nfunction ApiKeysTableHeader() {\n return (\n <Flex justify=\"between\" align=\"center\">\n <ApiKeysSearch name=\"api-keys-widget-search\" style={{ width: \"390px\" }} />\n <CreateApiKeyButton />\n </Flex>\n );\n}\n\nfunction CreatedOn({ createdOn }: { createdOn: Date }) {\n const isHydrated = useIsHydrated();\n const locale = useLocale();\n return (\n <>\n {createdOn.toLocaleDateString(locale, {\n timeZone: isHydrated ? undefined : \"UTC\",\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n })}\n </>\n );\n}\n\ninterface ApiKeyRowProps {\n apiKey: ListOrganizationApiKeysResponseData;\n}\n\nfunction ApiKeyRow({ apiKey }: ApiKeyRowProps) {\n const [revokeDialogOpen, setRevokeDialogOpen] = useState(false);\n const [detailsOpen, setDetailsOpen] = useState(false);\n const translate = useTranslation();\n return (\n <>\n <RevokeApiKeyDialog\n // always remount the form when the dialog is opened to reset the validation errors\n key={`${revokeDialogOpen}`}\n open={revokeDialogOpen}\n onOpenChange={setRevokeDialogOpen}\n apiKey={apiKey}\n />\n <ApiKeyDetailsDialog\n open={detailsOpen}\n onOpenChange={setDetailsOpen}\n apiKey={apiKey}\n permissions={apiKey.permissions}\n />\n <Table.Row align=\"center\">\n <Table.Cell>\n <Text>{apiKey.name}</Text>\n </Table.Cell>\n <Table.Cell>\n <Code color=\"gray\">{apiKey.obfuscatedValue}</Code>\n </Table.Cell>\n <Table.Cell>\n <Text\n style={apiKey.lastUsedAt ? undefined : { color: \"var(--gray-10)\" }}\n >\n <RelativeTime\n date={apiKey.lastUsedAt ? new Date(apiKey.lastUsedAt) : undefined}\n />\n </Text>\n </Table.Cell>\n <Table.Cell>\n <Text>\n <CreatedOn createdOn={new Date(apiKey.createdAt)} />\n </Text>\n </Table.Cell>\n <Table.Cell justify=\"end\">\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>\n {(() => {\n const title = translate({\n defaultMessage: \"API key actions\",\n id: \"RIBfYe\",\n description: \"Tooltip for API key actions menu button\",\n });\n return (\n <IconButton title={title}>\n <DotsHorizontalIcon />\n </IconButton>\n );\n })()}\n </DropdownMenu.Trigger>\n <DropdownMenu.Content size=\"2\" align=\"end\">\n <DropdownMenu.Item onSelect={() => setDetailsOpen(true)}>\n <Translation\n defaultMessage=\"View details\"\n id=\"VGKbbj\"\n description=\"Menu item to view API key details\"\n />\n </DropdownMenu.Item>\n <DropdownMenu.Item\n variant=\"destructive\"\n onSelect={() => setRevokeDialogOpen(true)}\n >\n <Translation\n defaultMessage=\"Revoke key\"\n id=\"KZIJPP\"\n description=\"Menu item to revoke an API key\"\n />\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n </Table.Cell>\n </Table.Row>\n </>\n );\n}\n\nexport function ApiKeysTable({\n apiKeys,\n}: {\n apiKeys: ListOrganizationApiKeysResponse;\n}) {\n const { dispatch } = useApiKeysContext();\n\n // The API response previously returned an object with the `listMetadata`\n // property. We might not need this, but it's a defensive check until we\n // verify the API response changes are correct.\n const pagination = getListMetadata(apiKeys);\n\n const hasPagination = !!(pagination.before || pagination.after);\n const hasPreviousPage = !!pagination.after;\n const hasNextPage = !!pagination.before;\n\n return (\n <Flex direction=\"column\" align=\"stretch\" gap=\"3\">\n <ApiKeysTableHeader />\n {apiKeys.data.length === 0 ? (\n <NoApiKeys />\n ) : (\n <>\n <Table.Root variant=\"ghost\" size=\"2\">\n <Table.Header>\n <Table.Row>\n <Table.ColumnHeaderCell width=\"25%\">\n <Translation\n defaultMessage=\"Name\"\n id=\"VYbVXN\"\n description=\"Table column header for API key name\"\n />\n </Table.ColumnHeaderCell>\n <Table.ColumnHeaderCell width=\"25%\">\n <Translation\n defaultMessage=\"Secret key\"\n id=\"H5k7GB\"\n description=\"Table column header for API key secret value\"\n />\n </Table.ColumnHeaderCell>\n <Table.ColumnHeaderCell width=\"25%\">\n <Translation\n defaultMessage=\"Last used\"\n id=\"E46t3O\"\n description=\"Table column header for API key last used timestamp\"\n />\n </Table.ColumnHeaderCell>\n <Table.ColumnHeaderCell width=\"25%\">\n <Translation\n defaultMessage=\"Created\"\n id=\"CXHhXd\"\n description=\"Table column header for API key creation date\"\n />\n </Table.ColumnHeaderCell>\n <Table.ColumnHeaderCell width=\"28px\" />\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {apiKeys.data.map((apiKey) => (\n <ApiKeyRow key={apiKey.id} apiKey={apiKey} />\n ))}\n </Table.Body>\n </Table.Root>\n {hasPagination && (\n <Flex gap=\"2\" justify=\"end\">\n <Button\n variant=\"secondary\"\n disabled={!hasPreviousPage}\n size=\"1\"\n onClick={() =>\n dispatch({\n type: \"SET_PAGINATION\",\n pagination,\n })\n }\n >\n <Translation\n defaultMessage=\"Previous\"\n id=\"f7TUj0\"\n description=\"Button to navigate to previous page of API keys\"\n />\n </Button>\n <Button\n variant=\"secondary\"\n disabled={!hasNextPage}\n size=\"1\"\n onClick={() =>\n dispatch({\n type: \"SET_PAGINATION\",\n pagination,\n })\n }\n >\n <Translation\n defaultMessage=\"Next\"\n id=\"L2EBxV\"\n description=\"Button to navigate to next page of API keys\"\n />\n </Button>\n </Flex>\n )}\n </>\n )}\n </Flex>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { WidgetRootDomProps } from './utils.js';
|
|
3
|
+
import { DirectoryType, DirectoryMetadata, DirectoryState } from '../api/endpoint.js';
|
|
4
|
+
import './elements.js';
|
|
5
|
+
import '@radix-ui/themes';
|
|
6
|
+
import '@radix-ui/themes/props';
|
|
7
|
+
import '../dialog-C15qCLN3.js';
|
|
8
|
+
import '@radix-ui/themes/components/dialog';
|
|
9
|
+
import '../alert-dialog-BlG3_awx.js';
|
|
10
|
+
import '@radix-ui/themes/components/alert-dialog';
|
|
11
|
+
import '../dropdown-menu-BQ5LtvdR.js';
|
|
12
|
+
import '@radix-ui/themes/components/dropdown-menu';
|
|
13
|
+
import '../select-KR89Qnvm.js';
|
|
14
|
+
import '@radix-ui/themes/components/select';
|
|
15
|
+
import '@tanstack/react-query';
|
|
16
|
+
import '../api/widgets-api-client.js';
|
|
17
|
+
|
|
18
|
+
interface BaseDirectorySyncProps {
|
|
19
|
+
type?: DirectoryType;
|
|
20
|
+
metadata?: DirectoryMetadata;
|
|
21
|
+
lastSyncAt?: string | null;
|
|
22
|
+
link?: string | null;
|
|
23
|
+
errorMessage?: never;
|
|
24
|
+
userCount?: never;
|
|
25
|
+
groupCount?: never;
|
|
26
|
+
currentDate?: never;
|
|
27
|
+
state: DirectoryState;
|
|
28
|
+
}
|
|
29
|
+
interface NotConfiguredProps extends BaseDirectorySyncProps {
|
|
30
|
+
state: (typeof DirectoryState)["unlinked"];
|
|
31
|
+
}
|
|
32
|
+
interface SetupInProgressProps extends Omit<BaseDirectorySyncProps, "type"> {
|
|
33
|
+
state: (typeof DirectoryState)["validating"];
|
|
34
|
+
type: DirectoryType;
|
|
35
|
+
}
|
|
36
|
+
interface ErrorBeforeConfigProps extends Omit<BaseDirectorySyncProps, "type" | "errorMessage"> {
|
|
37
|
+
state: DirectoryState;
|
|
38
|
+
type: DirectoryType;
|
|
39
|
+
errorMessage: React.ReactNode;
|
|
40
|
+
}
|
|
41
|
+
interface ValidatingProps extends Omit<BaseDirectorySyncProps, "type"> {
|
|
42
|
+
state: (typeof DirectoryState)["validating"];
|
|
43
|
+
type: DirectoryType;
|
|
44
|
+
}
|
|
45
|
+
interface ActiveProps extends Omit<BaseDirectorySyncProps, "type" | "lastSyncAt" | "currentDate" | "errorMessage"> {
|
|
46
|
+
state: (typeof DirectoryState)["linked"];
|
|
47
|
+
type: DirectoryType;
|
|
48
|
+
lastSyncAt: string | null;
|
|
49
|
+
currentDate?: Date | null;
|
|
50
|
+
errorMessage?: React.ReactNode;
|
|
51
|
+
}
|
|
52
|
+
interface InvalidCredentialsProps extends Omit<BaseDirectorySyncProps, "type" | "errorMessage"> {
|
|
53
|
+
state: (typeof DirectoryState)["invalid_credentials"];
|
|
54
|
+
type: DirectoryType;
|
|
55
|
+
errorMessage: React.ReactNode;
|
|
56
|
+
}
|
|
57
|
+
interface DeletingProps extends Omit<BaseDirectorySyncProps, "type"> {
|
|
58
|
+
state: (typeof DirectoryState)["deleting"];
|
|
59
|
+
type: DirectoryType;
|
|
60
|
+
}
|
|
61
|
+
type DirectorySyncStatusProps = NotConfiguredProps | SetupInProgressProps | ErrorBeforeConfigProps | ValidatingProps | ActiveProps | InvalidCredentialsProps | DeletingProps;
|
|
62
|
+
type DirectorySyncProps = WidgetRootDomProps & DirectorySyncStatusProps;
|
|
63
|
+
declare const DirectorySync: React.FC<DirectorySyncProps>;
|
|
64
|
+
interface DirectorySyncLoadingProps extends WidgetRootDomProps {
|
|
65
|
+
}
|
|
66
|
+
declare const DirectorySyncLoading: React.FC<DirectorySyncLoadingProps>;
|
|
67
|
+
interface DirectorySyncErrorProps extends WidgetRootDomProps {
|
|
68
|
+
error: unknown;
|
|
69
|
+
}
|
|
70
|
+
declare const DirectorySyncError: React.FC<DirectorySyncErrorProps>;
|
|
71
|
+
|
|
72
|
+
export { DirectorySync, DirectorySyncError, type DirectorySyncErrorProps, DirectorySyncLoading, type DirectorySyncLoadingProps, type DirectorySyncProps, type DirectorySyncStatusProps };
|