@workos-inc/widgets 1.7.2 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/dist/cjs/api/endpoint.cjs +1 -0
- package/dist/cjs/api/endpoint.cjs.map +1 -1
- package/dist/cjs/api/endpoint.d.cts +1 -0
- package/dist/cjs/index.cjs +5 -2
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +1 -0
- package/dist/cjs/lib/add-mfa-dialog.cjs +133 -61
- package/dist/cjs/lib/add-mfa-dialog.cjs.map +1 -1
- package/dist/cjs/lib/admin-portal-domain-verification.cjs +41 -5
- package/dist/cjs/lib/admin-portal-domain-verification.cjs.map +1 -1
- package/dist/cjs/lib/admin-portal-sso-connection.cjs +121 -44
- package/dist/cjs/lib/admin-portal-sso-connection.cjs.map +1 -1
- package/dist/cjs/lib/api-keys/api-key-details-card.cjs +25 -3
- package/dist/cjs/lib/api-keys/api-key-details-card.cjs.map +1 -1
- package/dist/cjs/lib/api-keys/api-key-details-dialog.cjs +25 -3
- package/dist/cjs/lib/api-keys/api-key-details-dialog.cjs.map +1 -1
- package/dist/cjs/lib/api-keys/api-keys-search.cjs +13 -4
- package/dist/cjs/lib/api-keys/api-keys-search.cjs.map +1 -1
- package/dist/cjs/lib/api-keys/api-keys-table.cjs +94 -12
- package/dist/cjs/lib/api-keys/api-keys-table.cjs.map +1 -1
- package/dist/cjs/lib/api-keys/api-keys.cjs +16 -2
- package/dist/cjs/lib/api-keys/api-keys.cjs.map +1 -1
- package/dist/cjs/lib/api-keys/create-api-key.cjs +172 -20
- package/dist/cjs/lib/api-keys/create-api-key.cjs.map +1 -1
- package/dist/cjs/lib/api-keys/relative-time.cjs +12 -2
- package/dist/cjs/lib/api-keys/relative-time.cjs.map +1 -1
- package/dist/cjs/lib/api-keys/revoke-api-key-dialog.cjs +49 -7
- package/dist/cjs/lib/api-keys/revoke-api-key-dialog.cjs.map +1 -1
- package/dist/cjs/lib/change-password-dialog.cjs +122 -16
- package/dist/cjs/lib/change-password-dialog.cjs.map +1 -1
- package/dist/cjs/lib/copy-button.cjs +14 -2
- package/dist/cjs/lib/copy-button.cjs.map +1 -1
- package/dist/cjs/lib/copy-button.d.cts +2 -1
- package/dist/cjs/lib/delete-domain-dialog.cjs +52 -19
- package/dist/cjs/lib/delete-domain-dialog.cjs.map +1 -1
- package/dist/cjs/lib/delete-user-dialog.cjs +46 -11
- package/dist/cjs/lib/delete-user-dialog.cjs.map +1 -1
- package/dist/cjs/lib/delete-user-dialog.d.cts +2 -2
- package/dist/cjs/lib/domain-actions.cjs +51 -7
- package/dist/cjs/lib/domain-actions.cjs.map +1 -1
- package/dist/cjs/lib/domain-item.cjs +42 -8
- package/dist/cjs/lib/domain-item.cjs.map +1 -1
- package/dist/cjs/lib/edit-user-profile-dialog.cjs +62 -11
- package/dist/cjs/lib/edit-user-profile-dialog.cjs.map +1 -1
- package/dist/cjs/lib/edit-user-role-dialog.cjs +90 -17
- package/dist/cjs/lib/edit-user-role-dialog.cjs.map +1 -1
- package/dist/cjs/lib/elements.cjs +14 -3
- package/dist/cjs/lib/elements.cjs.map +1 -1
- package/dist/cjs/lib/elements.d.cts +5 -2
- package/dist/cjs/lib/elevated-access.cjs +78 -18
- package/dist/cjs/lib/elevated-access.cjs.map +1 -1
- package/dist/cjs/lib/generic-error.cjs +53 -11
- package/dist/cjs/lib/generic-error.cjs.map +1 -1
- package/dist/cjs/lib/generic-error.d.cts +5 -1
- package/dist/cjs/lib/i18n/intl-context.cjs +47 -0
- package/dist/cjs/lib/i18n/intl-context.cjs.map +1 -0
- package/dist/cjs/lib/i18n/intl-context.d.cts +29 -0
- package/dist/cjs/lib/i18n/translation.cjs +67 -0
- package/dist/cjs/lib/i18n/translation.cjs.map +1 -0
- package/dist/cjs/lib/i18n/translation.d.cts +16 -0
- package/dist/cjs/lib/i18n/use-locale.cjs +33 -0
- package/dist/cjs/lib/i18n/use-locale.cjs.map +1 -0
- package/dist/cjs/lib/i18n/use-locale.d.cts +7 -0
- package/dist/cjs/lib/i18n/use-translation.cjs +47 -0
- package/dist/cjs/lib/i18n/use-translation.cjs.map +1 -0
- package/dist/cjs/lib/i18n/use-translation.d.cts +15 -0
- package/dist/cjs/lib/identity-providers.d.cts +1 -1
- package/dist/cjs/lib/invite-user-dialog.cjs +69 -14
- package/dist/cjs/lib/invite-user-dialog.cjs.map +1 -1
- package/dist/cjs/lib/logout-all-sessions-dialog.cjs +33 -4
- package/dist/cjs/lib/logout-all-sessions-dialog.cjs.map +1 -1
- package/dist/cjs/lib/logout-dialog.cjs +34 -10
- package/dist/cjs/lib/logout-dialog.cjs.map +1 -1
- package/dist/cjs/lib/organization-switcher.cjs +12 -2
- package/dist/cjs/lib/organization-switcher.cjs.map +1 -1
- package/dist/cjs/lib/pipes.cjs +175 -36
- package/dist/cjs/lib/pipes.cjs.map +1 -1
- package/dist/cjs/lib/resend-invite-dialog.cjs +67 -17
- package/dist/cjs/lib/resend-invite-dialog.cjs.map +1 -1
- package/dist/cjs/lib/reset-mfa-dialog.cjs +50 -7
- package/dist/cjs/lib/reset-mfa-dialog.cjs.map +1 -1
- package/dist/cjs/lib/revoke-invite-dialog.cjs +42 -10
- package/dist/cjs/lib/revoke-invite-dialog.cjs.map +1 -1
- package/dist/cjs/lib/save-button.cjs +9 -1
- package/dist/cjs/lib/save-button.cjs.map +1 -1
- package/dist/cjs/lib/set-password-dialog.cjs +101 -13
- package/dist/cjs/lib/set-password-dialog.cjs.map +1 -1
- package/dist/cjs/lib/user-actions-dropdown.cjs +54 -6
- package/dist/cjs/lib/user-actions-dropdown.cjs.map +1 -1
- package/dist/cjs/lib/user-profile.cjs +81 -10
- package/dist/cjs/lib/user-profile.cjs.map +1 -1
- package/dist/cjs/lib/user-security.cjs +127 -25
- package/dist/cjs/lib/user-security.cjs.map +1 -1
- package/dist/cjs/lib/user-sessions.cjs +74 -15
- package/dist/cjs/lib/user-sessions.cjs.map +1 -1
- package/dist/cjs/lib/users-management.cjs +265 -49
- package/dist/cjs/lib/users-management.cjs.map +1 -1
- package/dist/cjs/lib/users-search.cjs +18 -4
- package/dist/cjs/lib/users-search.cjs.map +1 -1
- package/dist/cjs/lib/utils.cjs +10 -7
- package/dist/cjs/lib/utils.cjs.map +1 -1
- package/dist/cjs/lib/utils.d.cts +2 -1
- package/dist/cjs/lib/view-dns-record-dialog.cjs +89 -18
- package/dist/cjs/lib/view-dns-record-dialog.cjs.map +1 -1
- package/dist/cjs/workos-widgets.client.cjs +2 -2
- package/dist/cjs/workos-widgets.client.cjs.map +1 -1
- package/dist/esm/api/endpoint.d.ts +1 -0
- package/dist/esm/api/endpoint.js +1 -0
- package/dist/esm/api/endpoint.js.map +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +3 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lib/add-mfa-dialog.js +133 -61
- package/dist/esm/lib/add-mfa-dialog.js.map +1 -1
- package/dist/esm/lib/admin-portal-domain-verification.js +41 -5
- package/dist/esm/lib/admin-portal-domain-verification.js.map +1 -1
- package/dist/esm/lib/admin-portal-sso-connection.js +121 -44
- package/dist/esm/lib/admin-portal-sso-connection.js.map +1 -1
- package/dist/esm/lib/api-keys/api-key-details-card.js +25 -3
- package/dist/esm/lib/api-keys/api-key-details-card.js.map +1 -1
- package/dist/esm/lib/api-keys/api-key-details-dialog.js +25 -3
- package/dist/esm/lib/api-keys/api-key-details-dialog.js.map +1 -1
- package/dist/esm/lib/api-keys/api-keys-search.js +13 -4
- package/dist/esm/lib/api-keys/api-keys-search.js.map +1 -1
- package/dist/esm/lib/api-keys/api-keys-table.js +94 -12
- package/dist/esm/lib/api-keys/api-keys-table.js.map +1 -1
- package/dist/esm/lib/api-keys/api-keys.js +16 -2
- package/dist/esm/lib/api-keys/api-keys.js.map +1 -1
- package/dist/esm/lib/api-keys/create-api-key.js +172 -20
- package/dist/esm/lib/api-keys/create-api-key.js.map +1 -1
- package/dist/esm/lib/api-keys/relative-time.js +12 -2
- package/dist/esm/lib/api-keys/relative-time.js.map +1 -1
- package/dist/esm/lib/api-keys/revoke-api-key-dialog.js +49 -7
- package/dist/esm/lib/api-keys/revoke-api-key-dialog.js.map +1 -1
- package/dist/esm/lib/change-password-dialog.js +122 -16
- package/dist/esm/lib/change-password-dialog.js.map +1 -1
- package/dist/esm/lib/copy-button.d.ts +2 -1
- package/dist/esm/lib/copy-button.js +14 -2
- package/dist/esm/lib/copy-button.js.map +1 -1
- package/dist/esm/lib/delete-domain-dialog.js +52 -19
- package/dist/esm/lib/delete-domain-dialog.js.map +1 -1
- package/dist/esm/lib/delete-user-dialog.d.ts +2 -2
- package/dist/esm/lib/delete-user-dialog.js +36 -11
- package/dist/esm/lib/delete-user-dialog.js.map +1 -1
- package/dist/esm/lib/domain-actions.js +41 -7
- package/dist/esm/lib/domain-actions.js.map +1 -1
- package/dist/esm/lib/domain-item.js +42 -8
- package/dist/esm/lib/domain-item.js.map +1 -1
- package/dist/esm/lib/edit-user-profile-dialog.js +62 -11
- package/dist/esm/lib/edit-user-profile-dialog.js.map +1 -1
- package/dist/esm/lib/edit-user-role-dialog.js +90 -17
- package/dist/esm/lib/edit-user-role-dialog.js.map +1 -1
- package/dist/esm/lib/elements.d.ts +5 -2
- package/dist/esm/lib/elements.js +14 -3
- package/dist/esm/lib/elements.js.map +1 -1
- package/dist/esm/lib/elevated-access.js +78 -18
- package/dist/esm/lib/elevated-access.js.map +1 -1
- package/dist/esm/lib/generic-error.d.ts +5 -1
- package/dist/esm/lib/generic-error.js +53 -11
- package/dist/esm/lib/generic-error.js.map +1 -1
- package/dist/esm/lib/i18n/intl-context.d.ts +29 -0
- package/dist/esm/lib/i18n/intl-context.js +12 -0
- package/dist/esm/lib/i18n/intl-context.js.map +1 -0
- package/dist/esm/lib/i18n/translation.d.ts +16 -0
- package/dist/esm/lib/i18n/translation.js +45 -0
- package/dist/esm/lib/i18n/translation.js.map +1 -0
- package/dist/esm/lib/i18n/use-locale.d.ts +7 -0
- package/dist/esm/lib/i18n/use-locale.js +9 -0
- package/dist/esm/lib/i18n/use-locale.js.map +1 -0
- package/dist/esm/lib/i18n/use-translation.d.ts +15 -0
- package/dist/esm/lib/i18n/use-translation.js +23 -0
- package/dist/esm/lib/i18n/use-translation.js.map +1 -0
- package/dist/esm/lib/identity-providers.d.ts +1 -1
- package/dist/esm/lib/invite-user-dialog.js +70 -15
- package/dist/esm/lib/invite-user-dialog.js.map +1 -1
- package/dist/esm/lib/logout-all-sessions-dialog.js +33 -4
- package/dist/esm/lib/logout-all-sessions-dialog.js.map +1 -1
- package/dist/esm/lib/logout-dialog.js +34 -10
- package/dist/esm/lib/logout-dialog.js.map +1 -1
- package/dist/esm/lib/organization-switcher.js +12 -2
- package/dist/esm/lib/organization-switcher.js.map +1 -1
- package/dist/esm/lib/pipes.js +175 -36
- package/dist/esm/lib/pipes.js.map +1 -1
- package/dist/esm/lib/resend-invite-dialog.js +67 -17
- package/dist/esm/lib/resend-invite-dialog.js.map +1 -1
- package/dist/esm/lib/reset-mfa-dialog.js +50 -7
- package/dist/esm/lib/reset-mfa-dialog.js.map +1 -1
- package/dist/esm/lib/revoke-invite-dialog.js +42 -10
- package/dist/esm/lib/revoke-invite-dialog.js.map +1 -1
- package/dist/esm/lib/save-button.js +9 -1
- package/dist/esm/lib/save-button.js.map +1 -1
- package/dist/esm/lib/set-password-dialog.js +101 -13
- package/dist/esm/lib/set-password-dialog.js.map +1 -1
- package/dist/esm/lib/user-actions-dropdown.js +54 -6
- package/dist/esm/lib/user-actions-dropdown.js.map +1 -1
- package/dist/esm/lib/user-profile.js +81 -10
- package/dist/esm/lib/user-profile.js.map +1 -1
- package/dist/esm/lib/user-security.js +127 -25
- package/dist/esm/lib/user-security.js.map +1 -1
- package/dist/esm/lib/user-sessions.js +74 -15
- package/dist/esm/lib/user-sessions.js.map +1 -1
- package/dist/esm/lib/users-management.js +266 -51
- package/dist/esm/lib/users-management.js.map +1 -1
- package/dist/esm/lib/users-search.js +18 -4
- package/dist/esm/lib/users-search.js.map +1 -1
- package/dist/esm/lib/utils.d.ts +2 -1
- package/dist/esm/lib/utils.js +10 -7
- package/dist/esm/lib/utils.js.map +1 -1
- package/dist/esm/lib/view-dns-record-dialog.js +89 -18
- package/dist/esm/lib/view-dns-record-dialog.js.map +1 -1
- package/dist/esm/workos-widgets.client.js +2 -2
- package/dist/esm/workos-widgets.client.js.map +1 -1
- package/package.json +11 -2
|
@@ -11,6 +11,9 @@ import { RelativeTime } from "./relative-time.js";
|
|
|
11
11
|
import { useApiKeysContext } from "./api-keys-context.js";
|
|
12
12
|
import { useApiKeysSearchContext } from "./api-keys-search-provider.js";
|
|
13
13
|
import { ApiKeysSearch } from "./api-keys-search.js";
|
|
14
|
+
import { Translation } from "../i18n/translation.js";
|
|
15
|
+
import { useTranslation } from "../i18n/use-translation.js";
|
|
16
|
+
import { useLocale } from "../i18n/use-locale.js";
|
|
14
17
|
function NoApiKeys() {
|
|
15
18
|
const { clearSearch } = useApiKeysSearchContext();
|
|
16
19
|
return /* @__PURE__ */ jsxs(Flex, { p: "6", gap: "4", justify: "center", align: "center", direction: "column", children: [
|
|
@@ -23,9 +26,23 @@ function NoApiKeys() {
|
|
|
23
26
|
height: "32px"
|
|
24
27
|
}
|
|
25
28
|
),
|
|
26
|
-
/* @__PURE__ */ jsx(Heading, { size: "5", mb: "1", wrap: "balance", as: "h3", children:
|
|
29
|
+
/* @__PURE__ */ jsx(Heading, { size: "5", mb: "1", wrap: "balance", as: "h3", children: /* @__PURE__ */ jsx(
|
|
30
|
+
Translation,
|
|
31
|
+
{
|
|
32
|
+
defaultMessage: "No API keys match your search",
|
|
33
|
+
id: "cKitHb",
|
|
34
|
+
description: "Empty state message when no API keys match search"
|
|
35
|
+
}
|
|
36
|
+
) })
|
|
27
37
|
] }),
|
|
28
|
-
/* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: clearSearch, children:
|
|
38
|
+
/* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: clearSearch, children: /* @__PURE__ */ jsx(
|
|
39
|
+
Translation,
|
|
40
|
+
{
|
|
41
|
+
defaultMessage: "Clear search",
|
|
42
|
+
id: "jTupOW",
|
|
43
|
+
description: "Button to clear API key search filters"
|
|
44
|
+
}
|
|
45
|
+
) })
|
|
29
46
|
] });
|
|
30
47
|
}
|
|
31
48
|
function ApiKeysTableHeader() {
|
|
@@ -36,7 +53,8 @@ function ApiKeysTableHeader() {
|
|
|
36
53
|
}
|
|
37
54
|
function CreatedOn({ createdOn }) {
|
|
38
55
|
const isHydrated = useIsHydrated();
|
|
39
|
-
|
|
56
|
+
const locale = useLocale();
|
|
57
|
+
return /* @__PURE__ */ jsx(Fragment, { children: createdOn.toLocaleDateString(locale, {
|
|
40
58
|
timeZone: isHydrated ? void 0 : "UTC",
|
|
41
59
|
month: "short",
|
|
42
60
|
day: "numeric",
|
|
@@ -46,6 +64,7 @@ function CreatedOn({ createdOn }) {
|
|
|
46
64
|
function ApiKeyRow({ apiKey }) {
|
|
47
65
|
const [revokeDialogOpen, setRevokeDialogOpen] = useState(false);
|
|
48
66
|
const [detailsOpen, setDetailsOpen] = useState(false);
|
|
67
|
+
const translate = useTranslation();
|
|
49
68
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
50
69
|
/* @__PURE__ */ jsx(
|
|
51
70
|
RevokeApiKeyDialog,
|
|
@@ -82,15 +101,36 @@ function ApiKeyRow({ apiKey }) {
|
|
|
82
101
|
) }),
|
|
83
102
|
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Text, { children: /* @__PURE__ */ jsx(CreatedOn, { createdOn: new Date(apiKey.createdAt) }) }) }),
|
|
84
103
|
/* @__PURE__ */ jsx(Table.Cell, { justify: "end", children: /* @__PURE__ */ jsxs(DropdownMenu.Root, { children: [
|
|
85
|
-
/* @__PURE__ */ jsx(DropdownMenu.Trigger, { children:
|
|
104
|
+
/* @__PURE__ */ jsx(DropdownMenu.Trigger, { children: (() => {
|
|
105
|
+
const title = translate({
|
|
106
|
+
defaultMessage: "API key actions",
|
|
107
|
+
id: "RIBfYe",
|
|
108
|
+
description: "Tooltip for API key actions menu button"
|
|
109
|
+
});
|
|
110
|
+
return /* @__PURE__ */ jsx(IconButton, { title, children: /* @__PURE__ */ jsx(DotsHorizontalIcon, {}) });
|
|
111
|
+
})() }),
|
|
86
112
|
/* @__PURE__ */ jsxs(DropdownMenu.Content, { size: "2", align: "end", children: [
|
|
87
|
-
/* @__PURE__ */ jsx(DropdownMenu.Item, { onSelect: () => setDetailsOpen(true), children:
|
|
113
|
+
/* @__PURE__ */ jsx(DropdownMenu.Item, { onSelect: () => setDetailsOpen(true), children: /* @__PURE__ */ jsx(
|
|
114
|
+
Translation,
|
|
115
|
+
{
|
|
116
|
+
defaultMessage: "View details",
|
|
117
|
+
id: "VGKbbj",
|
|
118
|
+
description: "Menu item to view API key details"
|
|
119
|
+
}
|
|
120
|
+
) }),
|
|
88
121
|
/* @__PURE__ */ jsx(
|
|
89
122
|
DropdownMenu.Item,
|
|
90
123
|
{
|
|
91
124
|
variant: "destructive",
|
|
92
125
|
onSelect: () => setRevokeDialogOpen(true),
|
|
93
|
-
children:
|
|
126
|
+
children: /* @__PURE__ */ jsx(
|
|
127
|
+
Translation,
|
|
128
|
+
{
|
|
129
|
+
defaultMessage: "Revoke key",
|
|
130
|
+
id: "KZIJPP",
|
|
131
|
+
description: "Menu item to revoke an API key"
|
|
132
|
+
}
|
|
133
|
+
)
|
|
94
134
|
}
|
|
95
135
|
)
|
|
96
136
|
] })
|
|
@@ -110,10 +150,38 @@ function ApiKeysTable({
|
|
|
110
150
|
apiKeys.data.length === 0 ? /* @__PURE__ */ jsx(NoApiKeys, {}) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
111
151
|
/* @__PURE__ */ jsxs(Table.Root, { variant: "ghost", size: "2", children: [
|
|
112
152
|
/* @__PURE__ */ jsx(Table.Header, { children: /* @__PURE__ */ jsxs(Table.Row, { children: [
|
|
113
|
-
/* @__PURE__ */ jsx(Table.ColumnHeaderCell, { width: "25%", children:
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
153
|
+
/* @__PURE__ */ jsx(Table.ColumnHeaderCell, { width: "25%", children: /* @__PURE__ */ jsx(
|
|
154
|
+
Translation,
|
|
155
|
+
{
|
|
156
|
+
defaultMessage: "Name",
|
|
157
|
+
id: "VYbVXN",
|
|
158
|
+
description: "Table column header for API key name"
|
|
159
|
+
}
|
|
160
|
+
) }),
|
|
161
|
+
/* @__PURE__ */ jsx(Table.ColumnHeaderCell, { width: "25%", children: /* @__PURE__ */ jsx(
|
|
162
|
+
Translation,
|
|
163
|
+
{
|
|
164
|
+
defaultMessage: "Secret key",
|
|
165
|
+
id: "H5k7GB",
|
|
166
|
+
description: "Table column header for API key secret value"
|
|
167
|
+
}
|
|
168
|
+
) }),
|
|
169
|
+
/* @__PURE__ */ jsx(Table.ColumnHeaderCell, { width: "25%", children: /* @__PURE__ */ jsx(
|
|
170
|
+
Translation,
|
|
171
|
+
{
|
|
172
|
+
defaultMessage: "Last used",
|
|
173
|
+
id: "E46t3O",
|
|
174
|
+
description: "Table column header for API key last used timestamp"
|
|
175
|
+
}
|
|
176
|
+
) }),
|
|
177
|
+
/* @__PURE__ */ jsx(Table.ColumnHeaderCell, { width: "25%", children: /* @__PURE__ */ jsx(
|
|
178
|
+
Translation,
|
|
179
|
+
{
|
|
180
|
+
defaultMessage: "Created",
|
|
181
|
+
id: "CXHhXd",
|
|
182
|
+
description: "Table column header for API key creation date"
|
|
183
|
+
}
|
|
184
|
+
) }),
|
|
117
185
|
/* @__PURE__ */ jsx(Table.ColumnHeaderCell, { width: "28px" })
|
|
118
186
|
] }) }),
|
|
119
187
|
/* @__PURE__ */ jsx(Table.Body, { children: apiKeys.data.map((apiKey) => /* @__PURE__ */ jsx(ApiKeyRow, { apiKey }, apiKey.id)) })
|
|
@@ -129,7 +197,14 @@ function ApiKeysTable({
|
|
|
129
197
|
type: "SET_PAGINATION",
|
|
130
198
|
pagination: { after: apiKeys.listMetadata.after }
|
|
131
199
|
}),
|
|
132
|
-
children:
|
|
200
|
+
children: /* @__PURE__ */ jsx(
|
|
201
|
+
Translation,
|
|
202
|
+
{
|
|
203
|
+
defaultMessage: "Previous",
|
|
204
|
+
id: "f7TUj0",
|
|
205
|
+
description: "Button to navigate to previous page of API keys"
|
|
206
|
+
}
|
|
207
|
+
)
|
|
133
208
|
}
|
|
134
209
|
),
|
|
135
210
|
/* @__PURE__ */ jsx(
|
|
@@ -142,7 +217,14 @@ function ApiKeysTable({
|
|
|
142
217
|
type: "SET_PAGINATION",
|
|
143
218
|
pagination: { before: apiKeys.listMetadata.before }
|
|
144
219
|
}),
|
|
145
|
-
children:
|
|
220
|
+
children: /* @__PURE__ */ jsx(
|
|
221
|
+
Translation,
|
|
222
|
+
{
|
|
223
|
+
defaultMessage: "Next",
|
|
224
|
+
id: "L2EBxV",
|
|
225
|
+
description: "Button to navigate to next page of API keys"
|
|
226
|
+
}
|
|
227
|
+
)
|
|
146
228
|
}
|
|
147
229
|
)
|
|
148
230
|
] })
|
|
@@ -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\";\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 No API keys match your search\n </Heading>\n </Flex>\n\n <Button variant=\"secondary\" onClick={clearSearch}>\n Clear search\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 return (\n <>\n {createdOn.toLocaleDateString(\"en-US\", {\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 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 <IconButton aria-label=\"API key actions\" title=\"API key actions\">\n <DotsHorizontalIcon />\n </IconButton>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content size=\"2\" align=\"end\">\n <DropdownMenu.Item onSelect={() => setDetailsOpen(true)}>\n View details\n </DropdownMenu.Item>\n <DropdownMenu.Item\n variant=\"destructive\"\n onSelect={() => setRevokeDialogOpen(true)}\n >\n Revoke key\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 Name\n </Table.ColumnHeaderCell>\n <Table.ColumnHeaderCell width=\"25%\">\n Secret key\n </Table.ColumnHeaderCell>\n <Table.ColumnHeaderCell width=\"25%\">\n Last used\n </Table.ColumnHeaderCell>\n <Table.ColumnHeaderCell width=\"25%\">\n Created\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 Previous\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 Next\n </Button>\n </Flex>\n )}\n </>\n )}\n </Flex>\n );\n}\n"],"mappings":"AAqBM,SA8BF,UA7BI,KADF;AArBN,SAAS,MAAM,MAAM,OAAO,MAAM,eAAe;AACjD,SAAS,QAAQ,cAAc,kBAAkB;AACjD,SAAS,oBAAoB,2BAA2B;AACxD,SAAS,gBAAgB;AACzB,SAAS,0BAA0B;AACnC,SAAS,0BAA0B;AACnC,SAAS,2BAA2B;AACpC,SAAS,qBAAqB;AAC9B,SAAS,oBAAoB;AAK7B,SAAS,yBAAyB;AAClC,SAAS,+BAA+B;AACxC,SAAS,qBAAqB;AAE9B,SAAS,YAAY;AACnB,QAAM,EAAE,YAAY,IAAI,wBAAwB;AAChD,SACE,qBAAC,QAAK,GAAE,KAAI,KAAI,KAAI,SAAQ,UAAS,OAAM,UAAS,WAAU,UAC5D;AAAA,yBAAC,QAAK,WAAU,UAAS,KAAI,KAAI,UAAS,SAAQ,OAAM,UACtD;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,OAAO,EAAE,OAAO,gBAAgB;AAAA,UAChC,OAAM;AAAA,UACN,QAAO;AAAA;AAAA,MACT;AAAA,MACA,oBAAC,WAAQ,MAAK,KAAI,IAAG,KAAI,MAAK,WAAU,IAAG,MAAK,2CAEhD;AAAA,OACF;AAAA,IAEA,oBAAC,UAAO,SAAQ,aAAY,SAAS,aAAa,0BAElD;AAAA,KACF;AAEJ;AAEA,SAAS,qBAAqB;AAC5B,SACE,qBAAC,QAAK,SAAQ,WAAU,OAAM,UAC5B;AAAA,wBAAC,iBAAc,MAAK,0BAAyB,OAAO,EAAE,OAAO,QAAQ,GAAG;AAAA,IACxE,oBAAC,sBAAmB;AAAA,KACtB;AAEJ;AAEA,SAAS,UAAU,EAAE,UAAU,GAAwB;AACrD,QAAM,aAAa,cAAc;AACjC,SACE,gCACG,oBAAU,mBAAmB,SAAS;AAAA,IACrC,UAAU,aAAa,SAAY;AAAA,IACnC,OAAO;AAAA,IACP,KAAK;AAAA,IACL,MAAM;AAAA,EACR,CAAC,GACH;AAEJ;AAMA,SAAS,UAAU,EAAE,OAAO,GAAmB;AAC7C,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,SAAS,KAAK;AAC9D,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,KAAK;AACpD,SACE,iCACE;AAAA;AAAA,MAAC;AAAA;AAAA,QAGC,MAAM;AAAA,QACN,cAAc;AAAA,QACd;AAAA;AAAA,MAHK,GAAG,gBAAgB;AAAA,IAI1B;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAM;AAAA,QACN,cAAc;AAAA,QACd;AAAA,QACA,aAAa,OAAO;AAAA;AAAA,IACtB;AAAA,IACA,qBAAC,MAAM,KAAN,EAAU,OAAM,UACf;AAAA,0BAAC,MAAM,MAAN,EACC,8BAAC,QAAM,iBAAO,MAAK,GACrB;AAAA,MACA,oBAAC,MAAM,MAAN,EACC,8BAAC,QAAK,OAAM,QAAQ,iBAAO,iBAAgB,GAC7C;AAAA,MACA,oBAAC,MAAM,MAAN,EACC;AAAA,QAAC;AAAA;AAAA,UACC,OAAO,OAAO,aAAa,SAAY,EAAE,OAAO,iBAAiB;AAAA,UAEjE;AAAA,YAAC;AAAA;AAAA,cACC,MAAM,OAAO,aAAa,IAAI,KAAK,OAAO,UAAU,IAAI;AAAA;AAAA,UAC1D;AAAA;AAAA,MACF,GACF;AAAA,MACA,oBAAC,MAAM,MAAN,EACC,8BAAC,QACC,8BAAC,aAAU,WAAW,IAAI,KAAK,OAAO,SAAS,GAAG,GACpD,GACF;AAAA,MACA,oBAAC,MAAM,MAAN,EAAW,SAAQ,OAClB,+BAAC,aAAa,MAAb,EACC;AAAA,4BAAC,aAAa,SAAb,EACC,8BAAC,cAAW,cAAW,mBAAkB,OAAM,mBAC7C,8BAAC,sBAAmB,GACtB,GACF;AAAA,QACA,qBAAC,aAAa,SAAb,EAAqB,MAAK,KAAI,OAAM,OACnC;AAAA,8BAAC,aAAa,MAAb,EAAkB,UAAU,MAAM,eAAe,IAAI,GAAG,0BAEzD;AAAA,UACA;AAAA,YAAC,aAAa;AAAA,YAAb;AAAA,cACC,SAAQ;AAAA,cACR,UAAU,MAAM,oBAAoB,IAAI;AAAA,cACzC;AAAA;AAAA,UAED;AAAA,WACF;AAAA,SACF,GACF;AAAA,OACF;AAAA,KACF;AAEJ;AAEO,SAAS,aAAa;AAAA,EAC3B;AACF,GAEG;AACD,QAAM,EAAE,SAAS,IAAI,kBAAkB;AACvC,QAAM,gBACJ,QAAQ,aAAa,UAAU,QAAQ,aAAa;AACtD,QAAM,kBAAkB,QAAQ,aAAa;AAC7C,QAAM,cAAc,QAAQ,aAAa;AAEzC,SACE,qBAAC,QAAK,WAAU,UAAS,OAAM,WAAU,KAAI,KAC3C;AAAA,wBAAC,sBAAmB;AAAA,IACnB,QAAQ,KAAK,WAAW,IACvB,oBAAC,aAAU,IAEX,iCACE;AAAA,2BAAC,MAAM,MAAN,EAAW,SAAQ,SAAQ,MAAK,KAC/B;AAAA,4BAAC,MAAM,QAAN,EACC,+BAAC,MAAM,KAAN,EACC;AAAA,8BAAC,MAAM,kBAAN,EAAuB,OAAM,OAAM,kBAEpC;AAAA,UACA,oBAAC,MAAM,kBAAN,EAAuB,OAAM,OAAM,wBAEpC;AAAA,UACA,oBAAC,MAAM,kBAAN,EAAuB,OAAM,OAAM,uBAEpC;AAAA,UACA,oBAAC,MAAM,kBAAN,EAAuB,OAAM,OAAM,qBAEpC;AAAA,UACA,oBAAC,MAAM,kBAAN,EAAuB,OAAM,QAAO;AAAA,WACvC,GACF;AAAA,QACA,oBAAC,MAAM,MAAN,EACE,kBAAQ,KAAK,IAAI,CAAC,WACjB,oBAAC,aAA0B,UAAX,OAAO,EAAoB,CAC5C,GACH;AAAA,SACF;AAAA,MACC,iBACC,qBAAC,QAAK,KAAI,KAAI,SAAQ,OACpB;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,SAAQ;AAAA,YACR,UAAU,CAAC;AAAA,YACX,MAAK;AAAA,YACL,SAAS,MACP,SAAS;AAAA,cACP,MAAM;AAAA,cACN,YAAY,EAAE,OAAO,QAAQ,aAAa,MAAM;AAAA,YAClD,CAAC;AAAA,YAEJ;AAAA;AAAA,QAED;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,SAAQ;AAAA,YACR,UAAU,CAAC;AAAA,YACX,MAAK;AAAA,YACL,SAAS,MACP,SAAS;AAAA,cACP,MAAM;AAAA,cACN,YAAY,EAAE,QAAQ,QAAQ,aAAa,OAAO;AAAA,YACpD,CAAC;AAAA,YAEJ;AAAA;AAAA,QAED;AAAA,SACF;AAAA,OAEJ;AAAA,KAEJ;AAEJ;","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\";\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":[]}
|
|
@@ -9,6 +9,8 @@ import { CreateApiKeyButton } from "./create-api-key.js";
|
|
|
9
9
|
import { getDomProps } from "../utils.js";
|
|
10
10
|
import { ApiKeysSearchProvider } from "./api-keys-search-provider.js";
|
|
11
11
|
import { ApiKeysTable } from "./api-keys-table.js";
|
|
12
|
+
import { Translation } from "../i18n/translation.js";
|
|
13
|
+
import { useTranslation } from "../i18n/use-translation.js";
|
|
12
14
|
const ApiKeys = ({
|
|
13
15
|
apiKeys,
|
|
14
16
|
searchQuery,
|
|
@@ -23,6 +25,7 @@ const ApiKeys = ({
|
|
|
23
25
|
) });
|
|
24
26
|
};
|
|
25
27
|
const ApiKeysLoading = (props) => {
|
|
28
|
+
const translate = useTranslation();
|
|
26
29
|
return /* @__PURE__ */ jsxs(
|
|
27
30
|
Flex,
|
|
28
31
|
{
|
|
@@ -37,11 +40,22 @@ const ApiKeysLoading = (props) => {
|
|
|
37
40
|
{
|
|
38
41
|
name: "api-keys-widget-search",
|
|
39
42
|
style: { width: "390px" },
|
|
40
|
-
placeholder:
|
|
43
|
+
placeholder: translate({
|
|
44
|
+
defaultMessage: "Search by name",
|
|
45
|
+
id: "VBESVz",
|
|
46
|
+
description: "Placeholder for API key search input in loading state"
|
|
47
|
+
}),
|
|
41
48
|
children: /* @__PURE__ */ jsx(TextFieldSlot, { side: "left", children: /* @__PURE__ */ jsx(MagnifyingGlassIcon, { "aria-hidden": "true", height: "16", width: "16" }) })
|
|
42
49
|
}
|
|
43
50
|
) }),
|
|
44
|
-
/* @__PURE__ */ jsx(Skeleton, { children: /* @__PURE__ */ jsx(Button, { children:
|
|
51
|
+
/* @__PURE__ */ jsx(Skeleton, { children: /* @__PURE__ */ jsx(Button, { children: /* @__PURE__ */ jsx(
|
|
52
|
+
Translation,
|
|
53
|
+
{
|
|
54
|
+
defaultMessage: "Create API key",
|
|
55
|
+
id: "eTEzjH",
|
|
56
|
+
description: "Button to create a new API key in loading state"
|
|
57
|
+
}
|
|
58
|
+
) }) })
|
|
45
59
|
] }),
|
|
46
60
|
/* @__PURE__ */ jsx(
|
|
47
61
|
SkeletonTable,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/api-keys/api-keys.tsx"],"sourcesContent":["import { Flex } from \"@radix-ui/themes\";\nimport { Button, Skeleton, TextField, TextFieldSlot } from \"../elements.js\";\nimport { GenericError } from \"../generic-error.js\";\nimport { EmptyState } from \"../empty-state.js\";\nimport { MagnifyingGlassIcon } from \"@radix-ui/react-icons\";\nimport { SkeletonTable } from \"./skeleton-table.js\";\nimport { CreateApiKeyButton } from \"./create-api-key.js\";\nimport { getDomProps, WidgetRootDomProps, WidgetRootState } from \"../utils.js\";\nimport { ListOrganizationApiKeysResponse } from \"../../api/endpoint.js\";\nimport { ApiKeysSearchProvider } from \"./api-keys-search-provider.js\";\nimport { ApiKeysTable } from \"./api-keys-table.js\";\n\ninterface ApiKeysProps extends WidgetRootDomProps {\n apiKeys: ListOrganizationApiKeysResponse;\n searchQuery: string | null;\n}\n\nconst ApiKeys: React.FC<ApiKeysProps> = ({\n apiKeys,\n searchQuery,\n ...domProps\n}) => {\n return apiKeys.data.length === 0 && !searchQuery ? (\n <ApiKeysEmptyState {...getWidgetRootDomProps(\"resolved\", domProps)} />\n ) : (\n <ApiKeysSearchProvider>\n <ApiKeysTable\n apiKeys={apiKeys}\n {...getWidgetRootDomProps(\"resolved\", domProps)}\n />\n </ApiKeysSearchProvider>\n );\n};\n\ninterface ApiKeysLoadingProps extends WidgetRootDomProps {}\n\nconst ApiKeysLoading: React.FC<ApiKeysLoadingProps> = (props) => {\n return (\n <Flex\n direction=\"column\"\n align=\"stretch\"\n gap=\"3\"\n {...getWidgetRootDomProps(\"loading\", props)}\n >\n <Flex justify=\"between\" align=\"center\">\n <Skeleton>\n <TextField\n name=\"api-keys-widget-search\"\n style={{ width: \"390px\" }}\n placeholder
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/api-keys/api-keys.tsx"],"sourcesContent":["import { Flex } from \"@radix-ui/themes\";\nimport { Button, Skeleton, TextField, TextFieldSlot } from \"../elements.js\";\nimport { GenericError } from \"../generic-error.js\";\nimport { EmptyState } from \"../empty-state.js\";\nimport { MagnifyingGlassIcon } from \"@radix-ui/react-icons\";\nimport { SkeletonTable } from \"./skeleton-table.js\";\nimport { CreateApiKeyButton } from \"./create-api-key.js\";\nimport { getDomProps, WidgetRootDomProps, WidgetRootState } from \"../utils.js\";\nimport { ListOrganizationApiKeysResponse } from \"../../api/endpoint.js\";\nimport { ApiKeysSearchProvider } from \"./api-keys-search-provider.js\";\nimport { ApiKeysTable } from \"./api-keys-table.js\";\nimport { Translation } from \"../i18n/translation.js\";\nimport { useTranslation } from \"../i18n/use-translation.js\";\n\ninterface ApiKeysProps extends WidgetRootDomProps {\n apiKeys: ListOrganizationApiKeysResponse;\n searchQuery: string | null;\n}\n\nconst ApiKeys: React.FC<ApiKeysProps> = ({\n apiKeys,\n searchQuery,\n ...domProps\n}) => {\n return apiKeys.data.length === 0 && !searchQuery ? (\n <ApiKeysEmptyState {...getWidgetRootDomProps(\"resolved\", domProps)} />\n ) : (\n <ApiKeysSearchProvider>\n <ApiKeysTable\n apiKeys={apiKeys}\n {...getWidgetRootDomProps(\"resolved\", domProps)}\n />\n </ApiKeysSearchProvider>\n );\n};\n\ninterface ApiKeysLoadingProps extends WidgetRootDomProps {}\n\nconst ApiKeysLoading: React.FC<ApiKeysLoadingProps> = (props) => {\n const translate = useTranslation();\n return (\n <Flex\n direction=\"column\"\n align=\"stretch\"\n gap=\"3\"\n {...getWidgetRootDomProps(\"loading\", props)}\n >\n <Flex justify=\"between\" align=\"center\">\n <Skeleton>\n <TextField\n name=\"api-keys-widget-search\"\n style={{ width: \"390px\" }}\n placeholder={translate({\n defaultMessage: \"Search by name\",\n id: \"VBESVz\",\n description:\n \"Placeholder for API key search input in loading state\",\n })}\n >\n <TextFieldSlot side=\"left\">\n <MagnifyingGlassIcon aria-hidden=\"true\" height=\"16\" width=\"16\" />\n </TextFieldSlot>\n </TextField>\n </Skeleton>\n <Skeleton>\n <Button>\n <Translation\n defaultMessage=\"Create API key\"\n id=\"eTEzjH\"\n description=\"Button to create a new API key in loading state\"\n />\n </Button>\n </Skeleton>\n </Flex>\n <SkeletonTable\n numRows={5}\n columns={[\n { children: \"Name\", width: \"25%\" },\n { children: \"Secret key\", width: \"25%\" },\n { children: \"Last used\", width: \"25%\" },\n { children: \"Created\", width: \"25%\" },\n ]}\n />\n </Flex>\n );\n};\n\ninterface ApiKeysErrorProps extends WidgetRootDomProps {\n error: unknown;\n}\n\nconst ApiKeysError: React.FC<ApiKeysErrorProps> = ({ error, ...domProps }) => {\n return (\n <GenericError error={error} {...getWidgetRootDomProps(\"error\", domProps)} />\n );\n};\n\nfunction ApiKeysEmptyState(props: WidgetRootDomProps) {\n return (\n <EmptyState\n heading=\"No API keys yet\"\n message=\"Generate an API key to authenticate and interact with our API.\"\n action={<CreateApiKeyButton />}\n {...props}\n />\n );\n}\n\nfunction getWidgetRootDomProps(\n state: WidgetRootState,\n domProps: WidgetRootDomProps,\n) {\n return getDomProps({\n ...domProps,\n isWidgetRoot: true,\n widgetId: \"api-keys\",\n widgetState: state,\n });\n}\n\nexport type { ApiKeysProps, ApiKeysLoadingProps, ApiKeysErrorProps };\nexport { ApiKeys, ApiKeysLoading, ApiKeysError };\n"],"mappings":"AAyBI,cAsBE,YAtBF;AAzBJ,SAAS,YAAY;AACrB,SAAS,QAAQ,UAAU,WAAW,qBAAqB;AAC3D,SAAS,oBAAoB;AAC7B,SAAS,kBAAkB;AAC3B,SAAS,2BAA2B;AACpC,SAAS,qBAAqB;AAC9B,SAAS,0BAA0B;AACnC,SAAS,mBAAwD;AAEjE,SAAS,6BAA6B;AACtC,SAAS,oBAAoB;AAC7B,SAAS,mBAAmB;AAC5B,SAAS,sBAAsB;AAO/B,MAAM,UAAkC,CAAC;AAAA,EACvC;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAAM;AACJ,SAAO,QAAQ,KAAK,WAAW,KAAK,CAAC,cACnC,oBAAC,qBAAmB,GAAG,sBAAsB,YAAY,QAAQ,GAAG,IAEpE,oBAAC,yBACC;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACC,GAAG,sBAAsB,YAAY,QAAQ;AAAA;AAAA,EAChD,GACF;AAEJ;AAIA,MAAM,iBAAgD,CAAC,UAAU;AAC/D,QAAM,YAAY,eAAe;AACjC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,OAAM;AAAA,MACN,KAAI;AAAA,MACH,GAAG,sBAAsB,WAAW,KAAK;AAAA,MAE1C;AAAA,6BAAC,QAAK,SAAQ,WAAU,OAAM,UAC5B;AAAA,8BAAC,YACC;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,OAAO,EAAE,OAAO,QAAQ;AAAA,cACxB,aAAa,UAAU;AAAA,gBACrB,gBAAgB;AAAA,gBAChB,IAAI;AAAA,gBACJ,aACE;AAAA,cACJ,CAAC;AAAA,cAED,8BAAC,iBAAc,MAAK,QAClB,8BAAC,uBAAoB,eAAY,QAAO,QAAO,MAAK,OAAM,MAAK,GACjE;AAAA;AAAA,UACF,GACF;AAAA,UACA,oBAAC,YACC,8BAAC,UACC;AAAA,YAAC;AAAA;AAAA,cACC,gBAAe;AAAA,cACf,IAAG;AAAA,cACH,aAAY;AAAA;AAAA,UACd,GACF,GACF;AAAA,WACF;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,SAAS;AAAA,YACT,SAAS;AAAA,cACP,EAAE,UAAU,QAAQ,OAAO,MAAM;AAAA,cACjC,EAAE,UAAU,cAAc,OAAO,MAAM;AAAA,cACvC,EAAE,UAAU,aAAa,OAAO,MAAM;AAAA,cACtC,EAAE,UAAU,WAAW,OAAO,MAAM;AAAA,YACtC;AAAA;AAAA,QACF;AAAA;AAAA;AAAA,EACF;AAEJ;AAMA,MAAM,eAA4C,CAAC,EAAE,OAAO,GAAG,SAAS,MAAM;AAC5E,SACE,oBAAC,gBAAa,OAAe,GAAG,sBAAsB,SAAS,QAAQ,GAAG;AAE9E;AAEA,SAAS,kBAAkB,OAA2B;AACpD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,SAAQ;AAAA,MACR,SAAQ;AAAA,MACR,QAAQ,oBAAC,sBAAmB;AAAA,MAC3B,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,SAAS,sBACP,OACA,UACA;AACA,SAAO,YAAY;AAAA,IACjB,GAAG;AAAA,IACH,cAAc;AAAA,IACd,UAAU;AAAA,IACV,aAAa;AAAA,EACf,CAAC;AACH;","names":[]}
|
|
@@ -22,12 +22,13 @@ import {
|
|
|
22
22
|
} from "@radix-ui/react-icons";
|
|
23
23
|
import { CopyButton, CopyIconButton } from "../copy-button.js";
|
|
24
24
|
import * as React from "react";
|
|
25
|
-
import { pluralize } from "../utils.js";
|
|
26
25
|
import {
|
|
27
26
|
useListOrganizationApiKeyPermissions
|
|
28
27
|
} from "../../api/endpoint.js";
|
|
29
28
|
import { useCreateApiKey } from "../api/api-key.js";
|
|
30
29
|
import { useApiKeysContext } from "./api-keys-context.js";
|
|
30
|
+
import { Translation } from "../i18n/translation.js";
|
|
31
|
+
import { useTranslation } from "../i18n/use-translation.js";
|
|
31
32
|
function CreateApiKeyDialog() {
|
|
32
33
|
const {
|
|
33
34
|
state: { createDialogOpen, createdApiKey },
|
|
@@ -52,6 +53,7 @@ function CreateApiKeyDialog() {
|
|
|
52
53
|
}
|
|
53
54
|
function CreateApiKeyForm() {
|
|
54
55
|
const { dispatch } = useApiKeysContext();
|
|
56
|
+
const translate = useTranslation();
|
|
55
57
|
const [errors, setErrors] = React.useState({ name: false });
|
|
56
58
|
const validate = (formData) => {
|
|
57
59
|
const name = formData.get("name")?.toString() ?? "";
|
|
@@ -68,7 +70,14 @@ function CreateApiKeyForm() {
|
|
|
68
70
|
} = useCreateApiKey();
|
|
69
71
|
const permissions = useListOrganizationApiKeyPermissions({ limit: 100 });
|
|
70
72
|
return /* @__PURE__ */ jsxs(Dialog.Content, { maxWidth: "529px", children: [
|
|
71
|
-
/* @__PURE__ */ jsx(Dialog.Title, { size: "4", weight: "bold", children:
|
|
73
|
+
/* @__PURE__ */ jsx(Dialog.Title, { size: "4", weight: "bold", children: /* @__PURE__ */ jsx(
|
|
74
|
+
Translation,
|
|
75
|
+
{
|
|
76
|
+
defaultMessage: "Create API key",
|
|
77
|
+
id: "eUFRNS",
|
|
78
|
+
description: "Dialog title for creating a new API key"
|
|
79
|
+
}
|
|
80
|
+
) }),
|
|
72
81
|
/* @__PURE__ */ jsxs(
|
|
73
82
|
Form.Root,
|
|
74
83
|
{
|
|
@@ -98,25 +107,64 @@ function CreateApiKeyForm() {
|
|
|
98
107
|
/* @__PURE__ */ jsxs(Flex, { direction: "column", align: "stretch", gap: "4", children: [
|
|
99
108
|
error && /* @__PURE__ */ jsxs(Callout.Root, { color: "red", role: "alert", children: [
|
|
100
109
|
/* @__PURE__ */ jsx(Callout.Icon, { children: /* @__PURE__ */ jsx(ExclamationTriangleIcon, {}) }),
|
|
101
|
-
/* @__PURE__ */ jsx(Callout.Text, { children:
|
|
110
|
+
/* @__PURE__ */ jsx(Callout.Text, { children: /* @__PURE__ */ jsx(
|
|
111
|
+
Translation,
|
|
112
|
+
{
|
|
113
|
+
defaultMessage: "An error occurred while creating the API key.",
|
|
114
|
+
id: "0LyBVd",
|
|
115
|
+
description: "Error message when API key creation fails"
|
|
116
|
+
}
|
|
117
|
+
) })
|
|
102
118
|
] }),
|
|
103
119
|
/* @__PURE__ */ jsx(Form.Field, { name: "name", asChild: true, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", align: "stretch", gap: "2", children: [
|
|
104
|
-
/* @__PURE__ */ jsx(Form.Label, { asChild: true, children: /* @__PURE__ */ jsx(Label, { children:
|
|
120
|
+
/* @__PURE__ */ jsx(Form.Label, { asChild: true, children: /* @__PURE__ */ jsx(Label, { children: /* @__PURE__ */ jsx(
|
|
121
|
+
Translation,
|
|
122
|
+
{
|
|
123
|
+
defaultMessage: "Name",
|
|
124
|
+
id: "v0VmRy",
|
|
125
|
+
description: "Label for API key name input field"
|
|
126
|
+
}
|
|
127
|
+
) }) }),
|
|
105
128
|
/* @__PURE__ */ jsx(Form.Control, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
106
129
|
TextField,
|
|
107
130
|
{
|
|
108
131
|
"data-1p-ignore": true,
|
|
109
132
|
autoComplete: "off",
|
|
110
|
-
placeholder:
|
|
133
|
+
placeholder: translate({
|
|
134
|
+
defaultMessage: "A descriptive name for the API key",
|
|
135
|
+
id: "moyvr4",
|
|
136
|
+
description: "Placeholder for API key name input"
|
|
137
|
+
})
|
|
111
138
|
}
|
|
112
139
|
) }),
|
|
113
|
-
errors.name && /* @__PURE__ */ jsx(Form.Message, { asChild: true, children: /* @__PURE__ */ jsx(Text, { size: "2", color: "red", children:
|
|
140
|
+
errors.name && /* @__PURE__ */ jsx(Form.Message, { asChild: true, children: /* @__PURE__ */ jsx(Text, { size: "2", color: "red", children: /* @__PURE__ */ jsx(
|
|
141
|
+
Translation,
|
|
142
|
+
{
|
|
143
|
+
defaultMessage: "The name is required",
|
|
144
|
+
id: "oF9d2V",
|
|
145
|
+
description: "Validation error when API key name is empty"
|
|
146
|
+
}
|
|
147
|
+
) }) })
|
|
114
148
|
] }) }),
|
|
115
149
|
permissions.isSuccess && permissions.data.data.length > 0 && /* @__PURE__ */ jsx(PermissionsField, { permissions: permissions.data.data })
|
|
116
150
|
] }),
|
|
117
151
|
/* @__PURE__ */ jsxs(Flex, { align: "center", gap: "3", justify: "end", mt: "5", children: [
|
|
118
|
-
/* @__PURE__ */ jsx(Dialog.Close, { children: /* @__PURE__ */ jsx(Button, { variant: "secondary", disabled: isPending || isSuccess, children:
|
|
119
|
-
|
|
152
|
+
/* @__PURE__ */ jsx(Dialog.Close, { children: /* @__PURE__ */ jsx(Button, { variant: "secondary", disabled: isPending || isSuccess, children: /* @__PURE__ */ jsx(
|
|
153
|
+
Translation,
|
|
154
|
+
{
|
|
155
|
+
defaultMessage: "Cancel",
|
|
156
|
+
id: "AyVAAW",
|
|
157
|
+
description: "Button to cancel API key creation"
|
|
158
|
+
}
|
|
159
|
+
) }) }),
|
|
160
|
+
/* @__PURE__ */ jsx(Button, { type: "submit", loading: isPending || isSuccess, children: /* @__PURE__ */ jsx(
|
|
161
|
+
Translation,
|
|
162
|
+
{
|
|
163
|
+
defaultMessage: "Create API key",
|
|
164
|
+
id: "d4BNWL",
|
|
165
|
+
description: "Button to submit and create the API key"
|
|
166
|
+
}
|
|
167
|
+
) })
|
|
120
168
|
] })
|
|
121
169
|
]
|
|
122
170
|
}
|
|
@@ -125,14 +173,42 @@ function CreateApiKeyForm() {
|
|
|
125
173
|
}
|
|
126
174
|
function SaveApiKeyContent({ apiKey }) {
|
|
127
175
|
return /* @__PURE__ */ jsxs(Dialog.Content, { maxWidth: "529px", children: [
|
|
128
|
-
/* @__PURE__ */ jsx(Dialog.Title, { size: "4", weight: "bold", children:
|
|
129
|
-
|
|
176
|
+
/* @__PURE__ */ jsx(Dialog.Title, { size: "4", weight: "bold", children: /* @__PURE__ */ jsx(
|
|
177
|
+
Translation,
|
|
178
|
+
{
|
|
179
|
+
defaultMessage: "Save your key",
|
|
180
|
+
id: "wFFCij",
|
|
181
|
+
description: "Dialog title prompting user to save their API key"
|
|
182
|
+
}
|
|
183
|
+
) }),
|
|
184
|
+
/* @__PURE__ */ jsx(Dialog.Description, { size: "2", children: /* @__PURE__ */ jsx(
|
|
185
|
+
Translation,
|
|
186
|
+
{
|
|
187
|
+
defaultMessage: "Please save this API key in a secure location. If you lose it, you'll need to generate a new one.",
|
|
188
|
+
id: "sy+2x7",
|
|
189
|
+
description: "Warning message about saving the API key"
|
|
190
|
+
}
|
|
191
|
+
) }),
|
|
130
192
|
/* @__PURE__ */ jsxs(Callout.Root, { mt: "5", mb: "4", children: [
|
|
131
193
|
/* @__PURE__ */ jsx(Callout.Icon, { children: /* @__PURE__ */ jsx(InfoCircledIcon, {}) }),
|
|
132
|
-
/* @__PURE__ */ jsx(Callout.Text, { children:
|
|
194
|
+
/* @__PURE__ */ jsx(Callout.Text, { children: /* @__PURE__ */ jsx(
|
|
195
|
+
Translation,
|
|
196
|
+
{
|
|
197
|
+
defaultMessage: "You won't be able to access the key again. Please copy it now.",
|
|
198
|
+
id: "EFAK/K",
|
|
199
|
+
description: "Callout warning that the key won't be accessible again"
|
|
200
|
+
}
|
|
201
|
+
) })
|
|
133
202
|
] }),
|
|
134
203
|
/* @__PURE__ */ jsx(TextField, { value: apiKey, readOnly: true, children: /* @__PURE__ */ jsx(TextFieldSlot, { side: "right", children: /* @__PURE__ */ jsx(CopyIconButton, { value: apiKey }) }) }),
|
|
135
|
-
/* @__PURE__ */ jsx(Flex, { align: "center", gap: "3", justify: "end", mt: "5", children: /* @__PURE__ */ jsx(Dialog.Close, { children: /* @__PURE__ */ jsx(CopyButton, { value: apiKey, children:
|
|
204
|
+
/* @__PURE__ */ jsx(Flex, { align: "center", gap: "3", justify: "end", mt: "5", children: /* @__PURE__ */ jsx(Dialog.Close, { children: /* @__PURE__ */ jsx(CopyButton, { value: apiKey, children: /* @__PURE__ */ jsx(
|
|
205
|
+
Translation,
|
|
206
|
+
{
|
|
207
|
+
defaultMessage: "Copy and close",
|
|
208
|
+
id: "ViYtvQ",
|
|
209
|
+
description: "Button to copy API key and close dialog"
|
|
210
|
+
}
|
|
211
|
+
) }) }) })
|
|
136
212
|
] });
|
|
137
213
|
}
|
|
138
214
|
function Permission({
|
|
@@ -177,6 +253,7 @@ function PermissionsField({
|
|
|
177
253
|
const [selectedPermissions, setSelectedPermissions] = React.useState([]);
|
|
178
254
|
const [filter, setFilter] = React.useState("");
|
|
179
255
|
const fieldRef = React.useRef(null);
|
|
256
|
+
const translate = useTranslation();
|
|
180
257
|
const filteredPermissions = React.useMemo(() => {
|
|
181
258
|
return permissions.filter((p) => {
|
|
182
259
|
return !filter.trim().length || p.description?.toLowerCase().match(filter.toLowerCase()) || p.name.toLowerCase().match(filter.toLowerCase()) || p.slug.toLowerCase().match(filter.toLowerCase());
|
|
@@ -194,8 +271,22 @@ function PermissionsField({
|
|
|
194
271
|
};
|
|
195
272
|
}, [filteredPermissions.length]);
|
|
196
273
|
return /* @__PURE__ */ jsx(Form.Field, { name: "permissions", asChild: true, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", align: "stretch", gap: "1", children: [
|
|
197
|
-
/* @__PURE__ */ jsx(Form.Label, { asChild: true, children: /* @__PURE__ */ jsx(Label, { children:
|
|
198
|
-
|
|
274
|
+
/* @__PURE__ */ jsx(Form.Label, { asChild: true, children: /* @__PURE__ */ jsx(Label, { children: /* @__PURE__ */ jsx(
|
|
275
|
+
Translation,
|
|
276
|
+
{
|
|
277
|
+
defaultMessage: "Permissions",
|
|
278
|
+
id: "6YN1wO",
|
|
279
|
+
description: "Label for API key permissions field"
|
|
280
|
+
}
|
|
281
|
+
) }) }),
|
|
282
|
+
/* @__PURE__ */ jsx(Text, { size: "2", mb: "2", color: "gray", children: /* @__PURE__ */ jsx(
|
|
283
|
+
Translation,
|
|
284
|
+
{
|
|
285
|
+
defaultMessage: "Only enable the minimum permissions required for your use case.",
|
|
286
|
+
id: "q2VEtG",
|
|
287
|
+
description: "Help text for API key permissions selection"
|
|
288
|
+
}
|
|
289
|
+
) }),
|
|
199
290
|
/* @__PURE__ */ jsxs(
|
|
200
291
|
Flex,
|
|
201
292
|
{
|
|
@@ -226,7 +317,11 @@ function PermissionsField({
|
|
|
226
317
|
borderRadius: "var(--radius-3) var(--radius-3) 0 0",
|
|
227
318
|
boxShadow: "none"
|
|
228
319
|
},
|
|
229
|
-
placeholder:
|
|
320
|
+
placeholder: translate({
|
|
321
|
+
defaultMessage: "Search",
|
|
322
|
+
id: "iyNcly",
|
|
323
|
+
description: "Placeholder for permissions search input"
|
|
324
|
+
}),
|
|
230
325
|
children: /* @__PURE__ */ jsx(TextFieldSlot, { side: "left", px: "3", children: /* @__PURE__ */ jsx(MagnifyingGlassIcon, { "aria-hidden": "true", height: "16", width: "16" }) })
|
|
231
326
|
}
|
|
232
327
|
),
|
|
@@ -301,14 +396,28 @@ function PermissionsField({
|
|
|
301
396
|
}
|
|
302
397
|
}
|
|
303
398
|
),
|
|
304
|
-
/* @__PURE__ */ jsx(Text, { size: "2", align: "center", mb: "2", wrap: "balance", weight: "bold", children:
|
|
399
|
+
/* @__PURE__ */ jsx(Text, { size: "2", align: "center", mb: "2", wrap: "balance", weight: "bold", children: /* @__PURE__ */ jsx(
|
|
400
|
+
Translation,
|
|
401
|
+
{
|
|
402
|
+
defaultMessage: "No permissions match your search",
|
|
403
|
+
id: "xjqT9f",
|
|
404
|
+
description: "Empty state message when no permissions match search"
|
|
405
|
+
}
|
|
406
|
+
) }),
|
|
305
407
|
/* @__PURE__ */ jsx(
|
|
306
408
|
Button,
|
|
307
409
|
{
|
|
308
410
|
variant: "secondary",
|
|
309
411
|
size: "1",
|
|
310
412
|
onClick: () => setFilter(""),
|
|
311
|
-
children:
|
|
413
|
+
children: /* @__PURE__ */ jsx(
|
|
414
|
+
Translation,
|
|
415
|
+
{
|
|
416
|
+
defaultMessage: "Clear search",
|
|
417
|
+
id: "YrMs63",
|
|
418
|
+
description: "Button to clear permissions search"
|
|
419
|
+
}
|
|
420
|
+
)
|
|
312
421
|
}
|
|
313
422
|
)
|
|
314
423
|
]
|
|
@@ -325,14 +434,50 @@ function SelectedPermissions({
|
|
|
325
434
|
onToggle
|
|
326
435
|
}) {
|
|
327
436
|
return /* @__PURE__ */ jsxs(Flex, { align: "center", gap: "2", children: [
|
|
328
|
-
/* @__PURE__ */ jsx(Text, { size: "1", style: { lineHeight: 1, color: "var(--gray-11)" }, children: selected === 0 ?
|
|
437
|
+
/* @__PURE__ */ jsx(Text, { size: "1", style: { lineHeight: 1, color: "var(--gray-11)" }, children: selected === 0 ? /* @__PURE__ */ jsx(
|
|
438
|
+
Translation,
|
|
439
|
+
{
|
|
440
|
+
defaultMessage: "No permissions selected",
|
|
441
|
+
id: "FqU9hv",
|
|
442
|
+
description: "Message when no permissions are selected"
|
|
443
|
+
}
|
|
444
|
+
) : selected === 1 ? /* @__PURE__ */ jsx(
|
|
445
|
+
Translation,
|
|
446
|
+
{
|
|
447
|
+
defaultMessage: "1 permission selected",
|
|
448
|
+
id: "VouLgT",
|
|
449
|
+
description: "Message showing count of selected permissions"
|
|
450
|
+
}
|
|
451
|
+
) : /* @__PURE__ */ jsx(
|
|
452
|
+
Translation,
|
|
453
|
+
{
|
|
454
|
+
defaultMessage: "{count} permissions selected",
|
|
455
|
+
id: "ZL90DI",
|
|
456
|
+
description: "Message showing count of selected permissions",
|
|
457
|
+
values: { count: selected }
|
|
458
|
+
}
|
|
459
|
+
) }),
|
|
329
460
|
/* @__PURE__ */ jsx(
|
|
330
461
|
Text,
|
|
331
462
|
{
|
|
332
463
|
size: "1",
|
|
333
464
|
onClick: onToggle,
|
|
334
465
|
style: { cursor: "pointer", color: "var(--accent-10)" },
|
|
335
|
-
children: total === selected ?
|
|
466
|
+
children: total === selected ? /* @__PURE__ */ jsx(
|
|
467
|
+
Translation,
|
|
468
|
+
{
|
|
469
|
+
defaultMessage: "Deselect all",
|
|
470
|
+
id: "63f7SY",
|
|
471
|
+
description: "Button to deselect all permissions"
|
|
472
|
+
}
|
|
473
|
+
) : /* @__PURE__ */ jsx(
|
|
474
|
+
Translation,
|
|
475
|
+
{
|
|
476
|
+
defaultMessage: "Select all",
|
|
477
|
+
id: "onTqlA",
|
|
478
|
+
description: "Button to select all permissions"
|
|
479
|
+
}
|
|
480
|
+
)
|
|
336
481
|
}
|
|
337
482
|
)
|
|
338
483
|
] });
|
|
@@ -344,7 +489,14 @@ function CreateApiKeyButton() {
|
|
|
344
489
|
{
|
|
345
490
|
variant: "secondary",
|
|
346
491
|
onClick: () => dispatch({ type: "OPEN_CREATE_DIALOG" }),
|
|
347
|
-
children:
|
|
492
|
+
children: /* @__PURE__ */ jsx(
|
|
493
|
+
Translation,
|
|
494
|
+
{
|
|
495
|
+
defaultMessage: "Create API key",
|
|
496
|
+
id: "vq5724",
|
|
497
|
+
description: "Button to open create API key dialog"
|
|
498
|
+
}
|
|
499
|
+
)
|
|
348
500
|
}
|
|
349
501
|
);
|
|
350
502
|
}
|