@cobaltcore-dev/aurora 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/client/AuroraApp.d.ts +2 -0
- package/dist/client/AuthProvider-DZqOvceF.mjs +64 -0
- package/dist/client/AuthProvider-DZqOvceF.mjs.map +1 -0
- package/dist/client/ContentHeader-DsuZD8fa.mjs +110 -0
- package/dist/client/ContentHeader-DsuZD8fa.mjs.map +1 -0
- package/dist/client/{DeleteFlavorModal-C3m7bQJu.mjs → DeleteFlavorModal-RnbspW_2.mjs} +135 -135
- package/dist/client/{DeleteFlavorModal-C3m7bQJu.mjs.map → DeleteFlavorModal-RnbspW_2.mjs.map} +1 -1
- package/dist/client/{DeleteVersionsModal-CyYZfB8d.mjs → DeleteVersionsModal-CsBJzXoW.mjs} +57 -57
- package/dist/client/{DeleteVersionsModal-CyYZfB8d.mjs.map → DeleteVersionsModal-CsBJzXoW.mjs.map} +1 -1
- package/dist/client/{EditSecurityGroupModal-DKusxfta.mjs → EditSecurityGroupModal-BPv3d7am.mjs} +15 -15
- package/dist/client/{EditSecurityGroupModal-DKusxfta.mjs.map → EditSecurityGroupModal-BPv3d7am.mjs.map} +1 -1
- package/dist/client/{FiltersInput-GzR4D0q6.mjs → FiltersInput-CViamP59.mjs} +2 -2
- package/dist/client/{FiltersInput-GzR4D0q6.mjs.map → FiltersInput-CViamP59.mjs.map} +1 -1
- package/dist/client/{FloatingIpActionModals-CRvROJ3H.mjs → FloatingIpActionModals-DTn3HFei.mjs} +45 -45
- package/dist/client/{FloatingIpActionModals-CRvROJ3H.mjs.map → FloatingIpActionModals-DTn3HFei.mjs.map} +1 -1
- package/dist/client/{ImageToastNotifications-BuDXpTkl.mjs → ImageToastNotifications-CFKQZTgf.mjs} +261 -261
- package/dist/client/{ImageToastNotifications-BuDXpTkl.mjs.map → ImageToastNotifications-CFKQZTgf.mjs.map} +1 -1
- package/dist/client/{RouteError-DVAiT0mT.mjs → RouteError-BebIhFpQ.mjs} +2 -2
- package/dist/client/{RouteError-DVAiT0mT.mjs.map → RouteError-BebIhFpQ.mjs.map} +1 -1
- package/dist/client/{SortInput-DLcusjGZ.mjs → SortInput-D0Vb864D.mjs} +2 -2
- package/dist/client/{SortInput-DLcusjGZ.mjs.map → SortInput-D0Vb864D.mjs.map} +1 -1
- package/dist/client/{_auth-DXJkv9QO.mjs → _auth-DnImOqR-.mjs} +2 -2
- package/dist/client/_auth-DnImOqR-.mjs.map +1 -0
- package/dist/client/{_flavorId-Dy7EYQum.mjs → _flavorId-C9SZd1jL.mjs} +8 -8
- package/dist/client/{_flavorId-Dy7EYQum.mjs.map → _flavorId-C9SZd1jL.mjs.map} +1 -1
- package/dist/client/{_flavorId-DsD2VTKA.mjs → _flavorId-DINgWoeV.mjs} +38 -38
- package/dist/client/{_flavorId-DsD2VTKA.mjs.map → _flavorId-DINgWoeV.mjs.map} +1 -1
- package/dist/client/{_floatingIpId-j17rCQqG2.mjs → _floatingIpId-BACLbMzi2.mjs} +32 -32
- package/dist/client/{_floatingIpId-j17rCQqG2.mjs.map → _floatingIpId-BACLbMzi2.mjs.map} +1 -1
- package/dist/client/{_floatingIpId-BjVbeNw_.mjs → _floatingIpId-BzVMOv97.mjs} +2 -2
- package/dist/client/{_floatingIpId-BjVbeNw_.mjs.map → _floatingIpId-BzVMOv97.mjs.map} +1 -1
- package/dist/client/_imageId-DCvaU7-S.mjs +534 -0
- package/dist/client/_imageId-DCvaU7-S.mjs.map +1 -0
- package/dist/client/{_pcaId-Bo7yHkNW.mjs → _pcaId-B3PqECyO.mjs} +115 -115
- package/dist/client/{_pcaId-Bo7yHkNW.mjs.map → _pcaId-B3PqECyO.mjs.map} +1 -1
- package/dist/client/{_pcaId-CKkCVC7b.mjs → _pcaId-DAJEt3ZI.mjs} +2 -2
- package/dist/client/{_pcaId-CKkCVC7b.mjs.map → _pcaId-DAJEt3ZI.mjs.map} +1 -1
- package/dist/client/{_projectId-CARHuZTU.mjs → _projectId-B2hG5peP.mjs} +3 -3
- package/dist/client/_projectId-B2hG5peP.mjs.map +1 -0
- package/dist/client/{_projectId-CY8W0IF6.mjs → _projectId-BnWXWTBR.mjs} +3 -3
- package/dist/client/{_projectId-CY8W0IF6.mjs.map → _projectId-BnWXWTBR.mjs.map} +1 -1
- package/dist/client/{_projectId-Dbck_MFa.mjs → _projectId-DRr9rLST.mjs} +66 -66
- package/dist/client/{_projectId-Dbck_MFa.mjs.map → _projectId-DRr9rLST.mjs.map} +1 -1
- package/dist/client/{_projectId-B_2sZKk-.mjs → _projectId-DU8qRiZk.mjs} +2 -2
- package/dist/client/_projectId-DU8qRiZk.mjs.map +1 -0
- package/dist/client/{_securityGroupId-gSEZbBII.mjs → _securityGroupId-Cj9IotMJ.mjs} +2 -2
- package/dist/client/{_securityGroupId-gSEZbBII.mjs.map → _securityGroupId-Cj9IotMJ.mjs.map} +1 -1
- package/dist/client/{_securityGroupId-CkN0CGVg.mjs → _securityGroupId-ClJiFh4R.mjs} +267 -267
- package/dist/client/{_securityGroupId-CkN0CGVg.mjs.map → _securityGroupId-ClJiFh4R.mjs.map} +1 -1
- package/dist/client/_storageType-BrHDa2bD.mjs +3005 -0
- package/dist/client/_storageType-BrHDa2bD.mjs.map +1 -0
- package/dist/client/{_storageType-6k8lUnQo.mjs → _storageType-CSLH93js.mjs} +2 -2
- package/dist/client/{_storageType-6k8lUnQo.mjs.map → _storageType-CSLH93js.mjs.map} +1 -1
- package/dist/client/_storageType-zeSZe--V.mjs.map +1 -1
- package/dist/client/{about-Nsxkyh9U.mjs → about-BnU297yB.mjs} +2 -2
- package/dist/client/about-BnU297yB.mjs.map +1 -0
- package/dist/client/{aurora-DDzsst74.mjs → aurora-6RsAZtnz.mjs} +2 -2
- package/dist/client/aurora-6RsAZtnz.mjs.map +1 -0
- package/dist/client/{build-BdRRmNf5.mjs → build-DF7MTyXG.mjs} +3582 -3114
- package/dist/client/{build-BdRRmNf5.mjs.map → build-DF7MTyXG.mjs.map} +1 -1
- package/dist/client/{constants-PMXUGI4Q.mjs → constants-BskfpGYY.mjs} +16 -16
- package/dist/client/{constants-PMXUGI4Q.mjs.map → constants-BskfpGYY.mjs.map} +1 -1
- package/dist/client/{flavors-p2TKcqP-.mjs → flavors-DAbtRoep.mjs} +151 -151
- package/dist/client/{flavors-p2TKcqP-.mjs.map → flavors-DAbtRoep.mjs.map} +1 -1
- package/dist/client/{flavors-BclEwobO.mjs → flavors-DODudzrA.mjs} +2 -2
- package/dist/client/{flavors-BclEwobO.mjs.map → flavors-DODudzrA.mjs.map} +1 -1
- package/dist/client/flavors-DWMZ6TuJ.mjs.map +1 -1
- package/dist/client/{floatingips-ph0ZxJw8.mjs → floatingips-DJW9ftN_.mjs} +83 -83
- package/dist/client/floatingips-DJW9ftN_.mjs.map +1 -0
- package/dist/client/{hooks-dSArr2Ca.mjs → hooks-CMgoYcDG.mjs} +1 -1
- package/dist/client/{images-CXdghaMW.mjs → images-BbLnuYrL.mjs} +2 -2
- package/dist/client/{images-CXdghaMW.mjs.map → images-BbLnuYrL.mjs.map} +1 -1
- package/dist/client/{images-Dbjo4yKn.mjs → images-C3JyPwer.mjs} +2 -2
- package/dist/client/images-C3JyPwer.mjs.map +1 -0
- package/dist/client/{images-BblnyWJq.mjs → images-Cp6V1nF5.mjs} +455 -455
- package/dist/client/{images-BblnyWJq.mjs.map → images-Cp6V1nF5.mjs.map} +1 -1
- package/dist/client/images-NBf2bV43.mjs.map +1 -1
- package/dist/client/index.js +257 -257
- package/dist/client/index.js.map +1 -1
- package/dist/client/network-DuZm76BZ.mjs.map +1 -1
- package/dist/client/{objects-B9Jh3SMG.mjs → objects-Bw96WXOs.mjs} +2 -2
- package/dist/client/{objects-B9Jh3SMG.mjs.map → objects-Bw96WXOs.mjs.map} +1 -1
- package/dist/client/{objects-Bw25cE1m.mjs → objects-DUmK3WgA.mjs} +1458 -1430
- package/dist/client/objects-DUmK3WgA.mjs.map +1 -0
- package/dist/client/objects-o2Cj_ndZ.mjs.map +1 -1
- package/dist/client/{pca-DUrQ_tIg.mjs → pca-DKeGzbww.mjs} +2 -2
- package/dist/client/{pca-DUrQ_tIg.mjs.map → pca-DKeGzbww.mjs.map} +1 -1
- package/dist/client/{pca-CiLPHmK7.mjs → pca-Dc_tdh4-.mjs} +47 -47
- package/dist/client/{pca-CiLPHmK7.mjs.map → pca-Dc_tdh4-.mjs.map} +1 -1
- package/dist/client/{projects-DNd3UTas.mjs → projects-CRL37ftA.mjs} +16 -16
- package/dist/client/{projects-DNd3UTas.mjs.map → projects-CRL37ftA.mjs.map} +1 -1
- package/dist/client/{projects-B5topuei.mjs → projects-DUWOgB3m.mjs} +2 -2
- package/dist/client/{projects-B5topuei.mjs.map → projects-DUWOgB3m.mjs.map} +1 -1
- package/dist/client/{projects-CHYn7L5e.mjs → projects-DpXQYfKc.mjs} +2 -2
- package/dist/client/projects-DpXQYfKc.mjs.map +1 -0
- package/dist/client/{securitygroups-CcA2TpAt.mjs → securitygroups-CWWFSjjj.mjs} +94 -94
- package/dist/client/securitygroups-CWWFSjjj.mjs.map +1 -0
- package/dist/client/{useListWithFiltering-CVzhMyEA.mjs → useListWithFiltering-C9k7xWqz.mjs} +7 -7
- package/dist/client/{useListWithFiltering-CVzhMyEA.mjs.map → useListWithFiltering-C9k7xWqz.mjs.map} +1 -1
- package/dist/server/index.js +697 -406
- package/package.json +3 -3
- package/dist/client/AuthProvider-Co4d0WzB.mjs +0 -100
- package/dist/client/AuthProvider-Co4d0WzB.mjs.map +0 -1
- package/dist/client/ContentHeader-D4jlOG-9.mjs +0 -96
- package/dist/client/ContentHeader-D4jlOG-9.mjs.map +0 -1
- package/dist/client/_auth-DXJkv9QO.mjs.map +0 -1
- package/dist/client/_imageId-BjfhqAje.mjs +0 -534
- package/dist/client/_imageId-BjfhqAje.mjs.map +0 -1
- package/dist/client/_projectId-B_2sZKk-.mjs.map +0 -1
- package/dist/client/_projectId-CARHuZTU.mjs.map +0 -1
- package/dist/client/_storageType-CLTxXjQZ.mjs +0 -3048
- package/dist/client/_storageType-CLTxXjQZ.mjs.map +0 -1
- package/dist/client/about-Nsxkyh9U.mjs.map +0 -1
- package/dist/client/aurora-DDzsst74.mjs.map +0 -1
- package/dist/client/floatingips-ph0ZxJw8.mjs.map +0 -1
- package/dist/client/images-Dbjo4yKn.mjs.map +0 -1
- package/dist/client/objects-Bw25cE1m.mjs.map +0 -1
- package/dist/client/projects-CHYn7L5e.mjs.map +0 -1
- package/dist/client/securitygroups-CcA2TpAt.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -167,10 +167,11 @@ function MyFooter(_props: SlotProps) {
|
|
|
167
167
|
| `login` | Replaces the default login form — use in OIDC environments | — | No |
|
|
168
168
|
| `serviceBadge` | Inline next to each service label in the side nav and project home cards | `currentService` (service key) | No |
|
|
169
169
|
| `servicePageActions` | Beside the page title in the service page header | `currentService` (service key) | No |
|
|
170
|
+
| `serviceBanner` | Below the page title divider on every service page | `currentService` (service key) | No |
|
|
170
171
|
| `projectsBanner` | Below the "Projects" heading on the projects list page | — | No |
|
|
171
172
|
| `projectOverviewBanner` | Below the project description on the project overview page (`/projects/:id`) | — | No |
|
|
172
173
|
|
|
173
|
-
The `serviceBadge` and `
|
|
174
|
+
The `serviceBadge`, `servicePageActions`, and `serviceBanner` slots receive `auroraContext.currentService` — a string identifying which service is being rendered (e.g. `"images"`, `"ceph-containers"`). Return `null` from these slots to suppress rendering for specific services.
|
|
174
175
|
|
|
175
176
|
**Service key reference:** `"images"`, `"flavors"`, `"securitygroups"`, `"floatingips"`, `"containers"`, `"ceph-containers"`, `"pca"`
|
|
176
177
|
|
|
@@ -27,6 +27,8 @@ export type Slots = {
|
|
|
27
27
|
projectsBanner?: FC<SlotProps>;
|
|
28
28
|
/** Rendered below the project description on the project overview page (/projects/$projectId). Renders outside shadow DOM. */
|
|
29
29
|
projectOverviewBanner?: FC<SlotProps>;
|
|
30
|
+
/** Rendered below the page title divider on every service page. Receives `auroraContext.currentService`. Renders outside shadow DOM. */
|
|
31
|
+
serviceBanner?: FC<SlotProps>;
|
|
30
32
|
};
|
|
31
33
|
/**
|
|
32
34
|
* Payload for analytics tracking events.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { jsx as e } from "react/jsx-runtime";
|
|
2
|
+
import t, { useCallback as n, useEffect as r, useRef as i, useState as a } from "react";
|
|
3
|
+
import { useRouter as o } from "@tanstack/react-router";
|
|
4
|
+
//#region src/client/store/AuthProvider.tsx
|
|
5
|
+
var s = /*#__PURE__*/ t.createContext(null);
|
|
6
|
+
function c({ children: c }) {
|
|
7
|
+
let l = o(), [u, d] = t.useState(null), [f, p] = t.useState(void 0), [m, h] = t.useState(void 0), [g, _] = a(!1), [v, y] = a(void 0), b = i(null), x = !!u, S = n(() => {
|
|
8
|
+
b.current &&= (clearTimeout(b.current), null);
|
|
9
|
+
}, []), C = n(() => {
|
|
10
|
+
_(!1), l.navigate({
|
|
11
|
+
to: "/",
|
|
12
|
+
search: v ? { redirect: v } : void 0
|
|
13
|
+
});
|
|
14
|
+
}, [l, v]), w = n(async (e = "manual") => {
|
|
15
|
+
if (S(), d(null), p(void 0), h(e), e === "expired") {
|
|
16
|
+
let e = window.location.pathname + window.location.search;
|
|
17
|
+
e && e.startsWith("/") && y(e), _(!0);
|
|
18
|
+
} else l.invalidate();
|
|
19
|
+
}, [l, S]), T = n(async (e, t) => {
|
|
20
|
+
d(e), h(void 0), _(!1), y(void 0), p(t ? new Date(t) : void 0);
|
|
21
|
+
}, []);
|
|
22
|
+
return r(() => {
|
|
23
|
+
if (S(), u && f) {
|
|
24
|
+
let e = f.getTime() - Date.now();
|
|
25
|
+
if (e <= 0) {
|
|
26
|
+
w("expired");
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
b.current = setTimeout(() => {
|
|
30
|
+
w("expired");
|
|
31
|
+
}, e);
|
|
32
|
+
}
|
|
33
|
+
return () => {
|
|
34
|
+
S();
|
|
35
|
+
};
|
|
36
|
+
}, [
|
|
37
|
+
u,
|
|
38
|
+
f,
|
|
39
|
+
w,
|
|
40
|
+
S
|
|
41
|
+
]), /*#__PURE__*/ e(s.Provider, {
|
|
42
|
+
value: {
|
|
43
|
+
isAuthenticated: x,
|
|
44
|
+
user: u,
|
|
45
|
+
login: T,
|
|
46
|
+
logout: w,
|
|
47
|
+
expiresAt: f,
|
|
48
|
+
logoutReason: m,
|
|
49
|
+
showInactivityModal: g,
|
|
50
|
+
closeInactivityModal: C,
|
|
51
|
+
redirectAfterModal: v
|
|
52
|
+
},
|
|
53
|
+
children: c
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
function l() {
|
|
57
|
+
let e = t.useContext(s);
|
|
58
|
+
if (!e) throw Error("useAuth must be used within an AuthProvider");
|
|
59
|
+
return e;
|
|
60
|
+
}
|
|
61
|
+
//#endregion
|
|
62
|
+
export { l as n, c as t };
|
|
63
|
+
|
|
64
|
+
//# sourceMappingURL=AuthProvider-DZqOvceF.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthProvider-DZqOvceF.mjs","names":["React","useEffect","useRef","useCallback","useState","useRouter","AuthContext","createContext","AuthProvider","children","router","user","setUser","expiresAt","setExpiresAt","undefined","logoutReason","setLogoutReason","showInactivityModal","setShowInactivityModal","redirectAfterModal","setRedirectAfterModal","logoutTimerRef","isAuthenticated","clearLogoutTimer","current","clearTimeout","closeInactivityModal","navigate","to","search","redirect","logout","reason","currentPath","window","location","pathname","startsWith","invalidate","login","expires_at","expiration","Date","timeUntilExpiry","getTime","now","setTimeout","Provider","value","useAuth","context","useContext","Error"],"sources":["../../src/client/store/AuthProvider.tsx"],"sourcesContent":["import React, { useEffect, useRef, useCallback, useState } from \"react\"\nimport { TokenData } from \"../../server/Authentication/types/models\"\nimport { useRouter } from \"@tanstack/react-router\"\n\nexport type User = TokenData[\"user\"] | null\n\nexport interface AuthContext {\n isAuthenticated: boolean\n login: (user: User, expires_at?: string) => Promise<void>\n logout: (reason?: \"inactive\" | \"expired\" | \"manual\") => Promise<void>\n user?: User\n expiresAt?: Date\n logoutReason?: \"inactive\" | \"expired\" | \"manual\"\n showInactivityModal: boolean\n closeInactivityModal: () => void\n redirectAfterModal?: string\n}\n\nconst AuthContext = React.createContext<AuthContext | null>(null)\n\nexport function AuthProvider({ children }: { children: React.ReactNode }) {\n const router = useRouter()\n const [user, setUser] = React.useState<User | null>(null)\n const [expiresAt, setExpiresAt] = React.useState<Date | undefined>(undefined)\n const [logoutReason, setLogoutReason] = React.useState<\"inactive\" | \"expired\" | \"manual\" | undefined>(undefined)\n const [showInactivityModal, setShowInactivityModal] = useState(false)\n const [redirectAfterModal, setRedirectAfterModal] = useState<string | undefined>(undefined)\n\n const logoutTimerRef = useRef<NodeJS.Timeout | null>(null)\n\n const isAuthenticated = !!user\n\n const clearLogoutTimer = useCallback(() => {\n if (logoutTimerRef.current) {\n clearTimeout(logoutTimerRef.current)\n logoutTimerRef.current = null\n }\n }, [])\n\n const closeInactivityModal = useCallback(() => {\n setShowInactivityModal(false)\n\n router.navigate({\n to: \"/\",\n search: redirectAfterModal ? { redirect: redirectAfterModal } : undefined,\n })\n }, [router, redirectAfterModal])\n\n const logout = useCallback(\n async (reason: \"inactive\" | \"expired\" | \"manual\" = \"manual\") => {\n clearLogoutTimer()\n\n setUser(null)\n setExpiresAt(undefined)\n setLogoutReason(reason)\n\n // For expired: Show modal instead of direct navigation\n if (reason === \"expired\") {\n const currentPath = window.location.pathname + window.location.search\n if (currentPath && currentPath.startsWith(\"/\")) {\n setRedirectAfterModal(currentPath)\n }\n\n setShowInactivityModal(true)\n } else {\n // Manual logout: direct navigation\n router.invalidate()\n }\n },\n [router, clearLogoutTimer]\n )\n\n const login = useCallback(async (user: User, expires_at?: string) => {\n setUser(user)\n setLogoutReason(undefined)\n setShowInactivityModal(false)\n setRedirectAfterModal(undefined)\n\n if (expires_at) {\n const expiration = new Date(expires_at)\n setExpiresAt(expiration)\n } else {\n setExpiresAt(undefined)\n }\n }, [])\n\n useEffect(() => {\n clearLogoutTimer()\n\n if (user && expiresAt) {\n const timeUntilExpiry = expiresAt.getTime() - Date.now()\n\n if (timeUntilExpiry <= 0) {\n logout(\"expired\")\n return\n }\n\n logoutTimerRef.current = setTimeout(() => {\n logout(\"expired\")\n }, timeUntilExpiry)\n }\n\n return () => {\n clearLogoutTimer()\n }\n }, [user, expiresAt, logout, clearLogoutTimer])\n\n return (\n <AuthContext.Provider\n value={{\n isAuthenticated,\n user,\n login,\n logout,\n expiresAt,\n logoutReason,\n showInactivityModal,\n closeInactivityModal,\n redirectAfterModal,\n }}\n >\n {children}\n </AuthContext.Provider>\n )\n}\n\nexport function useAuth() {\n const context = React.useContext(AuthContext)\n if (!context) {\n throw new Error(\"useAuth must be used within an AuthProvider\")\n }\n return context\n}\n"],"mappings":";;;;AAkBA,IAAMM,IAAcN,gBAAMO,cAAkC,IAAA;AAE5D,SAAgBC,EAAa,EAAEC,eAAyC;CACtE,IAAMC,IAASL,EAAAA,GACT,CAACM,GAAMC,KAAWZ,EAAMI,SAAsB,IAAA,GAC9C,CAACS,GAAWC,KAAgBd,EAAMI,SAA2BW,KAAAA,CAAAA,GAC7D,CAACC,GAAcC,KAAmBjB,EAAMI,SAAwDW,KAAAA,CAAAA,GAChG,CAACG,GAAqBC,KAA0Bf,EAAS,EAAA,GACzD,CAACgB,GAAoBC,KAAyBjB,EAA6BW,KAAAA,CAAAA,GAE3EO,IAAiBpB,EAA8B,IAAA,GAE/CqB,IAAkB,CAAC,CAACZ,GAEpBa,IAAmBrB,QAAY;EACnC,AAEEmB,EAAeG,aADfC,aAAaJ,EAAeG,OAAO,GACV;CAE7B,GAAG,CAAA,CAAE,GAECE,IAAuBxB,QAAY;EAGvCO,AAFAS,EAAuB,EAAA,GAEvBT,EAAOkB,SAAS;GACdC,IAAI;GACJC,QAAQV,IAAqB,EAAEW,UAAUX,EAAmB,IAAIL,KAAAA;EAClE,CAAA;CACF,GAAG,CAACL,GAAQU,CAAAA,CAAmB,GAEzBY,IAAS7B,EACb,OAAO8B,IAA4C,aAAQ;EAQzD,IAPAT,EAAAA,GAEAZ,EAAQ,IAAA,GACRE,EAAaC,KAAAA,CAAAA,GACbE,EAAgBgB,CAAAA,GAGZA,MAAW,WAAW;GACxB,IAAMC,IAAcC,OAAOC,SAASC,WAAWF,OAAOC,SAASN;GAK/DX,AAJIe,KAAeA,EAAYI,WAAW,GAAA,KACxCjB,EAAsBa,CAAAA,GAGxBf,EAAuB,EAAA;EACzB,OAEET,EAAO6B,WAAU;CAErB,GACA,CAAC7B,GAAQc,CAAAA,CAAiB,GAGtBgB,IAAQrC,EAAY,OAAOQ,GAAY8B,MAAAA;EAM3C,AALA7B,EAAQD,CAAAA,GACRM,EAAgBF,KAAAA,CAAAA,GAChBI,EAAuB,EAAA,GACvBE,EAAsBN,KAAAA,CAAAA,GAIpBD,EAFE2B,IAEWC,IADUC,KAAKF,CACfC,IAEA3B,KAAAA,CAAAA;CAEjB,GAAG,CAAA,CAAE;CAuBL,OArBAd,QAAU;EAGR,IAFAuB,EAAAA,GAEIb,KAAQE,GAAW;GACrB,IAAM+B,IAAkB/B,EAAUgC,QAAO,IAAKF,KAAKG,IAAG;GAEtD,IAAIF,KAAmB,GAAG;IACxBZ,EAAO,SAAA;IACP;GACF;GAEAV,EAAeG,UAAUsB,iBAAW;IAClCf,EAAO,SAAA;GACT,GAAGY,CAAAA;EACL;EAEA,aAAO;GACLpB,EAAAA;EACF;CACF,GAAG;EAACb;EAAME;EAAWmB;EAAQR;EAAiB,GAG5C,gBAAClB,EAAY0C,UAAQ;EACnBC,OAAO;GACL1B;GACAZ;GACA6B;GACAR;GACAnB;GACAG;GACAE;GACAS;GACAP;EACF;EAECX;;AAGP;AAEA,SAAgByC,IAAAA;CACd,IAAMC,IAAUnD,EAAMoD,WAAW9C,CAAAA;CACjC,IAAI,CAAC6C,GACH,MAAUE,MAAM,6CAAA;CAElB,OAAOF;AACT"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { A as e, C as t, X as n, c as r, et as i, lt as a, o } from "./build-DF7MTyXG.mjs";
|
|
2
|
+
import { t as s } from "./Slot-CWb612-_.mjs";
|
|
3
|
+
import { t as c } from "./routeInfo-Dy9l-wFB.mjs";
|
|
4
|
+
import { jsx as l, jsxs as u } from "react/jsx-runtime";
|
|
5
|
+
import { useState as d } from "react";
|
|
6
|
+
import { useMatches as f, useParams as p, useRouteContext as m } from "@tanstack/react-router";
|
|
7
|
+
import { Trans as h, useLingui as g } from "@lingui/react";
|
|
8
|
+
//#region src/client/components/ClipboardText.tsx
|
|
9
|
+
var _ = ({ text: i, tooltipContent: a, className: s, truncateAt: c, showTooltip: f = !0, ...p }) => {
|
|
10
|
+
let { i18n: m, _: h } = g(), [_, v] = d(!1), [y, b] = d(!1), x = `copyableTooltip inline-flex items-center ${s || ""}`, S = async (e) => {
|
|
11
|
+
e.preventDefault(), e.stopPropagation();
|
|
12
|
+
try {
|
|
13
|
+
await navigator.clipboard.writeText(i), v(!0), b(!1), setTimeout(() => v(!1), 2e3);
|
|
14
|
+
} catch (e) {
|
|
15
|
+
console.error("Failed to copy text:", e);
|
|
16
|
+
}
|
|
17
|
+
}, C = c && i.length > c ? `${i.slice(0, c)}...` : i, w = () => _ ? a || m._({ id: "u+VWhB" }) : m._({ id: "he3ygx" }), T = _ && f || y && f;
|
|
18
|
+
return /*#__PURE__*/ l("div", {
|
|
19
|
+
...p,
|
|
20
|
+
className: x,
|
|
21
|
+
children: /*#__PURE__*/ u(e, {
|
|
22
|
+
open: T,
|
|
23
|
+
children: [/*#__PURE__*/ l(o, {
|
|
24
|
+
onClick: S,
|
|
25
|
+
onMouseEnter: () => !_ && b(!0),
|
|
26
|
+
onMouseLeave: () => b(!1),
|
|
27
|
+
"aria-label": m._({
|
|
28
|
+
id: "Wbg1jv",
|
|
29
|
+
values: { text: i }
|
|
30
|
+
}),
|
|
31
|
+
className: "cursor-pointer",
|
|
32
|
+
asChild: !0,
|
|
33
|
+
"data-testid": "clipboard-copy-trigger",
|
|
34
|
+
children: /*#__PURE__*/ l("div", {
|
|
35
|
+
className: "group",
|
|
36
|
+
children: /*#__PURE__*/ u(n, {
|
|
37
|
+
direction: "horizontal",
|
|
38
|
+
gap: "1",
|
|
39
|
+
className: "items-center hover:underline",
|
|
40
|
+
children: [/*#__PURE__*/ l("span", {
|
|
41
|
+
className: "select-none",
|
|
42
|
+
children: C
|
|
43
|
+
}), /*#__PURE__*/ l(r, {
|
|
44
|
+
icon: _ ? "check" : "contentCopy",
|
|
45
|
+
size: "18"
|
|
46
|
+
})]
|
|
47
|
+
})
|
|
48
|
+
})
|
|
49
|
+
}), /*#__PURE__*/ l(t, { children: w() })]
|
|
50
|
+
})
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
//#endregion
|
|
54
|
+
//#region src/client/components/ContentHeader/ContentHeader.tsx
|
|
55
|
+
function v({ title: e, projectId: t, description: n, actions: r, badges: o }) {
|
|
56
|
+
let { slots: d } = m({ strict: !1 }), g = f(), { provider: v } = p({ strict: !1 }), y = [...g].reverse().find((e) => c(e.staticData)), b = y && c(y.staticData) ? y.staticData.service : void 0, x = b === "containers" && v === "ceph" ? "ceph-containers" : b, S = d?.servicePageActions && x ? /*#__PURE__*/ l(s, {
|
|
57
|
+
component: d.servicePageActions,
|
|
58
|
+
useShadowDOM: !1,
|
|
59
|
+
currentService: x
|
|
60
|
+
}) : null, C = d?.serviceBanner && x ? /*#__PURE__*/ l(s, {
|
|
61
|
+
component: d.serviceBanner,
|
|
62
|
+
useShadowDOM: !1,
|
|
63
|
+
currentService: x
|
|
64
|
+
}) : null;
|
|
65
|
+
return /*#__PURE__*/ u("header", {
|
|
66
|
+
className: "mb-8",
|
|
67
|
+
children: [
|
|
68
|
+
/*#__PURE__*/ u("div", {
|
|
69
|
+
className: "flex flex-col sm:flex-row sm:items-center sm:justify-between",
|
|
70
|
+
children: [/*#__PURE__*/ u("div", {
|
|
71
|
+
className: "flex items-center gap-3",
|
|
72
|
+
children: [/*#__PURE__*/ l(i, { children: e }), S]
|
|
73
|
+
}), /*#__PURE__*/ u("div", {
|
|
74
|
+
className: "text-theme-light flex shrink-0 items-center gap-1 text-sm",
|
|
75
|
+
children: [/*#__PURE__*/ u("span", {
|
|
76
|
+
className: "font-semibold",
|
|
77
|
+
children: [
|
|
78
|
+
/*#__PURE__*/ l(h, { id: "mSfwLL" }),
|
|
79
|
+
":",
|
|
80
|
+
" "
|
|
81
|
+
]
|
|
82
|
+
}), /*#__PURE__*/ l(_, {
|
|
83
|
+
text: t,
|
|
84
|
+
truncateAt: 15
|
|
85
|
+
})]
|
|
86
|
+
})]
|
|
87
|
+
}),
|
|
88
|
+
n && /*#__PURE__*/ l("p", {
|
|
89
|
+
className: "text-sm font-normal",
|
|
90
|
+
children: n
|
|
91
|
+
}),
|
|
92
|
+
/*#__PURE__*/ l(a, { className: "mt-4" }),
|
|
93
|
+
C,
|
|
94
|
+
(o || r) && /*#__PURE__*/ u("div", {
|
|
95
|
+
className: "mt-3 flex items-start justify-between",
|
|
96
|
+
children: [/*#__PURE__*/ u("div", {
|
|
97
|
+
className: "flex items-center gap-2",
|
|
98
|
+
children: [o, " "]
|
|
99
|
+
}), r && /*#__PURE__*/ l("div", {
|
|
100
|
+
className: "flex gap-2",
|
|
101
|
+
children: r
|
|
102
|
+
})]
|
|
103
|
+
})
|
|
104
|
+
]
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
//#endregion
|
|
108
|
+
export { _ as n, v as t };
|
|
109
|
+
|
|
110
|
+
//# sourceMappingURL=ContentHeader-DsuZD8fa.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ContentHeader-DsuZD8fa.mjs","names":["React","useState","Tooltip","TooltipTrigger","TooltipContent","Icon","Stack","ClipboardText","text","tooltipContent","className","truncateAt","showTooltip","props","useLingui","copied","setCopied","isHovering","setIsHovering","combinedClassName","handleCopy","e","preventDefault","stopPropagation","navigator","clipboard","writeText","setTimeout","err","console","error","displayText","length","slice","getTooltipContent","t","tooltipIsOpen","div","open","onClick","onMouseEnter","onMouseLeave","aria-label","asChild","data-testid","direction","gap","span","icon","size","Divider","ContentHeading","useRouteContext","useMatches","useParams","ClipboardText","Slot","isRouteInfo","ContentHeader","title","projectId","description","actions","badges","slots","strict","matches","provider","activeMatch","reverse","find","m","staticData","routeService","service","undefined","currentService","slotActions","servicePageActions","component","useShadowDOM","serviceBanner","header","className","div","span","text","truncateAt","p"],"sources":["../../src/client/components/ClipboardText.tsx","../../src/client/components/ContentHeader/ContentHeader.tsx"],"sourcesContent":["import React, { useState } from \"react\"\nimport { Tooltip, TooltipTrigger, TooltipContent, Icon, Stack } from \"@cloudoperators/juno-ui-components\"\nimport { useLingui } from \"@lingui/react/macro\"\n\nexport interface ClipboardTextProps extends React.HTMLAttributes<HTMLDivElement> {\n tooltipContent?: string\n text: string\n className?: string\n truncateAt?: number\n showTooltip?: boolean\n}\n\nconst ClipboardText: React.FC<ClipboardTextProps> = ({\n text,\n tooltipContent,\n className,\n truncateAt,\n showTooltip = true,\n ...props\n}) => {\n const { t } = useLingui()\n const [copied, setCopied] = useState(false)\n const [isHovering, setIsHovering] = useState(false)\n\n const combinedClassName = `copyableTooltip inline-flex items-center ${className || \"\"}`\n\n const handleCopy = async (e: React.MouseEvent) => {\n e.preventDefault()\n e.stopPropagation()\n\n try {\n await navigator.clipboard.writeText(text)\n setCopied(true)\n setIsHovering(false)\n setTimeout(() => setCopied(false), 2000)\n } catch (err) {\n console.error(\"Failed to copy text:\", err)\n }\n }\n\n const displayText = truncateAt && text.length > truncateAt ? `${text.slice(0, truncateAt)}...` : text\n\n // Determine tooltip content based on state\n const getTooltipContent = () => {\n if (copied) {\n return tooltipContent || t`Copied to clipboard!`\n }\n return t`Copy`\n }\n\n const tooltipIsOpen = (copied && showTooltip) || (isHovering && showTooltip)\n\n return (\n <div {...props} className={combinedClassName}>\n <Tooltip open={tooltipIsOpen}>\n <TooltipTrigger\n onClick={handleCopy}\n onMouseEnter={() => !copied && setIsHovering(true)}\n onMouseLeave={() => setIsHovering(false)}\n aria-label={t`Copy ${text} to clipboard`}\n className=\"cursor-pointer\"\n asChild\n data-testid=\"clipboard-copy-trigger\"\n >\n <div className=\"group\">\n <Stack direction=\"horizontal\" gap=\"1\" className=\"items-center hover:underline\">\n <span className=\"select-none\">{displayText}</span>\n <Icon icon={copied ? \"check\" : \"contentCopy\"} size=\"18\" />\n </Stack>\n </div>\n </TooltipTrigger>\n <TooltipContent>{getTooltipContent()}</TooltipContent>\n </Tooltip>\n </div>\n )\n}\n\nexport default ClipboardText\n","import type { ReactNode } from \"react\"\nimport { Divider, ContentHeading } from \"@cloudoperators/juno-ui-components\"\nimport { Trans } from \"@lingui/react/macro\"\nimport { useRouteContext, useMatches, useParams } from \"@tanstack/react-router\"\nimport ClipboardText from \"../ClipboardText\"\nimport { Slot } from \"../Slot\"\nimport { isRouteInfo } from \"@/client/routes/routeInfo\"\n\ninterface ContentHeaderProps {\n title: string\n projectId: string\n description?: string | null\n actions?: ReactNode\n badges?: ReactNode\n}\n\nexport function ContentHeader({ title, projectId, description, actions, badges }: ContentHeaderProps) {\n const { slots } = useRouteContext({ strict: false })\n const matches = useMatches()\n const { provider } = useParams({ strict: false }) as { provider?: string }\n\n const activeMatch = [...matches].reverse().find((m) => isRouteInfo(m.staticData))\n const routeService = activeMatch && isRouteInfo(activeMatch.staticData) ? activeMatch.staticData.service : undefined\n\n // Storage routes share service: \"containers\" for both Swift and Ceph.\n // Distinguish them by the $provider param.\n const currentService = routeService === \"containers\" && provider === \"ceph\" ? \"ceph-containers\" : routeService\n\n const slotActions =\n slots?.servicePageActions && currentService ? (\n <Slot component={slots.servicePageActions} useShadowDOM={false} currentService={currentService} />\n ) : null\n\n const serviceBanner =\n slots?.serviceBanner && currentService ? (\n <Slot component={slots.serviceBanner} useShadowDOM={false} currentService={currentService} />\n ) : null\n\n return (\n <header className=\"mb-8\">\n <div className=\"flex flex-col sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"flex items-center gap-3\">\n <ContentHeading>{title}</ContentHeading>\n {slotActions}\n </div>\n <div className=\"text-theme-light flex shrink-0 items-center gap-1 text-sm\">\n <span className=\"font-semibold\">\n <Trans>Project ID</Trans>:{\" \"}\n </span>\n <ClipboardText text={projectId} truncateAt={15} />\n </div>\n </div>\n {description && <p className=\"text-sm font-normal\">{description}</p>}\n <Divider className=\"mt-4\" />\n {serviceBanner}\n {(badges || actions) && (\n <div className=\"mt-3 flex items-start justify-between\">\n <div className=\"flex items-center gap-2\">{badges} </div>\n {actions && <div className=\"flex gap-2\">{actions}</div>}\n </div>\n )}\n </header>\n )\n}\n"],"mappings":"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"}
|