@replicated/portal-components 0.0.19 → 0.0.21
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/components/metadata/registry.json +2 -2
- package/components/metadata/registry.md +2 -2
- package/dist/actions/change-team.js +66 -7
- package/dist/actions/change-team.js.map +1 -1
- package/dist/actions/index.d.mts +3 -1
- package/dist/actions/index.d.ts +3 -1
- package/dist/actions/index.js +182 -465
- package/dist/actions/index.js.map +1 -1
- package/dist/actions/install-actions.d.mts +3 -1
- package/dist/actions/install-actions.d.ts +3 -1
- package/dist/actions/install-actions.js +58 -5
- package/dist/actions/install-actions.js.map +1 -1
- package/dist/actions/service-account.d.mts +3 -1
- package/dist/actions/service-account.d.ts +3 -1
- package/dist/actions/service-account.js +58 -5
- package/dist/actions/service-account.js.map +1 -1
- package/dist/actions/support-bundles.d.mts +3 -1
- package/dist/actions/support-bundles.d.ts +3 -1
- package/dist/actions/support-bundles.js +58 -5
- package/dist/actions/support-bundles.js.map +1 -1
- package/dist/actions/team-settings.d.mts +3 -1
- package/dist/actions/team-settings.d.ts +3 -1
- package/dist/actions/team-settings.js +91 -27
- package/dist/actions/team-settings.js.map +1 -1
- package/dist/actions/trial-signup.d.mts +24 -0
- package/dist/actions/trial-signup.d.ts +24 -0
- package/dist/actions/trial-signup.js +482 -0
- package/dist/actions/trial-signup.js.map +1 -0
- package/dist/actions/user-settings.d.mts +3 -1
- package/dist/actions/user-settings.d.ts +3 -1
- package/dist/actions/user-settings.js +58 -5
- package/dist/actions/user-settings.js.map +1 -1
- package/dist/airgap-instances.d.mts +3 -1
- package/dist/airgap-instances.d.ts +3 -1
- package/dist/airgap-instances.js +41 -112
- package/dist/airgap-instances.js.map +1 -1
- package/dist/branding-BsMSywts.d.mts +36 -0
- package/dist/branding-BsMSywts.d.ts +36 -0
- package/dist/error-page.js +10 -2
- package/dist/error-page.js.map +1 -1
- package/dist/error.js +10 -2
- package/dist/error.js.map +1 -1
- package/dist/esm/actions/change-team.js +66 -7
- package/dist/esm/actions/change-team.js.map +1 -1
- package/dist/esm/actions/index.js +181 -462
- package/dist/esm/actions/index.js.map +1 -1
- package/dist/esm/actions/install-actions.js +58 -5
- package/dist/esm/actions/install-actions.js.map +1 -1
- package/dist/esm/actions/service-account.js +58 -5
- package/dist/esm/actions/service-account.js.map +1 -1
- package/dist/esm/actions/support-bundles.js +58 -5
- package/dist/esm/actions/support-bundles.js.map +1 -1
- package/dist/esm/actions/team-settings.js +91 -27
- package/dist/esm/actions/team-settings.js.map +1 -1
- package/dist/esm/actions/trial-signup.js +478 -0
- package/dist/esm/actions/trial-signup.js.map +1 -0
- package/dist/esm/actions/user-settings.js +58 -5
- package/dist/esm/actions/user-settings.js.map +1 -1
- package/dist/esm/airgap-instances.js +40 -112
- package/dist/esm/airgap-instances.js.map +1 -1
- package/dist/esm/error-page.js +10 -2
- package/dist/esm/error-page.js.map +1 -1
- package/dist/esm/error.js +10 -2
- package/dist/esm/error.js.map +1 -1
- package/dist/esm/helm-install-wizard.js +118 -79
- package/dist/esm/helm-install-wizard.js.map +1 -1
- package/dist/esm/index.js +706 -438
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/install-actions.js +40 -5
- package/dist/esm/install-actions.js.map +1 -1
- package/dist/esm/install-card.js +9 -6
- package/dist/esm/install-card.js.map +1 -1
- package/dist/esm/install-targets.js +9 -2
- package/dist/esm/install-targets.js.map +1 -1
- package/dist/esm/instance-card.js +39 -111
- package/dist/esm/instance-card.js.map +1 -1
- package/dist/esm/join-team.js +9 -3
- package/dist/esm/join-team.js.map +1 -1
- package/dist/esm/license-card.js +24 -22
- package/dist/esm/license-card.js.map +1 -1
- package/dist/esm/license-details.js +128 -334
- package/dist/esm/license-details.js.map +1 -1
- package/dist/esm/linux-install-wizard.js +95 -41
- package/dist/esm/linux-install-wizard.js.map +1 -1
- package/dist/esm/login.js +20 -4
- package/dist/esm/login.js.map +1 -1
- package/dist/esm/middleware.js +33 -0
- package/dist/esm/middleware.js.map +1 -0
- package/dist/esm/online-instance-list.js +40 -112
- package/dist/esm/online-instance-list.js.map +1 -1
- package/dist/esm/release-history-panel.js +27 -14
- package/dist/esm/release-history-panel.js.map +1 -1
- package/dist/esm/saml-callback-client.js +82 -0
- package/dist/esm/saml-callback-client.js.map +1 -0
- package/dist/esm/saml-handlers.js +138 -0
- package/dist/esm/saml-handlers.js.map +1 -0
- package/dist/esm/security-card.js +53 -38
- package/dist/esm/security-card.js.map +1 -1
- package/dist/esm/service-accounts-tab.js +800 -0
- package/dist/esm/service-accounts-tab.js.map +1 -0
- package/dist/esm/support-bundle-collection-card.js +48 -24
- package/dist/esm/support-bundle-collection-card.js.map +1 -1
- package/dist/esm/support-bundles-card.js +10 -5
- package/dist/esm/support-bundles-card.js.map +1 -1
- package/dist/esm/support-card.js +37 -5
- package/dist/esm/support-card.js.map +1 -1
- package/dist/esm/team-selection.js +5 -1
- package/dist/esm/team-selection.js.map +1 -1
- package/dist/esm/team-settings-card.js +5 -2
- package/dist/esm/team-settings-card.js.map +1 -1
- package/dist/esm/team-settings.js +7 -2
- package/dist/esm/team-settings.js.map +1 -1
- package/dist/esm/top-nav-user-menu.js +5 -1
- package/dist/esm/top-nav-user-menu.js.map +1 -1
- package/dist/esm/top-nav.js +175 -62
- package/dist/esm/top-nav.js.map +1 -1
- package/dist/esm/trial-signup.js +256 -0
- package/dist/esm/trial-signup.js.map +1 -0
- package/dist/esm/update-layout.js +175 -62
- package/dist/esm/update-layout.js.map +1 -1
- package/dist/esm/updates-card.js +15 -4
- package/dist/esm/updates-card.js.map +1 -1
- package/dist/esm/upload-support-bundle-modal.js +9 -4
- package/dist/esm/upload-support-bundle-modal.js.map +1 -1
- package/dist/esm/user-settings-card.js +5 -2
- package/dist/esm/user-settings-card.js.map +1 -1
- package/dist/esm/user-settings.js +12 -6
- package/dist/esm/user-settings.js.map +1 -1
- package/dist/esm/utils/index.js +204 -13
- package/dist/esm/utils/index.js.map +1 -1
- package/dist/fetch-license-iTyF7_GY.d.mts +81 -0
- package/dist/fetch-license-iTyF7_GY.d.ts +81 -0
- package/dist/helm-install-wizard.d.mts +11 -3
- package/dist/helm-install-wizard.d.ts +11 -3
- package/dist/helm-install-wizard.js +118 -79
- package/dist/helm-install-wizard.js.map +1 -1
- package/dist/{index-BAiVrSSR.d.mts → index-DyzJ0yKD.d.mts} +48 -50
- package/dist/{index-DWt-N5od.d.ts → index-sMbq94M7.d.ts} +48 -50
- package/dist/index.d.mts +8 -2
- package/dist/index.d.ts +8 -2
- package/dist/index.js +726 -438
- package/dist/index.js.map +1 -1
- package/dist/install-actions.d.mts +4 -2
- package/dist/install-actions.d.ts +4 -2
- package/dist/install-actions.js +40 -5
- package/dist/install-actions.js.map +1 -1
- package/dist/install-card.d.mts +2 -3
- package/dist/install-card.d.ts +2 -3
- package/dist/install-card.js +9 -6
- package/dist/install-card.js.map +1 -1
- package/dist/install-targets.js +9 -2
- package/dist/install-targets.js.map +1 -1
- package/dist/instance-card.d.mts +3 -1
- package/dist/instance-card.d.ts +3 -1
- package/dist/instance-card.js +40 -111
- package/dist/instance-card.js.map +1 -1
- package/dist/join-team.js +9 -3
- package/dist/join-team.js.map +1 -1
- package/dist/license-card.d.mts +2 -3
- package/dist/license-card.d.ts +2 -3
- package/dist/license-card.js +24 -22
- package/dist/license-card.js.map +1 -1
- package/dist/license-details.js +128 -334
- package/dist/license-details.js.map +1 -1
- package/dist/linux-install-wizard.d.mts +9 -3
- package/dist/linux-install-wizard.d.ts +9 -3
- package/dist/linux-install-wizard.js +95 -41
- package/dist/linux-install-wizard.js.map +1 -1
- package/dist/login.d.mts +4 -0
- package/dist/login.d.ts +4 -0
- package/dist/login.js +20 -4
- package/dist/login.js.map +1 -1
- package/dist/middleware.d.mts +13 -0
- package/dist/middleware.d.ts +13 -0
- package/dist/middleware.js +35 -0
- package/dist/middleware.js.map +1 -0
- package/dist/online-instance-list.d.mts +3 -1
- package/dist/online-instance-list.d.ts +3 -1
- package/dist/online-instance-list.js +41 -112
- package/dist/online-instance-list.js.map +1 -1
- package/dist/pending-installations.d.mts +3 -1
- package/dist/pending-installations.d.ts +3 -1
- package/dist/release-history-panel.js +27 -14
- package/dist/release-history-panel.js.map +1 -1
- package/dist/saml-callback-client.d.mts +36 -0
- package/dist/saml-callback-client.d.ts +36 -0
- package/dist/saml-callback-client.js +88 -0
- package/dist/saml-callback-client.js.map +1 -0
- package/dist/saml-handlers.d.mts +50 -0
- package/dist/saml-handlers.d.ts +50 -0
- package/dist/saml-handlers.js +141 -0
- package/dist/saml-handlers.js.map +1 -0
- package/dist/security-card.d.mts +3 -1
- package/dist/security-card.d.ts +3 -1
- package/dist/security-card.js +53 -38
- package/dist/security-card.js.map +1 -1
- package/dist/service-accounts-tab.d.mts +51 -0
- package/dist/service-accounts-tab.d.ts +51 -0
- package/dist/service-accounts-tab.js +802 -0
- package/dist/service-accounts-tab.js.map +1 -0
- package/dist/styles.css +375 -127
- package/dist/support-bundle-collection-card.d.mts +1 -1
- package/dist/support-bundle-collection-card.d.ts +1 -1
- package/dist/support-bundle-collection-card.js +47 -23
- package/dist/support-bundle-collection-card.js.map +1 -1
- package/dist/support-bundles-card.d.mts +4 -2
- package/dist/support-bundles-card.d.ts +4 -2
- package/dist/support-bundles-card.js +10 -5
- package/dist/support-bundles-card.js.map +1 -1
- package/dist/support-card.js +37 -5
- package/dist/support-card.js.map +1 -1
- package/dist/team-selection.js +5 -1
- package/dist/team-selection.js.map +1 -1
- package/dist/team-settings-card.js +5 -2
- package/dist/team-settings-card.js.map +1 -1
- package/dist/team-settings.js +7 -2
- package/dist/team-settings.js.map +1 -1
- package/dist/{top-nav-IRIn66wS.d.ts → top-nav-BUQAGoG1.d.mts} +14 -2
- package/dist/{top-nav-IRIn66wS.d.mts → top-nav-CEqw0KpO.d.ts} +14 -2
- package/dist/top-nav-user-menu.js +5 -1
- package/dist/top-nav-user-menu.js.map +1 -1
- package/dist/top-nav.d.mts +2 -1
- package/dist/top-nav.d.ts +2 -1
- package/dist/top-nav.js +175 -62
- package/dist/top-nav.js.map +1 -1
- package/dist/trial-signup.d.mts +31 -0
- package/dist/trial-signup.d.ts +31 -0
- package/dist/trial-signup.js +258 -0
- package/dist/trial-signup.js.map +1 -0
- package/dist/update-layout.js +175 -62
- package/dist/update-layout.js.map +1 -1
- package/dist/updates-card.js +15 -4
- package/dist/updates-card.js.map +1 -1
- package/dist/upload-support-bundle-modal.js +9 -4
- package/dist/upload-support-bundle-modal.js.map +1 -1
- package/dist/user-settings-card.js +5 -2
- package/dist/user-settings-card.js.map +1 -1
- package/dist/user-settings.js +12 -6
- package/dist/user-settings.js.map +1 -1
- package/dist/utils/index.d.mts +74 -16
- package/dist/utils/index.d.ts +74 -16
- package/dist/utils/index.js +215 -12
- package/dist/utils/index.js.map +1 -1
- package/package.json +37 -2
|
@@ -0,0 +1,802 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var react = require('react');
|
|
5
|
+
var lucideReact = require('lucide-react');
|
|
6
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Enterprise Portal Components
|
|
10
|
+
* This file is generated by tsup. Do not edit manually.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
// src/utils/format.ts
|
|
15
|
+
function formatDate(dateString) {
|
|
16
|
+
if (!dateString) return "Never";
|
|
17
|
+
const date = new Date(dateString);
|
|
18
|
+
if (isNaN(date.getTime())) {
|
|
19
|
+
return dateString;
|
|
20
|
+
}
|
|
21
|
+
return date.toLocaleDateString("en-US", {
|
|
22
|
+
month: "short",
|
|
23
|
+
day: "numeric",
|
|
24
|
+
year: "numeric",
|
|
25
|
+
hour: "numeric",
|
|
26
|
+
minute: "2-digit",
|
|
27
|
+
hour12: true
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// src/utils/constants.ts
|
|
32
|
+
var DEFAULT_PRIMARY_COLOR = "#4f46e5";
|
|
33
|
+
var DEFAULT_SECONDARY_COLOR = "#6366f1";
|
|
34
|
+
function useCopyToClipboard(resetDelay = 2e3) {
|
|
35
|
+
const [copied, setCopied] = react.useState(false);
|
|
36
|
+
const copy = react.useCallback(async (text) => {
|
|
37
|
+
if (!navigator.clipboard) {
|
|
38
|
+
console.warn("[useCopyToClipboard] Clipboard API not available");
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
await navigator.clipboard.writeText(text);
|
|
43
|
+
setCopied(true);
|
|
44
|
+
setTimeout(() => setCopied(false), resetDelay);
|
|
45
|
+
return true;
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.error("[useCopyToClipboard] Failed to copy:", error);
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
}, [resetDelay]);
|
|
51
|
+
return { copy, copied };
|
|
52
|
+
}
|
|
53
|
+
async function copyToClipboard(text) {
|
|
54
|
+
if (!navigator.clipboard) {
|
|
55
|
+
console.warn("[copyToClipboard] Clipboard API not available");
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
try {
|
|
59
|
+
await navigator.clipboard.writeText(text);
|
|
60
|
+
return true;
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.error("[copyToClipboard] Failed to copy:", error);
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function ServiceAccountsTab({
|
|
67
|
+
initialServiceAccounts,
|
|
68
|
+
initialTotal,
|
|
69
|
+
initialInstances,
|
|
70
|
+
primaryColor,
|
|
71
|
+
secondaryColor,
|
|
72
|
+
actions
|
|
73
|
+
}) {
|
|
74
|
+
const [serviceAccounts, setServiceAccounts] = react.useState(initialServiceAccounts);
|
|
75
|
+
const [total, setTotal] = react.useState(initialTotal);
|
|
76
|
+
const [instances] = react.useState(initialInstances);
|
|
77
|
+
const [error, setError] = react.useState(null);
|
|
78
|
+
const [pageIndex, setPageIndex] = react.useState(0);
|
|
79
|
+
const [pageSize, setPageSize] = react.useState(25);
|
|
80
|
+
const [showRevoked, setShowRevoked] = react.useState(false);
|
|
81
|
+
const [isCreateModalOpen, setIsCreateModalOpen] = react.useState(false);
|
|
82
|
+
const [isTokenModalOpen, setIsTokenModalOpen] = react.useState(false);
|
|
83
|
+
const [isRevokeModalOpen, setIsRevokeModalOpen] = react.useState(false);
|
|
84
|
+
const [isRotateModalOpen, setIsRotateModalOpen] = react.useState(false);
|
|
85
|
+
const [isRotatedTokenModalOpen, setIsRotatedTokenModalOpen] = react.useState(false);
|
|
86
|
+
const [isInstancesModalOpen, setIsInstancesModalOpen] = react.useState(false);
|
|
87
|
+
const [selectedAccount, setSelectedAccount] = react.useState(null);
|
|
88
|
+
const [newToken, setNewToken] = react.useState("");
|
|
89
|
+
const [rotatedAccount, setRotatedAccount] = react.useState(null);
|
|
90
|
+
const [helmLoginCommand, setHelmLoginCommand] = react.useState("");
|
|
91
|
+
const [redeployHelm, setRedeployHelm] = react.useState([]);
|
|
92
|
+
const [openDropdown, setOpenDropdown] = react.useState(null);
|
|
93
|
+
const [dropdownPosition, setDropdownPosition] = react.useState(null);
|
|
94
|
+
const dropdownRefs = react.useRef({});
|
|
95
|
+
const handleOpenDropdown = (accountId) => {
|
|
96
|
+
const button = dropdownRefs.current[accountId];
|
|
97
|
+
if (button) {
|
|
98
|
+
const rect = button.getBoundingClientRect();
|
|
99
|
+
setDropdownPosition({
|
|
100
|
+
top: rect.bottom + 8,
|
|
101
|
+
right: window.innerWidth - rect.right
|
|
102
|
+
});
|
|
103
|
+
setOpenDropdown(accountId);
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
const handleCloseDropdown = () => {
|
|
107
|
+
setOpenDropdown(null);
|
|
108
|
+
setDropdownPosition(null);
|
|
109
|
+
};
|
|
110
|
+
const serviceAccountsWithInstances = react.useMemo(() => {
|
|
111
|
+
return serviceAccounts.map((account) => ({
|
|
112
|
+
...account,
|
|
113
|
+
instanceCount: instances.filter((i) => i.serviceAccountId === account.id).length
|
|
114
|
+
}));
|
|
115
|
+
}, [serviceAccounts, instances]);
|
|
116
|
+
const refreshData = async (size = pageSize, offset = pageIndex * pageSize, includeRevoked = showRevoked) => {
|
|
117
|
+
setError(null);
|
|
118
|
+
try {
|
|
119
|
+
const result = await actions.fetchServiceAccounts(size, offset, includeRevoked);
|
|
120
|
+
setServiceAccounts(result.serviceAccounts);
|
|
121
|
+
setTotal(result.total);
|
|
122
|
+
} catch (err) {
|
|
123
|
+
setError(err instanceof Error ? err.message : "Failed to fetch service accounts");
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
const handlePageChange = (newPageIndex) => {
|
|
127
|
+
setPageIndex(newPageIndex);
|
|
128
|
+
refreshData(pageSize, newPageIndex * pageSize, showRevoked);
|
|
129
|
+
};
|
|
130
|
+
const handlePageSizeChange = (newPageSize) => {
|
|
131
|
+
setPageSize(newPageSize);
|
|
132
|
+
setPageIndex(0);
|
|
133
|
+
refreshData(newPageSize, 0, showRevoked);
|
|
134
|
+
};
|
|
135
|
+
const handleShowRevokedChange = (value) => {
|
|
136
|
+
setShowRevoked(value);
|
|
137
|
+
setPageIndex(0);
|
|
138
|
+
refreshData(pageSize, 0, value);
|
|
139
|
+
};
|
|
140
|
+
const isRecentlyRotated = (dateString) => {
|
|
141
|
+
if (!dateString) return false;
|
|
142
|
+
const date = new Date(dateString);
|
|
143
|
+
const now = /* @__PURE__ */ new Date();
|
|
144
|
+
const hoursDiff = (now.getTime() - date.getTime()) / (1e3 * 60 * 60);
|
|
145
|
+
return hoursDiff < 24;
|
|
146
|
+
};
|
|
147
|
+
const getInstancesForAccount = (accountId) => {
|
|
148
|
+
return instances.filter((i) => i.serviceAccountId === accountId);
|
|
149
|
+
};
|
|
150
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
|
|
151
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center", children: [
|
|
152
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-gray-600", children: "Service Accounts can call all APIs associated with the Enterprise Portal" }),
|
|
153
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4", children: [
|
|
154
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
155
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
156
|
+
"input",
|
|
157
|
+
{
|
|
158
|
+
type: "checkbox",
|
|
159
|
+
id: "showRevokedCheckbox",
|
|
160
|
+
checked: showRevoked,
|
|
161
|
+
onChange: (e) => handleShowRevokedChange(e.target.checked),
|
|
162
|
+
className: "portal-checkbox cursor-pointer"
|
|
163
|
+
}
|
|
164
|
+
),
|
|
165
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "showRevokedCheckbox", className: "text-sm text-gray-700 cursor-pointer", children: "Show revoked accounts" })
|
|
166
|
+
] }),
|
|
167
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
168
|
+
"button",
|
|
169
|
+
{
|
|
170
|
+
onClick: () => setIsCreateModalOpen(true),
|
|
171
|
+
className: "px-4 py-2 text-white rounded-md font-medium text-sm transition-opacity duration-200 hover:opacity-90",
|
|
172
|
+
style: { backgroundColor: primaryColor || DEFAULT_PRIMARY_COLOR },
|
|
173
|
+
children: "Create Service Account"
|
|
174
|
+
}
|
|
175
|
+
)
|
|
176
|
+
] })
|
|
177
|
+
] }),
|
|
178
|
+
serviceAccountsWithInstances.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "rounded-2xl border border-dashed border-gray-200 bg-gray-50 px-6 py-10 text-center text-sm text-gray-500", children: "No service accounts have been created yet." }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-white shadow-sm rounded-lg w-full overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "divide-y divide-gray-200 w-full table-fixed min-w-[900px]", children: [
|
|
179
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-gray-50", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
180
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "w-[13%] px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider", children: "Nickname" }),
|
|
181
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "w-[9%] px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider", children: "Last Accessed" }),
|
|
182
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "w-[9%] px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider", children: "Created" }),
|
|
183
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "w-[16%] px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider", children: "Created By" }),
|
|
184
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "w-[9%] px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider", children: "Last Rotated" }),
|
|
185
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "w-[8%] px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider", children: "Instances" }),
|
|
186
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "w-[6%] px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider", children: "Token" }),
|
|
187
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "w-[6%] px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider", children: "Status" }),
|
|
188
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "w-[6%] px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider", children: "Actions" })
|
|
189
|
+
] }) }),
|
|
190
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "bg-white divide-y divide-gray-200", children: serviceAccountsWithInstances.map((account) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
191
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-sm text-gray-900 truncate", title: account.accountName, children: account.accountName }),
|
|
192
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-sm text-gray-500", children: formatDate(account.lastUsedAt) }),
|
|
193
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-sm text-gray-500", children: formatDate(account.createdAt) }),
|
|
194
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-sm text-gray-500 truncate", title: account.emailAddress || void 0, children: account.emailAddress || "\u2014" }),
|
|
195
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-sm text-gray-500", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
|
|
196
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: formatDate(account.tokenRegeneratedAt) }),
|
|
197
|
+
isRecentlyRotated(account.tokenRegeneratedAt) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-blue-600", children: "Recently rotated" })
|
|
198
|
+
] }) }),
|
|
199
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 whitespace-nowrap text-sm", children: account.instanceCount > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
200
|
+
"button",
|
|
201
|
+
{
|
|
202
|
+
onClick: () => {
|
|
203
|
+
setSelectedAccount(account);
|
|
204
|
+
setIsInstancesModalOpen(true);
|
|
205
|
+
},
|
|
206
|
+
className: "text-blue-500 hover:underline cursor-pointer bg-transparent border-0 p-0",
|
|
207
|
+
children: [
|
|
208
|
+
account.instanceCount,
|
|
209
|
+
" active"
|
|
210
|
+
]
|
|
211
|
+
}
|
|
212
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-500", children: "0 active" }) }),
|
|
213
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 whitespace-nowrap text-sm", children: !account.isRevoked ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
214
|
+
"button",
|
|
215
|
+
{
|
|
216
|
+
onClick: () => {
|
|
217
|
+
setSelectedAccount(account);
|
|
218
|
+
setNewToken("");
|
|
219
|
+
setIsTokenModalOpen(true);
|
|
220
|
+
},
|
|
221
|
+
className: "hover:underline cursor-pointer bg-transparent border-0 p-0",
|
|
222
|
+
style: { color: secondaryColor || DEFAULT_SECONDARY_COLOR },
|
|
223
|
+
children: "View"
|
|
224
|
+
}
|
|
225
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-500 cursor-not-allowed", children: "View" }) }),
|
|
226
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 whitespace-nowrap text-sm", children: account.isRevoked ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500", children: "Revoked" }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-green-500", children: "Active" }) }),
|
|
227
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 whitespace-nowrap text-center text-sm font-medium", children: !account.isRevoked && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
228
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
229
|
+
"button",
|
|
230
|
+
{
|
|
231
|
+
ref: (el) => {
|
|
232
|
+
dropdownRefs.current[account.id] = el;
|
|
233
|
+
},
|
|
234
|
+
onClick: () => openDropdown === account.id ? handleCloseDropdown() : handleOpenDropdown(account.id),
|
|
235
|
+
className: "bg-transparent border-0 p-0 cursor-pointer",
|
|
236
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoreVertical, { className: "w-5 h-5 text-gray-500" })
|
|
237
|
+
}
|
|
238
|
+
),
|
|
239
|
+
openDropdown === account.id && dropdownPosition && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
240
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 z-10", onClick: handleCloseDropdown }),
|
|
241
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
242
|
+
"div",
|
|
243
|
+
{
|
|
244
|
+
className: "fixed z-20 w-48 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5",
|
|
245
|
+
style: { top: `${dropdownPosition.top}px`, right: `${dropdownPosition.right}px` },
|
|
246
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-1", children: [
|
|
247
|
+
account.instanceCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
248
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
249
|
+
"button",
|
|
250
|
+
{
|
|
251
|
+
onClick: () => {
|
|
252
|
+
setSelectedAccount(account);
|
|
253
|
+
setIsInstancesModalOpen(true);
|
|
254
|
+
handleCloseDropdown();
|
|
255
|
+
},
|
|
256
|
+
className: "w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100",
|
|
257
|
+
children: "View instances"
|
|
258
|
+
}
|
|
259
|
+
),
|
|
260
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-gray-100" })
|
|
261
|
+
] }),
|
|
262
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
263
|
+
"button",
|
|
264
|
+
{
|
|
265
|
+
onClick: () => {
|
|
266
|
+
setSelectedAccount(account);
|
|
267
|
+
setIsRotateModalOpen(true);
|
|
268
|
+
handleCloseDropdown();
|
|
269
|
+
},
|
|
270
|
+
className: "w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100",
|
|
271
|
+
children: "Rotate token"
|
|
272
|
+
}
|
|
273
|
+
),
|
|
274
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-gray-100" }),
|
|
275
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
276
|
+
"button",
|
|
277
|
+
{
|
|
278
|
+
onClick: () => {
|
|
279
|
+
setSelectedAccount(account);
|
|
280
|
+
setIsRevokeModalOpen(true);
|
|
281
|
+
handleCloseDropdown();
|
|
282
|
+
},
|
|
283
|
+
className: "w-full text-left px-4 py-2 text-sm text-red-600 hover:bg-gray-100",
|
|
284
|
+
children: "Revoke"
|
|
285
|
+
}
|
|
286
|
+
)
|
|
287
|
+
] })
|
|
288
|
+
}
|
|
289
|
+
)
|
|
290
|
+
] })
|
|
291
|
+
] }) })
|
|
292
|
+
] }, account.id)) })
|
|
293
|
+
] }) }),
|
|
294
|
+
total > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-3 bg-gray-50 border-t border-gray-200 rounded-b-lg", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
295
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4", children: [
|
|
296
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-gray-700", children: [
|
|
297
|
+
"Showing ",
|
|
298
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: pageIndex * pageSize + 1 }),
|
|
299
|
+
" to",
|
|
300
|
+
" ",
|
|
301
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: Math.min((pageIndex + 1) * pageSize, total) }),
|
|
302
|
+
" ",
|
|
303
|
+
"of ",
|
|
304
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: total }),
|
|
305
|
+
" results"
|
|
306
|
+
] }),
|
|
307
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
308
|
+
"select",
|
|
309
|
+
{
|
|
310
|
+
value: pageSize,
|
|
311
|
+
onChange: (e) => handlePageSizeChange(Number(e.target.value)),
|
|
312
|
+
className: "portal-select text-sm",
|
|
313
|
+
children: [
|
|
314
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: 25, children: "25 per page" }),
|
|
315
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: 50, children: "50 per page" }),
|
|
316
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: 100, children: "100 per page" })
|
|
317
|
+
]
|
|
318
|
+
}
|
|
319
|
+
)
|
|
320
|
+
] }),
|
|
321
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", style: { gap: "8px" }, children: [
|
|
322
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
323
|
+
"button",
|
|
324
|
+
{
|
|
325
|
+
onClick: () => handlePageChange(Math.max(0, pageIndex - 1)),
|
|
326
|
+
disabled: pageIndex === 0,
|
|
327
|
+
className: "px-3 py-1 text-white rounded-md font-medium text-sm transition-opacity duration-200 hover:opacity-90 disabled:opacity-50",
|
|
328
|
+
style: { backgroundColor: primaryColor || DEFAULT_PRIMARY_COLOR },
|
|
329
|
+
children: "Previous"
|
|
330
|
+
}
|
|
331
|
+
),
|
|
332
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
333
|
+
"button",
|
|
334
|
+
{
|
|
335
|
+
onClick: () => handlePageChange(pageIndex + 1),
|
|
336
|
+
disabled: (pageIndex + 1) * pageSize >= total,
|
|
337
|
+
className: "px-3 py-1 text-white rounded-md font-medium text-sm transition-opacity duration-200 hover:opacity-90 disabled:opacity-50",
|
|
338
|
+
style: { backgroundColor: primaryColor || DEFAULT_PRIMARY_COLOR },
|
|
339
|
+
children: "Next"
|
|
340
|
+
}
|
|
341
|
+
)
|
|
342
|
+
] })
|
|
343
|
+
] }) }),
|
|
344
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-red-50 border border-red-200 rounded-md p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex", children: [
|
|
345
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-5 w-5 text-red-400" }),
|
|
346
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ml-3", children: [
|
|
347
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-sm font-medium text-red-800", children: "Error" }),
|
|
348
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 text-sm text-red-700", children: error })
|
|
349
|
+
] })
|
|
350
|
+
] }) }),
|
|
351
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
352
|
+
CreateServiceAccountModal,
|
|
353
|
+
{
|
|
354
|
+
isOpen: isCreateModalOpen,
|
|
355
|
+
onClose: () => setIsCreateModalOpen(false),
|
|
356
|
+
onSuccess: (token) => {
|
|
357
|
+
setNewToken(token);
|
|
358
|
+
setIsCreateModalOpen(false);
|
|
359
|
+
setIsTokenModalOpen(true);
|
|
360
|
+
refreshData();
|
|
361
|
+
},
|
|
362
|
+
primaryColor,
|
|
363
|
+
createServiceAccount: actions.createServiceAccount
|
|
364
|
+
}
|
|
365
|
+
),
|
|
366
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
367
|
+
ServiceAccountTokenModal,
|
|
368
|
+
{
|
|
369
|
+
isOpen: isTokenModalOpen,
|
|
370
|
+
onClose: () => {
|
|
371
|
+
setIsTokenModalOpen(false);
|
|
372
|
+
setSelectedAccount(null);
|
|
373
|
+
setNewToken("");
|
|
374
|
+
},
|
|
375
|
+
token: newToken || selectedAccount?.token || "",
|
|
376
|
+
accountName: selectedAccount?.accountName,
|
|
377
|
+
isNewToken: !!newToken
|
|
378
|
+
}
|
|
379
|
+
),
|
|
380
|
+
selectedAccount && /* @__PURE__ */ jsxRuntime.jsx(
|
|
381
|
+
ServiceAccountInstancesModal,
|
|
382
|
+
{
|
|
383
|
+
isOpen: isInstancesModalOpen,
|
|
384
|
+
onClose: () => {
|
|
385
|
+
setIsInstancesModalOpen(false);
|
|
386
|
+
setSelectedAccount(null);
|
|
387
|
+
},
|
|
388
|
+
accountName: selectedAccount.accountName,
|
|
389
|
+
instances: getInstancesForAccount(selectedAccount.id)
|
|
390
|
+
}
|
|
391
|
+
),
|
|
392
|
+
selectedAccount && /* @__PURE__ */ jsxRuntime.jsx(
|
|
393
|
+
RevokeServiceAccountModal,
|
|
394
|
+
{
|
|
395
|
+
isOpen: isRevokeModalOpen,
|
|
396
|
+
onClose: () => {
|
|
397
|
+
setIsRevokeModalOpen(false);
|
|
398
|
+
setSelectedAccount(null);
|
|
399
|
+
},
|
|
400
|
+
onSuccess: () => {
|
|
401
|
+
setIsRevokeModalOpen(false);
|
|
402
|
+
setSelectedAccount(null);
|
|
403
|
+
refreshData();
|
|
404
|
+
},
|
|
405
|
+
accountId: selectedAccount.id,
|
|
406
|
+
accountName: selectedAccount.accountName,
|
|
407
|
+
primaryColor,
|
|
408
|
+
revokeServiceAccount: actions.revokeServiceAccount
|
|
409
|
+
}
|
|
410
|
+
),
|
|
411
|
+
selectedAccount && /* @__PURE__ */ jsxRuntime.jsx(
|
|
412
|
+
RotateServiceAccountModal,
|
|
413
|
+
{
|
|
414
|
+
isOpen: isRotateModalOpen,
|
|
415
|
+
onClose: () => {
|
|
416
|
+
setIsRotateModalOpen(false);
|
|
417
|
+
setSelectedAccount(null);
|
|
418
|
+
},
|
|
419
|
+
onSuccess: (result) => {
|
|
420
|
+
setIsRotateModalOpen(false);
|
|
421
|
+
setRotatedAccount(result.serviceAccount);
|
|
422
|
+
setHelmLoginCommand(result.helmLoginCommand);
|
|
423
|
+
setRedeployHelm(result.redeployHelm);
|
|
424
|
+
setSelectedAccount(null);
|
|
425
|
+
setIsRotatedTokenModalOpen(true);
|
|
426
|
+
refreshData();
|
|
427
|
+
},
|
|
428
|
+
account: selectedAccount,
|
|
429
|
+
instances: getInstancesForAccount(selectedAccount.id),
|
|
430
|
+
primaryColor,
|
|
431
|
+
rotateServiceAccountToken: actions.rotateServiceAccountToken
|
|
432
|
+
}
|
|
433
|
+
),
|
|
434
|
+
rotatedAccount && /* @__PURE__ */ jsxRuntime.jsx(
|
|
435
|
+
RotatedTokenModal,
|
|
436
|
+
{
|
|
437
|
+
isOpen: isRotatedTokenModalOpen,
|
|
438
|
+
onClose: () => {
|
|
439
|
+
setIsRotatedTokenModalOpen(false);
|
|
440
|
+
setRotatedAccount(null);
|
|
441
|
+
setHelmLoginCommand("");
|
|
442
|
+
setRedeployHelm([]);
|
|
443
|
+
},
|
|
444
|
+
serviceAccount: rotatedAccount,
|
|
445
|
+
helmLoginCommand,
|
|
446
|
+
redeployHelm,
|
|
447
|
+
instances: instances.filter((i) => i.serviceAccountId === rotatedAccount.id),
|
|
448
|
+
primaryColor
|
|
449
|
+
}
|
|
450
|
+
)
|
|
451
|
+
] });
|
|
452
|
+
}
|
|
453
|
+
function CreateServiceAccountModal({
|
|
454
|
+
isOpen,
|
|
455
|
+
onClose,
|
|
456
|
+
onSuccess,
|
|
457
|
+
primaryColor,
|
|
458
|
+
createServiceAccount
|
|
459
|
+
}) {
|
|
460
|
+
const [name, setName] = react.useState("");
|
|
461
|
+
const [isSubmitting, setIsSubmitting] = react.useState(false);
|
|
462
|
+
const [error, setError] = react.useState(null);
|
|
463
|
+
if (!isOpen) return null;
|
|
464
|
+
const handleSubmit = async (e) => {
|
|
465
|
+
e.preventDefault();
|
|
466
|
+
setIsSubmitting(true);
|
|
467
|
+
setError(null);
|
|
468
|
+
try {
|
|
469
|
+
const result = await createServiceAccount(name);
|
|
470
|
+
setName("");
|
|
471
|
+
onSuccess(result.token);
|
|
472
|
+
} catch (err) {
|
|
473
|
+
setError(err instanceof Error ? err.message : "Failed to create service account");
|
|
474
|
+
} finally {
|
|
475
|
+
setIsSubmitting(false);
|
|
476
|
+
}
|
|
477
|
+
};
|
|
478
|
+
const handleClose = () => {
|
|
479
|
+
setName("");
|
|
480
|
+
setError(null);
|
|
481
|
+
onClose();
|
|
482
|
+
};
|
|
483
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 z-50 overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-screen items-center justify-center p-4", children: [
|
|
484
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 bg-gray-500 bg-opacity-75", onClick: handleClose }),
|
|
485
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative bg-white rounded-lg shadow-xl w-full max-w-md", children: [
|
|
486
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center p-6", children: [
|
|
487
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-xl font-semibold text-gray-900", children: "Create a Service Account" }),
|
|
488
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: handleClose, className: "text-gray-400 hover:text-gray-500 border-none bg-transparent", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-5 w-5" }) })
|
|
489
|
+
] }),
|
|
490
|
+
/* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, className: "px-6 pb-6", children: [
|
|
491
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-gray-600 mb-4", children: "Create a service account with a descriptive nickname to identify its purpose." }),
|
|
492
|
+
error && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-red-500 text-sm font-semibold mb-4", children: [
|
|
493
|
+
"Error: ",
|
|
494
|
+
error
|
|
495
|
+
] }),
|
|
496
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative mb-5", children: [
|
|
497
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Key, { className: "absolute w-5 h-5 text-gray-400 pointer-events-none", style: { left: "12px", top: "50%", transform: "translateY(-50%)" } }),
|
|
498
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { type: "text", value: name, onChange: (e) => setName(e.target.value), className: "portal-input w-full pr-4 py-2.5", style: { paddingLeft: "44px" }, placeholder: "Nickname", required: true })
|
|
499
|
+
] }),
|
|
500
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end space-x-3 mt-6", children: [
|
|
501
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: handleClose, className: "px-4 py-2 text-sm font-medium text-gray-700 bg-gray-100 hover:bg-gray-200 rounded-md", children: "Cancel" }),
|
|
502
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "submit", disabled: isSubmitting, className: "px-4 py-2 text-sm font-medium text-white rounded-md transition-opacity duration-200 hover:opacity-90 disabled:opacity-50", style: { backgroundColor: primaryColor || DEFAULT_PRIMARY_COLOR }, children: isSubmitting ? "Creating..." : "Create Service Account" })
|
|
503
|
+
] })
|
|
504
|
+
] })
|
|
505
|
+
] })
|
|
506
|
+
] }) });
|
|
507
|
+
}
|
|
508
|
+
function ServiceAccountTokenModal({ isOpen, onClose, token, accountName, isNewToken }) {
|
|
509
|
+
const { copy, copied } = useCopyToClipboard();
|
|
510
|
+
if (!isOpen) return null;
|
|
511
|
+
const title = isNewToken ? "Service Account Created" : `${accountName} Token`;
|
|
512
|
+
const handleCopy = () => copy(token);
|
|
513
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 z-50 overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-screen items-center justify-center p-4", children: [
|
|
514
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 bg-gray-500 bg-opacity-75", onClick: onClose }),
|
|
515
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative bg-white rounded-lg shadow-xl w-full max-w-2xl", children: [
|
|
516
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center p-6", children: [
|
|
517
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-xl font-semibold text-gray-900", children: title }),
|
|
518
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: onClose, className: "text-gray-400 hover:text-gray-500 border-none bg-transparent", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-5 w-5" }) })
|
|
519
|
+
] }),
|
|
520
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-6 pb-6 flex flex-col gap-4", children: [
|
|
521
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-gray-600 mb-0", children: "This is your token, keep it in a secure location." }),
|
|
522
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "bg-gray-900 text-gray-100 p-4 rounded-lg whitespace-pre-wrap break-all", children: /* @__PURE__ */ jsxRuntime.jsx("code", { children: token }) }) }),
|
|
523
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-3", children: [
|
|
524
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: handleCopy, className: "px-4 py-2 text-sm font-medium text-gray-700 bg-gray-100 hover:bg-gray-200 rounded-md inline-flex items-center gap-2", children: copied ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
525
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "w-4 h-4 text-green-600" }),
|
|
526
|
+
" Copied"
|
|
527
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
528
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "w-4 h-4" }),
|
|
529
|
+
" Copy token"
|
|
530
|
+
] }) }),
|
|
531
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: onClose, className: "px-4 py-2 text-sm font-medium text-gray-700 bg-gray-100 hover:bg-gray-200 rounded-md", children: "Close" })
|
|
532
|
+
] })
|
|
533
|
+
] })
|
|
534
|
+
] })
|
|
535
|
+
] }) });
|
|
536
|
+
}
|
|
537
|
+
function ServiceAccountInstancesModal({ isOpen, onClose, accountName, instances }) {
|
|
538
|
+
if (!isOpen) return null;
|
|
539
|
+
const isInstanceActive = (instance) => {
|
|
540
|
+
const day = 24 * 60 * 60 * 1e3;
|
|
541
|
+
const lastCheckin = instance.lastCheckin ? new Date(instance.lastCheckin).getTime() : 0;
|
|
542
|
+
return lastCheckin > Date.now() - day;
|
|
543
|
+
};
|
|
544
|
+
const getInstanceName = (instance) => {
|
|
545
|
+
const nameTag = instance.tags?.find((t) => t.key === "name");
|
|
546
|
+
return nameTag?.value || instance.id;
|
|
547
|
+
};
|
|
548
|
+
const getInstanceTags = (instance) => instance.tags?.filter((t) => t.key !== "name") || [];
|
|
549
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 z-50 overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-screen items-center justify-center p-4", children: [
|
|
550
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 bg-gray-500 bg-opacity-75", onClick: onClose }),
|
|
551
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative bg-white rounded-lg shadow-xl w-full max-w-2xl", children: [
|
|
552
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center p-6", children: [
|
|
553
|
+
/* @__PURE__ */ jsxRuntime.jsxs("h2", { className: "text-xl font-semibold text-gray-900", children: [
|
|
554
|
+
"Instances controlled by ",
|
|
555
|
+
accountName
|
|
556
|
+
] }),
|
|
557
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: onClose, className: "text-gray-400 hover:text-gray-500 border-none bg-transparent", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-5 w-5" }) })
|
|
558
|
+
] }),
|
|
559
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 pb-6", children: instances.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-gray-500", children: [
|
|
560
|
+
"No instances found for ",
|
|
561
|
+
accountName
|
|
562
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-4", children: instances.map((instance) => {
|
|
563
|
+
const tags = getInstanceTags(instance);
|
|
564
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[72px] pl-6 pr-3 rounded-lg border border-gray-200 flex items-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", children: [
|
|
565
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `h-2.5 w-2.5 rounded-full mr-6 flex-shrink-0 ${isInstanceActive(instance) ? "bg-green-500" : "bg-yellow-500"}` }),
|
|
566
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
567
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium text-gray-900 mb-1", children: getInstanceName(instance) }),
|
|
568
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm text-gray-500", children: [
|
|
569
|
+
"Version ",
|
|
570
|
+
instance.versionLabel || "Unknown"
|
|
571
|
+
] })
|
|
572
|
+
] }),
|
|
573
|
+
tags.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1.5 ml-6", children: tags.map((tag) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-gray-100 text-gray-700", children: [
|
|
574
|
+
tag.key,
|
|
575
|
+
"=",
|
|
576
|
+
tag.value
|
|
577
|
+
] }, tag.key)) })
|
|
578
|
+
] }) }, instance.id);
|
|
579
|
+
}) }) })
|
|
580
|
+
] })
|
|
581
|
+
] }) });
|
|
582
|
+
}
|
|
583
|
+
function RevokeServiceAccountModal({ isOpen, onClose, onSuccess, accountId, accountName, primaryColor, revokeServiceAccount }) {
|
|
584
|
+
const [confirmName, setConfirmName] = react.useState("");
|
|
585
|
+
const [isRevoking, setIsRevoking] = react.useState(false);
|
|
586
|
+
const [error, setError] = react.useState(null);
|
|
587
|
+
if (!isOpen) return null;
|
|
588
|
+
const handleRevoke = async () => {
|
|
589
|
+
setIsRevoking(true);
|
|
590
|
+
setError(null);
|
|
591
|
+
try {
|
|
592
|
+
await revokeServiceAccount(accountId);
|
|
593
|
+
setConfirmName("");
|
|
594
|
+
onSuccess();
|
|
595
|
+
} catch (err) {
|
|
596
|
+
setError(err instanceof Error ? err.message : "Failed to revoke service account");
|
|
597
|
+
} finally {
|
|
598
|
+
setIsRevoking(false);
|
|
599
|
+
}
|
|
600
|
+
};
|
|
601
|
+
const handleClose = () => {
|
|
602
|
+
setConfirmName("");
|
|
603
|
+
setError(null);
|
|
604
|
+
onClose();
|
|
605
|
+
};
|
|
606
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 z-50 overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-screen items-center justify-center p-4", children: [
|
|
607
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 bg-gray-500 bg-opacity-75", onClick: handleClose }),
|
|
608
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative bg-white rounded-lg shadow-xl w-full max-w-md", children: [
|
|
609
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center p-6", children: [
|
|
610
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-xl font-semibold text-gray-900", children: "Revoke service account" }),
|
|
611
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: handleClose, className: "text-gray-400 hover:text-gray-500 border-none bg-transparent", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-5 w-5" }) })
|
|
612
|
+
] }),
|
|
613
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-6 pb-6", children: [
|
|
614
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-gray-600 mb-4", children: "Are you sure you want to revoke this service account? This action cannot be undone." }),
|
|
615
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-gray-600 mb-4", children: [
|
|
616
|
+
"To confirm, please type the service account name: ",
|
|
617
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold", children: accountName })
|
|
618
|
+
] }),
|
|
619
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { type: "text", value: confirmName, onChange: (e) => setConfirmName(e.target.value), placeholder: "Enter service account name", className: "portal-input w-full mb-4" }),
|
|
620
|
+
error && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-red-500 text-sm font-semibold mb-4", children: [
|
|
621
|
+
"Error: ",
|
|
622
|
+
error
|
|
623
|
+
] }),
|
|
624
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end space-x-3", children: [
|
|
625
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: handleClose, disabled: isRevoking, className: "px-4 py-2 text-sm font-medium text-gray-700 bg-gray-100 hover:bg-gray-200 rounded-md border border-gray-300", children: "Cancel" }),
|
|
626
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: handleRevoke, disabled: confirmName !== accountName || isRevoking, className: "px-4 py-2 text-sm font-medium text-white rounded-md transition-opacity duration-200 hover:opacity-90 disabled:opacity-50", style: { backgroundColor: primaryColor || DEFAULT_PRIMARY_COLOR }, children: isRevoking ? "Revoking..." : "Revoke service account" })
|
|
627
|
+
] })
|
|
628
|
+
] })
|
|
629
|
+
] })
|
|
630
|
+
] }) });
|
|
631
|
+
}
|
|
632
|
+
function RotateServiceAccountModal({ isOpen, onClose, onSuccess, account, instances, primaryColor, rotateServiceAccountToken }) {
|
|
633
|
+
const [confirmRotate, setConfirmRotate] = react.useState(false);
|
|
634
|
+
const [confirmText, setConfirmText] = react.useState("");
|
|
635
|
+
const [isRotating, setIsRotating] = react.useState(false);
|
|
636
|
+
const [error, setError] = react.useState(null);
|
|
637
|
+
if (!isOpen) return null;
|
|
638
|
+
const requiredConfirmText = "Abandon instances and proceed anyways";
|
|
639
|
+
const hasOldECInstances = instances.some((i) => {
|
|
640
|
+
const v = i.embeddedClusterVersion;
|
|
641
|
+
if (!v) return false;
|
|
642
|
+
const m = v.match(/^v?(\d+)\.(\d+)\.(\d+)/);
|
|
643
|
+
if (!m || m.length < 4) return false;
|
|
644
|
+
const major = Number(m[1]);
|
|
645
|
+
const minor = Number(m[2]);
|
|
646
|
+
const patch = Number(m[3]);
|
|
647
|
+
return major < 2 || major === 2 && minor < 7 || major === 2 && minor === 7 && patch < 4;
|
|
648
|
+
});
|
|
649
|
+
const handleRotate = async () => {
|
|
650
|
+
setIsRotating(true);
|
|
651
|
+
setError(null);
|
|
652
|
+
try {
|
|
653
|
+
const result = await rotateServiceAccountToken(account.id);
|
|
654
|
+
onSuccess(result);
|
|
655
|
+
} catch (err) {
|
|
656
|
+
setError(err instanceof Error ? err.message : "Failed to rotate token");
|
|
657
|
+
} finally {
|
|
658
|
+
setIsRotating(false);
|
|
659
|
+
}
|
|
660
|
+
};
|
|
661
|
+
const handleClose = () => {
|
|
662
|
+
setConfirmRotate(false);
|
|
663
|
+
setConfirmText("");
|
|
664
|
+
onClose();
|
|
665
|
+
};
|
|
666
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 z-50 overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-screen items-center justify-center p-4", children: [
|
|
667
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 bg-gray-500 bg-opacity-75", onClick: handleClose }),
|
|
668
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative bg-white rounded-lg shadow-xl w-full max-w-lg", children: [
|
|
669
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center p-6", children: [
|
|
670
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-xl font-semibold text-gray-900", children: "Rotate Service Account Token" }),
|
|
671
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: handleClose, className: "text-gray-400 hover:text-gray-500 border-none bg-transparent", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-5 w-5" }) })
|
|
672
|
+
] }),
|
|
673
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-6 pb-6", children: [
|
|
674
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3 mb-4", children: [
|
|
675
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "w-5 h-5 text-yellow-500 flex-shrink-0 mt-0.5" }),
|
|
676
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
677
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-gray-900 font-medium mb-2", children: "This will invalidate the current token" }),
|
|
678
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-gray-600 mb-0", children: [
|
|
679
|
+
"Rotating the token for ",
|
|
680
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold", children: account.accountName }),
|
|
681
|
+
" will immediately invalidate the existing token. Any systems using the current token will need to be updated with the new token."
|
|
682
|
+
] })
|
|
683
|
+
] })
|
|
684
|
+
] }),
|
|
685
|
+
account.instanceCount > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-amber-50 border border-amber-200 rounded-md p-3 mb-4", children: /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-amber-800 text-sm mb-0", children: [
|
|
686
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Warning:" }),
|
|
687
|
+
" This service account is being used by ",
|
|
688
|
+
account.instanceCount,
|
|
689
|
+
" active instance",
|
|
690
|
+
account.instanceCount > 1 ? "s" : "",
|
|
691
|
+
". Make sure to update those instances with the new token."
|
|
692
|
+
] }) }),
|
|
693
|
+
hasOldECInstances && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-red-50 border border-red-200 rounded-md p-3 mb-4", children: [
|
|
694
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-red-800 text-sm mb-3", children: [
|
|
695
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Warning:" }),
|
|
696
|
+
" Some instances are running Embedded Cluster versions older than 2.7.4. There is no way to rotate service accounts for these instances without first updating. If rotated, these instances can no longer be updated."
|
|
697
|
+
] }),
|
|
698
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3", children: [
|
|
699
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium text-red-800 mb-2", children: "Type the following to continue:" }),
|
|
700
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-red-700 mb-2 italic", children: [
|
|
701
|
+
'"',
|
|
702
|
+
requiredConfirmText,
|
|
703
|
+
'"'
|
|
704
|
+
] }),
|
|
705
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { type: "text", value: confirmText, onChange: (e) => setConfirmText(e.target.value), placeholder: "Type the text above exactly as shown", className: "portal-input w-full" })
|
|
706
|
+
] })
|
|
707
|
+
] }),
|
|
708
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-4", children: [
|
|
709
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", id: "confirmRotateCheckbox", checked: confirmRotate, onChange: (e) => setConfirmRotate(e.target.checked), className: "portal-checkbox" }),
|
|
710
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "confirmRotateCheckbox", className: "text-sm text-gray-700 mb-0", children: "I understand that the current token will be invalidated" })
|
|
711
|
+
] }),
|
|
712
|
+
error && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-red-500 text-sm font-semibold mb-4", children: [
|
|
713
|
+
"Error: ",
|
|
714
|
+
error
|
|
715
|
+
] }),
|
|
716
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end space-x-3", children: [
|
|
717
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: handleClose, disabled: isRotating, className: "px-4 py-2 text-sm font-medium text-gray-700 bg-gray-100 hover:bg-gray-200 rounded-md border border-gray-300", children: "Cancel" }),
|
|
718
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: handleRotate, disabled: !confirmRotate || isRotating || hasOldECInstances && confirmText !== requiredConfirmText, className: "px-4 py-2 text-sm font-medium text-white rounded-md transition-opacity duration-200 hover:opacity-90 disabled:opacity-50", style: { backgroundColor: primaryColor || DEFAULT_PRIMARY_COLOR }, children: isRotating ? "Rotating..." : "Rotate token" })
|
|
719
|
+
] })
|
|
720
|
+
] })
|
|
721
|
+
] })
|
|
722
|
+
] }) });
|
|
723
|
+
}
|
|
724
|
+
function RotatedTokenModal({ isOpen, onClose, serviceAccount, helmLoginCommand, redeployHelm, instances, primaryColor }) {
|
|
725
|
+
const [copiedField, setCopiedField] = react.useState(null);
|
|
726
|
+
if (!isOpen) return null;
|
|
727
|
+
const handleCopy = async (text, field) => {
|
|
728
|
+
const success = await copyToClipboard(text);
|
|
729
|
+
if (success) {
|
|
730
|
+
setCopiedField(field);
|
|
731
|
+
setTimeout(() => setCopiedField(null), 2e3);
|
|
732
|
+
}
|
|
733
|
+
};
|
|
734
|
+
const hasECInstances = instances.some((i) => !!i.embeddedClusterVersion);
|
|
735
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 z-50 overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-screen items-center justify-center p-4", children: [
|
|
736
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 bg-gray-500 bg-opacity-75", onClick: onClose }),
|
|
737
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative bg-white rounded-lg shadow-xl w-full max-w-2xl max-h-[90vh] overflow-y-auto", children: [
|
|
738
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center p-6", children: [
|
|
739
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-xl font-semibold text-gray-900", children: "Token Rotated Successfully" }),
|
|
740
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: onClose, className: "text-gray-400 hover:text-gray-500 border-none bg-transparent", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-5 w-5" }) })
|
|
741
|
+
] }),
|
|
742
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-6 pb-6 flex flex-col gap-4", children: [
|
|
743
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-green-50 border border-green-200 rounded-md p-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2", children: [
|
|
744
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.RotateCcw, { className: "w-4 h-4 text-black mt-0.5 flex-shrink-0" }),
|
|
745
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
746
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-black font-medium text-sm mb-1", children: [
|
|
747
|
+
"Token rotated for ",
|
|
748
|
+
serviceAccount.accountName
|
|
749
|
+
] }),
|
|
750
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-black text-sm mb-0", children: "The previous token has been invalidated. Use this new token for authentication." })
|
|
751
|
+
] })
|
|
752
|
+
] }) }),
|
|
753
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
754
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between mb-2", children: /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium text-gray-700", children: "New Service Account Token" }) }),
|
|
755
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative group", children: [
|
|
756
|
+
/* @__PURE__ */ jsxRuntime.jsx("pre", { className: "bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto cursor-pointer", onClick: () => handleCopy(serviceAccount.token, "token"), children: /* @__PURE__ */ jsxRuntime.jsx("code", { children: serviceAccount.token }) }),
|
|
757
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => handleCopy(serviceAccount.token, "token"), className: "absolute top-2 right-2 p-2 text-gray-400 hover:text-gray-200 bg-transparent border-0", children: copiedField === "token" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "w-4 h-4 text-green-400" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "w-4 h-4" }) })
|
|
758
|
+
] }),
|
|
759
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500 mt-1", children: "Keep this token secure and update any systems that were using the previous token." })
|
|
760
|
+
] }),
|
|
761
|
+
hasECInstances && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-green-50 border border-green-200 rounded-md p-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2", children: [
|
|
762
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-4 h-4 bg-green-500 rounded-full mt-0.5 flex-shrink-0" }),
|
|
763
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
764
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-black font-medium text-sm mb-1", children: "Update Embedded Cluster Instances" }),
|
|
765
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-black text-sm mb-0", children: "For instances running Embedded Cluster, upload the new service account token via the instance admin console's License tab to ensure continued access." })
|
|
766
|
+
] })
|
|
767
|
+
] }) }),
|
|
768
|
+
helmLoginCommand && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
769
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between mb-2", children: /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium text-gray-700", children: "Helm Registry Login Command" }) }),
|
|
770
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative group", children: [
|
|
771
|
+
/* @__PURE__ */ jsxRuntime.jsx("pre", { className: "bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto cursor-pointer", onClick: () => handleCopy(helmLoginCommand, "helm"), children: /* @__PURE__ */ jsxRuntime.jsx("code", { children: helmLoginCommand }) }),
|
|
772
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => handleCopy(helmLoginCommand, "helm"), className: "absolute top-2 right-2 p-2 text-gray-400 hover:text-gray-200 bg-transparent border-0", children: copiedField === "helm" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "w-4 h-4 text-green-400" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "w-4 h-4" }) })
|
|
773
|
+
] }),
|
|
774
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500 mt-1", children: "Use this command to authenticate with the registry using your new token." })
|
|
775
|
+
] }),
|
|
776
|
+
redeployHelm.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
777
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium text-gray-700 mb-2 block", children: "Redeploy Commands" }),
|
|
778
|
+
redeployHelm.length > 1 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-yellow-50 border border-yellow-200 rounded-md p-3 mb-3", children: [
|
|
779
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-yellow-700 mb-2", children: "Since you have multiple instances, you may want to check which Helm charts are currently deployed on each instance to ensure you do not accidentally change chart versions:" }),
|
|
780
|
+
/* @__PURE__ */ jsxRuntime.jsx("pre", { className: "bg-gray-900 text-gray-100 p-2 rounded text-sm", children: /* @__PURE__ */ jsxRuntime.jsx("code", { children: "helm list" }) })
|
|
781
|
+
] }),
|
|
782
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: redeployHelm.map((commands, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
783
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between mb-2", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-medium text-gray-600", children: [
|
|
784
|
+
"Instance ",
|
|
785
|
+
index + 1
|
|
786
|
+
] }) }),
|
|
787
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative group", children: [
|
|
788
|
+
/* @__PURE__ */ jsxRuntime.jsx("pre", { className: "bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto cursor-pointer", onClick: () => handleCopy(commands, `redeploy-${index}`), children: /* @__PURE__ */ jsxRuntime.jsx("code", { children: commands }) }),
|
|
789
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => handleCopy(commands, `redeploy-${index}`), className: "absolute top-2 right-2 p-2 text-gray-400 hover:text-gray-200 bg-transparent border-0", children: copiedField === `redeploy-${index}` ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "w-4 h-4 text-green-400" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "w-4 h-4" }) })
|
|
790
|
+
] }),
|
|
791
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500 mt-1", children: "Use this command to redeploy your Helm charts with the new service account token." })
|
|
792
|
+
] }, index)) })
|
|
793
|
+
] }),
|
|
794
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-end mt-4", children: /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: onClose, className: "px-4 py-2 text-white rounded-md font-medium transition-opacity duration-200 hover:opacity-90", style: { backgroundColor: primaryColor || DEFAULT_PRIMARY_COLOR }, children: "Done" }) })
|
|
795
|
+
] })
|
|
796
|
+
] })
|
|
797
|
+
] }) });
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
exports.ServiceAccountsTab = ServiceAccountsTab;
|
|
801
|
+
//# sourceMappingURL=service-accounts-tab.js.map
|
|
802
|
+
//# sourceMappingURL=service-accounts-tab.js.map
|