@workos-inc/widgets 1.19.0 → 1.19.1-next.1790792916241

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.
Files changed (73) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/cjs/admin-portal-sso-connection.client.cjs +72 -75
  3. package/dist/cjs/admin-portal-sso-connection.client.cjs.map +1 -1
  4. package/dist/cjs/lib/admin-portal-audit-log-streaming.cjs +5 -22
  5. package/dist/cjs/lib/admin-portal-audit-log-streaming.cjs.map +1 -1
  6. package/dist/cjs/lib/admin-portal-sso-connection.cjs +7 -41
  7. package/dist/cjs/lib/admin-portal-sso-connection.cjs.map +1 -1
  8. package/dist/cjs/lib/admin-portal-sso-connection.d.cts +0 -1
  9. package/dist/cjs/lib/api-keys/api-key-expiration.cjs +5 -3
  10. package/dist/cjs/lib/api-keys/api-key-expiration.cjs.map +1 -1
  11. package/dist/cjs/lib/api-keys/api-key-expiration.d.cts +1 -1
  12. package/dist/cjs/lib/api-keys/create-api-key.cjs +4 -1
  13. package/dist/cjs/lib/api-keys/create-api-key.cjs.map +1 -1
  14. package/dist/cjs/lib/api-keys/relative-time.cjs +7 -12
  15. package/dist/cjs/lib/api-keys/relative-time.cjs.map +1 -1
  16. package/dist/cjs/lib/directory-sync.cjs +5 -30
  17. package/dist/cjs/lib/directory-sync.cjs.map +1 -1
  18. package/dist/cjs/lib/domain-item.cjs +5 -10
  19. package/dist/cjs/lib/domain-item.cjs.map +1 -1
  20. package/dist/cjs/lib/user-api-keys/create-user-api-key.cjs +4 -1
  21. package/dist/cjs/lib/user-api-keys/create-user-api-key.cjs.map +1 -1
  22. package/dist/cjs/lib/user-security.cjs +9 -17
  23. package/dist/cjs/lib/user-security.cjs.map +1 -1
  24. package/dist/cjs/lib/user-sessions.cjs +9 -13
  25. package/dist/cjs/lib/user-sessions.cjs.map +1 -1
  26. package/dist/cjs/lib/user-sessions.d.cts +2 -2
  27. package/dist/cjs/lib/users-management.cjs +14 -24
  28. package/dist/cjs/lib/users-management.cjs.map +1 -1
  29. package/dist/cjs/lib/utils.cjs +49 -13
  30. package/dist/cjs/lib/utils.cjs.map +1 -1
  31. package/dist/cjs/use-comparative-readable-date.cjs +70 -0
  32. package/dist/cjs/use-comparative-readable-date.cjs.map +1 -0
  33. package/dist/cjs/use-comparative-readable-date.d.cts +8 -0
  34. package/dist/cjs/use-now.cjs +101 -0
  35. package/dist/cjs/use-now.cjs.map +1 -0
  36. package/dist/cjs/use-now.d.cts +3 -0
  37. package/dist/esm/admin-portal-sso-connection.client.js +73 -66
  38. package/dist/esm/admin-portal-sso-connection.client.js.map +1 -1
  39. package/dist/esm/lib/admin-portal-audit-log-streaming.js +5 -22
  40. package/dist/esm/lib/admin-portal-audit-log-streaming.js.map +1 -1
  41. package/dist/esm/lib/admin-portal-sso-connection.d.ts +0 -1
  42. package/dist/esm/lib/admin-portal-sso-connection.js +7 -41
  43. package/dist/esm/lib/admin-portal-sso-connection.js.map +1 -1
  44. package/dist/esm/lib/api-keys/api-key-expiration.d.ts +1 -1
  45. package/dist/esm/lib/api-keys/api-key-expiration.js +5 -3
  46. package/dist/esm/lib/api-keys/api-key-expiration.js.map +1 -1
  47. package/dist/esm/lib/api-keys/create-api-key.js +4 -1
  48. package/dist/esm/lib/api-keys/create-api-key.js.map +1 -1
  49. package/dist/esm/lib/api-keys/relative-time.js +7 -12
  50. package/dist/esm/lib/api-keys/relative-time.js.map +1 -1
  51. package/dist/esm/lib/directory-sync.js +5 -30
  52. package/dist/esm/lib/directory-sync.js.map +1 -1
  53. package/dist/esm/lib/domain-item.js +5 -10
  54. package/dist/esm/lib/domain-item.js.map +1 -1
  55. package/dist/esm/lib/identity-providers.d.ts +2 -2
  56. package/dist/esm/lib/user-api-keys/create-user-api-key.js +4 -1
  57. package/dist/esm/lib/user-api-keys/create-user-api-key.js.map +1 -1
  58. package/dist/esm/lib/user-security.js +9 -18
  59. package/dist/esm/lib/user-security.js.map +1 -1
  60. package/dist/esm/lib/user-sessions.d.ts +2 -2
  61. package/dist/esm/lib/user-sessions.js +9 -14
  62. package/dist/esm/lib/user-sessions.js.map +1 -1
  63. package/dist/esm/lib/users-management.js +14 -25
  64. package/dist/esm/lib/users-management.js.map +1 -1
  65. package/dist/esm/lib/utils.js +49 -13
  66. package/dist/esm/lib/utils.js.map +1 -1
  67. package/dist/esm/use-comparative-readable-date.d.ts +8 -0
  68. package/dist/esm/use-comparative-readable-date.js +36 -0
  69. package/dist/esm/use-comparative-readable-date.js.map +1 -0
  70. package/dist/esm/use-now.d.ts +3 -0
  71. package/dist/esm/use-now.js +67 -0
  72. package/dist/esm/use-now.js.map +1 -0
  73. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.19.1-next.1790792916241
4
+
5
+ ### Patch Changes
6
+
7
+ - Unify relative date display logic across all Widgets.
8
+
9
+ - Stabilize dates during render to prevent dates re-rendering arbitrarily
10
+
3
11
  ## 1.19.0
4
12
 
5
13
  ### Minor Changes
@@ -1,10 +1,8 @@
1
1
  "use strict";
2
2
  "use client";
3
- var __create = Object.create;
4
3
  var __defProp = Object.defineProperty;
5
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
- var __getProtoOf = Object.getPrototypeOf;
8
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
7
  var __export = (target, all) => {
10
8
  for (var name in all)
@@ -18,14 +16,6 @@ var __copyProps = (to, from, except, desc) => {
18
16
  }
19
17
  return to;
20
18
  };
21
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
- // If the importer is in node compatibility mode or this is not an ESM
23
- // file that has been converted to a CommonJS file using a Babel-
24
- // compatible transform (i.e. "__esModule" has not been set), then set
25
- // "default" to the CommonJS "module.exports" for node compatibility.
26
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
- mod
28
- ));
29
19
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
20
  var admin_portal_sso_connection_client_exports = {};
31
21
  __export(admin_portal_sso_connection_client_exports, {
@@ -35,13 +25,13 @@ __export(admin_portal_sso_connection_client_exports, {
35
25
  });
36
26
  module.exports = __toCommonJS(admin_portal_sso_connection_client_exports);
37
27
  var import_jsx_runtime = require("react/jsx-runtime");
38
- var React = __toESM(require("react"), 1);
39
28
  var import_admin_portal_sso_connection = require("./lib/admin-portal-sso-connection.js");
40
29
  var import_api_provider = require("./api/api-provider.js");
41
30
  var import_hooks = require("./api/client-graphql/hooks.js");
42
31
  var import_widgets_context = require("./lib/widgets-context.js");
43
32
  var import_error_boundary = require("./lib/error-boundary.js");
44
33
  var import_utils = require("./lib/utils.js");
34
+ var import_use_now = require("./use-now.js");
45
35
  const AdminPortalSsoConnection = ({
46
36
  authToken,
47
37
  ...domProps
@@ -64,14 +54,10 @@ const AdminPortalSsoConnection = ({
64
54
  );
65
55
  };
66
56
  const AdminPortalSsoConnectionImpl = (props) => {
67
- const isApiReady = (0, import_api_provider.useApiReady)();
68
- const [currentDate, setCurrentDate] = React.useState(
69
- () => isApiReady ? /* @__PURE__ */ new Date() : null
70
- );
71
- if (isApiReady && currentDate === null) {
72
- setCurrentDate(/* @__PURE__ */ new Date());
73
- }
74
- const { mutate: generateAdminPortalLink, isPending } = (0, import_hooks.useClientGraphqlMutation)({
57
+ const {
58
+ mutate: generateAdminPortalLink,
59
+ isPending: isGeneratingAdminPortalLink
60
+ } = (0, import_hooks.useClientGraphqlMutation)({
75
61
  mutationFn: (sdk, intent) => sdk.CreateAdminPortalLink({ intent }),
76
62
  onSuccess: (data) => {
77
63
  (0, import_utils.openAdminPortalViaForm)(data.createAdminPortalLink.link, {
@@ -85,9 +71,6 @@ const AdminPortalSsoConnectionImpl = (props) => {
85
71
  queryFn: (sdk) => sdk.ListSsoConnections(),
86
72
  select: (data) => data.ssoConnections
87
73
  });
88
- const initConfig = () => {
89
- generateAdminPortalLink("Sso");
90
- };
91
74
  if (query.isLoading) {
92
75
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_admin_portal_sso_connection.AdminPortalSsoConnectionLoading, { ...props });
93
76
  }
@@ -95,6 +78,7 @@ const AdminPortalSsoConnectionImpl = (props) => {
95
78
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_admin_portal_sso_connection.AdminPortalSsoConnectionError, { error: query.error, ...props });
96
79
  }
97
80
  if (query.data) {
81
+ const initConfig = () => generateAdminPortalLink("Sso");
98
82
  const connection = query.data[0];
99
83
  if (!connection) {
100
84
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -106,12 +90,11 @@ const AdminPortalSsoConnectionImpl = (props) => {
106
90
  {
107
91
  ...props,
108
92
  connectionStatus: "NotConfigured",
109
- currentDate,
110
93
  lastSession: null,
111
94
  adminPortalOpenButton: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
112
95
  import_admin_portal_sso_connection.AdminPortalOpenButton,
113
96
  {
114
- isPending,
97
+ isPending: isGeneratingAdminPortalLink,
115
98
  initConfig
116
99
  }
117
100
  )
@@ -120,62 +103,78 @@ const AdminPortalSsoConnectionImpl = (props) => {
120
103
  }
121
104
  );
122
105
  }
123
- const connectionState = getConnectionState(connection, currentDate);
124
- const statusProps = (() => {
125
- const connectionStatus = connectionState.status;
126
- if (!connection || connectionStatus === "NotConfigured") {
127
- return {
128
- connectionStatus: "NotConfigured"
129
- };
130
- }
131
- const identityProvider = getIdentityProvider(connection.type);
132
- switch (connectionStatus) {
133
- case "Active":
134
- return {
135
- connectionStatus,
136
- identityProvider
137
- };
138
- case "Inactive":
139
- return {
140
- connectionStatus,
141
- identityProvider
142
- };
143
- case "Expired":
144
- case "Expiring":
145
- return {
146
- connectionStatus,
147
- expiryDate: connectionState.expiryDate,
148
- identityProvider
149
- };
150
- default:
151
- return (0, import_utils.unreachable)(connectionState);
152
- }
153
- })();
154
- const lastSession = connection.lastSession ? new Date(connection.lastSession.createdAt) : null;
155
106
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
156
107
  import_error_boundary.ErrorBoundary,
157
108
  {
158
109
  fallbackRender: ({ error }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_admin_portal_sso_connection.AdminPortalSsoConnectionError, { error, ...props }),
159
110
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
160
- import_admin_portal_sso_connection.AdminPortalSsoConnection,
111
+ AdminPortalSsoConnectionReady,
161
112
  {
162
113
  ...props,
163
- ...statusProps,
164
- currentDate,
165
- lastSession,
166
- adminPortalOpenButton: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
167
- import_admin_portal_sso_connection.AdminPortalOpenButton,
168
- {
169
- isPending,
170
- initConfig
171
- }
172
- )
114
+ connection,
115
+ isGeneratingAdminPortalLink,
116
+ initConfig
173
117
  }
174
118
  )
175
119
  }
176
120
  );
177
121
  }
178
122
  };
123
+ function AdminPortalSsoConnectionReady({
124
+ connection,
125
+ isGeneratingAdminPortalLink,
126
+ initConfig,
127
+ ...props
128
+ }) {
129
+ const currentDate = (0, import_use_now.useNow)();
130
+ const connectionState = getConnectionState(connection, currentDate);
131
+ const statusProps = (() => {
132
+ const connectionStatus = connectionState.status;
133
+ if (connectionStatus === "NotConfigured") {
134
+ return {
135
+ connectionStatus: "NotConfigured"
136
+ };
137
+ }
138
+ const identityProvider = getIdentityProvider(connection.type);
139
+ switch (connectionStatus) {
140
+ case "Active":
141
+ return {
142
+ connectionStatus,
143
+ identityProvider
144
+ };
145
+ case "Inactive":
146
+ return {
147
+ connectionStatus,
148
+ identityProvider
149
+ };
150
+ case "Expired":
151
+ case "Expiring":
152
+ return {
153
+ connectionStatus,
154
+ expiryDate: connectionState.expiryDate,
155
+ identityProvider
156
+ };
157
+ default:
158
+ return (0, import_utils.unreachable)(connectionState);
159
+ }
160
+ })();
161
+ const lastSession = connection.lastSession ? new Date(connection.lastSession.createdAt) : null;
162
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
163
+ import_admin_portal_sso_connection.AdminPortalSsoConnection,
164
+ {
165
+ ...props,
166
+ ...statusProps,
167
+ lastSession,
168
+ adminPortalOpenButton: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
169
+ import_admin_portal_sso_connection.AdminPortalOpenButton,
170
+ {
171
+ isPending: isGeneratingAdminPortalLink,
172
+ initConfig
173
+ }
174
+ )
175
+ }
176
+ );
177
+ }
179
178
  function getConnectionState(connection, currentDate) {
180
179
  switch (connection.state) {
181
180
  case "Active":
@@ -196,14 +195,12 @@ function getConnectionState(connection, currentDate) {
196
195
  return activeStatus;
197
196
  }
198
197
  const expiryDate = new Date(expiryTime);
199
- const daysUntilExpiry = (() => {
200
- const diff = expiryDate.getTime() - currentDate.getTime();
201
- if (diff < 0) {
202
- return -1;
203
- }
204
- return diff / (1e3 * 60 * 60 * 24);
205
- })();
206
- if (daysUntilExpiry !== -1 && daysUntilExpiry <= 30) {
198
+ const millisecondsUntilExpiry = expiryDate.getTime() - currentDate.getTime();
199
+ if (millisecondsUntilExpiry < 0) {
200
+ return { status: "Expired", expiryDate };
201
+ }
202
+ const daysUntilExpiry = millisecondsUntilExpiry / (1e3 * 60 * 60 * 24);
203
+ if (daysUntilExpiry <= 30) {
207
204
  return { status: "Expiring", daysUntilExpiry, expiryDate };
208
205
  }
209
206
  return activeStatus;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/admin-portal-sso-connection.client.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport {\n AdminPortalOpenButton,\n AdminPortalSsoConnectionError,\n AdminPortalSsoConnectionLoading,\n AdminPortalSsoConnection as AdminPortalSsoConnectionPresentational,\n} from \"./lib/admin-portal-sso-connection.js\";\nimport type {\n AdminPortalSsoConnectionErrorProps,\n AdminPortalSsoConnectionLoadingProps,\n AdminPortalSsoConnectionStatusProps,\n} from \"./lib/admin-portal-sso-connection.js\";\nimport { ApiProvider, AuthToken, useApiReady } from \"./api/api-provider.js\";\nimport {\n clientGraphqlQueryKey,\n useClientGraphqlMutation,\n useClientGraphqlQuery,\n} from \"./api/client-graphql/hooks.js\";\nimport type {\n AdminPortalLinkIntent,\n ConnectionFieldsFragment,\n ConnectionType,\n} from \"./api/client-graphql/generated.js\";\nimport { useWorkOsApiUrl } from \"./lib/widgets-context.js\";\nimport { ErrorBoundary } from \"./lib/error-boundary.js\";\nimport {\n openAdminPortalViaForm,\n unreachable,\n WidgetRootDomProps,\n} from \"./lib/utils.js\";\nimport { IdentityProvider } from \"./lib/identity-providers.js\";\n\ninterface AdminPortalSsoConnectionProps extends WidgetRootDomProps {\n authToken: AuthToken;\n}\n\nconst AdminPortalSsoConnection: React.FC<AdminPortalSsoConnectionProps> = ({\n authToken,\n ...domProps\n}) => {\n const baseUrl = useWorkOsApiUrl();\n return (\n <ErrorBoundary\n fallbackRender={({ error }) => (\n <AdminPortalSsoConnectionError error={error} {...domProps} />\n )}\n >\n <ApiProvider\n widgetType=\"admin-portal-sso-connection\"\n authToken={authToken}\n baseUrl={baseUrl}\n >\n <AdminPortalSsoConnectionImpl {...domProps} />\n </ApiProvider>\n </ErrorBoundary>\n );\n};\n\nconst AdminPortalSsoConnectionImpl = (props: WidgetRootDomProps) => {\n const isApiReady = useApiReady();\n const [currentDate, setCurrentDate] = React.useState<Date | null>(() =>\n isApiReady ? new Date() : null,\n );\n if (isApiReady && currentDate === null) {\n setCurrentDate(new Date());\n }\n\n const { mutate: generateAdminPortalLink, isPending } =\n useClientGraphqlMutation({\n mutationFn: (sdk, intent: AdminPortalLinkIntent) =>\n sdk.CreateAdminPortalLink({ intent }),\n onSuccess: (data) => {\n openAdminPortalViaForm(data.createAdminPortalLink.link, {\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n });\n },\n });\n\n const query = useClientGraphqlQuery({\n queryKey: clientGraphqlQueryKey(\"ListSsoConnections\"),\n queryFn: (sdk) => sdk.ListSsoConnections(),\n select: (data) => data.ssoConnections,\n });\n\n const initConfig = () => {\n generateAdminPortalLink(\"Sso\");\n };\n\n if (query.isLoading) {\n return <AdminPortalSsoConnectionLoading {...props} />;\n }\n\n if (query.isError) {\n return <AdminPortalSsoConnectionError error={query.error} {...props} />;\n }\n\n if (query.data) {\n const connection = query.data[0];\n if (!connection) {\n return (\n <ErrorBoundary\n fallbackRender={({ error }) => (\n <AdminPortalSsoConnectionError error={error} {...props} />\n )}\n >\n <AdminPortalSsoConnectionPresentational\n {...props}\n connectionStatus=\"NotConfigured\"\n currentDate={currentDate}\n lastSession={null}\n adminPortalOpenButton={\n <AdminPortalOpenButton\n isPending={isPending}\n initConfig={initConfig}\n />\n }\n />\n </ErrorBoundary>\n );\n }\n\n const connectionState = getConnectionState(connection, currentDate);\n const statusProps: AdminPortalSsoConnectionStatusProps = (() => {\n const connectionStatus = connectionState.status;\n if (!connection || connectionStatus === \"NotConfigured\") {\n return {\n connectionStatus: \"NotConfigured\",\n } satisfies AdminPortalSsoConnectionStatusProps;\n }\n\n const identityProvider = getIdentityProvider(connection.type);\n switch (connectionStatus) {\n case \"Active\":\n return {\n connectionStatus,\n identityProvider,\n } satisfies AdminPortalSsoConnectionStatusProps;\n case \"Inactive\":\n return {\n connectionStatus,\n identityProvider,\n } satisfies AdminPortalSsoConnectionStatusProps;\n case \"Expired\":\n case \"Expiring\":\n return {\n connectionStatus,\n expiryDate: connectionState.expiryDate,\n identityProvider,\n } satisfies AdminPortalSsoConnectionStatusProps;\n default:\n return unreachable(connectionState);\n }\n })();\n\n const lastSession = connection.lastSession\n ? new Date(connection.lastSession.createdAt)\n : null;\n\n return (\n <ErrorBoundary\n fallbackRender={({ error }) => (\n <AdminPortalSsoConnectionError error={error} {...props} />\n )}\n >\n <AdminPortalSsoConnectionPresentational\n {...props}\n {...statusProps}\n currentDate={currentDate}\n lastSession={lastSession}\n adminPortalOpenButton={\n <AdminPortalOpenButton\n isPending={isPending}\n initConfig={initConfig}\n />\n }\n />\n </ErrorBoundary>\n );\n }\n};\n\ntype ConnectionState =\n | { status: \"NotConfigured\" }\n | { status: \"Active\" }\n | { status: \"Inactive\" }\n | {\n status: \"Expiring\";\n daysUntilExpiry: number | null;\n expiryDate: Date | null;\n }\n | { status: \"Expired\"; expiryDate: Date | null };\n\nfunction getConnectionState(\n connection: ConnectionFieldsFragment,\n currentDate: Date | null,\n): ConnectionState {\n switch (connection.state) {\n case \"Active\":\n case \"Validating\":\n case \"Deleting\": {\n const activeStatus = { status: \"Active\" } satisfies ConnectionState;\n if (connection.providerTag !== \"Saml\") {\n return activeStatus;\n }\n\n if (connection.latestExpiredCertificate) {\n return {\n status: \"Expired\",\n expiryDate: connection.latestExpiredCertificate.notAfter\n ? new Date(connection.latestExpiredCertificate.notAfter)\n : null,\n };\n }\n\n const expiryTime = connection.latestExpiringCertificate?.notAfter;\n if (currentDate == null || expiryTime == null) {\n return activeStatus;\n }\n\n const expiryDate = new Date(expiryTime);\n const daysUntilExpiry = (() => {\n const diff = expiryDate.getTime() - currentDate.getTime();\n if (diff < 0) {\n return -1;\n }\n\n return diff / (1000 * 60 * 60 * 24);\n })();\n\n if (daysUntilExpiry !== -1 && daysUntilExpiry <= 30) {\n return { status: \"Expiring\", daysUntilExpiry, expiryDate };\n }\n\n return activeStatus;\n }\n case \"Inactive\": {\n return { status: \"Inactive\" };\n }\n default:\n return unreachable(connection.state);\n }\n}\n\nfunction getIdentityProvider(type: ConnectionType): IdentityProvider {\n switch (type) {\n case \"ADFSSAML\":\n case \"EntraIdOIDC\":\n case \"MicrosoftOAuth\":\n return \"microsoft\";\n case \"Auth0Migration\":\n case \"Auth0SAML\":\n return \"auth0\";\n case \"AzureSAML\":\n return \"azure\";\n case \"CasSAML\":\n return \"cas\";\n case \"ClassLinkSAML\":\n return \"classlink\";\n case \"CloudflareSAML\":\n return \"cloudflare\";\n case \"CyberArkSAML\":\n return \"cyberark\";\n case \"DuoSAML\":\n return \"duo\";\n case \"GenericSAML\":\n return \"generic-saml\";\n case \"GoogleSAML\":\n case \"GoogleOIDC\":\n case \"GoogleOAuth\":\n return \"google\";\n case \"JumpCloudSAML\":\n return \"jumpcloud\";\n case \"KeycloakSAML\":\n return \"keycloak\";\n case \"LastPassSAML\":\n return \"lastpass\";\n case \"MiniOrangeSAML\":\n return \"miniorange\";\n case \"NetIqSAML\":\n return \"net-iq\";\n case \"OktaOIDC\":\n case \"OktaSAML\":\n return \"okta\";\n case \"OneLoginSAML\":\n return \"onelogin\";\n case \"OracleSAML\":\n return \"oracle\";\n case \"PingFederateSAML\":\n case \"PingOneSAML\":\n return \"ping-identity\";\n case \"RipplingSAML\":\n return \"rippling\";\n case \"SalesforceSAML\":\n case \"SalesforceOAuth\":\n return \"salesforce\";\n case \"ShibbolethGenericSAML\":\n case \"ShibbolethSAML\":\n return \"shibboleth\";\n case \"SimpleSamlPhpSAML\":\n return \"simple-saml-php\";\n case \"TestIdp\":\n return \"test-idp\";\n case \"VMwareSAML\":\n return \"vmware\";\n case \"AdpOidc\":\n return \"adp\";\n case \"GenericOIDC\":\n return \"generic-oidc\";\n case \"LoginGovOidc\":\n return \"login-gov\";\n case \"CleverOIDC\":\n return \"clever\";\n case \"AppleOAuth\":\n return \"apple\";\n case \"BitbucketOAuth\":\n return \"bitbucket\";\n case \"DiscordOAuth\":\n return \"discord\";\n case \"GithubOAuth\":\n return \"github\";\n case \"GitLabOAuth\":\n return \"gitlab\";\n case \"IntuitOAuth\":\n return \"intuit\";\n case \"LinkedInOAuth\":\n return \"linkedin\";\n case \"SlackOAuth\":\n return \"slack\";\n case \"VercelOAuth\":\n case \"VercelMarketplaceOAuth\":\n return \"vercel\";\n case \"XeroOAuth\":\n return \"xero\";\n case \"GrokOAuth\":\n case \"XOAuth\":\n case \"MagicLink\":\n return \"workos\";\n default:\n return unreachable(type);\n }\n}\n\nexport type {\n AdminPortalSsoConnectionProps,\n AdminPortalSsoConnectionLoadingProps,\n AdminPortalSsoConnectionErrorProps,\n};\nexport {\n AdminPortalSsoConnection,\n AdminPortalSsoConnectionLoading,\n AdminPortalSsoConnectionError,\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA8CQ;AA5CR,YAAuB;AACvB,yCAKO;AAMP,0BAAoD;AACpD,mBAIO;AAMP,6BAAgC;AAChC,4BAA8B;AAC9B,mBAIO;AAOP,MAAM,2BAAoE,CAAC;AAAA,EACzE;AAAA,EACA,GAAG;AACL,MAAM;AACJ,QAAM,cAAU,wCAAgB;AAChC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,gBAAgB,CAAC,EAAE,MAAM,MACvB,4CAAC,oEAA8B,OAAe,GAAG,UAAU;AAAA,MAG7D;AAAA,QAAC;AAAA;AAAA,UACC,YAAW;AAAA,UACX;AAAA,UACA;AAAA,UAEA,sDAAC,gCAA8B,GAAG,UAAU;AAAA;AAAA,MAC9C;AAAA;AAAA,EACF;AAEJ;AAEA,MAAM,+BAA+B,CAAC,UAA8B;AAClE,QAAM,iBAAa,iCAAY;AAC/B,QAAM,CAAC,aAAa,cAAc,IAAI,MAAM;AAAA,IAAsB,MAChE,aAAa,oBAAI,KAAK,IAAI;AAAA,EAC5B;AACA,MAAI,cAAc,gBAAgB,MAAM;AACtC,mBAAe,oBAAI,KAAK,CAAC;AAAA,EAC3B;AAEA,QAAM,EAAE,QAAQ,yBAAyB,UAAU,QACjD,uCAAyB;AAAA,IACvB,YAAY,CAAC,KAAK,WAChB,IAAI,sBAAsB,EAAE,OAAO,CAAC;AAAA,IACtC,WAAW,CAAC,SAAS;AACnB,+CAAuB,KAAK,sBAAsB,MAAM;AAAA,QACtD,QAAQ;AAAA,QACR,KAAK;AAAA,MACP,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AAEH,QAAM,YAAQ,oCAAsB;AAAA,IAClC,cAAU,oCAAsB,oBAAoB;AAAA,IACpD,SAAS,CAAC,QAAQ,IAAI,mBAAmB;AAAA,IACzC,QAAQ,CAAC,SAAS,KAAK;AAAA,EACzB,CAAC;AAED,QAAM,aAAa,MAAM;AACvB,4BAAwB,KAAK;AAAA,EAC/B;AAEA,MAAI,MAAM,WAAW;AACnB,WAAO,4CAAC,sEAAiC,GAAG,OAAO;AAAA,EACrD;AAEA,MAAI,MAAM,SAAS;AACjB,WAAO,4CAAC,oEAA8B,OAAO,MAAM,OAAQ,GAAG,OAAO;AAAA,EACvE;AAEA,MAAI,MAAM,MAAM;AACd,UAAM,aAAa,MAAM,KAAK,CAAC;AAC/B,QAAI,CAAC,YAAY;AACf,aACE;AAAA,QAAC;AAAA;AAAA,UACC,gBAAgB,CAAC,EAAE,MAAM,MACvB,4CAAC,oEAA8B,OAAe,GAAG,OAAO;AAAA,UAG1D;AAAA,YAAC,mCAAAA;AAAA,YAAA;AAAA,cACE,GAAG;AAAA,cACJ,kBAAiB;AAAA,cACjB;AAAA,cACA,aAAa;AAAA,cACb,uBACE;AAAA,gBAAC;AAAA;AAAA,kBACC;AAAA,kBACA;AAAA;AAAA,cACF;AAAA;AAAA,UAEJ;AAAA;AAAA,MACF;AAAA,IAEJ;AAEA,UAAM,kBAAkB,mBAAmB,YAAY,WAAW;AAClE,UAAM,eAAoD,MAAM;AAC9D,YAAM,mBAAmB,gBAAgB;AACzC,UAAI,CAAC,cAAc,qBAAqB,iBAAiB;AACvD,eAAO;AAAA,UACL,kBAAkB;AAAA,QACpB;AAAA,MACF;AAEA,YAAM,mBAAmB,oBAAoB,WAAW,IAAI;AAC5D,cAAQ,kBAAkB;AAAA,QACxB,KAAK;AACH,iBAAO;AAAA,YACL;AAAA,YACA;AAAA,UACF;AAAA,QACF,KAAK;AACH,iBAAO;AAAA,YACL;AAAA,YACA;AAAA,UACF;AAAA,QACF,KAAK;AAAA,QACL,KAAK;AACH,iBAAO;AAAA,YACL;AAAA,YACA,YAAY,gBAAgB;AAAA,YAC5B;AAAA,UACF;AAAA,QACF;AACE,qBAAO,0BAAY,eAAe;AAAA,MACtC;AAAA,IACF,GAAG;AAEH,UAAM,cAAc,WAAW,cAC3B,IAAI,KAAK,WAAW,YAAY,SAAS,IACzC;AAEJ,WACE;AAAA,MAAC;AAAA;AAAA,QACC,gBAAgB,CAAC,EAAE,MAAM,MACvB,4CAAC,oEAA8B,OAAe,GAAG,OAAO;AAAA,QAG1D;AAAA,UAAC,mCAAAA;AAAA,UAAA;AAAA,YACE,GAAG;AAAA,YACH,GAAG;AAAA,YACJ;AAAA,YACA;AAAA,YACA,uBACE;AAAA,cAAC;AAAA;AAAA,gBACC;AAAA,gBACA;AAAA;AAAA,YACF;AAAA;AAAA,QAEJ;AAAA;AAAA,IACF;AAAA,EAEJ;AACF;AAaA,SAAS,mBACP,YACA,aACiB;AACjB,UAAQ,WAAW,OAAO;AAAA,IACxB,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK,YAAY;AACf,YAAM,eAAe,EAAE,QAAQ,SAAS;AACxC,UAAI,WAAW,gBAAgB,QAAQ;AACrC,eAAO;AAAA,MACT;AAEA,UAAI,WAAW,0BAA0B;AACvC,eAAO;AAAA,UACL,QAAQ;AAAA,UACR,YAAY,WAAW,yBAAyB,WAC5C,IAAI,KAAK,WAAW,yBAAyB,QAAQ,IACrD;AAAA,QACN;AAAA,MACF;AAEA,YAAM,aAAa,WAAW,2BAA2B;AACzD,UAAI,eAAe,QAAQ,cAAc,MAAM;AAC7C,eAAO;AAAA,MACT;AAEA,YAAM,aAAa,IAAI,KAAK,UAAU;AACtC,YAAM,mBAAmB,MAAM;AAC7B,cAAM,OAAO,WAAW,QAAQ,IAAI,YAAY,QAAQ;AACxD,YAAI,OAAO,GAAG;AACZ,iBAAO;AAAA,QACT;AAEA,eAAO,QAAQ,MAAO,KAAK,KAAK;AAAA,MAClC,GAAG;AAEH,UAAI,oBAAoB,MAAM,mBAAmB,IAAI;AACnD,eAAO,EAAE,QAAQ,YAAY,iBAAiB,WAAW;AAAA,MAC3D;AAEA,aAAO;AAAA,IACT;AAAA,IACA,KAAK,YAAY;AACf,aAAO,EAAE,QAAQ,WAAW;AAAA,IAC9B;AAAA,IACA;AACE,iBAAO,0BAAY,WAAW,KAAK;AAAA,EACvC;AACF;AAEA,SAAS,oBAAoB,MAAwC;AACnE,UAAQ,MAAM;AAAA,IACZ,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT;AACE,iBAAO,0BAAY,IAAI;AAAA,EAC3B;AACF;","names":["AdminPortalSsoConnectionPresentational"]}
1
+ {"version":3,"sources":["../../src/admin-portal-sso-connection.client.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport {\n AdminPortalOpenButton,\n AdminPortalSsoConnectionError,\n AdminPortalSsoConnectionLoading,\n AdminPortalSsoConnection as AdminPortalSsoConnectionPresentational,\n} from \"./lib/admin-portal-sso-connection.js\";\nimport type {\n AdminPortalSsoConnectionErrorProps,\n AdminPortalSsoConnectionLoadingProps,\n AdminPortalSsoConnectionStatusProps,\n} from \"./lib/admin-portal-sso-connection.js\";\nimport { ApiProvider, AuthToken } from \"./api/api-provider.js\";\nimport {\n clientGraphqlQueryKey,\n useClientGraphqlMutation,\n useClientGraphqlQuery,\n} from \"./api/client-graphql/hooks.js\";\nimport type {\n AdminPortalLinkIntent,\n ConnectionFieldsFragment,\n ConnectionType,\n} from \"./api/client-graphql/generated.js\";\nimport { useWorkOsApiUrl } from \"./lib/widgets-context.js\";\nimport { ErrorBoundary } from \"./lib/error-boundary.js\";\nimport {\n openAdminPortalViaForm,\n unreachable,\n WidgetRootDomProps,\n} from \"./lib/utils.js\";\nimport { IdentityProvider } from \"./lib/identity-providers.js\";\nimport { useNow } from \"./use-now.js\";\n\ninterface AdminPortalSsoConnectionProps extends WidgetRootDomProps {\n authToken: AuthToken;\n}\n\nconst AdminPortalSsoConnection: React.FC<AdminPortalSsoConnectionProps> = ({\n authToken,\n ...domProps\n}) => {\n const baseUrl = useWorkOsApiUrl();\n return (\n <ErrorBoundary\n fallbackRender={({ error }) => (\n <AdminPortalSsoConnectionError error={error} {...domProps} />\n )}\n >\n <ApiProvider\n widgetType=\"admin-portal-sso-connection\"\n authToken={authToken}\n baseUrl={baseUrl}\n >\n <AdminPortalSsoConnectionImpl {...domProps} />\n </ApiProvider>\n </ErrorBoundary>\n );\n};\n\nconst AdminPortalSsoConnectionImpl = (props: WidgetRootDomProps) => {\n const {\n mutate: generateAdminPortalLink,\n isPending: isGeneratingAdminPortalLink,\n } = useClientGraphqlMutation({\n mutationFn: (sdk, intent: AdminPortalLinkIntent) =>\n sdk.CreateAdminPortalLink({ intent }),\n onSuccess: (data) => {\n openAdminPortalViaForm(data.createAdminPortalLink.link, {\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n });\n },\n });\n\n const query = useClientGraphqlQuery({\n queryKey: clientGraphqlQueryKey(\"ListSsoConnections\"),\n queryFn: (sdk) => sdk.ListSsoConnections(),\n select: (data) => data.ssoConnections,\n });\n\n if (query.isLoading) {\n return <AdminPortalSsoConnectionLoading {...props} />;\n }\n\n if (query.isError) {\n return <AdminPortalSsoConnectionError error={query.error} {...props} />;\n }\n\n if (query.data) {\n const initConfig = () => generateAdminPortalLink(\"Sso\");\n const connection = query.data[0];\n if (!connection) {\n return (\n <ErrorBoundary\n fallbackRender={({ error }) => (\n <AdminPortalSsoConnectionError error={error} {...props} />\n )}\n >\n <AdminPortalSsoConnectionPresentational\n {...props}\n connectionStatus=\"NotConfigured\"\n lastSession={null}\n adminPortalOpenButton={\n <AdminPortalOpenButton\n isPending={isGeneratingAdminPortalLink}\n initConfig={initConfig}\n />\n }\n />\n </ErrorBoundary>\n );\n }\n\n return (\n <ErrorBoundary\n fallbackRender={({ error }) => (\n <AdminPortalSsoConnectionError error={error} {...props} />\n )}\n >\n <AdminPortalSsoConnectionReady\n {...props}\n connection={connection}\n isGeneratingAdminPortalLink={isGeneratingAdminPortalLink}\n initConfig={initConfig}\n />\n </ErrorBoundary>\n );\n }\n};\n\nfunction AdminPortalSsoConnectionReady({\n connection,\n isGeneratingAdminPortalLink,\n initConfig,\n ...props\n}: WidgetRootDomProps & {\n connection: ConnectionFieldsFragment;\n isGeneratingAdminPortalLink: boolean;\n initConfig: () => void;\n}) {\n const currentDate = useNow();\n const connectionState = getConnectionState(connection, currentDate);\n const statusProps: AdminPortalSsoConnectionStatusProps = (() => {\n const connectionStatus = connectionState.status;\n if (connectionStatus === \"NotConfigured\") {\n return {\n connectionStatus: \"NotConfigured\",\n } satisfies AdminPortalSsoConnectionStatusProps;\n }\n\n const identityProvider = getIdentityProvider(connection.type);\n switch (connectionStatus) {\n case \"Active\":\n return {\n connectionStatus,\n identityProvider,\n } satisfies AdminPortalSsoConnectionStatusProps;\n case \"Inactive\":\n return {\n connectionStatus,\n identityProvider,\n } satisfies AdminPortalSsoConnectionStatusProps;\n case \"Expired\":\n case \"Expiring\":\n return {\n connectionStatus,\n expiryDate: connectionState.expiryDate,\n identityProvider,\n } satisfies AdminPortalSsoConnectionStatusProps;\n default:\n return unreachable(connectionState);\n }\n })();\n\n const lastSession = connection.lastSession\n ? new Date(connection.lastSession.createdAt)\n : null;\n\n return (\n <AdminPortalSsoConnectionPresentational\n {...props}\n {...statusProps}\n lastSession={lastSession}\n adminPortalOpenButton={\n <AdminPortalOpenButton\n isPending={isGeneratingAdminPortalLink}\n initConfig={initConfig}\n />\n }\n />\n );\n}\n\ntype ConnectionState =\n | { status: \"NotConfigured\" }\n | { status: \"Active\" }\n | { status: \"Inactive\" }\n | {\n status: \"Expiring\";\n daysUntilExpiry: number | null;\n expiryDate: Date | null;\n }\n | { status: \"Expired\"; expiryDate: Date | null };\n\nfunction getConnectionState(\n connection: ConnectionFieldsFragment,\n currentDate: Date | null,\n): ConnectionState {\n switch (connection.state) {\n case \"Active\":\n case \"Validating\":\n case \"Deleting\": {\n const activeStatus = { status: \"Active\" } satisfies ConnectionState;\n if (connection.providerTag !== \"Saml\") {\n return activeStatus;\n }\n\n if (connection.latestExpiredCertificate) {\n return {\n status: \"Expired\",\n expiryDate: connection.latestExpiredCertificate.notAfter\n ? new Date(connection.latestExpiredCertificate.notAfter)\n : null,\n };\n }\n\n const expiryTime = connection.latestExpiringCertificate?.notAfter;\n if (currentDate == null || expiryTime == null) {\n return activeStatus;\n }\n\n const expiryDate = new Date(expiryTime);\n const millisecondsUntilExpiry =\n expiryDate.getTime() - currentDate.getTime();\n\n // This certificate is the longest-lived one the server still treats as\n // unexpired. Once `notAfter` passes, the cached query has not yet moved\n // it to `latestExpiredCertificate`, so derive Expired locally.\n if (millisecondsUntilExpiry < 0) {\n return { status: \"Expired\", expiryDate };\n }\n\n const daysUntilExpiry = millisecondsUntilExpiry / (1000 * 60 * 60 * 24);\n if (daysUntilExpiry <= 30) {\n return { status: \"Expiring\", daysUntilExpiry, expiryDate };\n }\n\n return activeStatus;\n }\n case \"Inactive\": {\n return { status: \"Inactive\" };\n }\n default:\n return unreachable(connection.state);\n }\n}\n\nfunction getIdentityProvider(type: ConnectionType): IdentityProvider {\n switch (type) {\n case \"ADFSSAML\":\n case \"EntraIdOIDC\":\n case \"MicrosoftOAuth\":\n return \"microsoft\";\n case \"Auth0Migration\":\n case \"Auth0SAML\":\n return \"auth0\";\n case \"AzureSAML\":\n return \"azure\";\n case \"CasSAML\":\n return \"cas\";\n case \"ClassLinkSAML\":\n return \"classlink\";\n case \"CloudflareSAML\":\n return \"cloudflare\";\n case \"CyberArkSAML\":\n return \"cyberark\";\n case \"DuoSAML\":\n return \"duo\";\n case \"GenericSAML\":\n return \"generic-saml\";\n case \"GoogleSAML\":\n case \"GoogleOIDC\":\n case \"GoogleOAuth\":\n return \"google\";\n case \"JumpCloudSAML\":\n return \"jumpcloud\";\n case \"KeycloakSAML\":\n return \"keycloak\";\n case \"LastPassSAML\":\n return \"lastpass\";\n case \"MiniOrangeSAML\":\n return \"miniorange\";\n case \"NetIqSAML\":\n return \"net-iq\";\n case \"OktaOIDC\":\n case \"OktaSAML\":\n return \"okta\";\n case \"OneLoginSAML\":\n return \"onelogin\";\n case \"OracleSAML\":\n return \"oracle\";\n case \"PingFederateSAML\":\n case \"PingOneSAML\":\n return \"ping-identity\";\n case \"RipplingSAML\":\n return \"rippling\";\n case \"SalesforceSAML\":\n case \"SalesforceOAuth\":\n return \"salesforce\";\n case \"ShibbolethGenericSAML\":\n case \"ShibbolethSAML\":\n return \"shibboleth\";\n case \"SimpleSamlPhpSAML\":\n return \"simple-saml-php\";\n case \"TestIdp\":\n return \"test-idp\";\n case \"VMwareSAML\":\n return \"vmware\";\n case \"AdpOidc\":\n return \"adp\";\n case \"GenericOIDC\":\n return \"generic-oidc\";\n case \"LoginGovOidc\":\n return \"login-gov\";\n case \"CleverOIDC\":\n return \"clever\";\n case \"AppleOAuth\":\n return \"apple\";\n case \"BitbucketOAuth\":\n return \"bitbucket\";\n case \"DiscordOAuth\":\n return \"discord\";\n case \"GithubOAuth\":\n return \"github\";\n case \"GitLabOAuth\":\n return \"gitlab\";\n case \"IntuitOAuth\":\n return \"intuit\";\n case \"LinkedInOAuth\":\n return \"linkedin\";\n case \"SlackOAuth\":\n return \"slack\";\n case \"VercelOAuth\":\n case \"VercelMarketplaceOAuth\":\n return \"vercel\";\n case \"XeroOAuth\":\n return \"xero\";\n case \"GrokOAuth\":\n case \"XOAuth\":\n case \"MagicLink\":\n return \"workos\";\n default:\n return unreachable(type);\n }\n}\n\nexport type {\n AdminPortalSsoConnectionProps,\n AdminPortalSsoConnectionLoadingProps,\n AdminPortalSsoConnectionErrorProps,\n};\nexport {\n AdminPortalSsoConnection,\n AdminPortalSsoConnectionLoading,\n AdminPortalSsoConnectionError,\n};\n"],"mappings":"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","names":["AdminPortalSsoConnectionPresentational"]}
@@ -49,6 +49,7 @@ var import_utils = require("./utils.js");
49
49
  var import_translation = require("./i18n/translation.js");
50
50
  var import_use_translation = require("./i18n/use-translation.js");
51
51
  var import_generic_error = require("./generic-error.js");
52
+ var import_use_comparative_readable_date = require("../use-comparative-readable-date.js");
52
53
  const AdminPortalAuditLogStreamingContext = React.createContext(null);
53
54
  function useAdminPortalAuditLogStreamingContext() {
54
55
  const context = React.useContext(AdminPortalAuditLogStreamingContext);
@@ -112,22 +113,6 @@ function decodeUlidTimestamp(ulid) {
112
113
  }
113
114
  return new Date(timestamp);
114
115
  }
115
- function getRelativeTimeString(currentDate, pastDate) {
116
- const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" });
117
- const diff = pastDate.getTime() - currentDate.getTime();
118
- const diffSeconds = Math.round(diff / 1e3);
119
- const diffMinutes = Math.round(diffSeconds / 60);
120
- const diffHours = Math.round(diffMinutes / 60);
121
- const diffDays = Math.round(diffHours / 24);
122
- const diffMonths = Math.round(diffDays / 30);
123
- const diffYears = Math.round(diffMonths / 12);
124
- if (Math.abs(diffSeconds) < 60) return "now";
125
- if (Math.abs(diffMinutes) < 60) return rtf.format(diffMinutes, "minute");
126
- if (Math.abs(diffHours) < 24) return rtf.format(diffHours, "hour");
127
- if (Math.abs(diffDays) < 30) return rtf.format(diffDays, "day");
128
- if (Math.abs(diffMonths) < 12) return rtf.format(diffMonths, "month");
129
- return rtf.format(diffYears, "year");
130
- }
131
116
  function AdminPortalAuditLogStreamingButton({
132
117
  isPending,
133
118
  href,
@@ -194,6 +179,9 @@ const AdminPortalAuditLogStreaming = (props) => {
194
179
  const lastSyncedEventId = connectionStatus === "Active" || connectionStatus === "Error" ? props.lastSyncedEventId : void 0;
195
180
  const lastSyncedAt = lastSyncedEventId ? decodeUlidTimestamp(lastSyncedEventId) : null;
196
181
  const icon = destinationType ? getDestinationIcon(destinationType) : null;
182
+ const relativeTime = (0, import_use_comparative_readable_date.useComparativeReadableDate)({
183
+ date: lastSyncedAt
184
+ });
197
185
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AdminPortalAuditLogStreamingContext.Provider, { value: { connectionStatus }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CardList.Root, { ...getWidgetRootDomProps("resolved", { className }), children: [
198
186
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardList.Item, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_themes.Flex, { direction: "row", justify: "between", align: "center", gap: "2", children: [
199
187
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.Flex, { gap: "4", align: "center", children: connectionStatus === "NotConfigured" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.Text, { size: "2", color: "gray", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -213,12 +201,7 @@ const AdminPortalAuditLogStreaming = (props) => {
213
201
  defaultMessage: "Last sync {relativeTime}",
214
202
  id: "fT9f0p",
215
203
  description: "Label showing when the last log stream sync occurred",
216
- values: {
217
- relativeTime: getRelativeTimeString(
218
- /* @__PURE__ */ new Date(),
219
- lastSyncedAt
220
- )
221
- }
204
+ values: { relativeTime }
222
205
  }
223
206
  ) })
224
207
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.Text, { size: "2", weight: "bold", children: getDestinationName(destinationType) })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/admin-portal-audit-log-streaming.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { Box, Card, Flex, Text } from \"@radix-ui/themes\";\nimport * as CardList from \"./card-list.js\";\nimport { Button, Skeleton } from \"./elements.js\";\nimport {\n ExternalLinkIcon,\n Cross2Icon,\n InfoCircledIcon,\n} from \"@radix-ui/react-icons\";\nimport { ProviderIcon } from \"./provider-icon.js\";\nimport { IconPanel } from \"./icon-panel.js\";\nimport { GenericHttpsIcon } from \"./audit-log-stream-icons.js\";\nimport { Status } from \"./status.js\";\nimport {\n getDomProps,\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\";\nimport type { AuditLogStreamType } from \"../api/client-graphql/generated.js\";\n\n// ============================================================================\n// TYPE DEFINITIONS\n// ============================================================================\n\ninterface NotConfiguredProps {\n connectionStatus: \"NotConfigured\";\n}\n\ninterface InactiveProps {\n connectionStatus: \"Inactive\";\n destinationType: AuditLogStreamType;\n}\n\ninterface ActiveProps {\n connectionStatus: \"Active\";\n destinationType: AuditLogStreamType;\n lastSyncedEventId?: string | null;\n}\n\ninterface ErrorProps {\n connectionStatus: \"Error\";\n destinationType: AuditLogStreamType;\n lastSyncedEventId?: string | null;\n}\n\nconst AdminPortalAuditLogStreamingContext = React.createContext<{\n connectionStatus: AdminPortalAuditLogStreamingStatusProps[\"connectionStatus\"];\n} | null>(null);\n\nfunction useAdminPortalAuditLogStreamingContext() {\n const context = React.useContext(AdminPortalAuditLogStreamingContext);\n if (!context) {\n throw new Error(\n \"useAdminPortalAuditLogStreamingContext must be used within a AdminPortalAuditLogStreamingContext provider\",\n );\n }\n return context;\n}\n\nexport type AdminPortalAuditLogStreamingStatusProps =\n | NotConfiguredProps\n | InactiveProps\n | ActiveProps\n | ErrorProps;\n\ntype AdminPortalAuditLogStreamingProps = WidgetRootDomProps &\n AdminPortalAuditLogStreamingStatusProps & {\n adminPortalOpenButton: React.ReactNode;\n };\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Maps AuditLogStreamType to display name\n */\nfunction getDestinationName(type: AuditLogStreamType): string {\n switch (type) {\n case \"Datadog\":\n return \"Datadog\";\n case \"Splunk\":\n return \"Splunk\";\n case \"S3\":\n return \"AWS S3\";\n case \"GoogleCloudStorage\":\n return \"Google Cloud Storage\";\n case \"AzureSentinel\":\n return \"Azure Sentinel\";\n case \"GenericHttps\":\n return \"Generic HTTPS\";\n default:\n return type;\n }\n}\n\n/**\n * Maps AuditLogStreamType to ProviderIcon provider name\n */\nfunction getDestinationIcon(\n type: AuditLogStreamType,\n): \"datadog\" | \"splunk\" | \"aws\" | \"google-cloud\" | \"azure\" | undefined {\n switch (type) {\n case \"Datadog\":\n return \"datadog\";\n case \"Splunk\":\n return \"splunk\";\n case \"S3\":\n return \"aws\";\n case \"GoogleCloudStorage\":\n return \"google-cloud\";\n case \"AzureSentinel\":\n return \"azure\";\n default:\n return undefined;\n }\n}\n\n/**\n * Helper to get the correct WidgetRootDomProps based on state\n */\nfunction getWidgetRootDomProps(\n state: WidgetRootState,\n domProps: WidgetRootDomProps,\n) {\n return getDomProps({\n ...domProps,\n isWidgetRoot: true,\n widgetId: \"admin-portal-audit-log-streaming\",\n widgetState: state,\n });\n}\n\nconst CROCKFORD_BASE32 = \"0123456789ABCDEFGHJKMNPQRSTVWXYZ\";\n\nfunction decodeUlidTimestamp(ulid: string): Date | null {\n if (!ulid || ulid.length < 10) return null;\n let timestamp = 0;\n for (let i = 0; i < 10; i++) {\n const charIndex = CROCKFORD_BASE32.indexOf(ulid.charAt(i).toUpperCase());\n if (charIndex === -1) return null;\n timestamp = timestamp * 32 + charIndex;\n }\n return new Date(timestamp);\n}\n\nfunction getRelativeTimeString(currentDate: Date, pastDate: Date): string {\n const rtf = new Intl.RelativeTimeFormat(\"en\", { numeric: \"auto\" });\n const diff = pastDate.getTime() - currentDate.getTime();\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) return \"now\";\n if (Math.abs(diffMinutes) < 60) return rtf.format(diffMinutes, \"minute\");\n if (Math.abs(diffHours) < 24) return rtf.format(diffHours, \"hour\");\n if (Math.abs(diffDays) < 30) return rtf.format(diffDays, \"day\");\n if (Math.abs(diffMonths) < 12) return rtf.format(diffMonths, \"month\");\n return rtf.format(diffYears, \"year\");\n}\n\nfunction AdminPortalAuditLogStreamingButton({\n isPending,\n href,\n initConfig,\n}: {\n isPending: boolean;\n href: string | null;\n initConfig: () => void;\n}) {\n const { connectionStatus } = useAdminPortalAuditLogStreamingContext();\n const label = (() => {\n switch (connectionStatus) {\n case \"NotConfigured\":\n return (\n <Translation\n defaultMessage=\"Set up Log Streams\"\n id=\"s3Wu7U\"\n description=\"Button label to start log stream setup\"\n />\n );\n case \"Inactive\":\n return (\n <Translation\n defaultMessage=\"Continue setup\"\n id=\"/oM/HY\"\n description=\"Button label to continue incomplete log stream setup\"\n />\n );\n case \"Active\":\n case \"Error\":\n return (\n <Translation\n defaultMessage=\"Manage\"\n id=\"+k5uUi\"\n description=\"Button label to manage log stream settings\"\n />\n );\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\n// ============================================================================\n// MAIN COMPONENT\n// ============================================================================\n\nconst AdminPortalAuditLogStreaming: React.FC<\n AdminPortalAuditLogStreamingProps\n> = (props) => {\n const { connectionStatus, adminPortalOpenButton, className } = props;\n\n const destinationType =\n connectionStatus !== \"NotConfigured\"\n ? (props as InactiveProps | ActiveProps | ErrorProps).destinationType\n : null;\n const lastSyncedEventId =\n connectionStatus === \"Active\" || connectionStatus === \"Error\"\n ? (props as ActiveProps | ErrorProps).lastSyncedEventId\n : undefined;\n const lastSyncedAt = lastSyncedEventId\n ? decodeUlidTimestamp(lastSyncedEventId)\n : null;\n\n const icon = destinationType ? getDestinationIcon(destinationType) : null;\n\n return (\n <AdminPortalAuditLogStreamingContext.Provider value={{ connectionStatus }}>\n <CardList.Root {...getWidgetRootDomProps(\"resolved\", { className })}>\n <CardList.Item>\n <Flex direction=\"row\" justify=\"between\" align=\"center\" gap=\"2\">\n <Flex gap=\"4\" align=\"center\">\n {connectionStatus === \"NotConfigured\" ? (\n <Text size=\"2\" color=\"gray\">\n <Translation\n defaultMessage=\"You haven't set up Log Streams yet.\"\n id=\"n4mruE\"\n description=\"Empty state message when log streaming is not configured\"\n />\n </Text>\n ) : (\n <>\n <IconPanel color=\"panel\">\n {icon ? (\n <ProviderIcon provider={icon} size=\"2\" />\n ) : (\n <GenericHttpsIcon />\n )}\n </IconPanel>\n {lastSyncedAt ? (\n <Flex direction=\"column\">\n <Text size=\"2\" weight=\"bold\">\n {getDestinationName(destinationType!)}\n </Text>\n <Text size=\"2\" color=\"gray\">\n <Translation\n defaultMessage=\"Last sync {relativeTime}\"\n id=\"fT9f0p\"\n description=\"Label showing when the last log stream sync occurred\"\n values={{\n relativeTime: getRelativeTimeString(\n new Date(),\n lastSyncedAt,\n ),\n }}\n />\n </Text>\n </Flex>\n ) : (\n <Text size=\"2\" weight=\"bold\">\n {getDestinationName(destinationType!)}\n </Text>\n )}\n </>\n )}\n </Flex>\n\n <Flex gap=\"5\" align=\"center\">\n {connectionStatus === \"NotConfigured\" ? (\n adminPortalOpenButton\n ) : (\n <>\n {connectionStatus === \"Inactive\" && (\n <Status state=\"waiting\">\n <Translation\n defaultMessage=\"Setup in progress\"\n id=\"M6iKLG\"\n description=\"Status when log stream setup is incomplete\"\n />\n </Status>\n )}\n {connectionStatus === \"Active\" && (\n <Status state=\"success\">\n <Translation\n defaultMessage=\"Streaming\"\n id=\"25L0J+\"\n description=\"Status when log stream is active\"\n />\n </Status>\n )}\n {connectionStatus === \"Error\" && (\n <Status state=\"error\">\n <Translation\n defaultMessage=\"Not streaming\"\n id=\"7fAKZo\"\n description=\"Status when log stream has an error\"\n />\n </Status>\n )}\n {adminPortalOpenButton}\n </>\n )}\n </Flex>\n </Flex>\n </CardList.Item>\n\n {connectionStatus === \"Error\" && (\n <CardList.Item>\n <Flex align=\"start\" gap=\"2\">\n <Box asChild mt=\"2px\" flexShrink=\"0\">\n <InfoCircledIcon color=\"gray\" />\n </Box>\n <Text size=\"2\" color=\"gray\">\n <Translation\n defaultMessage=\"The credentials provided are incorrect or missing. Please review and update your log stream configuration.\"\n id=\"23tmgn\"\n description=\"Error message shown when audit log stream has a configuration or delivery error\"\n />\n </Text>\n </Flex>\n </CardList.Item>\n )}\n </CardList.Root>\n </AdminPortalAuditLogStreamingContext.Provider>\n );\n};\n\n// ============================================================================\n// LOADING COMPONENT\n// ============================================================================\n\ninterface AdminPortalAuditLogStreamingLoadingProps extends WidgetRootDomProps {}\n\nconst AdminPortalAuditLogStreamingLoading: React.FC<\n AdminPortalAuditLogStreamingLoadingProps\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=\"datadog\" 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\">Datadog</Text>\n </Skeleton>\n <Skeleton>\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Text size=\"1\">Last sync 10 minutes ago</Text>\n </Skeleton>\n </Flex>\n </Flex>\n\n <Flex gap=\"5\" align=\"center\">\n <Skeleton>\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Status state=\"success\">Streaming</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\n// ============================================================================\n// ERROR COMPONENT\n// ============================================================================\n\ninterface AdminPortalAuditLogStreamingErrorProps extends WidgetRootDomProps {\n error: unknown;\n}\n\nconst AdminPortalAuditLogStreamingError: React.FC<\n AdminPortalAuditLogStreamingErrorProps\n> = ({ error, ...domProps }) => {\n React.useEffect(() => {\n console.error(error);\n }, [error]);\n\n const translate = useTranslation();\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 {/* Error icon circle */}\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 {/* Error text */}\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\n// ============================================================================\n// EXPORTS\n// ============================================================================\n\nexport type {\n AdminPortalAuditLogStreamingProps,\n AdminPortalAuditLogStreamingLoadingProps,\n AdminPortalAuditLogStreamingErrorProps,\n};\n\nexport {\n AdminPortalAuditLogStreaming,\n AdminPortalAuditLogStreamingLoading,\n AdminPortalAuditLogStreamingError,\n /** @internal */\n AdminPortalAuditLogStreamingButton,\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/admin-portal-audit-log-streaming.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { Box, Card, Flex, Text } from \"@radix-ui/themes\";\nimport * as CardList from \"./card-list.js\";\nimport { Button, Skeleton } from \"./elements.js\";\nimport {\n ExternalLinkIcon,\n Cross2Icon,\n InfoCircledIcon,\n} from \"@radix-ui/react-icons\";\nimport { ProviderIcon } from \"./provider-icon.js\";\nimport { IconPanel } from \"./icon-panel.js\";\nimport { GenericHttpsIcon } from \"./audit-log-stream-icons.js\";\nimport { Status } from \"./status.js\";\nimport {\n getDomProps,\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\";\nimport type { AuditLogStreamType } from \"../api/client-graphql/generated.js\";\nimport { useComparativeReadableDate } from \"../use-comparative-readable-date.js\";\n\n// ============================================================================\n// TYPE DEFINITIONS\n// ============================================================================\n\ninterface NotConfiguredProps {\n connectionStatus: \"NotConfigured\";\n}\n\ninterface InactiveProps {\n connectionStatus: \"Inactive\";\n destinationType: AuditLogStreamType;\n}\n\ninterface ActiveProps {\n connectionStatus: \"Active\";\n destinationType: AuditLogStreamType;\n lastSyncedEventId?: string | null;\n}\n\ninterface ErrorProps {\n connectionStatus: \"Error\";\n destinationType: AuditLogStreamType;\n lastSyncedEventId?: string | null;\n}\n\nconst AdminPortalAuditLogStreamingContext = React.createContext<{\n connectionStatus: AdminPortalAuditLogStreamingStatusProps[\"connectionStatus\"];\n} | null>(null);\n\nfunction useAdminPortalAuditLogStreamingContext() {\n const context = React.useContext(AdminPortalAuditLogStreamingContext);\n if (!context) {\n throw new Error(\n \"useAdminPortalAuditLogStreamingContext must be used within a AdminPortalAuditLogStreamingContext provider\",\n );\n }\n return context;\n}\n\nexport type AdminPortalAuditLogStreamingStatusProps =\n | NotConfiguredProps\n | InactiveProps\n | ActiveProps\n | ErrorProps;\n\ntype AdminPortalAuditLogStreamingProps = WidgetRootDomProps &\n AdminPortalAuditLogStreamingStatusProps & {\n adminPortalOpenButton: React.ReactNode;\n };\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Maps AuditLogStreamType to display name\n */\nfunction getDestinationName(type: AuditLogStreamType): string {\n switch (type) {\n case \"Datadog\":\n return \"Datadog\";\n case \"Splunk\":\n return \"Splunk\";\n case \"S3\":\n return \"AWS S3\";\n case \"GoogleCloudStorage\":\n return \"Google Cloud Storage\";\n case \"AzureSentinel\":\n return \"Azure Sentinel\";\n case \"GenericHttps\":\n return \"Generic HTTPS\";\n default:\n return type;\n }\n}\n\n/**\n * Maps AuditLogStreamType to ProviderIcon provider name\n */\nfunction getDestinationIcon(\n type: AuditLogStreamType,\n): \"datadog\" | \"splunk\" | \"aws\" | \"google-cloud\" | \"azure\" | undefined {\n switch (type) {\n case \"Datadog\":\n return \"datadog\";\n case \"Splunk\":\n return \"splunk\";\n case \"S3\":\n return \"aws\";\n case \"GoogleCloudStorage\":\n return \"google-cloud\";\n case \"AzureSentinel\":\n return \"azure\";\n default:\n return undefined;\n }\n}\n\n/**\n * Helper to get the correct WidgetRootDomProps based on state\n */\nfunction getWidgetRootDomProps(\n state: WidgetRootState,\n domProps: WidgetRootDomProps,\n) {\n return getDomProps({\n ...domProps,\n isWidgetRoot: true,\n widgetId: \"admin-portal-audit-log-streaming\",\n widgetState: state,\n });\n}\n\nconst CROCKFORD_BASE32 = \"0123456789ABCDEFGHJKMNPQRSTVWXYZ\";\n\nfunction decodeUlidTimestamp(ulid: string): Date | null {\n if (!ulid || ulid.length < 10) return null;\n let timestamp = 0;\n for (let i = 0; i < 10; i++) {\n const charIndex = CROCKFORD_BASE32.indexOf(ulid.charAt(i).toUpperCase());\n if (charIndex === -1) return null;\n timestamp = timestamp * 32 + charIndex;\n }\n return new Date(timestamp);\n}\n\nfunction AdminPortalAuditLogStreamingButton({\n isPending,\n href,\n initConfig,\n}: {\n isPending: boolean;\n href: string | null;\n initConfig: () => void;\n}) {\n const { connectionStatus } = useAdminPortalAuditLogStreamingContext();\n const label = (() => {\n switch (connectionStatus) {\n case \"NotConfigured\":\n return (\n <Translation\n defaultMessage=\"Set up Log Streams\"\n id=\"s3Wu7U\"\n description=\"Button label to start log stream setup\"\n />\n );\n case \"Inactive\":\n return (\n <Translation\n defaultMessage=\"Continue setup\"\n id=\"/oM/HY\"\n description=\"Button label to continue incomplete log stream setup\"\n />\n );\n case \"Active\":\n case \"Error\":\n return (\n <Translation\n defaultMessage=\"Manage\"\n id=\"+k5uUi\"\n description=\"Button label to manage log stream settings\"\n />\n );\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\n// ============================================================================\n// MAIN COMPONENT\n// ============================================================================\n\nconst AdminPortalAuditLogStreaming: React.FC<\n AdminPortalAuditLogStreamingProps\n> = (props) => {\n const { connectionStatus, adminPortalOpenButton, className } = props;\n\n const destinationType =\n connectionStatus !== \"NotConfigured\"\n ? (props as InactiveProps | ActiveProps | ErrorProps).destinationType\n : null;\n const lastSyncedEventId =\n connectionStatus === \"Active\" || connectionStatus === \"Error\"\n ? (props as ActiveProps | ErrorProps).lastSyncedEventId\n : undefined;\n const lastSyncedAt = lastSyncedEventId\n ? decodeUlidTimestamp(lastSyncedEventId)\n : null;\n\n const icon = destinationType ? getDestinationIcon(destinationType) : null;\n\n const relativeTime = useComparativeReadableDate({\n date: lastSyncedAt,\n });\n\n return (\n <AdminPortalAuditLogStreamingContext.Provider value={{ connectionStatus }}>\n <CardList.Root {...getWidgetRootDomProps(\"resolved\", { className })}>\n <CardList.Item>\n <Flex direction=\"row\" justify=\"between\" align=\"center\" gap=\"2\">\n <Flex gap=\"4\" align=\"center\">\n {connectionStatus === \"NotConfigured\" ? (\n <Text size=\"2\" color=\"gray\">\n <Translation\n defaultMessage=\"You haven't set up Log Streams yet.\"\n id=\"n4mruE\"\n description=\"Empty state message when log streaming is not configured\"\n />\n </Text>\n ) : (\n <>\n <IconPanel color=\"panel\">\n {icon ? (\n <ProviderIcon provider={icon} size=\"2\" />\n ) : (\n <GenericHttpsIcon />\n )}\n </IconPanel>\n {lastSyncedAt ? (\n <Flex direction=\"column\">\n <Text size=\"2\" weight=\"bold\">\n {getDestinationName(destinationType!)}\n </Text>\n <Text size=\"2\" color=\"gray\">\n <Translation\n defaultMessage=\"Last sync {relativeTime}\"\n id=\"fT9f0p\"\n description=\"Label showing when the last log stream sync occurred\"\n values={{ relativeTime }}\n />\n </Text>\n </Flex>\n ) : (\n <Text size=\"2\" weight=\"bold\">\n {getDestinationName(destinationType!)}\n </Text>\n )}\n </>\n )}\n </Flex>\n\n <Flex gap=\"5\" align=\"center\">\n {connectionStatus === \"NotConfigured\" ? (\n adminPortalOpenButton\n ) : (\n <>\n {connectionStatus === \"Inactive\" && (\n <Status state=\"waiting\">\n <Translation\n defaultMessage=\"Setup in progress\"\n id=\"M6iKLG\"\n description=\"Status when log stream setup is incomplete\"\n />\n </Status>\n )}\n {connectionStatus === \"Active\" && (\n <Status state=\"success\">\n <Translation\n defaultMessage=\"Streaming\"\n id=\"25L0J+\"\n description=\"Status when log stream is active\"\n />\n </Status>\n )}\n {connectionStatus === \"Error\" && (\n <Status state=\"error\">\n <Translation\n defaultMessage=\"Not streaming\"\n id=\"7fAKZo\"\n description=\"Status when log stream has an error\"\n />\n </Status>\n )}\n {adminPortalOpenButton}\n </>\n )}\n </Flex>\n </Flex>\n </CardList.Item>\n\n {connectionStatus === \"Error\" && (\n <CardList.Item>\n <Flex align=\"start\" gap=\"2\">\n <Box asChild mt=\"2px\" flexShrink=\"0\">\n <InfoCircledIcon color=\"gray\" />\n </Box>\n <Text size=\"2\" color=\"gray\">\n <Translation\n defaultMessage=\"The credentials provided are incorrect or missing. Please review and update your log stream configuration.\"\n id=\"23tmgn\"\n description=\"Error message shown when audit log stream has a configuration or delivery error\"\n />\n </Text>\n </Flex>\n </CardList.Item>\n )}\n </CardList.Root>\n </AdminPortalAuditLogStreamingContext.Provider>\n );\n};\n\n// ============================================================================\n// LOADING COMPONENT\n// ============================================================================\n\ninterface AdminPortalAuditLogStreamingLoadingProps extends WidgetRootDomProps {}\n\nconst AdminPortalAuditLogStreamingLoading: React.FC<\n AdminPortalAuditLogStreamingLoadingProps\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=\"datadog\" 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\">Datadog</Text>\n </Skeleton>\n <Skeleton>\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Text size=\"1\">Last sync 10 minutes ago</Text>\n </Skeleton>\n </Flex>\n </Flex>\n\n <Flex gap=\"5\" align=\"center\">\n <Skeleton>\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Status state=\"success\">Streaming</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\n// ============================================================================\n// ERROR COMPONENT\n// ============================================================================\n\ninterface AdminPortalAuditLogStreamingErrorProps extends WidgetRootDomProps {\n error: unknown;\n}\n\nconst AdminPortalAuditLogStreamingError: React.FC<\n AdminPortalAuditLogStreamingErrorProps\n> = ({ error, ...domProps }) => {\n React.useEffect(() => {\n console.error(error);\n }, [error]);\n\n const translate = useTranslation();\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 {/* Error icon circle */}\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 {/* Error text */}\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\n// ============================================================================\n// EXPORTS\n// ============================================================================\n\nexport type {\n AdminPortalAuditLogStreamingProps,\n AdminPortalAuditLogStreamingLoadingProps,\n AdminPortalAuditLogStreamingErrorProps,\n};\n\nexport {\n AdminPortalAuditLogStreaming,\n AdminPortalAuditLogStreamingLoading,\n AdminPortalAuditLogStreamingError,\n /** @internal */\n AdminPortalAuditLogStreamingButton,\n};\n"],"mappings":"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","names":[]}
@@ -49,6 +49,7 @@ var import_utils = require("./utils.js");
49
49
  var import_translation = require("./i18n/translation.js");
50
50
  var import_use_translation = require("./i18n/use-translation.js");
51
51
  var import_generic_error = require("./generic-error.js");
52
+ var import_use_comparative_readable_date = require("../use-comparative-readable-date.js");
52
53
  const AdminPortalSsoConnectionContext = React.createContext(null);
53
54
  AdminPortalSsoConnectionContext.displayName = "AdminPortalSsoConnectionContext";
54
55
  function useAdminPortalSsoConnectionContext() {
@@ -61,7 +62,6 @@ function useAdminPortalSsoConnectionContext() {
61
62
  return context;
62
63
  }
63
64
  const AdminPortalSsoConnection = ({
64
- currentDate,
65
65
  connectionStatus,
66
66
  identityProvider,
67
67
  expiryDate,
@@ -90,8 +90,7 @@ const AdminPortalSsoConnection = ({
90
90
  {
91
91
  connectionStatus,
92
92
  identityProvider,
93
- lastSession,
94
- currentDate
93
+ lastSession
95
94
  }
96
95
  ),
97
96
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_themes.Flex, { gap: "5", align: "center", children: [
@@ -204,28 +203,24 @@ function SsoStatus({
204
203
  return (0, import_utils.unreachable)(status);
205
204
  }
206
205
  function SessionInfo({
207
- currentDate,
208
206
  identityProvider,
209
207
  lastSession,
210
208
  connectionStatus
211
209
  }) {
212
- const relativeTimeString = React.useMemo(() => {
213
- if (!lastSession || !currentDate || connectionStatus === "NotConfigured" || connectionStatus === "Inactive") {
214
- return null;
215
- }
216
- return getRelativeTimeString(currentDate, lastSession);
217
- }, [lastSession, currentDate, connectionStatus]);
210
+ const relativeTime = (0, import_use_comparative_readable_date.useComparativeReadableDate)({
211
+ date: connectionStatus === "NotConfigured" || connectionStatus === "Inactive" ? null : lastSession
212
+ });
218
213
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_themes.Flex, { gap: "4", align: "center", children: [
219
214
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icon_panel.IconPanel, { color: "panel", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_provider_icon.ProviderIcon, { provider: identityProvider, size: "2" }) }),
220
215
  lastSession ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_themes.Flex, { direction: "column", children: [
221
216
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.Text, { size: "2", weight: "bold", children: (0, import_identity_providers.getIdentityProviderName)(identityProvider) }),
222
- relativeTimeString ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.Text, { color: "gray", size: "2", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
217
+ relativeTime ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.Text, { color: "gray", size: "2", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
223
218
  import_translation.Translation,
224
219
  {
225
220
  defaultMessage: "Last session {relativeTime}",
226
221
  id: "yN72Gc",
227
222
  description: "Label showing when the last SSO session occurred",
228
- values: { relativeTime: relativeTimeString }
223
+ values: { relativeTime }
229
224
  }
230
225
  ) }) : null
231
226
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_themes.Text, { size: "2", weight: "bold", children: (0, import_identity_providers.getIdentityProviderName)(identityProvider) })
@@ -333,35 +328,6 @@ const AdminPortalSsoConnectionError = ({ error, ...domProps }) => {
333
328
  ] })
334
329
  ] }) }) });
335
330
  };
336
- function getRelativeTimeString(currentDate, lastSession) {
337
- if (!currentDate || !lastSession) {
338
- return null;
339
- }
340
- const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" });
341
- const diff = lastSession.getTime() - currentDate.getTime();
342
- const diffSeconds = Math.round(diff / 1e3);
343
- const diffMinutes = Math.round(diffSeconds / 60);
344
- const diffHours = Math.round(diffMinutes / 60);
345
- const diffDays = Math.round(diffHours / 24);
346
- const diffMonths = Math.round(diffDays / 30);
347
- const diffYears = Math.round(diffMonths / 12);
348
- if (Math.abs(diffSeconds) < 60) {
349
- return "now";
350
- }
351
- if (Math.abs(diffMinutes) < 60) {
352
- return rtf.format(diffMinutes, "minute");
353
- }
354
- if (Math.abs(diffHours) < 24) {
355
- return rtf.format(diffHours, "hour");
356
- }
357
- if (Math.abs(diffDays) < 30) {
358
- return rtf.format(diffDays, "day");
359
- }
360
- if (Math.abs(diffMonths) < 12) {
361
- return rtf.format(diffMonths, "month");
362
- }
363
- return rtf.format(diffYears, "year");
364
- }
365
331
  function getWidgetRootDomProps(state, domProps) {
366
332
  return (0, import_utils.getDomProps)({
367
333
  ...domProps,