@cobaltcore-dev/aurora 1.3.0 → 2.1.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/ContentHeader-fKKZVu-o.mjs +116 -0
- package/dist/client/ContentHeader-fKKZVu-o.mjs.map +1 -0
- package/dist/client/DeleteFlavorModal-Be2GFiB_.mjs +802 -0
- package/dist/client/DeleteFlavorModal-Be2GFiB_.mjs.map +1 -0
- package/dist/client/{FiltersInput-CKI6zWnm.mjs → FiltersInput-Becwxo_J.mjs} +36 -33
- package/dist/client/FiltersInput-Becwxo_J.mjs.map +1 -0
- package/dist/client/{FloatingIpActionModals-Ch8uozH9.mjs → FloatingIpActionModals-Cq10WljB.mjs} +2 -2
- package/dist/client/{FloatingIpActionModals-Ch8uozH9.mjs.map → FloatingIpActionModals-Cq10WljB.mjs.map} +1 -1
- package/dist/client/ImageToastNotifications-BWfzOUMc.mjs +1135 -0
- package/dist/client/ImageToastNotifications-BWfzOUMc.mjs.map +1 -0
- package/dist/client/RouteIdLevelDefaultError-DPF_x2tG.mjs +26 -0
- package/dist/client/RouteIdLevelDefaultError-DPF_x2tG.mjs.map +1 -0
- package/dist/client/StorageNotFound-B-zVinVD.mjs +30 -0
- package/dist/client/StorageNotFound-B-zVinVD.mjs.map +1 -0
- package/dist/client/_flavorId-0PioWpEp.mjs +276 -0
- package/dist/client/_flavorId-0PioWpEp.mjs.map +1 -0
- package/dist/client/_flavorId-B7fp6Nk8.mjs +22 -0
- package/dist/client/_flavorId-B7fp6Nk8.mjs.map +1 -0
- package/dist/client/{_flavorId-Dg7MS0Af.mjs → _flavorId-CgueqKTs.mjs} +4 -3
- package/dist/client/_flavorId-CgueqKTs.mjs.map +1 -0
- package/dist/client/{_floatingIpId-DNn6ABCB.mjs → _floatingIpId-B8r64AL9.mjs} +6 -6
- package/dist/client/{_floatingIpId-DNn6ABCB.mjs.map → _floatingIpId-B8r64AL9.mjs.map} +1 -1
- package/dist/client/{_floatingIpId-C9xfRWot.mjs → _floatingIpId-lEobpOER.mjs} +2 -2
- package/dist/client/{_floatingIpId-C9xfRWot.mjs.map → _floatingIpId-lEobpOER.mjs.map} +1 -1
- package/dist/client/{_imageId-8JIbFmGB.mjs → _imageId-Ccv8PedW.mjs} +4 -3
- package/dist/client/_imageId-Ccv8PedW.mjs.map +1 -0
- package/dist/client/_imageId-CiqEQB_J.mjs +558 -0
- package/dist/client/_imageId-CiqEQB_J.mjs.map +1 -0
- package/dist/client/_imageId-D9LR-02T.mjs +22 -0
- package/dist/client/_imageId-D9LR-02T.mjs.map +1 -0
- package/dist/client/{_projectId-DPzv0CCp.mjs → _projectId-BDARsteX.mjs} +4 -4
- package/dist/client/_projectId-BDARsteX.mjs.map +1 -0
- package/dist/client/{_projectId-DfeVJy0G.mjs → _projectId-CtyAHqhH.mjs} +2 -2
- package/dist/client/_projectId-CtyAHqhH.mjs.map +1 -0
- package/dist/client/_projectId-D3VOH5lN.mjs +94 -0
- package/dist/client/_projectId-D3VOH5lN.mjs.map +1 -0
- package/dist/client/{_projectId-B3wmSala.mjs → _projectId-ZBk6vka0.mjs} +83 -81
- package/dist/client/_projectId-ZBk6vka0.mjs.map +1 -0
- package/dist/client/{_securityGroupId-C6eHmrx_.mjs → _securityGroupId-BwgZnoiR.mjs} +2 -2
- package/dist/client/_securityGroupId-BwgZnoiR.mjs.map +1 -0
- package/dist/client/{_securityGroupId-DmplhDgt.mjs → _securityGroupId-Cz2NUHdB.mjs} +750 -741
- package/dist/client/_securityGroupId-Cz2NUHdB.mjs.map +1 -0
- package/dist/client/{_storageType-CzZ4u9x_.mjs → _storageType-BNpP1A2N.mjs} +3 -2
- package/dist/client/_storageType-BNpP1A2N.mjs.map +1 -0
- package/dist/client/_storageType-BxSGKhAI.mjs +15 -0
- package/dist/client/_storageType-BxSGKhAI.mjs.map +1 -0
- package/dist/client/_storageType-DZYCmiLt.mjs +30 -0
- package/dist/client/_storageType-DZYCmiLt.mjs.map +1 -0
- package/dist/client/_storageType-UqAMP-8d.mjs +859 -0
- package/dist/client/_storageType-UqAMP-8d.mjs.map +1 -0
- package/dist/client/_storageType-u51_7OwJ.mjs +7 -0
- package/dist/client/_storageType-u51_7OwJ.mjs.map +1 -0
- package/dist/client/components/{Error → Errors}/RouteError.d.ts +5 -0
- package/dist/client/components/Errors/RouteIdLevelDefaultError.d.ts +18 -0
- package/dist/client/components/Errors/ServiceLevelDefaultError.d.ts +9 -0
- package/dist/client/components/ListToolbar/SelectedFilters.d.ts +7 -2
- package/dist/client/components/ListToolbar/types.d.ts +6 -0
- package/dist/client/components/ListToolbar/valueLabels.d.ts +11 -0
- package/dist/client/{flavors-B1SDOPDu.mjs → flavors-Ce3J-cFa.mjs} +2 -2
- package/dist/client/{flavors-B1SDOPDu.mjs.map → flavors-Ce3J-cFa.mjs.map} +1 -1
- package/dist/client/flavors-D5ThLaXO.mjs +666 -0
- package/dist/client/flavors-D5ThLaXO.mjs.map +1 -0
- package/dist/client/floatingips-Cz9k80cc.mjs.map +1 -1
- package/dist/client/{floatingips-DrCvtXtT.mjs → floatingips-DXnRlLvV.mjs} +7 -7
- package/dist/client/{floatingips-DrCvtXtT.mjs.map → floatingips-DXnRlLvV.mjs.map} +1 -1
- package/dist/client/floatingips-HRbuLxiN.mjs +22 -0
- package/dist/client/floatingips-HRbuLxiN.mjs.map +1 -0
- package/dist/client/floatingips-nN1kQmsu.mjs +14 -0
- package/dist/client/floatingips-nN1kQmsu.mjs.map +1 -0
- package/dist/client/{images-BGQv9kKT.mjs → images-C8M3ysWR.mjs} +810 -770
- package/dist/client/images-C8M3ysWR.mjs.map +1 -0
- package/dist/client/{images-CPmMa4SQ.mjs → images-Cf5R28NR.mjs} +2 -2
- package/dist/client/{images-CPmMa4SQ.mjs.map → images-Cf5R28NR.mjs.map} +1 -1
- package/dist/client/index.js +419 -415
- package/dist/client/index.js.map +1 -1
- package/dist/client/{objects-BR3eeSNH.mjs → objects-BudUAfWY.mjs} +5478 -5519
- package/dist/client/objects-BudUAfWY.mjs.map +1 -0
- package/dist/client/objects-Dc7sKUr8.mjs +67 -0
- package/dist/client/objects-Dc7sKUr8.mjs.map +1 -0
- package/dist/client/objects-Dw7oeTq2.mjs +80 -0
- package/dist/client/objects-Dw7oeTq2.mjs.map +1 -0
- package/dist/client/objects-_g7nGIn5.mjs +25 -0
- package/dist/client/objects-_g7nGIn5.mjs.map +1 -0
- package/dist/client/objects-eBxvY6_n.mjs +78 -0
- package/dist/client/objects-eBxvY6_n.mjs.map +1 -0
- package/dist/client/projects-yiK0HGSA.mjs.map +1 -1
- package/dist/client/{securitygroups-DEJQBcxm.mjs → securitygroups-67fFxiwt.mjs} +2 -2
- package/dist/client/{securitygroups-DEJQBcxm.mjs.map → securitygroups-67fFxiwt.mjs.map} +1 -1
- package/dist/client/securitygroups-CtKne8UQ.mjs.map +1 -1
- package/dist/client/securitygroups-DXrfyuVF.mjs +580 -0
- package/dist/client/securitygroups-DXrfyuVF.mjs.map +1 -0
- package/dist/client/securitygroups-WLB1_IM6.mjs +22 -0
- package/dist/client/securitygroups-WLB1_IM6.mjs.map +1 -0
- package/dist/client/securitygroups-o0IXZM6S.mjs +14 -0
- package/dist/client/securitygroups-o0IXZM6S.mjs.map +1 -0
- package/dist/client/serviceCatalog-B3lKWC9V.mjs +6 -0
- package/dist/client/serviceCatalog-B3lKWC9V.mjs.map +1 -0
- package/dist/client/storageProviders-CJ5rOh13.mjs +15 -0
- package/dist/client/storageProviders-CJ5rOh13.mjs.map +1 -0
- package/dist/client/trpcClient.d.ts +102 -4
- package/dist/client/useModalTracking-BYd37pXm.mjs +37 -0
- package/dist/client/useModalTracking-BYd37pXm.mjs.map +1 -0
- package/dist/client/useSecurityGroupPermissions--hK4aR8Y.mjs +294 -0
- package/dist/client/useSecurityGroupPermissions--hK4aR8Y.mjs.map +1 -0
- package/dist/client/utils/serviceCatalog.d.ts +9 -0
- package/dist/client/utils/storageProviders.d.ts +44 -0
- package/dist/server/index.d.ts +102 -4
- package/dist/server/index.js +1319 -416
- package/package.json +4 -4
- package/dist/client/ContentHeader-CPJbgYWn.mjs +0 -115
- package/dist/client/ContentHeader-CPJbgYWn.mjs.map +0 -1
- package/dist/client/DeleteFlavorModal-V44QCJBd.mjs +0 -773
- package/dist/client/DeleteFlavorModal-V44QCJBd.mjs.map +0 -1
- package/dist/client/FiltersInput-CKI6zWnm.mjs.map +0 -1
- package/dist/client/ImageToastNotifications-m6c3tVPb.mjs +0 -1152
- package/dist/client/ImageToastNotifications-m6c3tVPb.mjs.map +0 -1
- package/dist/client/_flavorId-Dg7MS0Af.mjs.map +0 -1
- package/dist/client/_flavorId-kHl-b8rI.mjs +0 -232
- package/dist/client/_flavorId-kHl-b8rI.mjs.map +0 -1
- package/dist/client/_imageId-8JIbFmGB.mjs.map +0 -1
- package/dist/client/_imageId-BBAlRioC.mjs +0 -574
- package/dist/client/_imageId-BBAlRioC.mjs.map +0 -1
- package/dist/client/_projectId-7Nl1MQTJ.mjs +0 -99
- package/dist/client/_projectId-7Nl1MQTJ.mjs.map +0 -1
- package/dist/client/_projectId-B3wmSala.mjs.map +0 -1
- package/dist/client/_projectId-DPzv0CCp.mjs.map +0 -1
- package/dist/client/_projectId-DfeVJy0G.mjs.map +0 -1
- package/dist/client/_securityGroupId-C6eHmrx_.mjs.map +0 -1
- package/dist/client/_securityGroupId-DmplhDgt.mjs.map +0 -1
- package/dist/client/_storageType-BRWWJtow.mjs +0 -14
- package/dist/client/_storageType-BRWWJtow.mjs.map +0 -1
- package/dist/client/_storageType-C5gS9eut.mjs +0 -845
- package/dist/client/_storageType-C5gS9eut.mjs.map +0 -1
- package/dist/client/_storageType-CzZ4u9x_.mjs.map +0 -1
- package/dist/client/_storageType-zeSZe--V.mjs +0 -7
- package/dist/client/_storageType-zeSZe--V.mjs.map +0 -1
- package/dist/client/flavors-D8_PzQUB.mjs +0 -628
- package/dist/client/flavors-D8_PzQUB.mjs.map +0 -1
- package/dist/client/images-BGQv9kKT.mjs.map +0 -1
- package/dist/client/objects-AERkhfiM.mjs +0 -66
- package/dist/client/objects-AERkhfiM.mjs.map +0 -1
- package/dist/client/objects-BR3eeSNH.mjs.map +0 -1
- package/dist/client/objects-DVccbrL1.mjs +0 -66
- package/dist/client/objects-DVccbrL1.mjs.map +0 -1
- package/dist/client/securitygroups-BjhgLBHm.mjs +0 -620
- package/dist/client/securitygroups-BjhgLBHm.mjs.map +0 -1
- package/dist/client/useModalTracking-BcOKTYRN.mjs +0 -33
- package/dist/client/useModalTracking-BcOKTYRN.mjs.map +0 -1
- package/dist/client/useSecurityGroupPermissions-BOyLQLdC.mjs +0 -227
- package/dist/client/useSecurityGroupPermissions-BOyLQLdC.mjs.map +0 -1
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { t as e } from "./storageProviders-CJ5rOh13.mjs";
|
|
2
|
+
import { C as t, S as n, b as r, n as i, t as a, v as o, x as s } from "./objects-BudUAfWY.mjs";
|
|
3
|
+
import { t as c } from "./useSetBreadcrumb-tn7lBaQV.mjs";
|
|
4
|
+
import { Fragment as l, jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
5
|
+
import { useParams as f } from "@tanstack/react-router";
|
|
6
|
+
import { Trans as p } from "@lingui/react";
|
|
7
|
+
import { ErrorBoundary as m } from "react-error-boundary";
|
|
8
|
+
//#region src/client/routes/_auth/projects/$projectId/storage/$provider/$storageType/$containerName/objects/index.tsx?tsr-split=component
|
|
9
|
+
function h() {
|
|
10
|
+
let { projectId: h, provider: g, containerName: _ } = f({
|
|
11
|
+
from: "/_auth/projects/$projectId/storage/$provider/$storageType/$containerName/objects/",
|
|
12
|
+
select: (e) => ({
|
|
13
|
+
projectId: e.projectId,
|
|
14
|
+
provider: e.provider,
|
|
15
|
+
containerName: e.containerName
|
|
16
|
+
})
|
|
17
|
+
});
|
|
18
|
+
c(a.id, _);
|
|
19
|
+
let { prefix: v, sortBy: y, sortDirection: b, search: x, view: S } = a.useSearch();
|
|
20
|
+
return /*#__PURE__*/ d(l, { children: [
|
|
21
|
+
g === e.CEPH && /*#__PURE__*/ u(o, { bucketName: _ }),
|
|
22
|
+
g === e.SWIFT && /*#__PURE__*/ u(i, { containerName: _ }),
|
|
23
|
+
/*#__PURE__*/ u("div", {
|
|
24
|
+
className: g === e.SWIFT ? "pt-4" : void 0,
|
|
25
|
+
children: h ? /*#__PURE__*/ u(m, {
|
|
26
|
+
resetKeys: [
|
|
27
|
+
h,
|
|
28
|
+
g,
|
|
29
|
+
_,
|
|
30
|
+
v,
|
|
31
|
+
y,
|
|
32
|
+
b,
|
|
33
|
+
x,
|
|
34
|
+
S
|
|
35
|
+
],
|
|
36
|
+
fallback: /*#__PURE__*/ u("div", {
|
|
37
|
+
className: "p-4 text-center",
|
|
38
|
+
children: /*#__PURE__*/ u(p, { id: "diFNkW" })
|
|
39
|
+
}),
|
|
40
|
+
children: (() => {
|
|
41
|
+
switch (g) {
|
|
42
|
+
case e.SWIFT: return /*#__PURE__*/ u(t, {
|
|
43
|
+
provider: g,
|
|
44
|
+
containerName: _
|
|
45
|
+
});
|
|
46
|
+
case e.CEPH: return u(S === "lifecycle-rules" ? r : S === "cors-rules" ? s : n, { bucketName: _ });
|
|
47
|
+
default: return /*#__PURE__*/ u("div", {
|
|
48
|
+
className: "p-4",
|
|
49
|
+
children: /*#__PURE__*/ u(p, {
|
|
50
|
+
id: "ubUrot",
|
|
51
|
+
values: { containerName: _ }
|
|
52
|
+
})
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
})()
|
|
56
|
+
}) : /*#__PURE__*/ u("div", {
|
|
57
|
+
className: "p-4 text-center",
|
|
58
|
+
children: /*#__PURE__*/ u(p, { id: "Z2fZGD" })
|
|
59
|
+
})
|
|
60
|
+
})
|
|
61
|
+
] });
|
|
62
|
+
}
|
|
63
|
+
var g = () => /*#__PURE__*/ u(h, {});
|
|
64
|
+
//#endregion
|
|
65
|
+
export { h as ObjectsDashboard, g as component };
|
|
66
|
+
|
|
67
|
+
//# sourceMappingURL=objects-Dc7sKUr8.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"objects-Dc7sKUr8.mjs","names":["useParams","ErrorBoundary","Trans","SwiftObjects","CephObjects","CephCorsRules","CephLifecycleRules","BucketHeader","ContainerHeader","useSetBreadcrumb","STORAGE_PROVIDER","Route","ObjectsDashboard","projectId","provider","containerName","from","select","params","id","prefix","sortBy","sortDirection","search","view","useSearch","CEPH","SWIFT","undefined","SplitComponent","component"],"sources":["../../src/client/routes/_auth/projects/$projectId/storage/$provider/$storageType/$containerName/objects/index.tsx?tsr-split=component"],"sourcesContent":["import {\n createFileRoute,\n useNavigate,\n useParams,\n type ErrorComponentProps,\n type NotFoundRouteComponent,\n} from \"@tanstack/react-router\"\nimport type { ReactNode } from \"react\"\nimport { Button } from \"@cloudoperators/juno-ui-components\"\nimport { isTRPCClientError } from \"@trpc/client\"\nimport { guardStorageRoute, type StorageNotFoundReason } from \"../../../../-components/utils/serviceAvailability\"\nimport { CONTAINER_NOT_FOUND, requireContainerExists } from \"../../../../-components/utils/containerExistence\"\nimport { RouteIdLevelDefaultError } from \"@/client/components/Errors/RouteIdLevelDefaultError\"\nimport { ErrorBoundary } from \"react-error-boundary\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { SwiftObjects } from \"../../../../-components/Swift/Objects\"\nimport { CephObjects } from \"../../../../-components/Ceph/Objects\"\nimport { CephCorsRules, CephLifecycleRules } from \"../../../../-components/Ceph/Buckets\"\nimport { z } from \"zod\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { BucketHeader } from \"../../../../-components/Ceph/Buckets/BucketHeader\"\nimport { ContainerHeader } from \"../../../../-components/Swift/Containers/ContainerHeader\"\nimport { useSetBreadcrumb } from \"@/client/hooks/useSetBreadcrumb\"\nimport { StorageNotFound } from \"../../../../-components/StorageNotFound\"\nimport { STORAGE_PROVIDER } from \"@/client/utils/storageProviders\"\n\n// Search params schema\n// - prefix: base64-encoded current folder path, safe to carry \"/\" chars in the URL\n// - sortBy: active sort column key — persisted so deep links and back navigation restore sort state\n// Accepts both Swift keys (last_modified, bytes) and Ceph keys (lastModified, size) for compatibility\n// - sortDirection: \"asc\" | \"desc\" — persisted alongside sortBy\n// - view: tab selection for Ceph bucket details page (overview shows objects, cors-rules shows CORS config, lifecycle-rules shows lifecycle config)\n// - corsSortBy: active sort column for CORS rules tab (ID, AllowedOrigins, etc.) — separate from objects sortBy\n// - corsSortDirection: \"asc\" | \"desc\" for CORS rules — separate from objects sortDirection\n// - corsSearch: search term for filtering CORS rules by Rule ID — separate from objects search\n// - lifecycleSortBy: active sort column for lifecycle rules tab (ID, Status, Expiration) — separate from objects sortBy\n// - lifecycleSortDirection: \"asc\" | \"desc\" for lifecycle rules — separate from objects sortDirection\n// - lifecycleSearch: search term for filtering lifecycle rules by Rule ID — separate from objects search\nconst objectsSearchSchema = z.object({\n prefix: z.string().optional(),\n sortBy: z.enum([\"name\", \"last_modified\", \"bytes\", \"lastModified\", \"size\"]).optional().default(\"name\"),\n sortDirection: z.enum([\"asc\", \"desc\"]).optional().default(\"asc\"),\n search: z.string().optional(),\n tab: z.enum([\"all\", \"deleted\"]).optional().default(\"all\"),\n view: z.enum([\"overview\", \"cors-rules\", \"lifecycle-rules\"]).optional().default(\"overview\"),\n corsSortBy: z\n .enum([\"ID\", \"AllowedOrigins\", \"AllowedMethods\", \"AllowedHeaders\", \"ExposeHeaders\", \"MaxAgeSeconds\"])\n .optional()\n .default(\"ID\"),\n corsSortDirection: z.enum([\"asc\", \"desc\"]).optional().default(\"asc\"),\n corsSearch: z.string().optional(),\n lifecycleSortBy: z.enum([\"ID\", \"Status\", \"Expiration\"]).optional().default(\"ID\"),\n lifecycleSortDirection: z.enum([\"asc\", \"desc\"]).optional().default(\"asc\"),\n lifecycleSearch: z.string().optional(),\n})\n\n/**\n * \"Back to Buckets\"/\"Back to Containers\" — the exit both boundaries below want. The list\n * is the one page that is certainly still there, so it beats `RouteIdLevelDefaultError`'s\n * default \"Go to Project Home\", which leaves storage altogether.\n *\n * Returns undefined when the params aren't readable, so the caller falls back to that\n * default rather than rendering a button that can't build a target.\n */\nfunction useBackToContainerList(): ReactNode {\n const { t } = useLingui()\n const navigate = useNavigate()\n const { projectId, provider, storageType } = useParams({ strict: false })\n\n if (!projectId || !provider || !storageType) return undefined\n\n return (\n <Button\n variant=\"primary\"\n onClick={() =>\n navigate({\n to: \"/projects/$projectId/storage/$provider/$storageType\",\n params: { projectId, provider, storageType },\n })\n }\n >\n {provider === STORAGE_PROVIDER.CEPH ? t`Back to Buckets` : t`Back to Containers`}\n </Button>\n )\n}\n\n/**\n * The route's single notFound boundary serves two unrelated 404s, so it dispatches on the\n * reason the throw carried:\n *\n * - the address is wrong (bad provider, non-canonical storage-type) → `StorageNotFound`,\n * whose action leads out of storage entirely, because no storage page here is valid;\n * - the address is fine but the container isn't there → `RouteIdLevelDefaultError`, whose\n * action leads back to the list, which is a page the user can actually use.\n *\n * (The router spreads the whole notFound error object into these props, so the reason\n * arrives nested under `data` — see StorageNotFound for the three files that establish it.)\n */\nfunction ObjectsNotFound({ data }: { data?: { reason?: StorageNotFoundReason | typeof CONTAINER_NOT_FOUND } }) {\n const { t } = useLingui()\n const { provider } = useParams({ strict: false })\n const backToList = useBackToContainerList()\n\n const reason = data?.reason\n\n if (reason !== CONTAINER_NOT_FOUND) {\n return <StorageNotFound data={reason ? { reason } : undefined} />\n }\n\n const isCeph = provider === STORAGE_PROVIDER.CEPH\n\n return (\n <RouteIdLevelDefaultError\n errorTitle={isCeph ? t`Bucket Not Found` : t`Container Not Found`}\n errorDescription={\n isCeph\n ? t`This bucket does not exist or is not accessible in this project.`\n : t`This container does not exist or is not accessible in this project.`\n }\n action={backToList}\n />\n )\n}\n\n/**\n * Route-level error boundary — for a request that failed, as opposed to a resource that\n * isn't there. Deliberately a boundary of its own: #1304 points one component at both, and\n * since that component hardcodes `code={404}` a 500 arrives labelled \"Resource Not Found\".\n * The split is in what the two say, not in which component they use — `code` is what lets\n * this one state the real status instead of inheriting that default.\n *\n * Catching here rather than letting it reach the root keeps everything the parent routes\n * render — shell, nav, the breadcrumb trail up to this page — on screen, and lets the\n * boundary reset when the user navigates.\n */\nfunction ObjectsError({ error }: ErrorComponentProps) {\n const { t } = useLingui()\n const backToList = useBackToContainerList()\n const trpcError = isTRPCClientError(error) ? error : undefined\n\n return (\n <RouteIdLevelDefaultError\n code={trpcError?.data?.httpStatus ?? null}\n errorTitle={t`Unable to Load Content`}\n errorDescription={trpcError?.message ?? t`An unexpected error occurred.`}\n action={backToList}\n />\n )\n}\n\nexport const Route = createFileRoute(\n \"/_auth/projects/$projectId/storage/$provider/$storageType/$containerName/objects/\"\n)({\n staticData: {\n section: \"storage\",\n service: \"containers\",\n analytics: {\n name: \"storage.objectstore.detail\",\n },\n } satisfies RouteInfo,\n validateSearch: objectsSearchSchema,\n head: ({ match }) => ({\n meta: [{ title: match.params.containerName }],\n }),\n component: () => {\n return <ObjectsDashboard />\n },\n notFoundComponent: ObjectsNotFound as NotFoundRouteComponent,\n errorComponent: ObjectsError,\n loader: async ({ context, params }) => {\n const { trpcClient } = context\n if (!trpcClient) {\n throw new Error(\"trpcClient is not available in route context\")\n }\n const availableServices = (await trpcClient.auth.getAvailableServices.query()) ?? []\n const provider = guardStorageRoute(availableServices, params)\n return requireContainerExists(trpcClient, { ...params, provider })\n },\n})\n\nexport function ObjectsDashboard() {\n const { projectId, provider, containerName } = useParams({\n from: \"/_auth/projects/$projectId/storage/$provider/$storageType/$containerName/objects/\",\n select: (params) => ({\n projectId: params.projectId,\n provider: params.provider,\n containerName: params.containerName,\n }),\n })\n\n useSetBreadcrumb(Route.id, containerName)\n\n const { prefix, sortBy, sortDirection, search, view } = Route.useSearch()\n\n return (\n <>\n {provider === STORAGE_PROVIDER.CEPH && <BucketHeader bucketName={containerName} />}\n {provider === STORAGE_PROVIDER.SWIFT && <ContainerHeader containerName={containerName} />}\n {/* Ceph gets extra breathing room below its header from BucketHeader's own\n tabs block; Swift has no such block, so pad the content wrapper directly\n to avoid the overflow menu sitting too close to the toolbar below it. */}\n <div className={provider === STORAGE_PROVIDER.SWIFT ? \"pt-4\" : undefined}>\n {projectId ? (\n <ErrorBoundary\n resetKeys={[projectId, provider, containerName, prefix, sortBy, sortDirection, search, view]}\n fallback={\n <div className=\"p-4 text-center\">\n <Trans>Error loading component</Trans>\n </div>\n }\n >\n {(() => {\n switch (provider) {\n case STORAGE_PROVIDER.SWIFT:\n return <SwiftObjects provider={provider} containerName={containerName} />\n case STORAGE_PROVIDER.CEPH:\n if (view === \"lifecycle-rules\") {\n return <CephLifecycleRules bucketName={containerName} />\n }\n if (view === \"cors-rules\") {\n return <CephCorsRules bucketName={containerName} />\n }\n return <CephObjects bucketName={containerName} />\n default:\n return (\n <div className=\"p-4\">\n <Trans>Objects: {containerName}</Trans>\n </div>\n )\n }\n })()}\n </ErrorBoundary>\n ) : (\n <div className=\"p-4 text-center\">\n <Trans>No project selected</Trans>\n </div>\n )}\n </div>\n </>\n )\n}\n"],"mappings":";;;;;;;;AAoLA,SAAgBY,IAAAA;CACd,IAAM,EAAEC,cAAWC,aAAUC,qBAAkBf,EAAU;EACvDgB,MAAM;EACNC,SAASC,OAAY;GACnBL,WAAWK,EAAOL;GAClBC,UAAUI,EAAOJ;GACjBC,eAAeG,EAAOH;EACxB;CACF,CAAA;CAEAN,EAAiBE,EAAMQ,IAAIJ,CAAAA;CAE3B,IAAM,EAAEK,WAAQC,WAAQC,kBAAeC,WAAQC,YAASb,EAAMc,UAAS;CAEvE,OACE,gBAAA,GAAA,EAAA,UAAA;EACGX,MAAaJ,EAAiBgB,QAAQ,gBAAC,GAAA,EAAa,YAAYX,EAAAA,CAAAA;EAChED,MAAaJ,EAAiBiB,SAAS,gBAAC,GAAA,EAA+BZ,iBAAAA,CAAAA;EAIxE,gBAAC,OAAA;GAAI,WAAWD,MAAaJ,EAAiBiB,QAAQ,SAASC,KAAAA;GAC5Df,UAAAA,IACC,gBAAC,GAAA;IACC,WAAW;KAACA;KAAWC;KAAUC;KAAeK;KAAQC;KAAQC;KAAeC;KAAQC;IAAK;IAC5F,UACE,gBAAC,OAAA;KAAI,WAAU;KACb,UAAA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;IAIH,iBAAC;KACA,QAAQV,GAAR;MACE,KAAKJ,EAAiBiB,OACpB,OAAO,gBAAC,GAAA;OAAuBb;OAAyBC;;MAC1D,KAAKL,EAAiBgB,MAOpB,OALS,EADLF,MAAS,oBACH,IAENA,MAAS,eACH,IAEF,GALE,EAAmB,YAAYT,EAAAA,CAAAA;MAM3C,SACE,OACE,gBAAC,OAAA;OAAI,WAAU;OACb,UAAA,gBAAA,GAAA;;QAAiBA,QAAAA,EAAAA,iBAAAA;;;KAGzB;IACF,EAAA,CAAA;GAGF,CAAA,IAAA,gBAAC,OAAA;IAAI,WAAU;IACb,UAAA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;;;AAMZ;AAAC,IAAAc,UA3EU,gBAAC,GAAA,CAAA,CAAA"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { t as e } from "./storageProviders-CJ5rOh13.mjs";
|
|
2
|
+
import { C as t, S as n, b as r, n as i, t as a, v as o, x as s } from "./objects-BudUAfWY.mjs";
|
|
3
|
+
import { t as c } from "./RouteIdLevelDefaultError-DPF_x2tG.mjs";
|
|
4
|
+
import { t as l } from "./useSetBreadcrumb-tn7lBaQV.mjs";
|
|
5
|
+
import { t as u } from "./objects-_g7nGIn5.mjs";
|
|
6
|
+
import { t as d } from "./StorageNotFound-B-zVinVD.mjs";
|
|
7
|
+
import { Fragment as f, jsx as p, jsxs as m } from "react/jsx-runtime";
|
|
8
|
+
import { useParams as h } from "@tanstack/react-router";
|
|
9
|
+
import { Trans as g, useLingui as _ } from "@lingui/react";
|
|
10
|
+
import { ErrorBoundary as v } from "react-error-boundary";
|
|
11
|
+
//#region src/client/routes/_auth/projects/$projectId/storage/$provider/$storageType/$containerName/objects/index.tsx?tsr-split=notFoundComponent
|
|
12
|
+
function y({ data: t }) {
|
|
13
|
+
let { i18n: n, _: r } = _(), { provider: i } = h({ strict: !1 }), a = u(), o = t?.reason;
|
|
14
|
+
if (o !== "container-not-found") return /*#__PURE__*/ p(d, { data: o ? { reason: o } : void 0 });
|
|
15
|
+
let s = i === e.CEPH;
|
|
16
|
+
return /*#__PURE__*/ p(c, {
|
|
17
|
+
errorTitle: s ? n._({ id: "uu0Tl6" }) : n._({ id: "HPV820" }),
|
|
18
|
+
errorDescription: s ? n._({ id: "oFW0cA" }) : n._({ id: "geLBjg" }),
|
|
19
|
+
action: a
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
function b() {
|
|
23
|
+
let { projectId: c, provider: u, containerName: d } = h({
|
|
24
|
+
from: "/_auth/projects/$projectId/storage/$provider/$storageType/$containerName/objects/",
|
|
25
|
+
select: (e) => ({
|
|
26
|
+
projectId: e.projectId,
|
|
27
|
+
provider: e.provider,
|
|
28
|
+
containerName: e.containerName
|
|
29
|
+
})
|
|
30
|
+
});
|
|
31
|
+
l(a.id, d);
|
|
32
|
+
let { prefix: _, sortBy: y, sortDirection: b, search: x, view: S } = a.useSearch();
|
|
33
|
+
return /*#__PURE__*/ m(f, { children: [
|
|
34
|
+
u === e.CEPH && /*#__PURE__*/ p(o, { bucketName: d }),
|
|
35
|
+
u === e.SWIFT && /*#__PURE__*/ p(i, { containerName: d }),
|
|
36
|
+
/*#__PURE__*/ p("div", {
|
|
37
|
+
className: u === e.SWIFT ? "pt-4" : void 0,
|
|
38
|
+
children: c ? /*#__PURE__*/ p(v, {
|
|
39
|
+
resetKeys: [
|
|
40
|
+
c,
|
|
41
|
+
u,
|
|
42
|
+
d,
|
|
43
|
+
_,
|
|
44
|
+
y,
|
|
45
|
+
b,
|
|
46
|
+
x,
|
|
47
|
+
S
|
|
48
|
+
],
|
|
49
|
+
fallback: /*#__PURE__*/ p("div", {
|
|
50
|
+
className: "p-4 text-center",
|
|
51
|
+
children: /*#__PURE__*/ p(g, { id: "diFNkW" })
|
|
52
|
+
}),
|
|
53
|
+
children: (() => {
|
|
54
|
+
switch (u) {
|
|
55
|
+
case e.SWIFT: return /*#__PURE__*/ p(t, {
|
|
56
|
+
provider: u,
|
|
57
|
+
containerName: d
|
|
58
|
+
});
|
|
59
|
+
case e.CEPH: return p(S === "lifecycle-rules" ? r : S === "cors-rules" ? s : n, { bucketName: d });
|
|
60
|
+
default: return /*#__PURE__*/ p("div", {
|
|
61
|
+
className: "p-4",
|
|
62
|
+
children: /*#__PURE__*/ p(g, {
|
|
63
|
+
id: "ubUrot",
|
|
64
|
+
values: { containerName: d }
|
|
65
|
+
})
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
})()
|
|
69
|
+
}) : /*#__PURE__*/ p("div", {
|
|
70
|
+
className: "p-4 text-center",
|
|
71
|
+
children: /*#__PURE__*/ p(g, { id: "Z2fZGD" })
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
] });
|
|
75
|
+
}
|
|
76
|
+
var x = y;
|
|
77
|
+
//#endregion
|
|
78
|
+
export { b as ObjectsDashboard, x as notFoundComponent };
|
|
79
|
+
|
|
80
|
+
//# sourceMappingURL=objects-Dw7oeTq2.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"objects-Dw7oeTq2.mjs","names":["useParams","CONTAINER_NOT_FOUND","RouteIdLevelDefaultError","ErrorBoundary","Trans","useLingui","SwiftObjects","CephObjects","CephCorsRules","CephLifecycleRules","BucketHeader","ContainerHeader","useSetBreadcrumb","StorageNotFound","STORAGE_PROVIDER","ObjectsNotFound","data","reason","StorageNotFoundReason","t","provider","strict","backToList","useBackToContainerList","undefined","isCeph","CEPH","Route","ObjectsDashboard","projectId","containerName","from","select","params","id","prefix","sortBy","sortDirection","search","view","useSearch","SWIFT","SplitNotFoundComponent","notFoundComponent"],"sources":["../../src/client/routes/_auth/projects/$projectId/storage/$provider/$storageType/$containerName/objects/index.tsx?tsr-split=notFoundComponent"],"sourcesContent":["import {\n createFileRoute,\n useNavigate,\n useParams,\n type ErrorComponentProps,\n type NotFoundRouteComponent,\n} from \"@tanstack/react-router\"\nimport type { ReactNode } from \"react\"\nimport { Button } from \"@cloudoperators/juno-ui-components\"\nimport { isTRPCClientError } from \"@trpc/client\"\nimport { guardStorageRoute, type StorageNotFoundReason } from \"../../../../-components/utils/serviceAvailability\"\nimport { CONTAINER_NOT_FOUND, requireContainerExists } from \"../../../../-components/utils/containerExistence\"\nimport { RouteIdLevelDefaultError } from \"@/client/components/Errors/RouteIdLevelDefaultError\"\nimport { ErrorBoundary } from \"react-error-boundary\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { SwiftObjects } from \"../../../../-components/Swift/Objects\"\nimport { CephObjects } from \"../../../../-components/Ceph/Objects\"\nimport { CephCorsRules, CephLifecycleRules } from \"../../../../-components/Ceph/Buckets\"\nimport { z } from \"zod\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { BucketHeader } from \"../../../../-components/Ceph/Buckets/BucketHeader\"\nimport { ContainerHeader } from \"../../../../-components/Swift/Containers/ContainerHeader\"\nimport { useSetBreadcrumb } from \"@/client/hooks/useSetBreadcrumb\"\nimport { StorageNotFound } from \"../../../../-components/StorageNotFound\"\nimport { STORAGE_PROVIDER } from \"@/client/utils/storageProviders\"\n\n// Search params schema\n// - prefix: base64-encoded current folder path, safe to carry \"/\" chars in the URL\n// - sortBy: active sort column key — persisted so deep links and back navigation restore sort state\n// Accepts both Swift keys (last_modified, bytes) and Ceph keys (lastModified, size) for compatibility\n// - sortDirection: \"asc\" | \"desc\" — persisted alongside sortBy\n// - view: tab selection for Ceph bucket details page (overview shows objects, cors-rules shows CORS config, lifecycle-rules shows lifecycle config)\n// - corsSortBy: active sort column for CORS rules tab (ID, AllowedOrigins, etc.) — separate from objects sortBy\n// - corsSortDirection: \"asc\" | \"desc\" for CORS rules — separate from objects sortDirection\n// - corsSearch: search term for filtering CORS rules by Rule ID — separate from objects search\n// - lifecycleSortBy: active sort column for lifecycle rules tab (ID, Status, Expiration) — separate from objects sortBy\n// - lifecycleSortDirection: \"asc\" | \"desc\" for lifecycle rules — separate from objects sortDirection\n// - lifecycleSearch: search term for filtering lifecycle rules by Rule ID — separate from objects search\nconst objectsSearchSchema = z.object({\n prefix: z.string().optional(),\n sortBy: z.enum([\"name\", \"last_modified\", \"bytes\", \"lastModified\", \"size\"]).optional().default(\"name\"),\n sortDirection: z.enum([\"asc\", \"desc\"]).optional().default(\"asc\"),\n search: z.string().optional(),\n tab: z.enum([\"all\", \"deleted\"]).optional().default(\"all\"),\n view: z.enum([\"overview\", \"cors-rules\", \"lifecycle-rules\"]).optional().default(\"overview\"),\n corsSortBy: z\n .enum([\"ID\", \"AllowedOrigins\", \"AllowedMethods\", \"AllowedHeaders\", \"ExposeHeaders\", \"MaxAgeSeconds\"])\n .optional()\n .default(\"ID\"),\n corsSortDirection: z.enum([\"asc\", \"desc\"]).optional().default(\"asc\"),\n corsSearch: z.string().optional(),\n lifecycleSortBy: z.enum([\"ID\", \"Status\", \"Expiration\"]).optional().default(\"ID\"),\n lifecycleSortDirection: z.enum([\"asc\", \"desc\"]).optional().default(\"asc\"),\n lifecycleSearch: z.string().optional(),\n})\n\n/**\n * \"Back to Buckets\"/\"Back to Containers\" — the exit both boundaries below want. The list\n * is the one page that is certainly still there, so it beats `RouteIdLevelDefaultError`'s\n * default \"Go to Project Home\", which leaves storage altogether.\n *\n * Returns undefined when the params aren't readable, so the caller falls back to that\n * default rather than rendering a button that can't build a target.\n */\nfunction useBackToContainerList(): ReactNode {\n const { t } = useLingui()\n const navigate = useNavigate()\n const { projectId, provider, storageType } = useParams({ strict: false })\n\n if (!projectId || !provider || !storageType) return undefined\n\n return (\n <Button\n variant=\"primary\"\n onClick={() =>\n navigate({\n to: \"/projects/$projectId/storage/$provider/$storageType\",\n params: { projectId, provider, storageType },\n })\n }\n >\n {provider === STORAGE_PROVIDER.CEPH ? t`Back to Buckets` : t`Back to Containers`}\n </Button>\n )\n}\n\n/**\n * The route's single notFound boundary serves two unrelated 404s, so it dispatches on the\n * reason the throw carried:\n *\n * - the address is wrong (bad provider, non-canonical storage-type) → `StorageNotFound`,\n * whose action leads out of storage entirely, because no storage page here is valid;\n * - the address is fine but the container isn't there → `RouteIdLevelDefaultError`, whose\n * action leads back to the list, which is a page the user can actually use.\n *\n * (The router spreads the whole notFound error object into these props, so the reason\n * arrives nested under `data` — see StorageNotFound for the three files that establish it.)\n */\nfunction ObjectsNotFound({ data }: { data?: { reason?: StorageNotFoundReason | typeof CONTAINER_NOT_FOUND } }) {\n const { t } = useLingui()\n const { provider } = useParams({ strict: false })\n const backToList = useBackToContainerList()\n\n const reason = data?.reason\n\n if (reason !== CONTAINER_NOT_FOUND) {\n return <StorageNotFound data={reason ? { reason } : undefined} />\n }\n\n const isCeph = provider === STORAGE_PROVIDER.CEPH\n\n return (\n <RouteIdLevelDefaultError\n errorTitle={isCeph ? t`Bucket Not Found` : t`Container Not Found`}\n errorDescription={\n isCeph\n ? t`This bucket does not exist or is not accessible in this project.`\n : t`This container does not exist or is not accessible in this project.`\n }\n action={backToList}\n />\n )\n}\n\n/**\n * Route-level error boundary — for a request that failed, as opposed to a resource that\n * isn't there. Deliberately a boundary of its own: #1304 points one component at both, and\n * since that component hardcodes `code={404}` a 500 arrives labelled \"Resource Not Found\".\n * The split is in what the two say, not in which component they use — `code` is what lets\n * this one state the real status instead of inheriting that default.\n *\n * Catching here rather than letting it reach the root keeps everything the parent routes\n * render — shell, nav, the breadcrumb trail up to this page — on screen, and lets the\n * boundary reset when the user navigates.\n */\nfunction ObjectsError({ error }: ErrorComponentProps) {\n const { t } = useLingui()\n const backToList = useBackToContainerList()\n const trpcError = isTRPCClientError(error) ? error : undefined\n\n return (\n <RouteIdLevelDefaultError\n code={trpcError?.data?.httpStatus ?? null}\n errorTitle={t`Unable to Load Content`}\n errorDescription={trpcError?.message ?? t`An unexpected error occurred.`}\n action={backToList}\n />\n )\n}\n\nexport const Route = createFileRoute(\n \"/_auth/projects/$projectId/storage/$provider/$storageType/$containerName/objects/\"\n)({\n staticData: {\n section: \"storage\",\n service: \"containers\",\n analytics: {\n name: \"storage.objectstore.detail\",\n },\n } satisfies RouteInfo,\n validateSearch: objectsSearchSchema,\n head: ({ match }) => ({\n meta: [{ title: match.params.containerName }],\n }),\n component: () => {\n return <ObjectsDashboard />\n },\n notFoundComponent: ObjectsNotFound as NotFoundRouteComponent,\n errorComponent: ObjectsError,\n loader: async ({ context, params }) => {\n const { trpcClient } = context\n if (!trpcClient) {\n throw new Error(\"trpcClient is not available in route context\")\n }\n const availableServices = (await trpcClient.auth.getAvailableServices.query()) ?? []\n const provider = guardStorageRoute(availableServices, params)\n return requireContainerExists(trpcClient, { ...params, provider })\n },\n})\n\nexport function ObjectsDashboard() {\n const { projectId, provider, containerName } = useParams({\n from: \"/_auth/projects/$projectId/storage/$provider/$storageType/$containerName/objects/\",\n select: (params) => ({\n projectId: params.projectId,\n provider: params.provider,\n containerName: params.containerName,\n }),\n })\n\n useSetBreadcrumb(Route.id, containerName)\n\n const { prefix, sortBy, sortDirection, search, view } = Route.useSearch()\n\n return (\n <>\n {provider === STORAGE_PROVIDER.CEPH && <BucketHeader bucketName={containerName} />}\n {provider === STORAGE_PROVIDER.SWIFT && <ContainerHeader containerName={containerName} />}\n {/* Ceph gets extra breathing room below its header from BucketHeader's own\n tabs block; Swift has no such block, so pad the content wrapper directly\n to avoid the overflow menu sitting too close to the toolbar below it. */}\n <div className={provider === STORAGE_PROVIDER.SWIFT ? \"pt-4\" : undefined}>\n {projectId ? (\n <ErrorBoundary\n resetKeys={[projectId, provider, containerName, prefix, sortBy, sortDirection, search, view]}\n fallback={\n <div className=\"p-4 text-center\">\n <Trans>Error loading component</Trans>\n </div>\n }\n >\n {(() => {\n switch (provider) {\n case STORAGE_PROVIDER.SWIFT:\n return <SwiftObjects provider={provider} containerName={containerName} />\n case STORAGE_PROVIDER.CEPH:\n if (view === \"lifecycle-rules\") {\n return <CephLifecycleRules bucketName={containerName} />\n }\n if (view === \"cors-rules\") {\n return <CephCorsRules bucketName={containerName} />\n }\n return <CephObjects bucketName={containerName} />\n default:\n return (\n <div className=\"p-4\">\n <Trans>Objects: {containerName}</Trans>\n </div>\n )\n }\n })()}\n </ErrorBoundary>\n ) : (\n <div className=\"p-4 text-center\">\n <Trans>No project selected</Trans>\n </div>\n )}\n </div>\n </>\n )\n}\n"],"mappings":";;;;;;;;;;;AAkGA,SAASe,EAAgB,EAAEC,WAAkF;CAC3G,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQX,EAAAA,GACR,EAAEe,gBAAapB,EAAU,EAAEqB,QAAQ,GAAM,CAAA,GACzCC,IAAaC,EAAAA,GAEbN,IAASD,GAAMC;CAErB,IAAIA,MAAAA,uBACF,OAAO,gBAAC,GAAA,EAAgB,MAAMA,IAAS,EAAEA,UAAO,IAAIO,KAAAA,EAAAA,CAAAA;CAGtD,IAAMC,IAASL,MAAaN,EAAiBY;CAE7C,OACE,gBAAC,GAAA;EACC,YAAYD,IAASN,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA,IAAqBA,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA;EAC5C,kBACEM,IACIN,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA,IACDA,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA;EAEP,QAAQG;;AAGd;AA0DA,SAAgBM,IAAAA;CACd,IAAM,EAAEC,cAAWT,aAAUU,qBAAkB9B,EAAU;EACvD+B,MAAM;EACNC,SAASC,OAAY;GACnBJ,WAAWI,EAAOJ;GAClBT,UAAUa,EAAOb;GACjBU,eAAeG,EAAOH;EACxB;CACF,CAAA;CAEAlB,EAAiBe,EAAMO,IAAIJ,CAAAA;CAE3B,IAAM,EAAEK,WAAQC,WAAQC,kBAAeC,WAAQC,YAASZ,EAAMa,UAAS;CAEvE,OACE,gBAAA,GAAA,EAAA,UAAA;EACGpB,MAAaN,EAAiBY,QAAQ,gBAAC,GAAA,EAAa,YAAYI,EAAAA,CAAAA;EAChEV,MAAaN,EAAiB2B,SAAS,gBAAC,GAAA,EAA+BX,iBAAAA,CAAAA;EAIxE,gBAAC,OAAA;GAAI,WAAWV,MAAaN,EAAiB2B,QAAQ,SAASjB,KAAAA;GAC5DK,UAAAA,IACC,gBAAC,GAAA;IACC,WAAW;KAACA;KAAWT;KAAUU;KAAeK;KAAQC;KAAQC;KAAeC;KAAQC;IAAK;IAC5F,UACE,gBAAC,OAAA;KAAI,WAAU;KACb,UAAA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;IAIH,iBAAC;KACA,QAAQnB,GAAR;MACE,KAAKN,EAAiB2B,OACpB,OAAO,gBAAC,GAAA;OAAuBrB;OAAyBU;;MAC1D,KAAKhB,EAAiBY,MAOpB,OALS,EADLa,MAAS,oBACH,IAENA,MAAS,eACH,IAEF,GALE,EAAmB,YAAYT,EAAAA,CAAAA;MAM3C,SACE,OACE,gBAAC,OAAA;OAAI,WAAU;OACb,UAAA,gBAAA,GAAA;;QAAiBA,QAAAA,EAAAA,iBAAAA;;;KAGzB;IACF,EAAA,CAAA;GAGF,CAAA,IAAA,gBAAC,OAAA;IAAI,WAAU;IACb,UAAA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;;;AAMZ;AAAC,IAAAY,IAzEoB3B"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { i as e } from "./build-WuxXRAqf.mjs";
|
|
2
|
+
import { t } from "./storageProviders-CJ5rOh13.mjs";
|
|
3
|
+
import { jsx as n } from "react/jsx-runtime";
|
|
4
|
+
import { useNavigate as r, useParams as i } from "@tanstack/react-router";
|
|
5
|
+
import { useLingui as a } from "@lingui/react";
|
|
6
|
+
//#region src/client/routes/_auth/projects/$projectId/storage/$provider/$storageType/$containerName/objects/index.tsx?tsr-shared=1
|
|
7
|
+
function o() {
|
|
8
|
+
let { i18n: o, _: s } = a(), c = r(), { projectId: l, provider: u, storageType: d } = i({ strict: !1 });
|
|
9
|
+
if (!(!l || !u || !d)) return /*#__PURE__*/ n(e, {
|
|
10
|
+
variant: "primary",
|
|
11
|
+
onClick: () => c({
|
|
12
|
+
to: "/projects/$projectId/storage/$provider/$storageType",
|
|
13
|
+
params: {
|
|
14
|
+
projectId: l,
|
|
15
|
+
provider: u,
|
|
16
|
+
storageType: d
|
|
17
|
+
}
|
|
18
|
+
}),
|
|
19
|
+
children: u === t.CEPH ? o._({ id: "Rzahyj" }) : o._({ id: "6nrGLS" })
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
export { o as t };
|
|
24
|
+
|
|
25
|
+
//# sourceMappingURL=objects-_g7nGIn5.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"objects-_g7nGIn5.mjs","names":["useNavigate","useParams","Button","useLingui","STORAGE_PROVIDER","useBackToContainerList","ReactNode","t","navigate","projectId","provider","storageType","strict","undefined","to","params","CEPH"],"sources":["../../src/client/routes/_auth/projects/$projectId/storage/$provider/$storageType/$containerName/objects/index.tsx?tsr-shared=1"],"sourcesContent":["import {\n createFileRoute,\n useNavigate,\n useParams,\n type ErrorComponentProps,\n type NotFoundRouteComponent,\n} from \"@tanstack/react-router\"\nimport type { ReactNode } from \"react\"\nimport { Button } from \"@cloudoperators/juno-ui-components\"\nimport { isTRPCClientError } from \"@trpc/client\"\nimport { guardStorageRoute, type StorageNotFoundReason } from \"../../../../-components/utils/serviceAvailability\"\nimport { CONTAINER_NOT_FOUND, requireContainerExists } from \"../../../../-components/utils/containerExistence\"\nimport { RouteIdLevelDefaultError } from \"@/client/components/Errors/RouteIdLevelDefaultError\"\nimport { ErrorBoundary } from \"react-error-boundary\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { SwiftObjects } from \"../../../../-components/Swift/Objects\"\nimport { CephObjects } from \"../../../../-components/Ceph/Objects\"\nimport { CephCorsRules, CephLifecycleRules } from \"../../../../-components/Ceph/Buckets\"\nimport { z } from \"zod\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { BucketHeader } from \"../../../../-components/Ceph/Buckets/BucketHeader\"\nimport { ContainerHeader } from \"../../../../-components/Swift/Containers/ContainerHeader\"\nimport { useSetBreadcrumb } from \"@/client/hooks/useSetBreadcrumb\"\nimport { StorageNotFound } from \"../../../../-components/StorageNotFound\"\nimport { STORAGE_PROVIDER } from \"@/client/utils/storageProviders\"\n\n// Search params schema\n// - prefix: base64-encoded current folder path, safe to carry \"/\" chars in the URL\n// - sortBy: active sort column key — persisted so deep links and back navigation restore sort state\n// Accepts both Swift keys (last_modified, bytes) and Ceph keys (lastModified, size) for compatibility\n// - sortDirection: \"asc\" | \"desc\" — persisted alongside sortBy\n// - view: tab selection for Ceph bucket details page (overview shows objects, cors-rules shows CORS config, lifecycle-rules shows lifecycle config)\n// - corsSortBy: active sort column for CORS rules tab (ID, AllowedOrigins, etc.) — separate from objects sortBy\n// - corsSortDirection: \"asc\" | \"desc\" for CORS rules — separate from objects sortDirection\n// - corsSearch: search term for filtering CORS rules by Rule ID — separate from objects search\n// - lifecycleSortBy: active sort column for lifecycle rules tab (ID, Status, Expiration) — separate from objects sortBy\n// - lifecycleSortDirection: \"asc\" | \"desc\" for lifecycle rules — separate from objects sortDirection\n// - lifecycleSearch: search term for filtering lifecycle rules by Rule ID — separate from objects search\nconst objectsSearchSchema = z.object({\n prefix: z.string().optional(),\n sortBy: z.enum([\"name\", \"last_modified\", \"bytes\", \"lastModified\", \"size\"]).optional().default(\"name\"),\n sortDirection: z.enum([\"asc\", \"desc\"]).optional().default(\"asc\"),\n search: z.string().optional(),\n tab: z.enum([\"all\", \"deleted\"]).optional().default(\"all\"),\n view: z.enum([\"overview\", \"cors-rules\", \"lifecycle-rules\"]).optional().default(\"overview\"),\n corsSortBy: z\n .enum([\"ID\", \"AllowedOrigins\", \"AllowedMethods\", \"AllowedHeaders\", \"ExposeHeaders\", \"MaxAgeSeconds\"])\n .optional()\n .default(\"ID\"),\n corsSortDirection: z.enum([\"asc\", \"desc\"]).optional().default(\"asc\"),\n corsSearch: z.string().optional(),\n lifecycleSortBy: z.enum([\"ID\", \"Status\", \"Expiration\"]).optional().default(\"ID\"),\n lifecycleSortDirection: z.enum([\"asc\", \"desc\"]).optional().default(\"asc\"),\n lifecycleSearch: z.string().optional(),\n})\n\n/**\n * \"Back to Buckets\"/\"Back to Containers\" — the exit both boundaries below want. The list\n * is the one page that is certainly still there, so it beats `RouteIdLevelDefaultError`'s\n * default \"Go to Project Home\", which leaves storage altogether.\n *\n * Returns undefined when the params aren't readable, so the caller falls back to that\n * default rather than rendering a button that can't build a target.\n */\nfunction useBackToContainerList(): ReactNode {\n const { t } = useLingui()\n const navigate = useNavigate()\n const { projectId, provider, storageType } = useParams({ strict: false })\n\n if (!projectId || !provider || !storageType) return undefined\n\n return (\n <Button\n variant=\"primary\"\n onClick={() =>\n navigate({\n to: \"/projects/$projectId/storage/$provider/$storageType\",\n params: { projectId, provider, storageType },\n })\n }\n >\n {provider === STORAGE_PROVIDER.CEPH ? t`Back to Buckets` : t`Back to Containers`}\n </Button>\n )\n}\n\n/**\n * The route's single notFound boundary serves two unrelated 404s, so it dispatches on the\n * reason the throw carried:\n *\n * - the address is wrong (bad provider, non-canonical storage-type) → `StorageNotFound`,\n * whose action leads out of storage entirely, because no storage page here is valid;\n * - the address is fine but the container isn't there → `RouteIdLevelDefaultError`, whose\n * action leads back to the list, which is a page the user can actually use.\n *\n * (The router spreads the whole notFound error object into these props, so the reason\n * arrives nested under `data` — see StorageNotFound for the three files that establish it.)\n */\nfunction ObjectsNotFound({ data }: { data?: { reason?: StorageNotFoundReason | typeof CONTAINER_NOT_FOUND } }) {\n const { t } = useLingui()\n const { provider } = useParams({ strict: false })\n const backToList = useBackToContainerList()\n\n const reason = data?.reason\n\n if (reason !== CONTAINER_NOT_FOUND) {\n return <StorageNotFound data={reason ? { reason } : undefined} />\n }\n\n const isCeph = provider === STORAGE_PROVIDER.CEPH\n\n return (\n <RouteIdLevelDefaultError\n errorTitle={isCeph ? t`Bucket Not Found` : t`Container Not Found`}\n errorDescription={\n isCeph\n ? t`This bucket does not exist or is not accessible in this project.`\n : t`This container does not exist or is not accessible in this project.`\n }\n action={backToList}\n />\n )\n}\n\n/**\n * Route-level error boundary — for a request that failed, as opposed to a resource that\n * isn't there. Deliberately a boundary of its own: #1304 points one component at both, and\n * since that component hardcodes `code={404}` a 500 arrives labelled \"Resource Not Found\".\n * The split is in what the two say, not in which component they use — `code` is what lets\n * this one state the real status instead of inheriting that default.\n *\n * Catching here rather than letting it reach the root keeps everything the parent routes\n * render — shell, nav, the breadcrumb trail up to this page — on screen, and lets the\n * boundary reset when the user navigates.\n */\nfunction ObjectsError({ error }: ErrorComponentProps) {\n const { t } = useLingui()\n const backToList = useBackToContainerList()\n const trpcError = isTRPCClientError(error) ? error : undefined\n\n return (\n <RouteIdLevelDefaultError\n code={trpcError?.data?.httpStatus ?? null}\n errorTitle={t`Unable to Load Content`}\n errorDescription={trpcError?.message ?? t`An unexpected error occurred.`}\n action={backToList}\n />\n )\n}\n\nexport const Route = createFileRoute(\n \"/_auth/projects/$projectId/storage/$provider/$storageType/$containerName/objects/\"\n)({\n staticData: {\n section: \"storage\",\n service: \"containers\",\n analytics: {\n name: \"storage.objectstore.detail\",\n },\n } satisfies RouteInfo,\n validateSearch: objectsSearchSchema,\n head: ({ match }) => ({\n meta: [{ title: match.params.containerName }],\n }),\n component: () => {\n return <ObjectsDashboard />\n },\n notFoundComponent: ObjectsNotFound as NotFoundRouteComponent,\n errorComponent: ObjectsError,\n loader: async ({ context, params }) => {\n const { trpcClient } = context\n if (!trpcClient) {\n throw new Error(\"trpcClient is not available in route context\")\n }\n const availableServices = (await trpcClient.auth.getAvailableServices.query()) ?? []\n const provider = guardStorageRoute(availableServices, params)\n return requireContainerExists(trpcClient, { ...params, provider })\n },\n})\n\nexport function ObjectsDashboard() {\n const { projectId, provider, containerName } = useParams({\n from: \"/_auth/projects/$projectId/storage/$provider/$storageType/$containerName/objects/\",\n select: (params) => ({\n projectId: params.projectId,\n provider: params.provider,\n containerName: params.containerName,\n }),\n })\n\n useSetBreadcrumb(Route.id, containerName)\n\n const { prefix, sortBy, sortDirection, search, view } = Route.useSearch()\n\n return (\n <>\n {provider === STORAGE_PROVIDER.CEPH && <BucketHeader bucketName={containerName} />}\n {provider === STORAGE_PROVIDER.SWIFT && <ContainerHeader containerName={containerName} />}\n {/* Ceph gets extra breathing room below its header from BucketHeader's own\n tabs block; Swift has no such block, so pad the content wrapper directly\n to avoid the overflow menu sitting too close to the toolbar below it. */}\n <div className={provider === STORAGE_PROVIDER.SWIFT ? \"pt-4\" : undefined}>\n {projectId ? (\n <ErrorBoundary\n resetKeys={[projectId, provider, containerName, prefix, sortBy, sortDirection, search, view]}\n fallback={\n <div className=\"p-4 text-center\">\n <Trans>Error loading component</Trans>\n </div>\n }\n >\n {(() => {\n switch (provider) {\n case STORAGE_PROVIDER.SWIFT:\n return <SwiftObjects provider={provider} containerName={containerName} />\n case STORAGE_PROVIDER.CEPH:\n if (view === \"lifecycle-rules\") {\n return <CephLifecycleRules bucketName={containerName} />\n }\n if (view === \"cors-rules\") {\n return <CephCorsRules bucketName={containerName} />\n }\n return <CephObjects bucketName={containerName} />\n default:\n return (\n <div className=\"p-4\">\n <Trans>Objects: {containerName}</Trans>\n </div>\n )\n }\n })()}\n </ErrorBoundary>\n ) : (\n <div className=\"p-4 text-center\">\n <Trans>No project selected</Trans>\n </div>\n )}\n </div>\n </>\n )\n}\n"],"mappings":";;;;;;AAgEA,SAASK,IAAAA;CACP,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQF,EAAAA,GACRK,IAAWR,EAAAA,GACX,EAAES,cAAWC,aAAUC,mBAAgBV,EAAU,EAAEW,QAAQ,GAAM,CAAA;CAEnE,OAACH,KAAa,CAACC,KAAY,CAACC,IAEhC,OACE,gBAAC,GAAA;EACC,SAAQ;EACR,eACEH,EAAS;GACPM,IAAI;GACJC,QAAQ;IAAEN;IAAWC;IAAUC;GAAY;EAC7C,CAAA;EAGDD,UAAAA,MAAaN,EAAiBY,OAAOT,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA,IAAoBA,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA;;AAGlE"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { t as e } from "./storageProviders-CJ5rOh13.mjs";
|
|
2
|
+
import { C as t, S as n, b as r, n as i, t as a, v as o, x as s } from "./objects-BudUAfWY.mjs";
|
|
3
|
+
import { t as c } from "./RouteIdLevelDefaultError-DPF_x2tG.mjs";
|
|
4
|
+
import { t as l } from "./useSetBreadcrumb-tn7lBaQV.mjs";
|
|
5
|
+
import { t as u } from "./objects-_g7nGIn5.mjs";
|
|
6
|
+
import { Fragment as d, jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
7
|
+
import { useParams as m } from "@tanstack/react-router";
|
|
8
|
+
import { isTRPCClientError as h } from "@trpc/client";
|
|
9
|
+
import { Trans as g, useLingui as _ } from "@lingui/react";
|
|
10
|
+
import { ErrorBoundary as v } from "react-error-boundary";
|
|
11
|
+
//#region src/client/routes/_auth/projects/$projectId/storage/$provider/$storageType/$containerName/objects/index.tsx?tsr-split=errorComponent
|
|
12
|
+
function y({ error: e }) {
|
|
13
|
+
let { i18n: t, _: n } = _(), r = u(), i = h(e) ? e : void 0;
|
|
14
|
+
return /*#__PURE__*/ f(c, {
|
|
15
|
+
code: i?.data?.httpStatus ?? null,
|
|
16
|
+
errorTitle: t._({ id: "Gfx1qQ" }),
|
|
17
|
+
errorDescription: i?.message ?? t._({ id: "W5A0Ly" }),
|
|
18
|
+
action: r
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
function b() {
|
|
22
|
+
let { projectId: c, provider: u, containerName: h } = m({
|
|
23
|
+
from: "/_auth/projects/$projectId/storage/$provider/$storageType/$containerName/objects/",
|
|
24
|
+
select: (e) => ({
|
|
25
|
+
projectId: e.projectId,
|
|
26
|
+
provider: e.provider,
|
|
27
|
+
containerName: e.containerName
|
|
28
|
+
})
|
|
29
|
+
});
|
|
30
|
+
l(a.id, h);
|
|
31
|
+
let { prefix: _, sortBy: y, sortDirection: b, search: x, view: S } = a.useSearch();
|
|
32
|
+
return /*#__PURE__*/ p(d, { children: [
|
|
33
|
+
u === e.CEPH && /*#__PURE__*/ f(o, { bucketName: h }),
|
|
34
|
+
u === e.SWIFT && /*#__PURE__*/ f(i, { containerName: h }),
|
|
35
|
+
/*#__PURE__*/ f("div", {
|
|
36
|
+
className: u === e.SWIFT ? "pt-4" : void 0,
|
|
37
|
+
children: c ? /*#__PURE__*/ f(v, {
|
|
38
|
+
resetKeys: [
|
|
39
|
+
c,
|
|
40
|
+
u,
|
|
41
|
+
h,
|
|
42
|
+
_,
|
|
43
|
+
y,
|
|
44
|
+
b,
|
|
45
|
+
x,
|
|
46
|
+
S
|
|
47
|
+
],
|
|
48
|
+
fallback: /*#__PURE__*/ f("div", {
|
|
49
|
+
className: "p-4 text-center",
|
|
50
|
+
children: /*#__PURE__*/ f(g, { id: "diFNkW" })
|
|
51
|
+
}),
|
|
52
|
+
children: (() => {
|
|
53
|
+
switch (u) {
|
|
54
|
+
case e.SWIFT: return /*#__PURE__*/ f(t, {
|
|
55
|
+
provider: u,
|
|
56
|
+
containerName: h
|
|
57
|
+
});
|
|
58
|
+
case e.CEPH: return f(S === "lifecycle-rules" ? r : S === "cors-rules" ? s : n, { bucketName: h });
|
|
59
|
+
default: return /*#__PURE__*/ f("div", {
|
|
60
|
+
className: "p-4",
|
|
61
|
+
children: /*#__PURE__*/ f(g, {
|
|
62
|
+
id: "ubUrot",
|
|
63
|
+
values: { containerName: h }
|
|
64
|
+
})
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
})()
|
|
68
|
+
}) : /*#__PURE__*/ f("div", {
|
|
69
|
+
className: "p-4 text-center",
|
|
70
|
+
children: /*#__PURE__*/ f(g, { id: "Z2fZGD" })
|
|
71
|
+
})
|
|
72
|
+
})
|
|
73
|
+
] });
|
|
74
|
+
}
|
|
75
|
+
//#endregion
|
|
76
|
+
export { b as ObjectsDashboard, y as errorComponent };
|
|
77
|
+
|
|
78
|
+
//# sourceMappingURL=objects-eBxvY6_n.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"objects-eBxvY6_n.mjs","names":["useParams","isTRPCClientError","RouteIdLevelDefaultError","ErrorBoundary","Trans","useLingui","SwiftObjects","CephObjects","CephCorsRules","CephLifecycleRules","BucketHeader","ContainerHeader","useSetBreadcrumb","STORAGE_PROVIDER","ObjectsError","error","ErrorComponentProps","t","backToList","useBackToContainerList","trpcError","undefined","data","httpStatus","message","Route","ObjectsDashboard","projectId","provider","containerName","from","select","params","id","prefix","sortBy","sortDirection","search","view","useSearch","CEPH","SWIFT","errorComponent"],"sources":["../../src/client/routes/_auth/projects/$projectId/storage/$provider/$storageType/$containerName/objects/index.tsx?tsr-split=errorComponent"],"sourcesContent":["import {\n createFileRoute,\n useNavigate,\n useParams,\n type ErrorComponentProps,\n type NotFoundRouteComponent,\n} from \"@tanstack/react-router\"\nimport type { ReactNode } from \"react\"\nimport { Button } from \"@cloudoperators/juno-ui-components\"\nimport { isTRPCClientError } from \"@trpc/client\"\nimport { guardStorageRoute, type StorageNotFoundReason } from \"../../../../-components/utils/serviceAvailability\"\nimport { CONTAINER_NOT_FOUND, requireContainerExists } from \"../../../../-components/utils/containerExistence\"\nimport { RouteIdLevelDefaultError } from \"@/client/components/Errors/RouteIdLevelDefaultError\"\nimport { ErrorBoundary } from \"react-error-boundary\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { SwiftObjects } from \"../../../../-components/Swift/Objects\"\nimport { CephObjects } from \"../../../../-components/Ceph/Objects\"\nimport { CephCorsRules, CephLifecycleRules } from \"../../../../-components/Ceph/Buckets\"\nimport { z } from \"zod\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { BucketHeader } from \"../../../../-components/Ceph/Buckets/BucketHeader\"\nimport { ContainerHeader } from \"../../../../-components/Swift/Containers/ContainerHeader\"\nimport { useSetBreadcrumb } from \"@/client/hooks/useSetBreadcrumb\"\nimport { StorageNotFound } from \"../../../../-components/StorageNotFound\"\nimport { STORAGE_PROVIDER } from \"@/client/utils/storageProviders\"\n\n// Search params schema\n// - prefix: base64-encoded current folder path, safe to carry \"/\" chars in the URL\n// - sortBy: active sort column key — persisted so deep links and back navigation restore sort state\n// Accepts both Swift keys (last_modified, bytes) and Ceph keys (lastModified, size) for compatibility\n// - sortDirection: \"asc\" | \"desc\" — persisted alongside sortBy\n// - view: tab selection for Ceph bucket details page (overview shows objects, cors-rules shows CORS config, lifecycle-rules shows lifecycle config)\n// - corsSortBy: active sort column for CORS rules tab (ID, AllowedOrigins, etc.) — separate from objects sortBy\n// - corsSortDirection: \"asc\" | \"desc\" for CORS rules — separate from objects sortDirection\n// - corsSearch: search term for filtering CORS rules by Rule ID — separate from objects search\n// - lifecycleSortBy: active sort column for lifecycle rules tab (ID, Status, Expiration) — separate from objects sortBy\n// - lifecycleSortDirection: \"asc\" | \"desc\" for lifecycle rules — separate from objects sortDirection\n// - lifecycleSearch: search term for filtering lifecycle rules by Rule ID — separate from objects search\nconst objectsSearchSchema = z.object({\n prefix: z.string().optional(),\n sortBy: z.enum([\"name\", \"last_modified\", \"bytes\", \"lastModified\", \"size\"]).optional().default(\"name\"),\n sortDirection: z.enum([\"asc\", \"desc\"]).optional().default(\"asc\"),\n search: z.string().optional(),\n tab: z.enum([\"all\", \"deleted\"]).optional().default(\"all\"),\n view: z.enum([\"overview\", \"cors-rules\", \"lifecycle-rules\"]).optional().default(\"overview\"),\n corsSortBy: z\n .enum([\"ID\", \"AllowedOrigins\", \"AllowedMethods\", \"AllowedHeaders\", \"ExposeHeaders\", \"MaxAgeSeconds\"])\n .optional()\n .default(\"ID\"),\n corsSortDirection: z.enum([\"asc\", \"desc\"]).optional().default(\"asc\"),\n corsSearch: z.string().optional(),\n lifecycleSortBy: z.enum([\"ID\", \"Status\", \"Expiration\"]).optional().default(\"ID\"),\n lifecycleSortDirection: z.enum([\"asc\", \"desc\"]).optional().default(\"asc\"),\n lifecycleSearch: z.string().optional(),\n})\n\n/**\n * \"Back to Buckets\"/\"Back to Containers\" — the exit both boundaries below want. The list\n * is the one page that is certainly still there, so it beats `RouteIdLevelDefaultError`'s\n * default \"Go to Project Home\", which leaves storage altogether.\n *\n * Returns undefined when the params aren't readable, so the caller falls back to that\n * default rather than rendering a button that can't build a target.\n */\nfunction useBackToContainerList(): ReactNode {\n const { t } = useLingui()\n const navigate = useNavigate()\n const { projectId, provider, storageType } = useParams({ strict: false })\n\n if (!projectId || !provider || !storageType) return undefined\n\n return (\n <Button\n variant=\"primary\"\n onClick={() =>\n navigate({\n to: \"/projects/$projectId/storage/$provider/$storageType\",\n params: { projectId, provider, storageType },\n })\n }\n >\n {provider === STORAGE_PROVIDER.CEPH ? t`Back to Buckets` : t`Back to Containers`}\n </Button>\n )\n}\n\n/**\n * The route's single notFound boundary serves two unrelated 404s, so it dispatches on the\n * reason the throw carried:\n *\n * - the address is wrong (bad provider, non-canonical storage-type) → `StorageNotFound`,\n * whose action leads out of storage entirely, because no storage page here is valid;\n * - the address is fine but the container isn't there → `RouteIdLevelDefaultError`, whose\n * action leads back to the list, which is a page the user can actually use.\n *\n * (The router spreads the whole notFound error object into these props, so the reason\n * arrives nested under `data` — see StorageNotFound for the three files that establish it.)\n */\nfunction ObjectsNotFound({ data }: { data?: { reason?: StorageNotFoundReason | typeof CONTAINER_NOT_FOUND } }) {\n const { t } = useLingui()\n const { provider } = useParams({ strict: false })\n const backToList = useBackToContainerList()\n\n const reason = data?.reason\n\n if (reason !== CONTAINER_NOT_FOUND) {\n return <StorageNotFound data={reason ? { reason } : undefined} />\n }\n\n const isCeph = provider === STORAGE_PROVIDER.CEPH\n\n return (\n <RouteIdLevelDefaultError\n errorTitle={isCeph ? t`Bucket Not Found` : t`Container Not Found`}\n errorDescription={\n isCeph\n ? t`This bucket does not exist or is not accessible in this project.`\n : t`This container does not exist or is not accessible in this project.`\n }\n action={backToList}\n />\n )\n}\n\n/**\n * Route-level error boundary — for a request that failed, as opposed to a resource that\n * isn't there. Deliberately a boundary of its own: #1304 points one component at both, and\n * since that component hardcodes `code={404}` a 500 arrives labelled \"Resource Not Found\".\n * The split is in what the two say, not in which component they use — `code` is what lets\n * this one state the real status instead of inheriting that default.\n *\n * Catching here rather than letting it reach the root keeps everything the parent routes\n * render — shell, nav, the breadcrumb trail up to this page — on screen, and lets the\n * boundary reset when the user navigates.\n */\nfunction ObjectsError({ error }: ErrorComponentProps) {\n const { t } = useLingui()\n const backToList = useBackToContainerList()\n const trpcError = isTRPCClientError(error) ? error : undefined\n\n return (\n <RouteIdLevelDefaultError\n code={trpcError?.data?.httpStatus ?? null}\n errorTitle={t`Unable to Load Content`}\n errorDescription={trpcError?.message ?? t`An unexpected error occurred.`}\n action={backToList}\n />\n )\n}\n\nexport const Route = createFileRoute(\n \"/_auth/projects/$projectId/storage/$provider/$storageType/$containerName/objects/\"\n)({\n staticData: {\n section: \"storage\",\n service: \"containers\",\n analytics: {\n name: \"storage.objectstore.detail\",\n },\n } satisfies RouteInfo,\n validateSearch: objectsSearchSchema,\n head: ({ match }) => ({\n meta: [{ title: match.params.containerName }],\n }),\n component: () => {\n return <ObjectsDashboard />\n },\n notFoundComponent: ObjectsNotFound as NotFoundRouteComponent,\n errorComponent: ObjectsError,\n loader: async ({ context, params }) => {\n const { trpcClient } = context\n if (!trpcClient) {\n throw new Error(\"trpcClient is not available in route context\")\n }\n const availableServices = (await trpcClient.auth.getAvailableServices.query()) ?? []\n const provider = guardStorageRoute(availableServices, params)\n return requireContainerExists(trpcClient, { ...params, provider })\n },\n})\n\nexport function ObjectsDashboard() {\n const { projectId, provider, containerName } = useParams({\n from: \"/_auth/projects/$projectId/storage/$provider/$storageType/$containerName/objects/\",\n select: (params) => ({\n projectId: params.projectId,\n provider: params.provider,\n containerName: params.containerName,\n }),\n })\n\n useSetBreadcrumb(Route.id, containerName)\n\n const { prefix, sortBy, sortDirection, search, view } = Route.useSearch()\n\n return (\n <>\n {provider === STORAGE_PROVIDER.CEPH && <BucketHeader bucketName={containerName} />}\n {provider === STORAGE_PROVIDER.SWIFT && <ContainerHeader containerName={containerName} />}\n {/* Ceph gets extra breathing room below its header from BucketHeader's own\n tabs block; Swift has no such block, so pad the content wrapper directly\n to avoid the overflow menu sitting too close to the toolbar below it. */}\n <div className={provider === STORAGE_PROVIDER.SWIFT ? \"pt-4\" : undefined}>\n {projectId ? (\n <ErrorBoundary\n resetKeys={[projectId, provider, containerName, prefix, sortBy, sortDirection, search, view]}\n fallback={\n <div className=\"p-4 text-center\">\n <Trans>Error loading component</Trans>\n </div>\n }\n >\n {(() => {\n switch (provider) {\n case STORAGE_PROVIDER.SWIFT:\n return <SwiftObjects provider={provider} containerName={containerName} />\n case STORAGE_PROVIDER.CEPH:\n if (view === \"lifecycle-rules\") {\n return <CephLifecycleRules bucketName={containerName} />\n }\n if (view === \"cors-rules\") {\n return <CephCorsRules bucketName={containerName} />\n }\n return <CephObjects bucketName={containerName} />\n default:\n return (\n <div className=\"p-4\">\n <Trans>Objects: {containerName}</Trans>\n </div>\n )\n }\n })()}\n </ErrorBoundary>\n ) : (\n <div className=\"p-4 text-center\">\n <Trans>No project selected</Trans>\n </div>\n )}\n </div>\n </>\n )\n}\n"],"mappings":";;;;;;;;;;;AAuIA,SAASc,EAAa,EAAEC,YAA4B;CAClD,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQV,EAAAA,GACRa,IAAaC,EAAAA,GACbC,IAAYnB,EAAkBc,CAAAA,IAASA,IAAQM,KAAAA;CAErD,OACE,gBAAC,GAAA;EACC,MAAMD,GAAWE,MAAMC,cAAc;EACrC,YAAYN,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA;EACb,kBAAkBG,GAAWI,WAAWP,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA;EACzC,QAAQC;;AAGd;AAgCA,SAAgBQ,IAAAA;CACd,IAAM,EAAEC,cAAWC,aAAUC,qBAAkB7B,EAAU;EACvD8B,MAAM;EACNC,SAASC,OAAY;GACnBL,WAAWK,EAAOL;GAClBC,UAAUI,EAAOJ;GACjBC,eAAeG,EAAOH;EACxB;CACF,CAAA;CAEAjB,EAAiBa,EAAMQ,IAAIJ,CAAAA;CAE3B,IAAM,EAAEK,WAAQC,WAAQC,kBAAeC,WAAQC,YAASb,EAAMc,UAAS;CAEvE,OACE,gBAAA,GAAA,EAAA,UAAA;EACGX,MAAaf,EAAiB2B,QAAQ,gBAAC,GAAA,EAAa,YAAYX,EAAAA,CAAAA;EAChED,MAAaf,EAAiB4B,SAAS,gBAAC,GAAA,EAA+BZ,iBAAAA,CAAAA;EAIxE,gBAAC,OAAA;GAAI,WAAWD,MAAaf,EAAiB4B,QAAQ,SAASpB,KAAAA;GAC5DM,UAAAA,IACC,gBAAC,GAAA;IACC,WAAW;KAACA;KAAWC;KAAUC;KAAeK;KAAQC;KAAQC;KAAeC;KAAQC;IAAK;IAC5F,UACE,gBAAC,OAAA;KAAI,WAAU;KACb,UAAA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;IAIH,iBAAC;KACA,QAAQV,GAAR;MACE,KAAKf,EAAiB4B,OACpB,OAAO,gBAAC,GAAA;OAAuBb;OAAyBC;;MAC1D,KAAKhB,EAAiB2B,MAOpB,OALS,EADLF,MAAS,oBACH,IAENA,MAAS,eACH,IAEF,GALE,EAAmB,YAAYT,EAAAA,CAAAA;MAM3C,SACE,OACE,gBAAC,OAAA;OAAI,WAAU;OACb,UAAA,gBAAA,GAAA;;QAAiBA,QAAAA,EAAAA,iBAAAA;;;KAGzB;IACF,EAAA,CAAA;GAGF,CAAA,IAAA,gBAAC,OAAA;IAAI,WAAU;IACb,UAAA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;;;AAMZ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projects-yiK0HGSA.mjs","names":["ProjectsContentProps","
|
|
1
|
+
{"version":3,"file":"projects-yiK0HGSA.mjs","names":["ProjectsContentProps","searchTerm","SplitNotFoundComponent","notFoundComponent"],"sources":["../../src/client/routes/_auth/projects/index.tsx?tsr-split=notFoundComponent"],"sourcesContent":["import { Suspense } from \"react\"\nimport { ErrorBoundary } from \"react-error-boundary\"\nimport { createFileRoute, useRouteContext } from \"@tanstack/react-router\"\nimport { ProjectsOverviewNavBar } from \"@/client/routes/_auth/projects/-components/ProjectOverviewNavBar\"\nimport { ProjectCardView } from \"@/client/routes/_auth/projects/-components/ProjectCardView\"\nimport { RouteError } from \"@/client/components/Errors/RouteError\"\nimport { TRPCClientError } from \"@trpc/client\"\nimport { Container, ContentHeading, Status } from \"@cloudoperators/juno-ui-components\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { z } from \"zod\"\nimport { Slot } from \"@/client/components/Slot\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\n\nconst searchSchema = z.object({\n search: z.string().optional(),\n})\n\nexport const Route = createFileRoute(\"/_auth/projects/\")({\n staticData: {\n analytics: {\n name: \"projects.list\",\n },\n } satisfies RouteInfo,\n component: ProjectsOverview,\n notFoundComponent: () => {\n return <p>Projects not found</p>\n },\n validateSearch: searchSchema,\n})\n\ninterface ProjectsContentProps {\n searchTerm: string\n}\n\nfunction ProjectsContent({ searchTerm }: ProjectsContentProps) {\n const [projects] = trpcReact.project.listProjectsWithSearch.useSuspenseQuery({\n searchTerm: searchTerm.trim() || undefined,\n })\n\n return <ProjectCardView projects={projects} />\n}\n\nexport function ProjectsOverview() {\n const { search = \"\" } = Route.useSearch()\n const navigate = Route.useNavigate()\n const { slots } = useRouteContext({ strict: false })\n const { t } = useLingui()\n\n const handleSearch = (value: string) => {\n navigate({ search: (prev) => ({ ...prev, search: value || undefined }), replace: true })\n }\n\n return (\n <Container py>\n <ContentHeading className=\"pb-4\">\n <Trans>Projects</Trans>\n </ContentHeading>\n {slots?.projectsBanner && (\n <ErrorBoundary fallbackRender={() => null}>\n <Suspense fallback={null}>\n <Slot component={slots.projectsBanner} useShadowDOM={false} />\n </Suspense>\n </ErrorBoundary>\n )}\n <ErrorBoundary\n fallbackRender={({ error }) => (\n <RouteError error={error} safeErrorMessage={error instanceof TRPCClientError ? error.message : undefined} />\n )}\n >\n <ProjectsOverviewNavBar searchTerm={search} onSearch={handleSearch} />\n <div className=\"pt-5\">\n <Suspense fallback={<Status status=\"progress\" title={t`Loading...`} />}>\n <ProjectsContent searchTerm={search} />\n </Suspense>\n </div>\n </ErrorBoundary>\n </Container>\n )\n}\n"],"mappings":";;AAiCC,IAAAE,UAPU,gBAAC,KAAA,EAAE,UAAA,qBAAA,CAAA"}
|
|
@@ -7,9 +7,9 @@ var r = e("/_auth/projects/$projectId/network/securitygroups/")({
|
|
|
7
7
|
analytics: { name: "network.securitygroups.list" }
|
|
8
8
|
},
|
|
9
9
|
head: () => ({ meta: [{ title: n._({ id: "4opp4r" }) }] }),
|
|
10
|
-
component: t(() => import("./securitygroups-
|
|
10
|
+
component: t(() => import("./securitygroups-DXrfyuVF.mjs"), "component")
|
|
11
11
|
});
|
|
12
12
|
//#endregion
|
|
13
13
|
export { r as t };
|
|
14
14
|
|
|
15
|
-
//# sourceMappingURL=securitygroups-
|
|
15
|
+
//# sourceMappingURL=securitygroups-67fFxiwt.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"securitygroups-
|
|
1
|
+
{"version":3,"file":"securitygroups-67fFxiwt.mjs","names":["createFileRoute","t","Route","staticData","section","service","analytics","name","RouteInfo","head","meta","title","component","lazyRouteComponent","$$splitComponentImporter"],"sources":["../../src/client/routes/_auth/projects/$projectId/network/securitygroups/index.tsx"],"sourcesContent":["import { createFileRoute } from \"@tanstack/react-router\"\nimport { t } from \"@lingui/core/macro\"\nimport { SecurityGroups } from \"./-components/SecurityGroupsList\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/network/securitygroups/\")({\n staticData: {\n section: \"network\",\n service: \"securitygroups\",\n analytics: {\n name: \"network.securitygroups.list\",\n },\n } satisfies RouteInfo,\n head: () => ({ meta: [{ title: t`Security Groups` }] }),\n component: RouteComponent,\n})\n\nfunction RouteComponent() {\n const { projectId } = Route.useParams()\n const { trpcClient } = Route.useRouteContext()\n\n if (!trpcClient) {\n throw new Error(\"trpcClient is not available in route context\")\n }\n\n return <SecurityGroups project={projectId} />\n}\n"],"mappings":";;AAKA,IAAaE,IAAQF,EAAgB,oDAAA,CAAA,CAAsD;CACzFG,YAAY;EACVC,SAAS;EACTC,SAAS;EACTC,WAAW,EACTC,MAAM,8BACR;CACF;CACAE,aAAa,EAAEC,MAAM,CAAC,EAAEC,OAAOV,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA,EAAkB,CAAC,EAAE;CACrDW,WAASC,iDAAA,WAAA;AACX,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"securitygroups-CtKne8UQ.mjs","names":["Outlet","SplitComponent","component"],"sources":["../../src/client/routes/_auth/projects/$projectId/network/securitygroups.tsx?tsr-split=component"],"sourcesContent":["import { createFileRoute, Outlet } from \"@tanstack/react-router\"\nimport { msg } from \"@lingui/core/macro\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/network/securitygroups\")({\n staticData: {\n section: \"network\",\n service: \"securitygroups\",\n crumb: { text: msg`Security Groups` },\n } satisfies RouteInfo,\n component: () => <Outlet />,\n})\n"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"securitygroups-CtKne8UQ.mjs","names":["Outlet","SplitComponent","component"],"sources":["../../src/client/routes/_auth/projects/$projectId/network/securitygroups.tsx?tsr-split=component"],"sourcesContent":["import { createFileRoute, Outlet, useNavigate } from \"@tanstack/react-router\"\nimport { RouteIdLevelDefaultError } from \"@/client/components/Errors/RouteIdLevelDefaultError\"\nimport { Button } from \"@cloudoperators/juno-ui-components\"\nimport { msg } from \"@lingui/core/macro\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\n\nconst SecurityGroupsErrorComponent = () => {\n const { t } = useLingui()\n const navigate = useNavigate()\n const { projectId } = Route.useParams()\n\n return (\n <RouteIdLevelDefaultError\n action={\n <Button\n variant=\"primary\"\n onClick={() => navigate({ to: \"/projects/$projectId/network/securitygroups\", params: { projectId } })}\n >\n {t`Back to Security Groups`}\n </Button>\n }\n />\n )\n}\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/network/securitygroups\")({\n staticData: {\n section: \"network\",\n service: \"securitygroups\",\n crumb: { text: msg`Security Groups` },\n } satisfies RouteInfo,\n component: () => <Outlet />,\n // Render errors from the security groups subtree inside the project layout\n // (side navigation, header, breadcrumbs) instead of the full-screen route error.\n errorComponent: SecurityGroupsErrorComponent,\n})\n"],"mappings":";;;AAA6E,IAAAC,UAgC1D,gBAAC,GAAA,CAAA,CAAA"}
|