@cobaltcore-dev/aurora 0.20.3 → 0.22.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/dist/client/AuthProvider-p1e1DuKU.mjs +69 -0
- package/dist/client/AuthProvider-p1e1DuKU.mjs.map +1 -0
- package/dist/client/{ContentHeader-CIAzorGI.mjs → ContentHeader-BIScbvb4.mjs} +3 -2
- package/dist/client/{ContentHeader-CIAzorGI.mjs.map → ContentHeader-BIScbvb4.mjs.map} +1 -1
- package/dist/client/DeleteFlavorModal-lFMExcq_.mjs +713 -0
- package/dist/client/DeleteFlavorModal-lFMExcq_.mjs.map +1 -0
- package/dist/client/{DeletePcaModal-YUlNw8cw.mjs → DeletePcaModal-Dg9dej-H.mjs} +2 -2
- package/dist/client/{DeletePcaModal-YUlNw8cw.mjs.map → DeletePcaModal-Dg9dej-H.mjs.map} +1 -1
- package/dist/client/{DetailsInfo-Cv3oke-R.mjs → DetailsInfo-DwCo9P1o.mjs} +2 -2
- package/dist/client/{DetailsInfo-Cv3oke-R.mjs.map → DetailsInfo-DwCo9P1o.mjs.map} +1 -1
- package/dist/client/{FloatingIpActionModals-PLN6CWZ9.mjs → FloatingIpActionModals-CDF8LVtX.mjs} +2 -2
- package/dist/client/{FloatingIpActionModals-PLN6CWZ9.mjs.map → FloatingIpActionModals-CDF8LVtX.mjs.map} +1 -1
- package/dist/client/{ImageToastNotifications-BQM7HOyE.mjs → ImageToastNotifications-Dzq6jNTm.mjs} +2 -2
- package/dist/client/{ImageToastNotifications-BQM7HOyE.mjs.map → ImageToastNotifications-Dzq6jNTm.mjs.map} +1 -1
- package/dist/client/Slot-CWb612-_.mjs +28 -0
- package/dist/client/Slot-CWb612-_.mjs.map +1 -0
- package/dist/client/{_auth-BtRCgHQe.mjs → _auth-Dut7CaMR.mjs} +2 -2
- package/dist/client/{_auth-BtRCgHQe.mjs.map → _auth-Dut7CaMR.mjs.map} +1 -1
- package/dist/client/{_flavorId-BaNJ1CDY.mjs → _flavorId-BMJcnI7H.mjs} +2 -2
- package/dist/client/{_flavorId-BaNJ1CDY.mjs.map → _flavorId-BMJcnI7H.mjs.map} +1 -1
- package/dist/client/{_flavorId-BMX239RH.mjs → _flavorId-DUWdFEMH.mjs} +13 -14
- package/dist/client/{_flavorId-BMX239RH.mjs.map → _flavorId-DUWdFEMH.mjs.map} +1 -1
- package/dist/client/{_floatingIpId-DQFtZNeg.mjs → _floatingIpId-CjQLzpC5.mjs} +2 -2
- package/dist/client/{_floatingIpId-DQFtZNeg.mjs.map → _floatingIpId-CjQLzpC5.mjs.map} +1 -1
- package/dist/client/{_floatingIpId-E6x99cmW.mjs → _floatingIpId-KcWWq9ZW2.mjs} +4 -4
- package/dist/client/_floatingIpId-KcWWq9ZW2.mjs.map +1 -0
- package/dist/client/{_imageId-C2662dZr.mjs → _imageId-BkEpwbCr.mjs} +3 -3
- package/dist/client/{_imageId-C2662dZr.mjs.map → _imageId-BkEpwbCr.mjs.map} +1 -1
- package/dist/client/{_pcaId-CNbmhUF8.mjs → _pcaId-BcwGho7g.mjs} +4 -4
- package/dist/client/{_pcaId-CNbmhUF8.mjs.map → _pcaId-BcwGho7g.mjs.map} +1 -1
- package/dist/client/{_projectId-B4ScifQf.mjs → _projectId-CoMD6nq6.mjs} +3 -3
- package/dist/client/{_projectId-B4ScifQf.mjs.map → _projectId-CoMD6nq6.mjs.map} +1 -1
- package/dist/client/{_projectId-CYq4KZXB.mjs → _projectId-D8FHe0gr.mjs} +3 -3
- package/dist/client/{_projectId-CYq4KZXB.mjs.map → _projectId-D8FHe0gr.mjs.map} +1 -1
- package/dist/client/{_projectId-DxgPaiA7.mjs → _projectId-MjFv839t.mjs} +2 -2
- package/dist/client/{_projectId-DxgPaiA7.mjs.map → _projectId-MjFv839t.mjs.map} +1 -1
- package/dist/client/{_projectId-DJLjspKf.mjs → _projectId-hMtrqW6m.mjs} +24 -23
- package/dist/client/{_projectId-DJLjspKf.mjs.map → _projectId-hMtrqW6m.mjs.map} +1 -1
- package/dist/client/{_securityGroupId-ju2ZSIYe.mjs → _securityGroupId-B5-gJe1u.mjs} +3 -3
- package/dist/client/{_securityGroupId-ju2ZSIYe.mjs.map → _securityGroupId-B5-gJe1u.mjs.map} +1 -1
- package/dist/client/{_securityGroupId-a46ExjsA.mjs → _securityGroupId-fPJWtDPU.mjs} +2 -2
- package/dist/client/{_securityGroupId-a46ExjsA.mjs.map → _securityGroupId-fPJWtDPU.mjs.map} +1 -1
- package/dist/client/{_storageType-BkhbKG_G.mjs → _storageType-CI5f4CsI.mjs} +2 -2
- package/dist/client/{_storageType-BkhbKG_G.mjs.map → _storageType-CI5f4CsI.mjs.map} +1 -1
- package/dist/client/{_storageType-ByLL106s.mjs → _storageType-DePX1Aah.mjs} +3 -3
- package/dist/client/{_storageType-ByLL106s.mjs.map → _storageType-DePX1Aah.mjs.map} +1 -1
- package/dist/client/{aurora-Owys0YMN.mjs → aurora-Dp_NPGe8.mjs} +2 -2
- package/dist/client/{aurora-Owys0YMN.mjs.map → aurora-Dp_NPGe8.mjs.map} +1 -1
- package/dist/client/components/Auth/LoginForm.d.ts +1 -0
- package/dist/client/{flavors-C7PVJUqZ.mjs → flavors-DLxUiBhE.mjs} +2 -2
- package/dist/client/{flavors-C7PVJUqZ.mjs.map → flavors-DLxUiBhE.mjs.map} +1 -1
- package/dist/client/{flavors-Bwjig3k2.mjs → flavors-DkGuWvge.mjs} +11 -12
- package/dist/client/{flavors-Bwjig3k2.mjs.map → flavors-DkGuWvge.mjs.map} +1 -1
- package/dist/client/{floatingips-D98DrjA0.mjs → floatingips-DC5OrR8h.mjs} +3 -3
- package/dist/client/{floatingips-D98DrjA0.mjs.map → floatingips-DC5OrR8h.mjs.map} +1 -1
- package/dist/client/{hooks-BsbKkpZc.mjs → hooks-D0wGUhRF.mjs} +2 -2
- package/dist/client/{hooks-BsbKkpZc.mjs.map → hooks-D0wGUhRF.mjs.map} +1 -1
- package/dist/client/{images-CfBrglGJ.mjs → images-D9nfOtSC.mjs} +5 -5
- package/dist/client/{images-CfBrglGJ.mjs.map → images-D9nfOtSC.mjs.map} +1 -1
- package/dist/client/{images-CD7DNwru.mjs → images-h9i7S4LN.mjs} +2 -2
- package/dist/client/{images-CD7DNwru.mjs.map → images-h9i7S4LN.mjs.map} +1 -1
- package/dist/client/index.js +302 -502
- package/dist/client/index.js.map +1 -1
- package/dist/client/{objects-CEBrL7k-.mjs → objects-B3Z8h4RU.mjs} +2 -2
- package/dist/client/{objects-CEBrL7k-.mjs.map → objects-B3Z8h4RU.mjs.map} +1 -1
- package/dist/client/{objects-DvIxpzGI.mjs → objects-CGOfO00N.mjs} +3 -3
- package/dist/client/{objects-DvIxpzGI.mjs.map → objects-CGOfO00N.mjs.map} +1 -1
- package/dist/client/{pca-ZgGU0UPF.mjs → pca-C7cMT8fW.mjs} +2 -2
- package/dist/client/{pca-ZgGU0UPF.mjs.map → pca-C7cMT8fW.mjs.map} +1 -1
- package/dist/client/{pca-CpMqoF00.mjs → pca-Nppb8aVa.mjs} +5 -5
- package/dist/client/{pca-CpMqoF00.mjs.map → pca-Nppb8aVa.mjs.map} +1 -1
- package/dist/client/routeInfo-CdTRlSxv.mjs +32 -0
- package/dist/client/routeInfo-CdTRlSxv.mjs.map +1 -0
- package/dist/client/routes-Bz4zb2H4.mjs +10 -0
- package/dist/client/routes-Bz4zb2H4.mjs.map +1 -0
- package/dist/client/routes-CaqfgBYu.mjs +112 -0
- package/dist/client/routes-CaqfgBYu.mjs.map +1 -0
- package/dist/client/{securitygroups-BwhVyNmZ.mjs → securitygroups-JMvcJLpb.mjs} +2 -2
- package/dist/client/{securitygroups-BwhVyNmZ.mjs.map → securitygroups-JMvcJLpb.mjs.map} +1 -1
- package/dist/client/store/AuthProvider.d.ts +10 -11
- package/dist/server/index.js +1 -10
- package/package.json +1 -2
- package/dist/client/AuthProvider-Cj_Btfnc.mjs +0 -56
- package/dist/client/AuthProvider-Cj_Btfnc.mjs.map +0 -1
- package/dist/client/DeleteFlavorModal-Dwm0Hh84.mjs +0 -638
- package/dist/client/DeleteFlavorModal-Dwm0Hh84.mjs.map +0 -1
- package/dist/client/_floatingIpId-E6x99cmW.mjs.map +0 -1
- package/dist/client/routeInfo-Ct5r4Gen.mjs +0 -56
- package/dist/client/routeInfo-Ct5r4Gen.mjs.map +0 -1
- package/dist/client/useErrorTranslation-Dc0eE8Zt.mjs +0 -83
- package/dist/client/useErrorTranslation-Dc0eE8Zt.mjs.map +0 -1
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { n as e } from "./trpcClient-BxcNKnhv.mjs";
|
|
2
|
+
import { jsx as t } from "react/jsx-runtime";
|
|
3
|
+
import n, { useEffect as r, useState as i } from "react";
|
|
4
|
+
//#region src/client/store/AuthProvider.tsx
|
|
5
|
+
var a = /*#__PURE__*/ n.createContext(null);
|
|
6
|
+
function o({ children: n }) {
|
|
7
|
+
let [o, s] = i(null), [c, l] = i(!0), [u, d] = i(null), [f, p] = i(null), m = (e = !1) => {
|
|
8
|
+
if (window.location.pathname !== "/") {
|
|
9
|
+
let t = e ? `/?redirect=${encodeURIComponent(window.location.pathname + window.location.search)}` : "/";
|
|
10
|
+
window.location.href = t;
|
|
11
|
+
}
|
|
12
|
+
}, h = () => {
|
|
13
|
+
s(null), p(null);
|
|
14
|
+
};
|
|
15
|
+
return r(() => {
|
|
16
|
+
e.auth.getCurrentUserSession.query().then((e) => {
|
|
17
|
+
e && (s(e.user), p(e.expires_at));
|
|
18
|
+
}).catch((e) => {
|
|
19
|
+
d(e instanceof Error ? e.message : "Could not load session");
|
|
20
|
+
}).finally(() => l(!1));
|
|
21
|
+
}, []), r(() => {
|
|
22
|
+
if (!o || !f) return;
|
|
23
|
+
let e = new Date(f).getTime() - Date.now(), t = () => {
|
|
24
|
+
h(), m(!0);
|
|
25
|
+
};
|
|
26
|
+
if (e <= 0) {
|
|
27
|
+
t();
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
let n = setTimeout(t, e);
|
|
31
|
+
return () => clearTimeout(n);
|
|
32
|
+
}, [o, f]), /*#__PURE__*/ t(a.Provider, {
|
|
33
|
+
value: {
|
|
34
|
+
user: o,
|
|
35
|
+
isAuthenticated: !!o,
|
|
36
|
+
isLoading: c,
|
|
37
|
+
error: u,
|
|
38
|
+
login: async ({ domain: t, user: n, password: r }) => {
|
|
39
|
+
d(null), l(!0);
|
|
40
|
+
try {
|
|
41
|
+
let i = await e.auth.createUserSession.mutate({
|
|
42
|
+
domainName: t,
|
|
43
|
+
user: n,
|
|
44
|
+
password: r
|
|
45
|
+
});
|
|
46
|
+
return s(i.user), p(i.expires_at), { success: !0 };
|
|
47
|
+
} catch (e) {
|
|
48
|
+
return d(e instanceof Error ? e.message : `Could not create session: ${e}`), { success: !1 };
|
|
49
|
+
} finally {
|
|
50
|
+
l(!1);
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
logout: async () => {
|
|
54
|
+
l(!0), await e.auth.terminateUserSession.mutate().catch(() => {}), h(), m(!1), window.location.pathname === "/" && l(!1);
|
|
55
|
+
},
|
|
56
|
+
expiresAt: f ? new Date(f) : void 0
|
|
57
|
+
},
|
|
58
|
+
children: n
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
function s() {
|
|
62
|
+
let e = n.useContext(a);
|
|
63
|
+
if (!e) throw Error("useAuth must be used within an AuthProvider");
|
|
64
|
+
return e;
|
|
65
|
+
}
|
|
66
|
+
//#endregion
|
|
67
|
+
export { s as n, o as t };
|
|
68
|
+
|
|
69
|
+
//# sourceMappingURL=AuthProvider-p1e1DuKU.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthProvider-p1e1DuKU.mjs","names":["React","useEffect","useState","trpcClient","AuthContext","createContext","AuthProvider","children","user","setUser","isLoading","setIsLoading","error","setError","expiresAt","setExpiresAt","redirectToLogin","saveReturnUrl","window","location","pathname","returnUrl","encodeURIComponent","search","href","clearLocalSession","auth","getCurrentUserSession","query","then","session","expires_at","catch","err","Error","message","finally","timeUntilExpiry","Date","getTime","now","handleExpiry","timer","setTimeout","clearTimeout","login","domain","password","createUserSession","mutate","domainName","success","logout","terminateUserSession","Provider","value","isAuthenticated","undefined","useAuth","context","useContext"],"sources":["../../src/client/store/AuthProvider.tsx"],"sourcesContent":["import React, { useEffect, useState } from \"react\"\nimport { TokenData } from \"../../server/Authentication/types/models\"\nimport { trpcClient } from \"../trpcClient\"\n\nexport type User = TokenData[\"user\"] | null\n\nexport interface AuthContext {\n isAuthenticated: boolean\n isLoading: boolean\n error: string | null\n login: (credentials: { domain: string; user: string; password: string }) => Promise<{ success: boolean }>\n logout: () => Promise<void>\n user?: User\n expiresAt?: Date\n}\n\nconst AuthContext = React.createContext<AuthContext | null>(null)\n\nexport function AuthProvider({ children }: { children: React.ReactNode }) {\n const [user, setUser] = useState<User | null>(null)\n const [isLoading, setIsLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n const [expiresAt, setExpiresAt] = useState<string | null>(null)\n\n // Redirect to login, optionally with return URL\n const redirectToLogin = (saveReturnUrl: boolean = false) => {\n if (window.location.pathname !== \"/\") {\n const returnUrl = saveReturnUrl\n ? `/?redirect=${encodeURIComponent(window.location.pathname + window.location.search)}`\n : \"/\"\n window.location.href = returnUrl\n }\n }\n\n // Clear local session state\n const clearLocalSession = () => {\n setUser(null)\n setExpiresAt(null)\n }\n\n // Get current session on mount\n useEffect(() => {\n trpcClient.auth.getCurrentUserSession\n .query()\n .then((session) => {\n if (session) {\n setUser(session.user)\n setExpiresAt(session.expires_at)\n }\n })\n .catch((err) => {\n setError(err instanceof Error ? err.message : \"Could not load session\")\n })\n .finally(() => setIsLoading(false))\n }, [])\n\n // Auto-logout when session expires\n useEffect(() => {\n if (!user || !expiresAt) return\n\n const timeUntilExpiry = new Date(expiresAt).getTime() - Date.now()\n\n const handleExpiry = () => {\n clearLocalSession()\n redirectToLogin(true)\n }\n\n if (timeUntilExpiry <= 0) {\n handleExpiry()\n return\n }\n\n const timer = setTimeout(handleExpiry, timeUntilExpiry)\n return () => clearTimeout(timer)\n }, [user, expiresAt])\n\n const login = async ({ domain, user, password }: { domain: string; user: string; password: string }) => {\n setError(null)\n setIsLoading(true)\n try {\n const session = await trpcClient.auth.createUserSession.mutate({ domainName: domain, user, password })\n setUser(session.user)\n setExpiresAt(session.expires_at)\n return { success: true }\n } catch (err) {\n setError(err instanceof Error ? err.message : `Could not create session: ${err}`)\n return { success: false }\n } finally {\n setIsLoading(false)\n }\n }\n\n const logout = async () => {\n setIsLoading(true)\n await trpcClient.auth.terminateUserSession.mutate().catch(() => {})\n clearLocalSession()\n redirectToLogin(false) // Don't save return URL on manual logout\n // If already on login page, no redirect happens - reset loading state\n if (window.location.pathname === \"/\") {\n setIsLoading(false)\n }\n }\n\n return (\n <AuthContext.Provider\n value={{\n user,\n isAuthenticated: !!user,\n isLoading,\n error,\n login,\n logout,\n expiresAt: expiresAt ? new Date(expiresAt) : undefined,\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":";;;;AAgBA,IAAMI,IAAcJ,gBAAMK,cAAkC,IAAA;AAE5D,SAAgBC,EAAa,EAAEC,eAAyC;CACtE,IAAM,CAACC,GAAMC,KAAWP,EAAsB,IAAA,GACxC,CAACQ,GAAWC,KAAgBT,EAAS,EAAA,GACrC,CAACU,GAAOC,KAAYX,EAAwB,IAAA,GAC5C,CAACY,GAAWC,KAAgBb,EAAwB,IAAA,GAGpDc,KAAmBC,IAAyB,OAAK;EACrD,IAAIC,OAAOC,SAASC,aAAa,KAAK;GACpC,IAAMC,IAAYJ,IACd,cAAcK,mBAAmBJ,OAAOC,SAASC,WAAWF,OAAOC,SAASI,MAAM,MAClF;GACJL,OAAOC,SAASK,OAAOH;EACzB;CACF,GAGMI,UAAoB;EAExBV,AADAN,EAAQ,IAAA,GACRM,EAAa,IAAA;CACf;CAiEA,OA9DAd,QAAU;EACRE,EAAWuB,KAAKC,sBACbC,MAAK,EACLC,MAAMC,MAAAA;GACL,AAAIA,MACFrB,EAAQqB,EAAQtB,IAAI,GACpBO,EAAae,EAAQC,UAAU;EAEnC,CAAA,EACCC,OAAOC,MAAAA;GACNpB,EAASoB,aAAeC,QAAQD,EAAIE,UAAU,wBAAA;EAChD,CAAA,EACCC,cAAczB,EAAa,EAAA,CAAA;CAChC,GAAG,CAAA,CAAE,GAGLV,QAAU;EACR,IAAI,CAACO,KAAQ,CAACM,GAAW;EAEzB,IAAMuB,IAAkB,IAAIC,KAAKxB,CAAAA,EAAWyB,QAAO,IAAKD,KAAKE,IAAG,GAE1DC,UAAe;GAEnBzB,AADAS,EAAAA,GACAT,EAAgB,EAAA;EAClB;EAEA,IAAIqB,KAAmB,GAAG;GACxBI,EAAAA;GACA;EACF;EAEA,IAAMC,IAAQC,WAAWF,GAAcJ,CAAAA;EACvC,aAAaO,aAAaF,CAAAA;CAC5B,GAAG,CAAClC,GAAMM,CAAAA,CAAU,GA8BlB,gBAACV,EAAYkD,UAAQ;EACnBC,OAAO;GACL/C;GACAgD,iBAAiB,CAAC,CAAChD;GACnBE;GACAE;GACAiC,cAlCe,EAAEC,WAAQtC,SAAMuC,kBAA8D;IAEjGpC,AADAE,EAAS,IAAA,GACTF,EAAa,EAAA;IACb,IAAI;KACF,IAAMmB,IAAU,MAAM3B,EAAWuB,KAAKsB,kBAAkBC,OAAO;MAAEC,YAAYJ;MAAQtC;MAAMuC;KAAS,CAAA;KAGpG,OAFAtC,EAAQqB,EAAQtB,IAAI,GACpBO,EAAae,EAAQC,UAAU,GACxB,EAAEoB,SAAS,GAAK;IACzB,SAASlB,GAAK;KAEZ,OADApB,EAASoB,aAAeC,QAAQD,EAAIE,UAAU,6BAA6BF,GAAK,GACzE,EAAEkB,SAAS,GAAM;IAC1B,UAAU;KACRxC,EAAa,EAAA;IACf;GACF;GAqBMyC,oBAnBS;IAMb,AALAzC,EAAa,EAAA,GACb,MAAMR,EAAWuB,KAAK2B,qBAAqBJ,OAAM,EAAGjB,YAAM,CAAO,CAAA,GACjEP,EAAAA,GACAT,EAAgB,EAAA,GAEZE,OAAOC,SAASC,aAAa,OAC/BT,EAAa,EAAA;GAEjB;GAWMG,WAAWA,IAAY,IAAIwB,KAAKxB,CAAAA,IAAa2C,KAAAA;EAC/C;EAEClD;;AAGP;AAEA,SAAgBmD,IAAAA;CACd,IAAMC,IAAU3D,EAAM4D,WAAWxD,CAAAA;CACjC,IAAI,CAACuD,GACH,MAAUzB,MAAM,6CAAA;CAElB,OAAOyB;AACT"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Y as e, f as t, j as n, l as r, ot as i, s as a, tt as o } from "./build-DgeVmENN.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { t as s } from "./Slot-CWb612-_.mjs";
|
|
3
|
+
import { t as c } from "./routeInfo-CdTRlSxv.mjs";
|
|
3
4
|
import { jsx as l, jsxs as u } from "react/jsx-runtime";
|
|
4
5
|
import { useState as d } from "react";
|
|
5
6
|
import { useMatches as f, useParams as p, useRouteContext as m } from "@tanstack/react-router";
|
|
@@ -110,4 +111,4 @@ function v({ title: t, projectId: r, description: i, actions: a, badges: o }) {
|
|
|
110
111
|
//#endregion
|
|
111
112
|
export { _ as n, v as t };
|
|
112
113
|
|
|
113
|
-
//# sourceMappingURL=ContentHeader-
|
|
114
|
+
//# sourceMappingURL=ContentHeader-BIScbvb4.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContentHeader-
|
|
1
|
+
{"version":3,"file":"ContentHeader-BIScbvb4.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","projectOverviewBanner","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 const projectOverviewBanner =\n slots?.projectOverviewBanner && !currentService ? (\n <Slot component={slots.projectOverviewBanner} useShadowDOM={false} />\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 {serviceBanner}\n {projectOverviewBanner}\n <Divider className=\"mt-4\" />\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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"}
|