@cobaltcore-dev/aurora 0.23.0 → 0.23.1
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/{BucketToastNotifications-BhPi4WWw.mjs → BucketToastNotifications-Dq4dudkM.mjs} +222 -170
- package/dist/client/BucketToastNotifications-Dq4dudkM.mjs.map +1 -0
- package/dist/client/{_storageType-BKfQcpgp.mjs → _storageType-Cn7TSOki.mjs} +2 -2
- package/dist/client/{_storageType-BKfQcpgp.mjs.map → _storageType-Cn7TSOki.mjs.map} +1 -1
- package/dist/client/{_storageType-sMj9NEJz.mjs → _storageType-_8Ambhxc.mjs} +828 -839
- package/dist/client/_storageType-_8Ambhxc.mjs.map +1 -0
- package/dist/client/hooks/useAvailableViewportHeight.d.ts +30 -0
- package/dist/client/hooks/useVirtualizedTableBody.d.ts +39 -0
- package/dist/client/index.js +3 -3
- package/dist/client/index.js.map +1 -1
- package/dist/client/{objects-BG1saVLZ.mjs → objects-B3mbk6V0.mjs} +852 -864
- package/dist/client/objects-B3mbk6V0.mjs.map +1 -0
- package/dist/client/{objects-Dahys529.mjs → objects-BQ8xvSW8.mjs} +2 -2
- package/dist/client/{objects-Dahys529.mjs.map → objects-BQ8xvSW8.mjs.map} +1 -1
- package/package.json +4 -4
- package/dist/client/BucketToastNotifications-BhPi4WWw.mjs.map +0 -1
- package/dist/client/_storageType-sMj9NEJz.mjs.map +0 -1
- package/dist/client/objects-BG1saVLZ.mjs.map +0 -1
|
@@ -57,7 +57,7 @@ var a = (t, n) => {
|
|
|
57
57
|
}
|
|
58
58
|
});
|
|
59
59
|
}
|
|
60
|
-
}, o = () => import("./objects-o2Cj_ndZ.mjs"), s = () => import("./objects-
|
|
60
|
+
}, o = () => import("./objects-o2Cj_ndZ.mjs"), s = () => import("./objects-B3mbk6V0.mjs"), c = i.object({
|
|
61
61
|
prefix: i.string().optional(),
|
|
62
62
|
sortBy: i.enum([
|
|
63
63
|
"name",
|
|
@@ -100,4 +100,4 @@ var a = (t, n) => {
|
|
|
100
100
|
//#endregion
|
|
101
101
|
export { l as t };
|
|
102
102
|
|
|
103
|
-
//# sourceMappingURL=objects-
|
|
103
|
+
//# sourceMappingURL=objects-BQ8xvSW8.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"objects-Dahys529.mjs","names":["redirect","getServiceIndex","checkServiceAvailability","availableServices","params","provider","projectId","storageType","containerName","serviceIndex","to","hasSwift","Boolean","hasCeph","cephFallbackEnabled","hasEffectiveCeph","fallbackProvider","fallbackStorageType","expectedStorageType","createFileRoute","checkServiceAvailability","z","objectsSearchSchema","object","prefix","string","optional","sortBy","enum","default","sortDirection","search","tab","Route","staticData","section","service","analytics","name","isDetail","sectionCrumb","labelKey","crumb","useParamAsLabel","to","RouteInfo","validateSearch","head","match","meta","title","params","containerName","component","lazyRouteComponent","$$splitComponentImporter","notFoundComponent","$$splitNotFoundComponentImporter","loader","context","trpcClient","availableServices","auth","getAvailableServices","query","client","beforeLoad"],"sources":["../../src/client/routes/_auth/projects/$projectId/storage/-components/utils/serviceAvailability.ts","../../src/client/routes/_auth/projects/$projectId/storage/$provider/$storageType/$containerName/objects/index.tsx"],"sourcesContent":["import { redirect } from \"@tanstack/react-router\"\nimport { getServiceIndex } from \"@/server/Authentication/helpers\"\n\ninterface ServiceInfo {\n type: string\n name: string\n}\n\ninterface RouteParams {\n projectId: string\n provider: string\n storageType: string\n containerName: string\n}\n\n/**\n * Validates storage service availability and redirects to appropriate provider/storage type.\n *\n * Redirect logic:\n * 1. If no object-store services available → redirect to project overview\n * 2. If provider is invalid → redirect to fallback provider (swift → ceph)\n * 3. If provider unavailable → redirect to available alternative\n * 4. If storageType doesn't match provider → canonicalize URL\n *\n * @throws redirect - TanStack Router redirect on validation failure\n */\nexport const checkServiceAvailability = (availableServices: ServiceInfo[], params: RouteParams) => {\n const { provider, projectId, storageType, containerName } = params\n\n const serviceIndex = getServiceIndex(availableServices)\n\n // Redirect to the \"Projects Overview\" page if no storage services available\n if (!serviceIndex[\"object-store\"]) {\n throw redirect({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n\n // Check provider availability\n const hasSwift = Boolean(serviceIndex[\"object-store\"][\"swift\"])\n const hasCeph = Boolean(serviceIndex[\"object-store\"][\"ceph\"])\n\n // TEMPORARY: Allow Ceph access even if not in catalog (relies on env config)\n // TODO: Properly register Ceph in OpenStack service catalog\n const cephFallbackEnabled = true // Set to false once Ceph is in catalog\n\n // Effective availability includes fallback flag for Ceph\n const hasEffectiveCeph = hasCeph || cephFallbackEnabled\n const fallbackProvider = hasSwift ? \"swift\" : hasEffectiveCeph ? \"ceph\" : null\n const fallbackStorageType = hasSwift ? \"containers\" : hasEffectiveCeph ? \"buckets\" : null\n\n if (provider !== \"swift\" && provider !== \"ceph\") {\n if (!fallbackProvider || !fallbackStorageType) {\n throw redirect({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n throw redirect({\n to: \"/projects/$projectId/storage/$provider/$storageType/$containerName/objects\",\n params: { projectId, provider: fallbackProvider, storageType: fallbackStorageType, containerName },\n })\n }\n\n if (provider === \"swift\" && !hasSwift) {\n if (!hasEffectiveCeph) {\n throw redirect({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n\n throw redirect({\n to: \"/projects/$projectId/storage/$provider/$storageType/$containerName/objects\",\n params: { projectId, provider: \"ceph\", storageType: \"buckets\", containerName },\n })\n }\n\n if (provider === \"ceph\" && !hasEffectiveCeph) {\n if (!hasSwift) {\n throw redirect({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n\n throw redirect({\n to: \"/projects/$projectId/storage/$provider/$storageType/$containerName/objects\",\n params: { projectId, provider: \"swift\", storageType: \"containers\", containerName },\n })\n }\n\n // Canonicalize the URL terminology for the resolved provider. Availability is\n // already settled above, so by this point provider is a valid, available\n // swift|ceph. The storageType segment is user-controllable and the router never\n // validates it, so a mismatched noun (e.g. ceph + \"containers\", swift + \"buckets\")\n // must redirect to the canonical path to keep URLs normalized.\n if (provider === \"swift\" || provider === \"ceph\") {\n const expectedStorageType = provider === \"swift\" ? \"containers\" : \"buckets\"\n if (storageType !== expectedStorageType) {\n throw redirect({\n to: \"/projects/$projectId/storage/$provider/$storageType/$containerName/objects\",\n params: { projectId, provider, storageType: expectedStorageType, containerName },\n })\n }\n }\n}\n","import { createFileRoute, useParams } from \"@tanstack/react-router\"\nimport { checkServiceAvailability } from \"../../../../-components/utils/serviceAvailability\"\nimport { ErrorBoundary } from \"react-error-boundary\"\nimport { Trans } from \"@lingui/react/macro\"\nimport { SwiftObjects } from \"../../../../-components/Swift/Objects\"\nimport { CephObjects } from \"../../../../-components/Ceph/Objects\"\nimport { z } from \"zod\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { BucketHeader } from \"../../../../-components/Ceph/Buckets/BucketHeader\"\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\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})\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 isDetail: true,\n sectionCrumb: { labelKey: \"Storage\" },\n crumb: { useParamAsLabel: \"provider\", to: \"/projects/$projectId/storage/$provider/$storageType\" },\n } satisfies RouteInfo,\n validateSearch: objectsSearchSchema,\n head: ({ match }) => ({\n meta: [{ title: match.params.containerName }],\n }),\n component: () => {\n return <ObjectsDashboard />\n },\n notFoundComponent: () => {\n return (\n <p>\n <Trans>Storage container not found</Trans>\n </p>\n )\n },\n loader: async ({ context }) => {\n const { trpcClient } = context\n const availableServices = await trpcClient?.auth.getAvailableServices.query()\n\n return {\n client: trpcClient,\n availableServices,\n }\n },\n beforeLoad: async ({ context, params }) => {\n const { trpcClient } = context\n const availableServices = await trpcClient?.auth.getAvailableServices.query()\n checkServiceAvailability(availableServices!, params)\n },\n})\n\nfunction 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 const { prefix, sortBy, sortDirection, search } = Route.useSearch()\n\n // For Ceph buckets, we show ContentHeader with badges and actions\n // For Swift containers, the component handles its own header\n const showContentHeader = provider === \"ceph\"\n\n return (\n <>\n {showContentHeader && <BucketHeader bucketName={containerName} />}\n <div>\n {projectId ? (\n <ErrorBoundary\n resetKeys={[projectId, provider, containerName, prefix, sortBy, sortDirection, search]}\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 \"swift\":\n return <SwiftObjects provider={provider} containerName={containerName} />\n case \"ceph\":\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":";;;;AA0BA,IAAaE,KAA4BC,GAAkCC,MAAAA;CACzE,IAAM,EAAEC,aAAUC,cAAWC,gBAAaC,qBAAkBJ,GAEtDK,IAAeR,EAAgBE,CAAAA;CAGrC,IAAI,CAACM,EAAa,iBAChB,MAAMT,EAAS;EACbU,IAAI;EACJN,QAAQ,EAAEE,aAAU;CACtB,CAAA;CAIF,IAAMK,IAAWC,EAAQH,EAAa,gBAAgB,OAQhDM,IAPUH,EAAQH,EAAa,gBAAgB,QAOjBK,IAC9BE,IAAmBL,IAAW,UAAUI,IAAmB,SAAS,MACpEE,IAAsBN,IAAW,eAAeI,IAAmB,YAAY;CAErF,IAAIV,MAAa,WAAWA,MAAa,QAOvC,MALQL,EADJ,CAACgB,KAAoB,CAACC,IACT;EACbP,IAAI;EACJN,QAAQ,EAAEE,aAAU;CACtB,IAEa;EACbI,IAAI;EACJN,QAAQ;GAAEE;GAAWD,UAAUW;GAAkBT,aAAaU;GAAqBT;EAAc;CACnG,CALE;CAQJ,IAAIH,MAAa,WAAW,CAACM,GAQ3B,MAAMX,EAPDe,IAOU;EACbL,IAAI;EACJN,QAAQ;GAAEE;GAAWD,UAAU;GAAQE,aAAa;GAAWC;EAAc;CAC/E,IATiB;EACbE,IAAI;EACJN,QAAQ,EAAEE,aAAU;CACtB,CAAA;CASJ,IAAID,MAAa,UAAU,CAACU,GAQ1B,MAAMf,EAPDW,IAOU;EACbD,IAAI;EACJN,QAAQ;GAAEE;GAAWD,UAAU;GAASE,aAAa;GAAcC;EAAc;CACnF,IATiB;EACbE,IAAI;EACJN,QAAQ,EAAEE,aAAU;CACtB,CAAA;CAcJ,IAAID,MAAa,WAAWA,MAAa,QAAQ;EAC/C,IAAMa,IAAsBb,MAAa,UAAU,eAAe;EAClE,IAAIE,MAAgBW,GAClB,MAAMlB,EAAS;GACbU,IAAI;GACJN,QAAQ;IAAEE;IAAWD;IAAUE,aAAaW;IAAqBV;GAAc;EACjF,CAAA;CAEJ;AACF,2FC5FMc,IAAsBD,EAAEE,OAAO;CACnCC,QAAQH,EAAEI,OAAM,EAAGC,SAAQ;CAC3BC,QAAQN,EAAEO,KAAK;EAAC;EAAQ;EAAiB;EAAS;EAAgB;EAAO,EAAEF,SAAQ,EAAGG,QAAQ,MAAA;CAC9FC,eAAeT,EAAEO,KAAK,CAAC,OAAO,MAAA,CAAO,EAAEF,SAAQ,EAAGG,QAAQ,KAAA;CAC1DE,QAAQV,EAAEI,OAAM,EAAGC,SAAQ;CAC3BM,KAAKX,EAAEO,KAAK,CAAC,OAAO,SAAA,CAAU,EAAEF,SAAQ,EAAGG,QAAQ,KAAA;AACrD,CAAA,GAEaI,IAAQd,EACnB,mFAAA,EACA;CACAe,YAAY;EACVC,SAAS;EACTC,SAAS;EACTC,WAAW,EACTC,MAAM,6BACR;EACAC,UAAU;EACVC,cAAc,EAAEC,UAAU,UAAU;EACpCC,OAAO;GAAEC,iBAAiB;GAAYC,IAAI;EAAsD;CAClG;CACAE,gBAAgBxB;CAChByB,OAAO,EAAEC,gBAAa,EACpBC,MAAM,CAAC,EAAEC,OAAOF,EAAMG,OAAOC,cAAc,CAAA,EAC7C;CACAC,WAASC,EAAAC,GAAA,WAAA;CAGTC,mBAAiBF,EAAAG,GAAA,mBAAA;CAOjBC,QAAQ,OAAO,EAAEC,iBAAS;EACxB,IAAM,EAAEC,kBAAeD;EAGvB,OAAO;GACLM,QAAQL;GACRC,mBAAAA,MAJ8BD,GAAYE,KAAKC,qBAAqBC,MAAAA;EAKtE;CACF;CACAE,YAAY,OAAO,EAAEP,YAASR,gBAAQ;EACpC,IAAM,EAAES,kBAAeD;EAEvBvC,EAAyByC,MADOD,GAAYE,KAAKC,qBAAqBC,MAAAA,GACzBb,CAAAA;CAC/C;AACF,CAAA"}
|
|
1
|
+
{"version":3,"file":"objects-BQ8xvSW8.mjs","names":["redirect","getServiceIndex","checkServiceAvailability","availableServices","params","provider","projectId","storageType","containerName","serviceIndex","to","hasSwift","Boolean","hasCeph","cephFallbackEnabled","hasEffectiveCeph","fallbackProvider","fallbackStorageType","expectedStorageType","createFileRoute","checkServiceAvailability","z","objectsSearchSchema","object","prefix","string","optional","sortBy","enum","default","sortDirection","search","tab","Route","staticData","section","service","analytics","name","isDetail","sectionCrumb","labelKey","crumb","useParamAsLabel","to","RouteInfo","validateSearch","head","match","meta","title","params","containerName","component","lazyRouteComponent","$$splitComponentImporter","notFoundComponent","$$splitNotFoundComponentImporter","loader","context","trpcClient","availableServices","auth","getAvailableServices","query","client","beforeLoad"],"sources":["../../src/client/routes/_auth/projects/$projectId/storage/-components/utils/serviceAvailability.ts","../../src/client/routes/_auth/projects/$projectId/storage/$provider/$storageType/$containerName/objects/index.tsx"],"sourcesContent":["import { redirect } from \"@tanstack/react-router\"\nimport { getServiceIndex } from \"@/server/Authentication/helpers\"\n\ninterface ServiceInfo {\n type: string\n name: string\n}\n\ninterface RouteParams {\n projectId: string\n provider: string\n storageType: string\n containerName: string\n}\n\n/**\n * Validates storage service availability and redirects to appropriate provider/storage type.\n *\n * Redirect logic:\n * 1. If no object-store services available → redirect to project overview\n * 2. If provider is invalid → redirect to fallback provider (swift → ceph)\n * 3. If provider unavailable → redirect to available alternative\n * 4. If storageType doesn't match provider → canonicalize URL\n *\n * @throws redirect - TanStack Router redirect on validation failure\n */\nexport const checkServiceAvailability = (availableServices: ServiceInfo[], params: RouteParams) => {\n const { provider, projectId, storageType, containerName } = params\n\n const serviceIndex = getServiceIndex(availableServices)\n\n // Redirect to the \"Projects Overview\" page if no storage services available\n if (!serviceIndex[\"object-store\"]) {\n throw redirect({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n\n // Check provider availability\n const hasSwift = Boolean(serviceIndex[\"object-store\"][\"swift\"])\n const hasCeph = Boolean(serviceIndex[\"object-store\"][\"ceph\"])\n\n // TEMPORARY: Allow Ceph access even if not in catalog (relies on env config)\n // TODO: Properly register Ceph in OpenStack service catalog\n const cephFallbackEnabled = true // Set to false once Ceph is in catalog\n\n // Effective availability includes fallback flag for Ceph\n const hasEffectiveCeph = hasCeph || cephFallbackEnabled\n const fallbackProvider = hasSwift ? \"swift\" : hasEffectiveCeph ? \"ceph\" : null\n const fallbackStorageType = hasSwift ? \"containers\" : hasEffectiveCeph ? \"buckets\" : null\n\n if (provider !== \"swift\" && provider !== \"ceph\") {\n if (!fallbackProvider || !fallbackStorageType) {\n throw redirect({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n throw redirect({\n to: \"/projects/$projectId/storage/$provider/$storageType/$containerName/objects\",\n params: { projectId, provider: fallbackProvider, storageType: fallbackStorageType, containerName },\n })\n }\n\n if (provider === \"swift\" && !hasSwift) {\n if (!hasEffectiveCeph) {\n throw redirect({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n\n throw redirect({\n to: \"/projects/$projectId/storage/$provider/$storageType/$containerName/objects\",\n params: { projectId, provider: \"ceph\", storageType: \"buckets\", containerName },\n })\n }\n\n if (provider === \"ceph\" && !hasEffectiveCeph) {\n if (!hasSwift) {\n throw redirect({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n\n throw redirect({\n to: \"/projects/$projectId/storage/$provider/$storageType/$containerName/objects\",\n params: { projectId, provider: \"swift\", storageType: \"containers\", containerName },\n })\n }\n\n // Canonicalize the URL terminology for the resolved provider. Availability is\n // already settled above, so by this point provider is a valid, available\n // swift|ceph. The storageType segment is user-controllable and the router never\n // validates it, so a mismatched noun (e.g. ceph + \"containers\", swift + \"buckets\")\n // must redirect to the canonical path to keep URLs normalized.\n if (provider === \"swift\" || provider === \"ceph\") {\n const expectedStorageType = provider === \"swift\" ? \"containers\" : \"buckets\"\n if (storageType !== expectedStorageType) {\n throw redirect({\n to: \"/projects/$projectId/storage/$provider/$storageType/$containerName/objects\",\n params: { projectId, provider, storageType: expectedStorageType, containerName },\n })\n }\n }\n}\n","import { createFileRoute, useParams } from \"@tanstack/react-router\"\nimport { checkServiceAvailability } from \"../../../../-components/utils/serviceAvailability\"\nimport { ErrorBoundary } from \"react-error-boundary\"\nimport { Trans } from \"@lingui/react/macro\"\nimport { SwiftObjects } from \"../../../../-components/Swift/Objects\"\nimport { CephObjects } from \"../../../../-components/Ceph/Objects\"\nimport { z } from \"zod\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { BucketHeader } from \"../../../../-components/Ceph/Buckets/BucketHeader\"\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\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})\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 isDetail: true,\n sectionCrumb: { labelKey: \"Storage\" },\n crumb: { useParamAsLabel: \"provider\", to: \"/projects/$projectId/storage/$provider/$storageType\" },\n } satisfies RouteInfo,\n validateSearch: objectsSearchSchema,\n head: ({ match }) => ({\n meta: [{ title: match.params.containerName }],\n }),\n component: () => {\n return <ObjectsDashboard />\n },\n notFoundComponent: () => {\n return (\n <p>\n <Trans>Storage container not found</Trans>\n </p>\n )\n },\n loader: async ({ context }) => {\n const { trpcClient } = context\n const availableServices = await trpcClient?.auth.getAvailableServices.query()\n\n return {\n client: trpcClient,\n availableServices,\n }\n },\n beforeLoad: async ({ context, params }) => {\n const { trpcClient } = context\n const availableServices = await trpcClient?.auth.getAvailableServices.query()\n checkServiceAvailability(availableServices!, params)\n },\n})\n\nfunction 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 const { prefix, sortBy, sortDirection, search } = Route.useSearch()\n\n // For Ceph buckets, we show ContentHeader with badges and actions\n // For Swift containers, the component handles its own header\n const showContentHeader = provider === \"ceph\"\n\n return (\n <>\n {showContentHeader && <BucketHeader bucketName={containerName} />}\n <div>\n {projectId ? (\n <ErrorBoundary\n resetKeys={[projectId, provider, containerName, prefix, sortBy, sortDirection, search]}\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 \"swift\":\n return <SwiftObjects provider={provider} containerName={containerName} />\n case \"ceph\":\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":";;;;AA0BA,IAAaE,KAA4BC,GAAkCC,MAAAA;CACzE,IAAM,EAAEC,aAAUC,cAAWC,gBAAaC,qBAAkBJ,GAEtDK,IAAeR,EAAgBE,CAAAA;CAGrC,IAAI,CAACM,EAAa,iBAChB,MAAMT,EAAS;EACbU,IAAI;EACJN,QAAQ,EAAEE,aAAU;CACtB,CAAA;CAIF,IAAMK,IAAWC,EAAQH,EAAa,gBAAgB,OAQhDM,IAPUH,EAAQH,EAAa,gBAAgB,QAOjBK,IAC9BE,IAAmBL,IAAW,UAAUI,IAAmB,SAAS,MACpEE,IAAsBN,IAAW,eAAeI,IAAmB,YAAY;CAErF,IAAIV,MAAa,WAAWA,MAAa,QAOvC,MALQL,EADJ,CAACgB,KAAoB,CAACC,IACT;EACbP,IAAI;EACJN,QAAQ,EAAEE,aAAU;CACtB,IAEa;EACbI,IAAI;EACJN,QAAQ;GAAEE;GAAWD,UAAUW;GAAkBT,aAAaU;GAAqBT;EAAc;CACnG,CALE;CAQJ,IAAIH,MAAa,WAAW,CAACM,GAQ3B,MAAMX,EAPDe,IAOU;EACbL,IAAI;EACJN,QAAQ;GAAEE;GAAWD,UAAU;GAAQE,aAAa;GAAWC;EAAc;CAC/E,IATiB;EACbE,IAAI;EACJN,QAAQ,EAAEE,aAAU;CACtB,CAAA;CASJ,IAAID,MAAa,UAAU,CAACU,GAQ1B,MAAMf,EAPDW,IAOU;EACbD,IAAI;EACJN,QAAQ;GAAEE;GAAWD,UAAU;GAASE,aAAa;GAAcC;EAAc;CACnF,IATiB;EACbE,IAAI;EACJN,QAAQ,EAAEE,aAAU;CACtB,CAAA;CAcJ,IAAID,MAAa,WAAWA,MAAa,QAAQ;EAC/C,IAAMa,IAAsBb,MAAa,UAAU,eAAe;EAClE,IAAIE,MAAgBW,GAClB,MAAMlB,EAAS;GACbU,IAAI;GACJN,QAAQ;IAAEE;IAAWD;IAAUE,aAAaW;IAAqBV;GAAc;EACjF,CAAA;CAEJ;AACF,2FC5FMc,IAAsBD,EAAEE,OAAO;CACnCC,QAAQH,EAAEI,OAAM,EAAGC,SAAQ;CAC3BC,QAAQN,EAAEO,KAAK;EAAC;EAAQ;EAAiB;EAAS;EAAgB;EAAO,EAAEF,SAAQ,EAAGG,QAAQ,MAAA;CAC9FC,eAAeT,EAAEO,KAAK,CAAC,OAAO,MAAA,CAAO,EAAEF,SAAQ,EAAGG,QAAQ,KAAA;CAC1DE,QAAQV,EAAEI,OAAM,EAAGC,SAAQ;CAC3BM,KAAKX,EAAEO,KAAK,CAAC,OAAO,SAAA,CAAU,EAAEF,SAAQ,EAAGG,QAAQ,KAAA;AACrD,CAAA,GAEaI,IAAQd,EACnB,mFAAA,EACA;CACAe,YAAY;EACVC,SAAS;EACTC,SAAS;EACTC,WAAW,EACTC,MAAM,6BACR;EACAC,UAAU;EACVC,cAAc,EAAEC,UAAU,UAAU;EACpCC,OAAO;GAAEC,iBAAiB;GAAYC,IAAI;EAAsD;CAClG;CACAE,gBAAgBxB;CAChByB,OAAO,EAAEC,gBAAa,EACpBC,MAAM,CAAC,EAAEC,OAAOF,EAAMG,OAAOC,cAAc,CAAA,EAC7C;CACAC,WAASC,EAAAC,GAAA,WAAA;CAGTC,mBAAiBF,EAAAG,GAAA,mBAAA;CAOjBC,QAAQ,OAAO,EAAEC,iBAAS;EACxB,IAAM,EAAEC,kBAAeD;EAGvB,OAAO;GACLM,QAAQL;GACRC,mBAAAA,MAJ8BD,GAAYE,KAAKC,qBAAqBC,MAAAA;EAKtE;CACF;CACAE,YAAY,OAAO,EAAEP,YAASR,gBAAQ;EACpC,IAAM,EAAES,kBAAeD;EAEvBvC,EAAyByC,MADOD,GAAYE,KAAKC,qBAAqBC,MAAAA,GACzBb,CAAAA;CAC/C;AACF,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cobaltcore-dev/aurora",
|
|
3
|
-
"version": "0.23.
|
|
3
|
+
"version": "0.23.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Aurora OpenStack dashboard — server and client library",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
"eslint-plugin-react-refresh": "^0.5.0",
|
|
95
95
|
"globals": "^17.4.0",
|
|
96
96
|
"jsdom": "^29.0.0",
|
|
97
|
-
"postcss": "^8.
|
|
97
|
+
"postcss": "^8.5.12",
|
|
98
98
|
"prettier": "^3.4.2",
|
|
99
99
|
"tailwindcss": "^4.1.7",
|
|
100
100
|
"tsc-alias": "^1.8.16",
|
|
@@ -107,9 +107,9 @@
|
|
|
107
107
|
"vite-plugin-svgr": "^5.0.0",
|
|
108
108
|
"vite-tsconfig-paths": "^6.1.1",
|
|
109
109
|
"vitest": "^4.1.2",
|
|
110
|
-
"@cobaltcore-dev/aurora-config": "0.0.1",
|
|
111
110
|
"@cobaltcore-dev/policy-engine": "2.0.0",
|
|
112
|
-
"@cobaltcore-dev/signal-openstack": "1.0.0"
|
|
111
|
+
"@cobaltcore-dev/signal-openstack": "1.0.0",
|
|
112
|
+
"@cobaltcore-dev/aurora-config": "0.0.1"
|
|
113
113
|
},
|
|
114
114
|
"scripts": {
|
|
115
115
|
"build": "pnpm build:server && pnpm build:client",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"BucketToastNotifications-BhPi4WWw.mjs","names":["useEffect","useRef","useRouteContext","useModalTracking","isOpen","actionPrefix","onTrackEvent","strict","hasTrackedOpen","hasSubmitted","current","source","action","trackClose","markSubmitted","resetTracking","useEffect","trpcReact","Modal","Stack","Spinner","Message","useProjectId","useModalTracking","DeleteBucketPolicyModal","isOpen","bucketName","onClose","onSuccess","onError","useLingui","projectId","utils","useUtils","trackClose","markSubmitted","resetTracking","actionPrefix","data","policyData","isLoading","isPolicyLoading","error","policyError","storage","ceph","bucketPolicy","get","useQuery","project_id","enabled","retry","deleteMutation","delete","useMutation","invalidate","name","handleClose","message","reset","handleDelete","mutate","hasPolicy","policy","isDeleting","isPending","title","t","open","onCancel","confirmButtonLabel","confirmButtonVariant","onConfirm","cancelButtonLabel","size","disableConfirmButton","direction","gap","div","className","variant","p","strong","isError","calculateBucketState","allVersions","isVersioningEnabled","bucketObjectCount","currentVersions","filter","v","isLatest","isDeleteMarker","realVersions","hasOnlyDeleteMarkers","length","hasOldVersionsOrDeleteMarkers","some","effectiveCurrentObjectCount","isBucketEmpty","useState","trpcReact","Modal","TextInput","Stack","Checkbox","Spinner","useProjectId","calculateBucketState","useModalTracking","EmptyBucketModal","isOpen","bucket","onClose","onSuccess","onError","useLingui","projectId","confirmName","setConfirmName","nameError","setNameError","deleteVersionsAndMarkers","setDeleteVersionsAndMarkers","trackClose","markSubmitted","resetTracking","actionPrefix","utils","useUtils","data","versioningStatus","isLoading","isLoadingVersioning","error","versioningError","storage","ceph","versioning","getStatus","useQuery","project_id","name","enabled","staleTime","versionCheckData","isLoadingVersionCheck","versionCheckError","objects","list","containerName","maxKeys","delimiter","showVersions","status","isVersioningEnabled","allVersions","versions","bucketObjectCount","count","isBucketEmpty","hasOnlyDeleteMarkers","isBucketEmptyWithVersions","emptyBucketMutation","deleteAll","useMutation","onSettled","containers","invalidate","handleClose","reset","handleConfirmNameChange","e","value","target","handleSubmit","trim","t","bucketName","shouldDeleteVersions","mutate","includeVersionsAndDeleteMarkers","deletedCount","message","handleKeyDown","key","hasQueryError","title","open","onCancel","confirmButtonLabel","confirmButtonVariant","onConfirm","cancelButtonLabel","size","disableConfirmButton","isPending","direction","gap","div","className","p","label","required","onChange","onKeyDown","invalid","errortext","undefined","disabled","placeholder","autoFocus","alignment","span","checked","useState","useEffect","trpcReact","Modal","ModalFooter","ButtonRow","TextInput","Stack","Spinner","Button","useProjectId","calculateBucketState","useModalTracking","DeleteBucketModal","isOpen","bucket","onClose","onSuccess","onError","useLingui","projectId","confirmName","setConfirmName","nameError","setNameError","trackClose","markSubmitted","resetTracking","actionPrefix","utils","useUtils","data","versioningStatus","isLoading","isLoadingVersioning","storage","ceph","versioning","getStatus","useQuery","project_id","name","enabled","isVersioningEnabled","status","objects","isLoadingObjects","error","objectsError","list","containerName","maxKeys","delimiter","showVersions","deleteBucketMutation","containers","delete","useMutation","onSettled","invalidate","reset","handleClose","handleConfirmNameChange","e","value","target","handleSubmit","trim","t","bucketName","mutate","message","handleKeyDown","key","currentObjectCount","length","allVersions","versions","effectiveCurrentObjectCount","hasOldVersionsOrDeleteMarkers","hasCurrentObjects","hasVersionsInVersionedBucket","cannotDelete","errorMessage","title","open","onCancel","confirmButtonLabel","undefined","confirmButtonVariant","onConfirm","cancelButtonLabel","modalFooter","className","variant","onClick","data-testid","size","disableConfirmButton","isPending","direction","gap","p","role","aria-live","alignment","span","div","ul","li","label","required","onChange","onKeyDown","invalid","errortext","disabled","placeholder","useState","trpcReact","Modal","TextInput","Stack","useProjectId","useModalTracking","DeleteVersionsModal","isOpen","bucket","onClose","onSuccess","onError","useLingui","projectId","confirmName","setConfirmName","nameError","setNameError","trackClose","markSubmitted","resetTracking","actionPrefix","utils","useUtils","deleteVersionsMutation","storage","ceph","objects","deleteAll","useMutation","onSettled","containers","list","invalidate","handleClose","reset","handleConfirmNameChange","e","value","target","handleSubmit","trim","name","t","bucketName","mutate","project_id","containerName","includeVersionsAndDeleteMarkers","deletedCount","error","message","handleKeyDown","key","title","open","onCancel","confirmButtonLabel","confirmButtonVariant","onConfirm","cancelButtonLabel","size","disableConfirmButton","isPending","direction","gap","p","className","label","required","onChange","onKeyDown","invalid","errortext","undefined","disabled","placeholder","autoFocus","getBucketCreatedToast","bucketName","message","description","getBucketCreateErrorToast","errorMessage","getBucketEmptiedToast","deletedCount","getBucketEmptyErrorToast","getBucketDeletedToast","getBucketDeleteErrorToast","getBucketsEmptyCompleteToast","emptiedCount","totalDeleted","errors","hasErrors","length","totalBuckets","errorsLength","getVersioningEnabledToast","getVersioningEnableErrorToast","getVersioningSuspendedToast","getVersioningSuspendErrorToast","getBucketPolicyDeletedToast","getBucketPolicyDeleteErrorToast","getVersionsDeletedToast","getVersionsDeleteErrorToast"],"sources":["../../src/client/hooks/useModalTracking.ts","../../src/client/routes/_auth/projects/$projectId/storage/-components/Ceph/Buckets/DeleteBucketPolicyModal.tsx","../../src/client/routes/_auth/projects/$projectId/storage/-components/Ceph/hooks/bucketStateHelpers.ts","../../src/client/routes/_auth/projects/$projectId/storage/-components/Ceph/Buckets/EmptyBucketModal.tsx","../../src/client/routes/_auth/projects/$projectId/storage/-components/Ceph/Buckets/DeleteBucketModal.tsx","../../src/client/routes/_auth/projects/$projectId/storage/-components/Ceph/Buckets/DeleteVersionsModal.tsx","../../src/client/routes/_auth/projects/$projectId/storage/-components/Ceph/Buckets/BucketToastNotifications.tsx"],"sourcesContent":["import { useEffect, useRef } from \"react\"\nimport { useRouteContext } from \"@tanstack/react-router\"\n\ninterface UseModalTrackingOptions {\n isOpen: boolean\n actionPrefix: string // e.g., \"storage.ceph.bucket.create\"\n}\n\ninterface UseModalTrackingReturn {\n trackClose: () => void\n markSubmitted: () => void\n resetTracking: () => void\n}\n\n/**\n * Custom hook to handle modal open/close analytics tracking.\n *\n * Tracks:\n * - `.open` event when modal opens (once per modal open)\n * - `.close` event when modal closes without submission (cancelled)\n *\n * @example\n * const { trackClose, markSubmitted, resetTracking } = useModalTracking({\n * isOpen,\n * actionPrefix: \"storage.ceph.bucket.create\"\n * })\n *\n * // In handleClose:\n * trackClose()\n *\n * // In handleSubmit:\n * markSubmitted()\n *\n * // In cleanup/reset:\n * resetTracking()\n */\nexport const useModalTracking = ({ isOpen, actionPrefix }: UseModalTrackingOptions): UseModalTrackingReturn => {\n const { onTrackEvent } = useRouteContext({ strict: false })\n const hasTrackedOpen = useRef(false)\n // Use useRef instead of useState to avoid timing race with synchronous close paths\n // See: https://github.com/... - setState doesn't apply until next render, so trackClose()\n // could read stale hasSubmitted === false even after markSubmitted() was called\n const hasSubmitted = useRef(false)\n\n // Track when user opens the modal (once per modal open)\n useEffect(() => {\n if (isOpen && !hasTrackedOpen.current) {\n onTrackEvent?.({\n source: \"modal\",\n action: `${actionPrefix}.open`,\n })\n hasTrackedOpen.current = true\n }\n }, [isOpen, onTrackEvent, actionPrefix])\n\n /**\n * Track close event if user didn't submit.\n * Call this at the start of your handleClose function.\n */\n const trackClose = () => {\n if (isOpen && !hasSubmitted.current) {\n onTrackEvent?.({\n source: \"modal\",\n action: `${actionPrefix}.close`,\n })\n }\n }\n\n /**\n * Mark that the user submitted the form.\n * Call this in your handleSubmit function before the mutation.\n */\n const markSubmitted = () => {\n hasSubmitted.current = true\n }\n\n /**\n * Reset tracking state.\n * Call this in handleClose after tracking close event.\n */\n const resetTracking = () => {\n hasSubmitted.current = false\n hasTrackedOpen.current = false\n }\n\n return {\n trackClose,\n markSubmitted,\n resetTracking,\n }\n}\n","import { useEffect } from \"react\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { Modal, Stack, Spinner, Message } from \"@cloudoperators/juno-ui-components\"\nimport { useProjectId } from \"@/client/hooks/useProjectId\"\nimport { useModalTracking } from \"@/client/hooks/useModalTracking\"\n\ninterface DeleteBucketPolicyModalProps {\n isOpen: boolean\n bucketName: string\n onClose: () => void\n onSuccess?: (bucketName: string) => void\n onError?: (bucketName: string, errorMessage: string) => void\n}\n\nexport const DeleteBucketPolicyModal = ({\n isOpen,\n bucketName,\n onClose,\n onSuccess,\n onError,\n}: DeleteBucketPolicyModalProps) => {\n const { t } = useLingui()\n const projectId = useProjectId()\n const utils = trpcReact.useUtils()\n\n const { trackClose, markSubmitted, resetTracking } = useModalTracking({\n isOpen,\n actionPrefix: \"storage.ceph.bucket.policy.delete\",\n })\n\n // Query to verify policy exists\n const {\n data: policyData,\n isLoading: isPolicyLoading,\n error: policyError,\n } = trpcReact.storage.ceph.bucketPolicy.get.useQuery(\n {\n project_id: projectId,\n bucketName,\n },\n {\n enabled: isOpen && !!projectId,\n retry: false,\n }\n )\n\n // Delete mutation\n const deleteMutation = trpcReact.storage.ceph.bucketPolicy.delete.useMutation({\n onSuccess: () => {\n utils.storage.ceph.bucketPolicy.get.invalidate()\n const name = bucketName\n onSuccess?.(name)\n handleClose()\n },\n onError: (error) => {\n const name = bucketName\n onError?.(name, error.message)\n },\n })\n\n useEffect(() => {\n if (!isOpen) {\n deleteMutation.reset()\n resetTracking()\n }\n }, [isOpen, bucketName])\n\n const handleClose = () => {\n deleteMutation.reset()\n resetTracking()\n onClose()\n }\n\n const handleDelete = () => {\n markSubmitted()\n deleteMutation.mutate({\n project_id: projectId,\n bucketName,\n })\n }\n\n if (!isOpen) return null\n\n const hasPolicy = !!policyData?.policy\n const isDeleting = deleteMutation.isPending\n\n return (\n <Modal\n title={t`Delete Bucket Policy`}\n open={isOpen}\n onCancel={() => {\n trackClose()\n handleClose()\n }}\n confirmButtonLabel={t`Delete Policy`}\n confirmButtonVariant=\"primary-danger\"\n onConfirm={handleDelete}\n cancelButtonLabel={t`Cancel`}\n size=\"small\"\n disableConfirmButton={isDeleting || isPolicyLoading || !hasPolicy || !!policyError}\n >\n <Stack direction=\"vertical\" gap=\"4\">\n {isPolicyLoading && (\n <div className=\"flex items-center justify-center py-4\">\n <Spinner variant=\"primary\" size=\"large\" />\n </div>\n )}\n\n {policyError && (\n <Message variant=\"error\" title={t`Failed to load policy`}>\n {policyError.message}\n </Message>\n )}\n\n {!isPolicyLoading && !policyError && !hasPolicy && (\n <Message variant=\"warning\" title={t`No policy found`}>\n <Trans>This bucket does not have a policy attached.</Trans>\n </Message>\n )}\n\n {!isPolicyLoading && !policyError && hasPolicy && (\n <>\n <p className=\"text-theme-default\">\n <Trans>\n Are you sure you want to delete the policy for bucket <strong>{bucketName}</strong>?\n </Trans>\n </p>\n <p className=\"text-theme-default\">\n <Trans>\n Deleting the policy will remove all access restrictions defined by it. This action cannot be undone.\n </Trans>\n </p>\n </>\n )}\n\n {deleteMutation.isError && (\n <Message variant=\"error\" title={t`Failed to delete policy`}>\n {deleteMutation.error?.message}\n </Message>\n )}\n </Stack>\n </Modal>\n )\n}\n","import type { S3ObjectVersion } from \"@/server/Storage/types/ceph\"\n\n/**\n * Helper to calculate bucket state from versioning data\n *\n * @param allVersions - All versions/objects from the list query with showVersions=true\n * @param isVersioningEnabled - Whether bucket has versioning Enabled or Suspended\n * @param bucketObjectCount - Object count from bucket metadata (may be 0 even with objects due to how S3 counts)\n * @returns Calculated state flags for bucket emptiness and version status\n */\nexport function calculateBucketState(\n allVersions: S3ObjectVersion[],\n isVersioningEnabled: boolean,\n bucketObjectCount: number\n) {\n // Current objects = isLatest=true and not delete markers\n const currentVersions = allVersions.filter((v) => v.isLatest && !v.isDeleteMarker)\n\n // Real versions (not delete markers) - includes both current and old\n const realVersions = allVersions.filter((v) => !v.isDeleteMarker)\n\n // Check if there are ONLY delete markers (no real objects/versions at all)\n const hasOnlyDeleteMarkers = isVersioningEnabled && allVersions.length > 0 && realVersions.length === 0\n\n // Check if there are old versions (not current) or any delete markers\n // Used to determine if \"Delete Versions\" action is needed\n const hasOldVersionsOrDeleteMarkers =\n isVersioningEnabled && allVersions.some((v) => v.isDeleteMarker || (!v.isLatest && !v.isDeleteMarker))\n\n // Count current objects for bucket emptiness check\n // - For versioned buckets: use bucketObjectCount from metadata OR count current versions if metadata is 0\n // - For unversioned buckets: count all real versions (they are all current)\n const effectiveCurrentObjectCount = isVersioningEnabled\n ? bucketObjectCount > 0\n ? bucketObjectCount\n : currentVersions.length\n : bucketObjectCount + realVersions.length\n\n // Bucket is empty only if there are no current objects\n const isBucketEmpty = effectiveCurrentObjectCount === 0\n\n return {\n currentVersions,\n hasOnlyDeleteMarkers,\n hasOldVersionsOrDeleteMarkers,\n effectiveCurrentObjectCount,\n isBucketEmpty,\n }\n}\n","import { useState } from \"react\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { Modal, TextInput, Stack, Checkbox, Spinner } from \"@cloudoperators/juno-ui-components\"\nimport { Bucket } from \"@/server/Storage/types/ceph\"\nimport { useProjectId } from \"@/client/hooks/useProjectId\"\nimport { calculateBucketState } from \"../hooks/bucketStateHelpers\"\nimport { useModalTracking } from \"@/client/hooks/useModalTracking\"\n\ninterface EmptyBucketModalProps {\n isOpen: boolean\n bucket: Bucket | null\n onClose: () => void\n onSuccess?: (bucketName: string, deletedCount: number) => void\n onError?: (bucketName: string, errorMessage: string) => void\n}\n\nexport const EmptyBucketModal = ({ isOpen, bucket, onClose, onSuccess, onError }: EmptyBucketModalProps) => {\n const { t } = useLingui()\n const projectId = useProjectId()\n const [confirmName, setConfirmName] = useState(\"\")\n const [nameError, setNameError] = useState<string | null>(null)\n const [deleteVersionsAndMarkers, setDeleteVersionsAndMarkers] = useState(false)\n\n const { trackClose, markSubmitted, resetTracking } = useModalTracking({\n isOpen,\n actionPrefix: \"storage.ceph.bucket.empty\",\n })\n\n const utils = trpcReact.useUtils()\n\n // Query versioning status for the bucket\n const {\n data: versioningStatus,\n isLoading: isLoadingVersioning,\n error: versioningError,\n } = trpcReact.storage.ceph.versioning.getStatus.useQuery(\n {\n project_id: projectId ?? \"\",\n bucket: bucket?.name ?? \"\",\n },\n {\n enabled: !!projectId && !!bucket && isOpen,\n staleTime: 30 * 1000,\n }\n )\n\n // Query to check if bucket has versions/delete markers (only when versioning is enabled/suspended)\n // Use maxKeys=100 to get enough data - with maxKeys=1 we might miss current objects\n // if the first result is a delete marker\n const {\n data: versionCheckData,\n isLoading: isLoadingVersionCheck,\n error: versionCheckError,\n } = trpcReact.storage.ceph.objects.list.useQuery(\n {\n project_id: projectId ?? \"\",\n containerName: bucket?.name ?? \"\",\n maxKeys: 100,\n delimiter: \"\",\n showVersions: true,\n },\n {\n enabled: !!projectId && !!bucket && isOpen && versioningStatus?.status !== \"Unversioned\",\n staleTime: 30 * 1000,\n }\n )\n\n // Check bucket state using shared helper\n const isVersioningEnabled = versioningStatus?.status === \"Enabled\" || versioningStatus?.status === \"Suspended\"\n const allVersions = versionCheckData?.versions ?? []\n const bucketObjectCount = bucket?.count ?? 0\n const { isBucketEmpty, hasOnlyDeleteMarkers } = calculateBucketState(\n allVersions,\n isVersioningEnabled,\n bucketObjectCount\n )\n const isBucketEmptyWithVersions = isBucketEmpty && hasOnlyDeleteMarkers\n\n const emptyBucketMutation = trpcReact.storage.ceph.objects.deleteAll.useMutation({\n onSettled: () => {\n // Invalidate both containers.list (to update bucket metadata) and objects.list (to refresh empty state)\n utils.storage.ceph.containers.list.invalidate()\n utils.storage.ceph.objects.list.invalidate()\n handleClose()\n },\n })\n\n const handleClose = () => {\n setConfirmName(\"\")\n setNameError(null)\n setDeleteVersionsAndMarkers(false)\n emptyBucketMutation.reset()\n resetTracking()\n onClose()\n }\n\n const handleConfirmNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value\n setConfirmName(value)\n if (nameError) setNameError(null)\n }\n\n const handleSubmit = () => {\n if (!bucket) return\n if (confirmName.trim() !== bucket.name) {\n setNameError(t`Bucket name does not match`)\n return\n }\n\n markSubmitted()\n\n // Capture bucket name before async operation to avoid dereferencing null bucket in callbacks\n const bucketName = bucket.name\n\n // If bucket is empty with only delete markers, always delete versions\n const shouldDeleteVersions = isBucketEmptyWithVersions || deleteVersionsAndMarkers\n\n emptyBucketMutation.mutate(\n {\n project_id: projectId,\n containerName: bucketName,\n includeVersionsAndDeleteMarkers: shouldDeleteVersions,\n },\n {\n onSuccess: (deletedCount) => {\n onSuccess?.(bucketName, deletedCount)\n },\n onError: (error) => {\n onError?.(bucketName, error.message)\n },\n }\n )\n }\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\") handleSubmit()\n }\n\n if (!isOpen || !bucket) return null\n\n const bucketName = bucket.name\n const isLoading = isLoadingVersioning || isLoadingVersionCheck\n const hasQueryError = !!versioningError || !!versionCheckError\n\n // If bucket is empty with only delete markers, show \"Delete Versions\" UI\n if (isBucketEmptyWithVersions && !isLoading) {\n return (\n <Modal\n title={t`Delete Versions`}\n open={isOpen}\n onCancel={() => {\n trackClose()\n handleClose()\n }}\n confirmButtonLabel={t`Delete Versions`}\n confirmButtonVariant=\"primary-danger\"\n onConfirm={handleSubmit}\n cancelButtonLabel={t`Cancel`}\n size=\"small\"\n disableConfirmButton={emptyBucketMutation.isPending || confirmName.trim() !== bucket.name || hasQueryError}\n >\n <Stack direction=\"vertical\" gap=\"6\">\n {hasQueryError && (\n <div className=\"bg-theme-danger-10 text-theme-danger rounded p-4\">\n <Trans>Unable to verify bucket versioning status. Please try again.</Trans>\n </div>\n )}\n\n <p className=\"text-theme-default m-0\">\n <Trans>\n This action will permanently delete all versions and delete markers. This will enable you to delete the\n bucket. This action cannot be undone.\n </Trans>\n </p>\n\n <TextInput\n label={t`Type the bucket name to confirm`}\n required\n value={confirmName}\n onChange={handleConfirmNameChange}\n onKeyDown={handleKeyDown}\n invalid={!!nameError}\n errortext={nameError || undefined}\n disabled={emptyBucketMutation.isPending || hasQueryError}\n placeholder={bucket.name}\n autoFocus\n />\n </Stack>\n </Modal>\n )\n }\n\n // Otherwise show normal \"Empty Bucket\" UI\n return (\n <Modal\n title={t`Empty Bucket`}\n open={isOpen}\n onCancel={() => {\n trackClose()\n handleClose()\n }}\n confirmButtonLabel={t`Empty Bucket`}\n confirmButtonVariant=\"primary-danger\"\n onConfirm={handleSubmit}\n cancelButtonLabel={t`Cancel`}\n size=\"small\"\n disableConfirmButton={emptyBucketMutation.isPending || confirmName.trim() !== bucket.name || hasQueryError}\n >\n {isLoading ? (\n <Stack direction=\"horizontal\" gap=\"2\" alignment=\"center\">\n <Spinner />\n <span className=\"text-juno-grey-light-1 text-sm\">\n <Trans>Checking bucket contents...</Trans>\n </span>\n </Stack>\n ) : (\n <Stack direction=\"vertical\" gap=\"6\">\n {hasQueryError && (\n <div className=\"bg-theme-danger-10 text-theme-danger rounded p-4\">\n <Trans>Unable to verify bucket versioning status. Please try again.</Trans>\n </div>\n )}\n\n <p className=\"text-theme-default m-0\">\n {versioningStatus && versioningStatus.status !== \"Unversioned\" ? (\n <Trans>\n This action will permanently delete all objects from {bucketName}. You may choose to also delete all\n versions and delete markers. This will enable you to delete the bucket. This action cannot be undone.\n </Trans>\n ) : (\n <Trans>\n This action will permanently delete all objects from {bucketName}. This action cannot be undone.\n </Trans>\n )}\n </p>\n\n {versioningStatus && versioningStatus.status !== \"Unversioned\" && (\n <Checkbox\n checked={deleteVersionsAndMarkers}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => setDeleteVersionsAndMarkers(e.target.checked)}\n label={t`Also delete all versions and all delete markers`}\n disabled={emptyBucketMutation.isPending || hasQueryError}\n />\n )}\n\n <TextInput\n label={t`Type the bucket name to confirm`}\n required\n value={confirmName}\n onChange={handleConfirmNameChange}\n onKeyDown={handleKeyDown}\n invalid={!!nameError}\n errortext={nameError || undefined}\n disabled={emptyBucketMutation.isPending || hasQueryError}\n placeholder={bucket.name}\n autoFocus\n />\n </Stack>\n )}\n </Modal>\n )\n}\n","import { useState, useEffect } from \"react\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { Modal, ModalFooter, ButtonRow, TextInput, Stack, Spinner, Button } from \"@cloudoperators/juno-ui-components\"\nimport type { Bucket } from \"@/server/Storage/types/ceph\"\nimport { useProjectId } from \"@/client/hooks/useProjectId\"\nimport { calculateBucketState } from \"../hooks/bucketStateHelpers\"\nimport { useModalTracking } from \"@/client/hooks/useModalTracking\"\n\ninterface DeleteBucketModalProps {\n isOpen: boolean\n bucket: Bucket | null\n onClose: () => void\n onSuccess?: (bucketName: string) => void\n onError?: (bucketName: string, errorMessage: string) => void\n}\n\nexport const DeleteBucketModal = ({ isOpen, bucket, onClose, onSuccess, onError }: DeleteBucketModalProps) => {\n const { t } = useLingui()\n const projectId = useProjectId()\n const [confirmName, setConfirmName] = useState(\"\")\n const [nameError, setNameError] = useState<string | null>(null)\n\n const { trackClose, markSubmitted, resetTracking } = useModalTracking({\n isOpen,\n actionPrefix: \"storage.ceph.bucket.delete\",\n })\n\n const utils = trpcReact.useUtils()\n\n // Fetch versioning status to determine if bucket has versioning enabled\n const { data: versioningStatus, isLoading: isLoadingVersioning } =\n trpcReact.storage.ceph.versioning.getStatus.useQuery(\n { project_id: projectId ?? \"\", bucket: bucket?.name ?? \"\" },\n { enabled: isOpen && bucket !== null }\n )\n\n const isVersioningEnabled = versioningStatus?.status === \"Enabled\" || versioningStatus?.status === \"Suspended\"\n\n // Fetch actual objects and versions to get accurate real-time state\n // Use showVersions=true to also detect delete markers in versioned buckets\n // Use delimiter=\"\" to get ALL objects including folder markers (zero-byte objects ending in \"/\")\n // Without this, folders are returned as CommonPrefixes and we can't accurately check if bucket is empty\n // Use maxKeys=100 to get enough objects/versions to accurately determine bucket state\n // (with maxKeys=1 we might miss current objects if the first result is a delete marker)\n const {\n data: objects,\n isLoading: isLoadingObjects,\n error: objectsError,\n } = trpcReact.storage.ceph.objects.list.useQuery(\n { project_id: projectId ?? \"\", containerName: bucket?.name ?? \"\", maxKeys: 100, delimiter: \"\", showVersions: true },\n { enabled: isOpen && bucket !== null }\n )\n\n const deleteBucketMutation = trpcReact.storage.ceph.containers.delete.useMutation({\n onSettled: () => {\n utils.storage.ceph.containers.list.invalidate()\n },\n })\n\n useEffect(() => {\n if (!isOpen) {\n setConfirmName(\"\")\n setNameError(null)\n deleteBucketMutation.reset()\n resetTracking()\n }\n }, [isOpen, bucket?.name])\n\n const handleClose = () => {\n setConfirmName(\"\")\n setNameError(null)\n deleteBucketMutation.reset()\n resetTracking()\n onClose()\n }\n\n const handleConfirmNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value\n setConfirmName(value)\n if (nameError) setNameError(null)\n }\n\n const handleSubmit = () => {\n if (!bucket) return\n if (objectsError) return\n if (confirmName.trim() !== bucket.name) {\n setNameError(t`Bucket name does not match`)\n return\n }\n\n markSubmitted()\n\n // Capture bucket name before async operation to avoid dereferencing null bucket in callbacks\n const bucketName = bucket.name\n\n deleteBucketMutation.mutate(\n { project_id: projectId, bucketName },\n {\n onSuccess: () => {\n handleClose()\n onSuccess?.(bucketName)\n },\n onError: (error) => {\n handleClose()\n onError?.(bucketName, error.message)\n },\n }\n )\n }\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\") handleSubmit()\n }\n\n if (!isOpen || !bucket) return null\n\n // Calculate bucket state using shared helper\n // When showVersions=true, BFF returns all objects in \"versions\" array, not \"objects\"\n // So bucketObjectCount from objects?.objects is used only as a fallback\n const currentObjectCount = objects?.objects?.length ?? 0\n const allVersions = objects?.versions ?? []\n const { effectiveCurrentObjectCount, hasOldVersionsOrDeleteMarkers } = calculateBucketState(\n allVersions,\n isVersioningEnabled,\n currentObjectCount\n )\n\n // Bucket cannot be deleted if it has:\n // 1. Current objects (effectiveCurrentObjectCount > 0) - show \"Empty the bucket\"\n // 2. Old versions or any delete markers in a versioned bucket - show \"Delete all versions\"\n const hasCurrentObjects = effectiveCurrentObjectCount > 0\n const hasVersionsInVersionedBucket = hasOldVersionsOrDeleteMarkers\n const cannotDelete = hasCurrentObjects || hasVersionsInVersionedBucket\n const errorMessage = objectsError?.message\n const isLoading = isLoadingObjects || isLoadingVersioning\n\n return (\n <Modal\n title={t`Delete Bucket`}\n open={isOpen}\n onCancel={() => {\n trackClose()\n handleClose()\n }}\n confirmButtonLabel={cannotDelete ? undefined : t`Delete Bucket`}\n confirmButtonVariant={cannotDelete ? undefined : \"primary-danger\"}\n onConfirm={cannotDelete ? undefined : handleSubmit}\n cancelButtonLabel={cannotDelete ? undefined : t`Cancel`}\n modalFooter={\n cannotDelete ? (\n <ModalFooter className=\"flex justify-end\">\n <ButtonRow>\n <Button variant=\"primary\" onClick={handleClose} data-testid=\"delete-has-objects-close-button\">\n <Trans>Close</Trans>\n </Button>\n </ButtonRow>\n </ModalFooter>\n ) : undefined\n }\n size=\"small\"\n disableConfirmButton={\n deleteBucketMutation.isPending || isLoading || !!objectsError || confirmName.trim() !== bucket.name\n }\n >\n <Stack direction=\"vertical\" gap=\"6\">\n {objectsError && (\n <p className=\"text-theme-error\" role=\"alert\" aria-live=\"assertive\">\n <Trans>Failed to check bucket contents: {errorMessage}</Trans>\n </p>\n )}\n\n {isLoading ? (\n <Stack direction=\"horizontal\" gap=\"2\" alignment=\"center\">\n <Spinner />\n <span className=\"text-juno-grey-light-1 text-sm\">\n <Trans>Checking bucket contents...</Trans>\n </span>\n </Stack>\n ) : cannotDelete ? (\n <div className=\"text-theme-default\">\n <p className=\"mb-4\">\n <Trans>This bucket cannot be deleted yet. Do the following to be able to delete the bucket:</Trans>\n </p>\n <ul className=\"list-disc space-y-1 pl-5\">\n {hasCurrentObjects && (\n <li>\n <Trans>Empty the bucket</Trans>\n </li>\n )}\n {hasVersionsInVersionedBucket && (\n <li>\n <Trans>Delete all versions and delete markers</Trans>\n </li>\n )}\n </ul>\n </div>\n ) : (\n <>\n <p className=\"text-theme-default\">\n <Trans>\n This action is irreversible. Deleting a bucket permanently removes it and cannot be undone. The bucket\n must be empty before deletion.\n </Trans>\n </p>\n\n <TextInput\n label={t`Type the bucket name to confirm`}\n required\n value={confirmName}\n onChange={handleConfirmNameChange}\n onKeyDown={handleKeyDown}\n invalid={!!nameError}\n errortext={nameError || undefined}\n disabled={deleteBucketMutation.isPending}\n placeholder={bucket.name}\n />\n </>\n )}\n </Stack>\n </Modal>\n )\n}\n","import { useState } from \"react\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { Modal, TextInput, Stack } from \"@cloudoperators/juno-ui-components\"\nimport { Bucket } from \"@/server/Storage/types/ceph\"\nimport { useProjectId } from \"@/client/hooks/useProjectId\"\nimport { useModalTracking } from \"@/client/hooks/useModalTracking\"\n\ninterface DeleteVersionsModalProps {\n isOpen: boolean\n bucket: Bucket | null\n onClose: () => void\n onSuccess?: (bucketName: string, deletedCount: number) => void\n onError?: (bucketName: string, errorMessage: string) => void\n}\n\nexport const DeleteVersionsModal = ({ isOpen, bucket, onClose, onSuccess, onError }: DeleteVersionsModalProps) => {\n const { t } = useLingui()\n const projectId = useProjectId()\n const [confirmName, setConfirmName] = useState(\"\")\n const [nameError, setNameError] = useState<string | null>(null)\n\n const { trackClose, markSubmitted, resetTracking } = useModalTracking({\n isOpen,\n actionPrefix: \"storage.ceph.bucket.versions.delete\",\n })\n\n const utils = trpcReact.useUtils()\n\n const deleteVersionsMutation = trpcReact.storage.ceph.objects.deleteAll.useMutation({\n onSettled: () => {\n // Invalidate both containers.list (to update bucket metadata) and objects.list (to refresh empty state)\n utils.storage.ceph.containers.list.invalidate()\n utils.storage.ceph.objects.list.invalidate()\n handleClose()\n },\n })\n\n const handleClose = () => {\n setConfirmName(\"\")\n setNameError(null)\n deleteVersionsMutation.reset()\n resetTracking()\n onClose()\n }\n\n const handleConfirmNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value\n setConfirmName(value)\n if (nameError) setNameError(null)\n }\n\n const handleSubmit = () => {\n if (!bucket) return\n if (confirmName.trim() !== bucket.name) {\n setNameError(t`Bucket name does not match`)\n return\n }\n\n markSubmitted()\n\n // Capture bucket name before async operation to avoid dereferencing null bucket in callbacks\n const bucketName = bucket.name\n\n // Always delete all versions and delete markers (includeVersionsAndDeleteMarkers: true)\n deleteVersionsMutation.mutate(\n {\n project_id: projectId,\n containerName: bucketName,\n includeVersionsAndDeleteMarkers: true,\n },\n {\n onSuccess: (deletedCount) => {\n onSuccess?.(bucketName, deletedCount)\n },\n onError: (error) => {\n onError?.(bucketName, error.message)\n },\n }\n )\n }\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\") handleSubmit()\n }\n\n if (!isOpen || !bucket) return null\n\n return (\n <Modal\n title={t`Delete Versions`}\n open={isOpen}\n onCancel={() => {\n trackClose()\n handleClose()\n }}\n confirmButtonLabel={t`Delete Versions`}\n confirmButtonVariant=\"primary-danger\"\n onConfirm={handleSubmit}\n cancelButtonLabel={t`Cancel`}\n size=\"small\"\n disableConfirmButton={deleteVersionsMutation.isPending || confirmName.trim() !== bucket.name}\n >\n <Stack direction=\"vertical\" gap=\"6\">\n <p className=\"text-theme-default m-0\">\n <Trans>\n This action will permanently delete all versions and delete markers. This will enable you to delete the\n bucket. This action cannot be undone.\n </Trans>\n </p>\n\n <TextInput\n label={t`Type the bucket name to confirm`}\n required\n value={confirmName}\n onChange={handleConfirmNameChange}\n onKeyDown={handleKeyDown}\n invalid={!!nameError}\n errortext={nameError || undefined}\n disabled={deleteVersionsMutation.isPending}\n placeholder={bucket.name}\n autoFocus\n className=\"overflow-x-hidden [overflow-wrap:anywhere]\"\n />\n </Stack>\n </Modal>\n )\n}\n","import { ReactNode } from \"react\"\nimport { NotificationOptions } from \"@cloudoperators/juno-ui-components\"\nimport { Trans, Plural } from \"@lingui/react/macro\"\n\nexport const getBucketCreatedToast = (bucketName: string): { message: ReactNode } & NotificationOptions => ({\n message: <Trans>Bucket Created</Trans>,\n description: <Trans>Bucket \"{bucketName}\" was successfully created.</Trans>,\n})\n\nexport const getBucketCreateErrorToast = (\n bucketName: string,\n errorMessage: string\n): { message: ReactNode } & NotificationOptions => ({\n message: <Trans>Failed to Create Bucket</Trans>,\n description: (\n <Trans>\n Could not create bucket \"{bucketName}\": {errorMessage}\n </Trans>\n ),\n})\n\nexport const getBucketEmptiedToast = (\n bucketName: string,\n deletedCount: number\n): { message: ReactNode } & NotificationOptions => ({\n message: <Trans>Bucket Emptied</Trans>,\n description:\n deletedCount === 0 ? (\n <Trans>Bucket \"{bucketName}\" was already empty.</Trans>\n ) : deletedCount === 1 ? (\n <Trans>\n Bucket \"{bucketName}\" was successfully emptied. {deletedCount} object deleted.\n </Trans>\n ) : (\n <Trans>\n Bucket \"{bucketName}\" was successfully emptied. {deletedCount} objects deleted.\n </Trans>\n ),\n})\n\nexport const getBucketEmptyErrorToast = (\n bucketName: string,\n errorMessage: string\n): { message: ReactNode } & NotificationOptions => ({\n message: <Trans>Failed to Empty Bucket</Trans>,\n description: (\n <Trans>\n Could not empty bucket \"{bucketName}\": {errorMessage}\n </Trans>\n ),\n})\n\nexport const getBucketDeletedToast = (bucketName: string): { message: ReactNode } & NotificationOptions => ({\n message: <Trans>Bucket Deleted</Trans>,\n description: <Trans>Bucket \"{bucketName}\" was successfully deleted.</Trans>,\n})\n\nexport const getBucketDeleteErrorToast = (\n bucketName: string,\n errorMessage: string\n): { message: ReactNode } & NotificationOptions => ({\n message: <Trans>Failed to Delete Bucket</Trans>,\n description: (\n <Trans>\n Could not delete bucket \"{bucketName}\": {errorMessage}\n </Trans>\n ),\n})\n\nexport const getBucketsEmptyCompleteToast = (\n emptiedCount: number,\n totalDeleted: number,\n errors: string[]\n): { message: ReactNode } & NotificationOptions => {\n const hasErrors = errors.length > 0\n const totalBuckets = emptiedCount + errors.length\n const errorsLength = errors.length\n\n return {\n message: hasErrors ? <Trans>Empty All Completed with Errors</Trans> : <Trans>All Buckets Emptied</Trans>,\n description: hasErrors ? (\n <Trans>\n Successfully emptied {emptiedCount} of {totalBuckets}{\" \"}\n <Plural value={totalBuckets} one=\"bucket\" other=\"buckets\" />, deleting {totalDeleted}{\" \"}\n <Plural value={totalDeleted} one=\"object\" other=\"objects\" />. {errorsLength}{\" \"}\n <Plural value={errorsLength} one=\"bucket\" other=\"buckets\" /> failed.\n </Trans>\n ) : (\n <Trans>\n Successfully emptied {emptiedCount} <Plural value={emptiedCount} one=\"bucket\" other=\"buckets\" />, deleting{\" \"}\n {totalDeleted} <Plural value={totalDeleted} one=\"object\" other=\"objects\" />.\n </Trans>\n ),\n }\n}\n\n// ── Versioning operations ──────────────────────────────────────────────────\n\nexport const getVersioningEnabledToast = (bucketName: string): { message: ReactNode } & NotificationOptions => ({\n message: <Trans>Versioning Enabled</Trans>,\n description: <Trans>Versioning was successfully enabled for bucket \"{bucketName}\".</Trans>,\n})\n\nexport const getVersioningEnableErrorToast = (\n bucketName: string,\n errorMessage: string\n): { message: ReactNode } & NotificationOptions => ({\n message: <Trans>Failed to Enable Versioning</Trans>,\n description: (\n <Trans>\n Could not enable versioning for bucket \"{bucketName}\": {errorMessage}\n </Trans>\n ),\n})\n\nexport const getVersioningSuspendedToast = (bucketName: string): { message: ReactNode } & NotificationOptions => ({\n message: <Trans>Versioning Suspended</Trans>,\n description: <Trans>Versioning was successfully suspended for bucket \"{bucketName}\".</Trans>,\n})\n\nexport const getVersioningSuspendErrorToast = (\n bucketName: string,\n errorMessage: string\n): { message: ReactNode } & NotificationOptions => ({\n message: <Trans>Failed to Suspend Versioning</Trans>,\n description: (\n <Trans>\n Could not suspend versioning for bucket \"{bucketName}\": {errorMessage}\n </Trans>\n ),\n})\n\n// ── Bucket policy operations ───────────────────────────────────────────────\n\nexport const getBucketPolicyDeletedToast = (bucketName: string): { message: ReactNode } & NotificationOptions => ({\n message: <Trans>Policy Deleted</Trans>,\n description: <Trans>Bucket policy was successfully deleted from \"{bucketName}\".</Trans>,\n})\n\nexport const getBucketPolicyDeleteErrorToast = (\n bucketName: string,\n errorMessage: string\n): { message: ReactNode } & NotificationOptions => ({\n message: <Trans>Failed to Delete Policy</Trans>,\n description: (\n <Trans>\n Could not delete bucket policy from \"{bucketName}\": {errorMessage}\n </Trans>\n ),\n})\n\n// ── Delete versions operation ──────────────────────────────────────────────\n\nexport const getVersionsDeletedToast = (\n bucketName: string,\n deletedCount: number\n): { message: ReactNode } & NotificationOptions => ({\n message: <Trans>Versions Deleted</Trans>,\n description:\n deletedCount === 0 ? (\n <Trans>No versions to delete in bucket \"{bucketName}\".</Trans>\n ) : deletedCount === 1 ? (\n <Trans>\n Successfully deleted {deletedCount} version from bucket \"{bucketName}\".\n </Trans>\n ) : (\n <Trans>\n Successfully deleted {deletedCount} versions from bucket \"{bucketName}\".\n </Trans>\n ),\n})\n\nexport const getVersionsDeleteErrorToast = (\n bucketName: string,\n errorMessage: string\n): { message: ReactNode } & NotificationOptions => ({\n message: <Trans>Failed to Delete Versions</Trans>,\n description: (\n <Trans>\n Could not delete versions from bucket \"{bucketName}\": {errorMessage}\n </Trans>\n ),\n})\n"],"mappings":"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"}
|