@cobaltcore-dev/aurora 0.21.0 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/{AuthProvider-p1e1DuKU.mjs → AuthProvider-CQ6Yppoh.mjs} +2 -2
- package/dist/client/{AuthProvider-p1e1DuKU.mjs.map → AuthProvider-CQ6Yppoh.mjs.map} +1 -1
- package/dist/client/{BucketToastNotifications-BGd2wVmh.mjs → BucketToastNotifications-BhPi4WWw.mjs} +3 -3
- package/dist/client/{BucketToastNotifications-BGd2wVmh.mjs.map → BucketToastNotifications-BhPi4WWw.mjs.map} +1 -1
- package/dist/client/{ContentHeader-CIAzorGI.mjs → ContentHeader-9KZdhOoA.mjs} +4 -3
- package/dist/client/{ContentHeader-CIAzorGI.mjs.map → ContentHeader-9KZdhOoA.mjs.map} +1 -1
- package/dist/client/{DeleteFlavorModal-lFMExcq_.mjs → DeleteFlavorModal-Be2qZo4w.mjs} +2 -2
- package/dist/client/{DeleteFlavorModal-lFMExcq_.mjs.map → DeleteFlavorModal-Be2qZo4w.mjs.map} +1 -1
- package/dist/client/{DeletePcaModal-Dg9dej-H.mjs → DeletePcaModal-CIFsGWyj.mjs} +4 -4
- package/dist/client/{DeletePcaModal-Dg9dej-H.mjs.map → DeletePcaModal-CIFsGWyj.mjs.map} +1 -1
- package/dist/client/{DetailsInfo-DwCo9P1o.mjs → DetailsInfo-CHVD7d-W.mjs} +3 -3
- package/dist/client/{DetailsInfo-DwCo9P1o.mjs.map → DetailsInfo-CHVD7d-W.mjs.map} +1 -1
- package/dist/client/{FiltersInput-cOaaRpcQ.mjs → FiltersInput-DqT08Ib-.mjs} +2 -2
- package/dist/client/{FiltersInput-cOaaRpcQ.mjs.map → FiltersInput-DqT08Ib-.mjs.map} +1 -1
- package/dist/client/{FloatingIpActionModals-CDF8LVtX.mjs → FloatingIpActionModals-BcceUHcg.mjs} +4 -4
- package/dist/client/{FloatingIpActionModals-CDF8LVtX.mjs.map → FloatingIpActionModals-BcceUHcg.mjs.map} +1 -1
- package/dist/client/{ImageToastNotifications-Dzq6jNTm.mjs → ImageToastNotifications-BGyX2J6j.mjs} +5 -5
- package/dist/client/ImageToastNotifications-BGyX2J6j.mjs.map +1 -0
- package/dist/client/{RouteError-BmZRk_ss.mjs → RouteError-Rm08PcxN.mjs} +2 -2
- package/dist/client/{RouteError-BmZRk_ss.mjs.map → RouteError-Rm08PcxN.mjs.map} +1 -1
- package/dist/client/Slot-CWb612-_.mjs +28 -0
- package/dist/client/Slot-CWb612-_.mjs.map +1 -0
- package/dist/client/{SortInput-DjaEHvcO.mjs → SortInput-D_q_jDfe.mjs} +2 -2
- package/dist/client/{SortInput-DjaEHvcO.mjs.map → SortInput-D_q_jDfe.mjs.map} +1 -1
- package/dist/client/{StatusError-CLB026fg.mjs → StatusError-2ZU1gFpu.mjs} +2 -2
- package/dist/client/{StatusError-CLB026fg.mjs.map → StatusError-2ZU1gFpu.mjs.map} +1 -1
- package/dist/client/{_auth-Dut7CaMR.mjs → _auth-D5_QNUos.mjs} +2 -2
- package/dist/client/{_auth-Dut7CaMR.mjs.map → _auth-D5_QNUos.mjs.map} +1 -1
- package/dist/client/{_flavorId-Cu1nWwOq.mjs → _flavorId-BsmqS9hP.mjs} +7 -7
- package/dist/client/{_flavorId-Cu1nWwOq.mjs.map → _flavorId-BsmqS9hP.mjs.map} +1 -1
- package/dist/client/{_flavorId-BsIWL0XK.mjs → _flavorId-CFmkmg2Y.mjs} +2 -2
- package/dist/client/{_flavorId-BsIWL0XK.mjs.map → _flavorId-CFmkmg2Y.mjs.map} +1 -1
- package/dist/client/{_floatingIpId-B_M3gyMA.mjs → _floatingIpId-Bb9ZEJ6b.mjs} +6 -6
- package/dist/client/{_floatingIpId-B_M3gyMA.mjs.map → _floatingIpId-Bb9ZEJ6b.mjs.map} +1 -1
- package/dist/client/{_floatingIpId-8-UPUV8M.mjs → _floatingIpId-Dzh6_JCI.mjs} +2 -2
- package/dist/client/{_floatingIpId-8-UPUV8M.mjs.map → _floatingIpId-Dzh6_JCI.mjs.map} +1 -1
- package/dist/client/{_imageId-D1Z0xIco.mjs → _imageId-C3As7sHE.mjs} +5 -5
- package/dist/client/{_imageId-D1Z0xIco.mjs.map → _imageId-C3As7sHE.mjs.map} +1 -1
- package/dist/client/{_pcaId-BcwGho7g.mjs → _pcaId-n0q0aDb6.mjs} +6 -6
- package/dist/client/{_pcaId-BcwGho7g.mjs.map → _pcaId-n0q0aDb6.mjs.map} +1 -1
- package/dist/client/{_projectId-DJLjspKf.mjs → _projectId-BuBIFdgG.mjs} +25 -24
- package/dist/client/{_projectId-DJLjspKf.mjs.map → _projectId-BuBIFdgG.mjs.map} +1 -1
- package/dist/client/{_projectId-B4ScifQf.mjs → _projectId-CAQkJHZ4.mjs} +3 -3
- package/dist/client/{_projectId-B4ScifQf.mjs.map → _projectId-CAQkJHZ4.mjs.map} +1 -1
- package/dist/client/_projectId-D-b7paXE.mjs +29 -0
- package/dist/client/_projectId-D-b7paXE.mjs.map +1 -0
- package/dist/client/{_projectId-CYq4KZXB.mjs → _projectId-DNZsNxJw.mjs} +4 -4
- package/dist/client/{_projectId-CYq4KZXB.mjs.map → _projectId-DNZsNxJw.mjs.map} +1 -1
- package/dist/client/{_securityGroupId-B5-gJe1u.mjs → _securityGroupId-DFdNKa2l.mjs} +641 -504
- package/dist/client/_securityGroupId-DFdNKa2l.mjs.map +1 -0
- package/dist/client/{_securityGroupId-fPJWtDPU.mjs → _securityGroupId-DRkY3Gt6.mjs} +2 -2
- package/dist/client/_securityGroupId-DRkY3Gt6.mjs.map +1 -0
- package/dist/client/{_storageType-BkhbKG_G.mjs → _storageType-BKfQcpgp.mjs} +2 -2
- package/dist/client/{_storageType-BkhbKG_G.mjs.map → _storageType-BKfQcpgp.mjs.map} +1 -1
- package/dist/client/{_storageType-ByLL106s.mjs → _storageType-sMj9NEJz.mjs} +7 -7
- package/dist/client/{_storageType-ByLL106s.mjs.map → _storageType-sMj9NEJz.mjs.map} +1 -1
- package/dist/client/{about-B4sGnxeW.mjs → about-C8tTrQaW.mjs} +2 -2
- package/dist/client/{about-B4sGnxeW.mjs.map → about-C8tTrQaW.mjs.map} +1 -1
- package/dist/client/assets/objectDownload.worker-BAc5Au4B.js.map +1 -0
- package/dist/client/{aurora-Dp_NPGe8.mjs → aurora-jyvXcI4T.mjs} +2 -2
- package/dist/client/{aurora-Dp_NPGe8.mjs.map → aurora-jyvXcI4T.mjs.map} +1 -1
- package/dist/client/{build-DgeVmENN.mjs → build-CRLQyqu2.mjs} +2616 -3346
- package/dist/client/{build-DgeVmENN.mjs.map → build-CRLQyqu2.mjs.map} +1 -1
- package/dist/client/{flavors-CT1bHP61.mjs → flavors-BfTXqmoD.mjs} +6 -6
- package/dist/client/{flavors-CT1bHP61.mjs.map → flavors-BfTXqmoD.mjs.map} +1 -1
- package/dist/client/{flavors-q1j-y3e-.mjs → flavors-Dy-2mRGv.mjs} +2 -2
- package/dist/client/{flavors-q1j-y3e-.mjs.map → flavors-Dy-2mRGv.mjs.map} +1 -1
- package/dist/client/floatingips-zhNK6Xxn.mjs +562 -0
- package/dist/client/floatingips-zhNK6Xxn.mjs.map +1 -0
- package/dist/client/{hooks-D0wGUhRF.mjs → hooks-Bw3sHHOg.mjs} +2 -2
- package/dist/client/{hooks-D0wGUhRF.mjs.map → hooks-Bw3sHHOg.mjs.map} +1 -1
- package/dist/client/{images-CPYewah0.mjs → images-DPKUXryV.mjs} +2 -2
- package/dist/client/{images-CPYewah0.mjs.map → images-DPKUXryV.mjs.map} +1 -1
- package/dist/client/{images-BklcxYWi.mjs → images-DhZnqUG_.mjs} +29 -29
- package/dist/client/images-DhZnqUG_.mjs.map +1 -0
- package/dist/client/images-NBf2bV43.mjs.map +1 -1
- package/dist/client/index.js +301 -309
- package/dist/client/index.js.map +1 -1
- package/dist/client/{objects-DvIxpzGI.mjs → objects-BG1saVLZ.mjs} +1153 -862
- package/dist/client/objects-BG1saVLZ.mjs.map +1 -0
- package/dist/client/{objects-CEBrL7k-.mjs → objects-Dahys529.mjs} +2 -2
- package/dist/client/{objects-CEBrL7k-.mjs.map → objects-Dahys529.mjs.map} +1 -1
- package/dist/client/{pca-Ddk0YfgK.mjs → pca-B60iWWfG.mjs} +7 -7
- package/dist/client/{pca-Ddk0YfgK.mjs.map → pca-B60iWWfG.mjs.map} +1 -1
- package/dist/client/{pca-BAuZA0K3.mjs → pca-D0kKxHp4.mjs} +2 -2
- package/dist/client/{pca-BAuZA0K3.mjs.map → pca-D0kKxHp4.mjs.map} +1 -1
- package/dist/client/projects-yiK0HGSA.mjs.map +1 -1
- package/dist/client/routeInfo-CdTRlSxv.mjs +32 -0
- package/dist/client/routeInfo-CdTRlSxv.mjs.map +1 -0
- package/dist/client/{routes-BzBTVAjK.mjs → routes-BOf-GDMM.mjs} +41 -34
- package/dist/client/routes-BOf-GDMM.mjs.map +1 -0
- package/dist/client/{routes-DsisKFfG.mjs → routes-CtfnI-aY.mjs} +2 -2
- package/dist/client/routes-CtfnI-aY.mjs.map +1 -0
- package/dist/client/securitygroups-B8aLyFK7.mjs +17 -0
- package/dist/client/securitygroups-B8aLyFK7.mjs.map +1 -0
- package/dist/client/securitygroups-DRhFle2O.mjs +589 -0
- package/dist/client/securitygroups-DRhFle2O.mjs.map +1 -0
- package/dist/client/trpcClient-Di56hpVv.mjs +71 -0
- package/dist/client/trpcClient-Di56hpVv.mjs.map +1 -0
- package/dist/client/trpcClient.d.ts +40 -4
- package/dist/client/useListWithFiltering-aPTUNRaW.mjs +32 -0
- package/dist/client/useListWithFiltering-aPTUNRaW.mjs.map +1 -0
- package/dist/client/useSecurityGroupPermissions-BPS1ibWq.mjs +161 -0
- package/dist/client/useSecurityGroupPermissions-BPS1ibWq.mjs.map +1 -0
- package/dist/server/index.d.ts +56 -53
- package/dist/server/index.js +297 -20
- package/package.json +15 -15
- package/dist/client/EditSecurityGroupModal-BGPXglju.mjs +0 -137
- package/dist/client/EditSecurityGroupModal-BGPXglju.mjs.map +0 -1
- package/dist/client/ImageToastNotifications-Dzq6jNTm.mjs.map +0 -1
- package/dist/client/_projectId-DxgPaiA7.mjs +0 -25
- package/dist/client/_projectId-DxgPaiA7.mjs.map +0 -1
- package/dist/client/_securityGroupId-B5-gJe1u.mjs.map +0 -1
- package/dist/client/_securityGroupId-fPJWtDPU.mjs.map +0 -1
- package/dist/client/buildFilterParams-DoZzMKX9.mjs +0 -15
- package/dist/client/buildFilterParams-DoZzMKX9.mjs.map +0 -1
- package/dist/client/floatingips-DC5OrR8h.mjs +0 -434
- package/dist/client/floatingips-DC5OrR8h.mjs.map +0 -1
- package/dist/client/images-B5ktfqg6.mjs +0 -8
- package/dist/client/images-B5ktfqg6.mjs.map +0 -1
- package/dist/client/images-BklcxYWi.mjs.map +0 -1
- package/dist/client/objects-DvIxpzGI.mjs.map +0 -1
- package/dist/client/projects-DvSiI5Vg.mjs +0 -12
- package/dist/client/projects-DvSiI5Vg.mjs.map +0 -1
- package/dist/client/routeInfo-Ct5r4Gen.mjs +0 -56
- package/dist/client/routeInfo-Ct5r4Gen.mjs.map +0 -1
- package/dist/client/routes-BzBTVAjK.mjs.map +0 -1
- package/dist/client/routes-DsisKFfG.mjs.map +0 -1
- package/dist/client/securitygroups-JMvcJLpb.mjs +0 -440
- package/dist/client/securitygroups-JMvcJLpb.mjs.map +0 -1
- package/dist/client/trpcClient-BxcNKnhv.mjs +0 -65
- package/dist/client/trpcClient-BxcNKnhv.mjs.map +0 -1
- package/dist/client/useListWithFiltering-BuhE81I6.mjs +0 -157
- package/dist/client/useListWithFiltering-BuhE81I6.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-BG1saVLZ.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-Dahys529.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"objects-CEBrL7k-.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-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,12 +1,12 @@
|
|
|
1
|
-
import { A as e, B as t, C as n, E as r, G as i, H as a, K as o, P as s, R as c, U as l, Y as u, at as d, o as f, r as p, rt as m, tt as h, y as g } from "./build-
|
|
2
|
-
import {
|
|
3
|
-
import { t as v } from "./pca-
|
|
1
|
+
import { A as e, B as t, C as n, E as r, G as i, H as a, K as o, P as s, R as c, U as l, Y as u, at as d, o as f, r as p, rt as m, tt as h, y as g } from "./build-CRLQyqu2.mjs";
|
|
2
|
+
import { a as _ } from "./trpcClient-Di56hpVv.mjs";
|
|
3
|
+
import { t as v } from "./pca-D0kKxHp4.mjs";
|
|
4
4
|
import { t as y } from "./useProjectId-DBc5lpoU.mjs";
|
|
5
|
-
import "./hooks-
|
|
6
|
-
import { t as b } from "./ContentHeader-
|
|
5
|
+
import "./hooks-Bw3sHHOg.mjs";
|
|
6
|
+
import { t as b } from "./ContentHeader-9KZdhOoA.mjs";
|
|
7
7
|
import { t as x } from "./useModal-DCs1OJh7.mjs";
|
|
8
8
|
import { d as S, h as C, n as w, r as T, u as E } from "./md-CyCflQee.mjs";
|
|
9
|
-
import { t as D } from "./DeletePcaModal-
|
|
9
|
+
import { t as D } from "./DeletePcaModal-CIFsGWyj.mjs";
|
|
10
10
|
import { Fragment as O, jsx as k, jsxs as A } from "react/jsx-runtime";
|
|
11
11
|
import { useState as j } from "react";
|
|
12
12
|
import { useNavigate as M } from "@tanstack/react-router";
|
|
@@ -248,4 +248,4 @@ function W() {
|
|
|
248
248
|
//#endregion
|
|
249
249
|
export { W as component };
|
|
250
250
|
|
|
251
|
-
//# sourceMappingURL=pca-
|
|
251
|
+
//# sourceMappingURL=pca-B60iWWfG.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pca-Ddk0YfgK.mjs","names":["MdAutorenew","MdCheckCircle","MdHelpOutline","MdHourglassEmpty","MdReportProblem","useNavigate","DataGridCell","DataGridRow","PopupMenu","PopupMenuItem","PopupMenuOptions","useModal","useProjectId","DeletePcaModal","PcaTableRow","pca","useLingui","navigate","projectId","deletePcaModalOpen","toggleDeletePcaModal","navigateToDetailsPage","to","params","pcaId","id","STATE_CONFIG","CREATING","text","t","icon","size","color","fill","AWAITING_CERTIFICATE","READY","FAILED","UNEXPECTED","data-testid","onClick","div","className","state","display_subject","e","stopPropagation","label","open","onClose","z","useForm","useStore","useNavigate","Modal","Form","FormSection","Spinner","TextInput","Message","trpcReact","useProjectId","csrRegex","isValidCommonName","value","test","CreatePcaModal","open","onClose","useLingui","navigate","projectId","utils","useUtils","isPending","createPcaMutation","services","pca","create","useMutation","onSettled","list","invalidate","formSchema","object","common_name","string","trim","min","t","refine","message","form","defaultValues","validators","onSubmit","createdPca","mutateAsync","project_id","configuration","subject","named_attributes","cn","handleClose","to","params","pcaId","id","reset","isCreateDisabled","store","state","isSubmitting","values","length","size","title","onCancel","cancelButtonLabel","confirmButtonLabel","onConfirm","handleSubmit","disableConfirmButton","error","dismissible","variant","className","div","span","e","preventDefault","Field","name","children","field","onBlur","handleBlur","onChange","handleChange","target","label","placeholder","helptext","errortext","meta","errors","map","join","disabled","useState","Stack","Spinner","DataGrid","DataGridRow","DataGridCell","ContentHeading","DataGridHeadCell","Button","Pagination","trpcReact","useProjectId","useModal","PcaTableRow","CreatePcaModal","ITEMS_PER_PAGE","PcaListContainer","useLingui","projectId","createCaOpen","toggleCreateCa","pageMarkers","setPageMarkers","undefined","currentPage","setCurrentPage","currentMarker","data","isLoading","isError","error","services","pca","list","useQuery","project_id","limit","next_page_marker","pcas","certificate_authorities","nextMarker","computedTotal","totalPages","Math","max","length","goToPage","page","prev","updated","className","distribution","alignment","direction","variant","size","message","t","TABLE_COLUMNS","columnsLength","div","label","onClick","columns","data-testid","colSpan","p","map","id","pages","onPressPrevious","onPressNext","open","onClose","useLingui","ContentHeader","PcaListContainer","Route","RouteComponent","t","projectId","useParams","component"],"sources":["../../src/client/routes/_auth/projects/$projectId/services/pca/-components/-table/PcaTableRow.tsx","../../src/client/routes/_auth/projects/$projectId/services/pca/-components/-modals/CreatePcaModal.tsx","../../src/client/routes/_auth/projects/$projectId/services/pca/-components/-table/PcaListContainer.tsx","../../src/client/routes/_auth/projects/$projectId/services/pca/index.tsx?tsr-split=component"],"sourcesContent":["import { MdAutorenew, MdCheckCircle, MdHelpOutline, MdHourglassEmpty, MdReportProblem } from \"react-icons/md\"\nimport { useNavigate } from \"@tanstack/react-router\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport {\n DataGridCell,\n DataGridRow,\n PopupMenu,\n PopupMenuItem,\n PopupMenuOptions,\n} from \"@cloudoperators/juno-ui-components\"\nimport { CertificateAuthority } from \"@/server/Services/types/pca\"\nimport { useModal } from \"@/client/utils/useModal\"\nimport { useProjectId } from \"@/client/hooks\"\nimport { DeletePcaModal } from \"../-modals/DeletePcaModal\"\n\ninterface PcaTableRowProps {\n pca: CertificateAuthority\n}\n\nexport const PcaTableRow = ({ pca }: PcaTableRowProps) => {\n const { t } = useLingui()\n const navigate = useNavigate()\n const projectId = useProjectId()\n const [deletePcaModalOpen, toggleDeletePcaModal] = useModal(false)\n\n const navigateToDetailsPage = () =>\n navigate({\n to: \"/projects/$projectId/services/pca/$pcaId\",\n params: { projectId, pcaId: pca.id },\n })\n\n const STATE_CONFIG = {\n CREATING: {\n text: t`Creating`,\n icon: <MdAutorenew size={20} color=\"white\" fill=\"#1976D2\" />,\n },\n AWAITING_CERTIFICATE: {\n text: t`Awaiting Certificate`,\n icon: <MdHourglassEmpty size={20} color=\"white\" fill=\"#FBC02D\" />,\n },\n READY: {\n text: t`Ready`,\n icon: <MdCheckCircle size={20} color=\"white\" fill=\"#4FB81C\" />,\n },\n FAILED: {\n text: t`Failed`,\n icon: <MdReportProblem size={20} color=\"white\" fill=\"#D32F2F\" />,\n },\n UNEXPECTED: {\n text: t`Unexpected`,\n icon: <MdHelpOutline size={20} color=\"white\" fill=\"#757575\" />,\n },\n } as const\n\n return (\n <>\n <DataGridRow key={pca.id} data-testid={`pca-row-${pca.id}`} onClick={navigateToDetailsPage}>\n <DataGridCell>\n <div className=\"flex items-center gap-2\">\n {STATE_CONFIG[pca.state].icon}\n {STATE_CONFIG[pca.state].text}\n </div>\n </DataGridCell>\n <DataGridCell>{pca.id}</DataGridCell>\n <DataGridCell>{pca.display_subject || \"—\"}</DataGridCell>\n <DataGridCell onClick={(e) => e.stopPropagation()} className=\"items-end pr-0\">\n <PopupMenu>\n <PopupMenuOptions>\n <PopupMenuItem label={t`Show Details`} onClick={navigateToDetailsPage} />\n <PopupMenuItem label={t`Delete CA`} onClick={toggleDeletePcaModal} />\n </PopupMenuOptions>\n </PopupMenu>\n </DataGridCell>\n </DataGridRow>\n\n {deletePcaModalOpen && <DeletePcaModal pca={pca} open={deletePcaModalOpen} onClose={toggleDeletePcaModal} />}\n </>\n )\n}\n","import { z } from \"zod\"\nimport { useForm, useStore } from \"@tanstack/react-form\"\nimport { useNavigate } from \"@tanstack/react-router\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { Modal, Form, FormSection, Spinner, TextInput, Message } from \"@cloudoperators/juno-ui-components\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { useProjectId } from \"@/client/hooks\"\n\ninterface CreatePcaModalProps {\n open: boolean\n onClose: () => void\n}\n\nconst csrRegex = /^(?=.{1,253}$)(?:\\*\\.)?(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\\.)+[A-Za-z]{2,63}$/\nconst isValidCommonName = (value: string) => csrRegex.test(value)\n\nexport const CreatePcaModal = ({ open, onClose }: CreatePcaModalProps) => {\n const { t } = useLingui()\n const navigate = useNavigate()\n const projectId = useProjectId()\n const utils = trpcReact.useUtils()\n\n const { isPending, ...createPcaMutation } = trpcReact.services.pca.create.useMutation({\n onSettled: () => utils.services.pca.list.invalidate(),\n })\n\n const formSchema = z.object({\n common_name: z\n .string()\n .trim()\n .min(1, t`Common name is required.`)\n .refine((value) => isValidCommonName(value), { message: t`Must be a valid common name (FQDN).` }),\n })\n\n const form = useForm({\n defaultValues: {\n common_name: \"\",\n },\n validators: {\n onSubmit: formSchema,\n },\n onSubmit: async ({ value }) => {\n if (isPending) return\n\n const createdPca = await createPcaMutation.mutateAsync({\n project_id: projectId,\n configuration: {\n subject: {\n named_attributes: {\n cn: value.common_name,\n },\n },\n },\n })\n handleClose()\n\n await navigate({\n to: \"/projects/$projectId/services/pca/$pcaId\",\n params: { projectId, pcaId: createdPca.id },\n })\n },\n })\n\n const handleClose = () => {\n if (isPending) return\n\n form.reset()\n createPcaMutation.reset()\n onClose()\n }\n\n // Reactive subscription used to control create action disabled state.\n const isCreateDisabled = useStore(\n form.store,\n (state) => state.isSubmitting || state.values.common_name.trim().length === 0\n )\n\n return (\n <Modal\n open={open}\n size=\"large\"\n title={t`Create Certificate Authority`}\n onCancel={handleClose}\n cancelButtonLabel={t`Cancel`}\n confirmButtonLabel={t`Save`}\n onConfirm={form.handleSubmit}\n disableConfirmButton={isPending || isCreateDisabled}\n >\n {createPcaMutation.error?.message && (\n <Message dismissible={false} variant=\"error\" className=\"mb-4\">\n {createPcaMutation.error.message}\n </Message>\n )}\n\n {isPending && (\n <div className=\"mb-4 flex items-center justify-center gap-2\">\n <Spinner variant=\"primary\" />\n <span className=\"text-theme-high text-sm\">\n <Trans>Creating Certificate Authority...</Trans>\n </span>\n </div>\n )}\n\n {!isPending && (\n <Form\n className=\"mb-0\"\n id=\"create-certificate-authority-form\"\n onSubmit={(e) => {\n e.preventDefault()\n form.handleSubmit()\n }}\n >\n <FormSection className=\"mb-4\">\n <form.Field\n name=\"common_name\"\n children={(field) => (\n <TextInput\n id={field.name}\n name={field.name}\n value={field.state.value}\n onBlur={field.handleBlur}\n onChange={(e) => field.handleChange(e.target.value)}\n label={t`Common name`}\n placeholder={t`Enter Common name (e.g., demo-ca.test.sci)`}\n helptext={t`Enter a valid common name in FQDN format (e.g., demo-ca.test.sci).`}\n errortext={field.state.meta.errors.map((e) => e?.message).join(\", \")}\n disabled={isPending}\n />\n )}\n />\n </FormSection>\n </Form>\n )}\n </Modal>\n )\n}\n","import { Trans, useLingui } from \"@lingui/react/macro\"\nimport { useState } from \"react\"\nimport {\n Stack,\n Spinner,\n DataGrid,\n DataGridRow,\n DataGridCell,\n ContentHeading,\n DataGridHeadCell,\n Button,\n Pagination,\n} from \"@cloudoperators/juno-ui-components\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { useProjectId } from \"@/client/hooks\"\nimport { useModal } from \"@/client/utils/useModal\"\nimport { PcaTableRow } from \"./PcaTableRow\"\nimport { CreatePcaModal } from \"../-modals/CreatePcaModal\"\n\nconst ITEMS_PER_PAGE = 50\n\nexport const PcaListContainer = () => {\n const { t } = useLingui()\n const projectId = useProjectId()\n const [createCaOpen, toggleCreateCa] = useModal(false)\n const [pageMarkers, setPageMarkers] = useState<(string | undefined)[]>([undefined])\n const [currentPage, setCurrentPage] = useState(1)\n const currentMarker = pageMarkers[currentPage - 1]\n\n const { data, isLoading, isError, error } = trpcReact.services.pca.list.useQuery({\n project_id: projectId,\n limit: ITEMS_PER_PAGE,\n next_page_marker: currentMarker,\n })\n\n const pcas = data?.certificate_authorities ?? []\n const nextMarker = data?.next_page_marker\n const computedTotal = nextMarker ? currentPage + 1 : currentPage\n const totalPages = Math.max(computedTotal, pageMarkers.length)\n\n const goToPage = (page: number) => {\n if (page < 1 || page > totalPages) return\n if (page > currentPage && nextMarker) {\n setPageMarkers((prev) => {\n const updated = [...prev]\n updated[page - 1] = nextMarker\n return updated\n })\n }\n setCurrentPage(page)\n }\n\n if (isLoading) {\n return (\n <Stack className=\"py-8\" distribution=\"center\" alignment=\"center\" direction=\"vertical\">\n <Spinner variant=\"primary\" size=\"large\" className=\"mb-2\" />\n <Trans>Loading...</Trans>\n </Stack>\n )\n }\n\n if (isError) {\n return (\n <Stack className=\"py-8\" distribution=\"center\" alignment=\"center\" direction=\"vertical\">\n {error?.message ?? t`Failed to load PCAs`}\n </Stack>\n )\n }\n\n const TABLE_COLUMNS = [\n t`State`,\n t`ID`,\n t`Subject information`,\n \"\", // empty column for item-action with context menu containing \"Delete CA\" button\n ] as const\n const columnsLength = TABLE_COLUMNS.length\n\n return (\n <div className=\"relative\">\n <Stack className=\"pt-3 pb-2\" distribution=\"end\">\n <Button variant=\"primary\" label={t`Create Certificate Authority`} onClick={toggleCreateCa} />\n </Stack>\n\n {pcas.length === 0 && currentPage === 1 ? (\n <DataGrid columns={columnsLength} className=\"pca\" data-testid=\"no-pcas\">\n <DataGridRow>\n <DataGridCell colSpan={columnsLength}>\n <ContentHeading>\n <Trans>No PCAs found</Trans>\n </ContentHeading>\n <p>\n <Trans>There are no PCAs available for this project.</Trans>\n </p>\n </DataGridCell>\n </DataGridRow>\n </DataGrid>\n ) : (\n <>\n <DataGrid columns={columnsLength}>\n <DataGridRow>\n {TABLE_COLUMNS.map((label) => (\n <DataGridHeadCell key={label}>{label}</DataGridHeadCell>\n ))}\n </DataGridRow>\n {pcas.map((pca) => (\n <PcaTableRow key={pca.id} pca={pca} />\n ))}\n </DataGrid>\n\n {totalPages > 1 && (\n <div className=\"flex justify-center py-4\">\n <Pagination\n variant=\"input\"\n currentPage={currentPage}\n pages={totalPages}\n onPressPrevious={() => goToPage(currentPage - 1)}\n onPressNext={() => goToPage(currentPage + 1)}\n />\n </div>\n )}\n </>\n )}\n\n {createCaOpen && <CreatePcaModal open={createCaOpen} onClose={toggleCreateCa} />}\n </div>\n )\n}\n","import { createFileRoute, redirect } from \"@tanstack/react-router\"\nimport { t } from \"@lingui/core/macro\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { getServiceIndex } from \"@/server/Authentication/helpers\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { ContentHeader } from \"@/client/components/ContentHeader/ContentHeader\"\nimport { canAccessClavisPca } from \"./-components/pcaAccess\"\nimport { PcaListContainer } from \"./-components/-table/PcaListContainer\"\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/services/pca/\")({\n staticData: {\n section: \"services\",\n service: \"pca\",\n analytics: {\n name: \"services.pca.list\",\n },\n sectionCrumb: { labelKey: \"Services\" },\n crumb: { labelKey: \"PCA (Clavis)\" },\n } satisfies RouteInfo,\n head: () => ({ meta: [{ title: t`PCA` }] }),\n beforeLoad: async ({ context, params }) => {\n const availableServices = (await context.trpcClient?.auth.getAvailableServices.query()) || []\n const serviceIndex = getServiceIndex(availableServices)\n\n if (!canAccessClavisPca(serviceIndex, context.enabledServices)) {\n throw redirect({\n to: \"/projects/$projectId\",\n params: { projectId: params.projectId },\n })\n }\n },\n component: RouteComponent,\n})\n\nfunction RouteComponent() {\n const { t } = useLingui()\n const { projectId } = Route.useParams()\n\n return (\n <>\n <ContentHeader title={t`PCA`} projectId={projectId} />\n <PcaListContainer />\n </>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pca-B60iWWfG.mjs","names":["MdAutorenew","MdCheckCircle","MdHelpOutline","MdHourglassEmpty","MdReportProblem","useNavigate","DataGridCell","DataGridRow","PopupMenu","PopupMenuItem","PopupMenuOptions","useModal","useProjectId","DeletePcaModal","PcaTableRow","pca","useLingui","navigate","projectId","deletePcaModalOpen","toggleDeletePcaModal","navigateToDetailsPage","to","params","pcaId","id","STATE_CONFIG","CREATING","text","t","icon","size","color","fill","AWAITING_CERTIFICATE","READY","FAILED","UNEXPECTED","data-testid","onClick","div","className","state","display_subject","e","stopPropagation","label","open","onClose","z","useForm","useStore","useNavigate","Modal","Form","FormSection","Spinner","TextInput","Message","trpcReact","useProjectId","csrRegex","isValidCommonName","value","test","CreatePcaModal","open","onClose","useLingui","navigate","projectId","utils","useUtils","isPending","createPcaMutation","services","pca","create","useMutation","onSettled","list","invalidate","formSchema","object","common_name","string","trim","min","t","refine","message","form","defaultValues","validators","onSubmit","createdPca","mutateAsync","project_id","configuration","subject","named_attributes","cn","handleClose","to","params","pcaId","id","reset","isCreateDisabled","store","state","isSubmitting","values","length","size","title","onCancel","cancelButtonLabel","confirmButtonLabel","onConfirm","handleSubmit","disableConfirmButton","error","dismissible","variant","className","div","span","e","preventDefault","Field","name","children","field","onBlur","handleBlur","onChange","handleChange","target","label","placeholder","helptext","errortext","meta","errors","map","join","disabled","useState","Stack","Spinner","DataGrid","DataGridRow","DataGridCell","ContentHeading","DataGridHeadCell","Button","Pagination","trpcReact","useProjectId","useModal","PcaTableRow","CreatePcaModal","ITEMS_PER_PAGE","PcaListContainer","useLingui","projectId","createCaOpen","toggleCreateCa","pageMarkers","setPageMarkers","undefined","currentPage","setCurrentPage","currentMarker","data","isLoading","isError","error","services","pca","list","useQuery","project_id","limit","next_page_marker","pcas","certificate_authorities","nextMarker","computedTotal","totalPages","Math","max","length","goToPage","page","prev","updated","className","distribution","alignment","direction","variant","size","message","t","TABLE_COLUMNS","columnsLength","div","label","onClick","columns","data-testid","colSpan","p","map","id","pages","onPressPrevious","onPressNext","open","onClose","useLingui","ContentHeader","PcaListContainer","Route","RouteComponent","t","projectId","useParams","component"],"sources":["../../src/client/routes/_auth/projects/$projectId/services/pca/-components/-table/PcaTableRow.tsx","../../src/client/routes/_auth/projects/$projectId/services/pca/-components/-modals/CreatePcaModal.tsx","../../src/client/routes/_auth/projects/$projectId/services/pca/-components/-table/PcaListContainer.tsx","../../src/client/routes/_auth/projects/$projectId/services/pca/index.tsx?tsr-split=component"],"sourcesContent":["import { MdAutorenew, MdCheckCircle, MdHelpOutline, MdHourglassEmpty, MdReportProblem } from \"react-icons/md\"\nimport { useNavigate } from \"@tanstack/react-router\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport {\n DataGridCell,\n DataGridRow,\n PopupMenu,\n PopupMenuItem,\n PopupMenuOptions,\n} from \"@cloudoperators/juno-ui-components\"\nimport { CertificateAuthority } from \"@/server/Services/types/pca\"\nimport { useModal } from \"@/client/utils/useModal\"\nimport { useProjectId } from \"@/client/hooks\"\nimport { DeletePcaModal } from \"../-modals/DeletePcaModal\"\n\ninterface PcaTableRowProps {\n pca: CertificateAuthority\n}\n\nexport const PcaTableRow = ({ pca }: PcaTableRowProps) => {\n const { t } = useLingui()\n const navigate = useNavigate()\n const projectId = useProjectId()\n const [deletePcaModalOpen, toggleDeletePcaModal] = useModal(false)\n\n const navigateToDetailsPage = () =>\n navigate({\n to: \"/projects/$projectId/services/pca/$pcaId\",\n params: { projectId, pcaId: pca.id },\n })\n\n const STATE_CONFIG = {\n CREATING: {\n text: t`Creating`,\n icon: <MdAutorenew size={20} color=\"white\" fill=\"#1976D2\" />,\n },\n AWAITING_CERTIFICATE: {\n text: t`Awaiting Certificate`,\n icon: <MdHourglassEmpty size={20} color=\"white\" fill=\"#FBC02D\" />,\n },\n READY: {\n text: t`Ready`,\n icon: <MdCheckCircle size={20} color=\"white\" fill=\"#4FB81C\" />,\n },\n FAILED: {\n text: t`Failed`,\n icon: <MdReportProblem size={20} color=\"white\" fill=\"#D32F2F\" />,\n },\n UNEXPECTED: {\n text: t`Unexpected`,\n icon: <MdHelpOutline size={20} color=\"white\" fill=\"#757575\" />,\n },\n } as const\n\n return (\n <>\n <DataGridRow key={pca.id} data-testid={`pca-row-${pca.id}`} onClick={navigateToDetailsPage}>\n <DataGridCell>\n <div className=\"flex items-center gap-2\">\n {STATE_CONFIG[pca.state].icon}\n {STATE_CONFIG[pca.state].text}\n </div>\n </DataGridCell>\n <DataGridCell>{pca.id}</DataGridCell>\n <DataGridCell>{pca.display_subject || \"—\"}</DataGridCell>\n <DataGridCell onClick={(e) => e.stopPropagation()} className=\"items-end pr-0\">\n <PopupMenu>\n <PopupMenuOptions>\n <PopupMenuItem label={t`Show Details`} onClick={navigateToDetailsPage} />\n <PopupMenuItem label={t`Delete CA`} onClick={toggleDeletePcaModal} />\n </PopupMenuOptions>\n </PopupMenu>\n </DataGridCell>\n </DataGridRow>\n\n {deletePcaModalOpen && <DeletePcaModal pca={pca} open={deletePcaModalOpen} onClose={toggleDeletePcaModal} />}\n </>\n )\n}\n","import { z } from \"zod\"\nimport { useForm, useStore } from \"@tanstack/react-form\"\nimport { useNavigate } from \"@tanstack/react-router\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { Modal, Form, FormSection, Spinner, TextInput, Message } from \"@cloudoperators/juno-ui-components\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { useProjectId } from \"@/client/hooks\"\n\ninterface CreatePcaModalProps {\n open: boolean\n onClose: () => void\n}\n\nconst csrRegex = /^(?=.{1,253}$)(?:\\*\\.)?(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\\.)+[A-Za-z]{2,63}$/\nconst isValidCommonName = (value: string) => csrRegex.test(value)\n\nexport const CreatePcaModal = ({ open, onClose }: CreatePcaModalProps) => {\n const { t } = useLingui()\n const navigate = useNavigate()\n const projectId = useProjectId()\n const utils = trpcReact.useUtils()\n\n const { isPending, ...createPcaMutation } = trpcReact.services.pca.create.useMutation({\n onSettled: () => utils.services.pca.list.invalidate(),\n })\n\n const formSchema = z.object({\n common_name: z\n .string()\n .trim()\n .min(1, t`Common name is required.`)\n .refine((value) => isValidCommonName(value), { message: t`Must be a valid common name (FQDN).` }),\n })\n\n const form = useForm({\n defaultValues: {\n common_name: \"\",\n },\n validators: {\n onSubmit: formSchema,\n },\n onSubmit: async ({ value }) => {\n if (isPending) return\n\n const createdPca = await createPcaMutation.mutateAsync({\n project_id: projectId,\n configuration: {\n subject: {\n named_attributes: {\n cn: value.common_name,\n },\n },\n },\n })\n handleClose()\n\n await navigate({\n to: \"/projects/$projectId/services/pca/$pcaId\",\n params: { projectId, pcaId: createdPca.id },\n })\n },\n })\n\n const handleClose = () => {\n if (isPending) return\n\n form.reset()\n createPcaMutation.reset()\n onClose()\n }\n\n // Reactive subscription used to control create action disabled state.\n const isCreateDisabled = useStore(\n form.store,\n (state) => state.isSubmitting || state.values.common_name.trim().length === 0\n )\n\n return (\n <Modal\n open={open}\n size=\"large\"\n title={t`Create Certificate Authority`}\n onCancel={handleClose}\n cancelButtonLabel={t`Cancel`}\n confirmButtonLabel={t`Save`}\n onConfirm={form.handleSubmit}\n disableConfirmButton={isPending || isCreateDisabled}\n >\n {createPcaMutation.error?.message && (\n <Message dismissible={false} variant=\"error\" className=\"mb-4\">\n {createPcaMutation.error.message}\n </Message>\n )}\n\n {isPending && (\n <div className=\"mb-4 flex items-center justify-center gap-2\">\n <Spinner variant=\"primary\" />\n <span className=\"text-theme-high text-sm\">\n <Trans>Creating Certificate Authority...</Trans>\n </span>\n </div>\n )}\n\n {!isPending && (\n <Form\n className=\"mb-0\"\n id=\"create-certificate-authority-form\"\n onSubmit={(e) => {\n e.preventDefault()\n form.handleSubmit()\n }}\n >\n <FormSection className=\"mb-4\">\n <form.Field\n name=\"common_name\"\n children={(field) => (\n <TextInput\n id={field.name}\n name={field.name}\n value={field.state.value}\n onBlur={field.handleBlur}\n onChange={(e) => field.handleChange(e.target.value)}\n label={t`Common name`}\n placeholder={t`Enter Common name (e.g., demo-ca.test.sci)`}\n helptext={t`Enter a valid common name in FQDN format (e.g., demo-ca.test.sci).`}\n errortext={field.state.meta.errors.map((e) => e?.message).join(\", \")}\n disabled={isPending}\n />\n )}\n />\n </FormSection>\n </Form>\n )}\n </Modal>\n )\n}\n","import { Trans, useLingui } from \"@lingui/react/macro\"\nimport { useState } from \"react\"\nimport {\n Stack,\n Spinner,\n DataGrid,\n DataGridRow,\n DataGridCell,\n ContentHeading,\n DataGridHeadCell,\n Button,\n Pagination,\n} from \"@cloudoperators/juno-ui-components\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { useProjectId } from \"@/client/hooks\"\nimport { useModal } from \"@/client/utils/useModal\"\nimport { PcaTableRow } from \"./PcaTableRow\"\nimport { CreatePcaModal } from \"../-modals/CreatePcaModal\"\n\nconst ITEMS_PER_PAGE = 50\n\nexport const PcaListContainer = () => {\n const { t } = useLingui()\n const projectId = useProjectId()\n const [createCaOpen, toggleCreateCa] = useModal(false)\n const [pageMarkers, setPageMarkers] = useState<(string | undefined)[]>([undefined])\n const [currentPage, setCurrentPage] = useState(1)\n const currentMarker = pageMarkers[currentPage - 1]\n\n const { data, isLoading, isError, error } = trpcReact.services.pca.list.useQuery({\n project_id: projectId,\n limit: ITEMS_PER_PAGE,\n next_page_marker: currentMarker,\n })\n\n const pcas = data?.certificate_authorities ?? []\n const nextMarker = data?.next_page_marker\n const computedTotal = nextMarker ? currentPage + 1 : currentPage\n const totalPages = Math.max(computedTotal, pageMarkers.length)\n\n const goToPage = (page: number) => {\n if (page < 1 || page > totalPages) return\n if (page > currentPage && nextMarker) {\n setPageMarkers((prev) => {\n const updated = [...prev]\n updated[page - 1] = nextMarker\n return updated\n })\n }\n setCurrentPage(page)\n }\n\n if (isLoading) {\n return (\n <Stack className=\"py-8\" distribution=\"center\" alignment=\"center\" direction=\"vertical\">\n <Spinner variant=\"primary\" size=\"large\" className=\"mb-2\" />\n <Trans>Loading...</Trans>\n </Stack>\n )\n }\n\n if (isError) {\n return (\n <Stack className=\"py-8\" distribution=\"center\" alignment=\"center\" direction=\"vertical\">\n {error?.message ?? t`Failed to load PCAs`}\n </Stack>\n )\n }\n\n const TABLE_COLUMNS = [\n t`State`,\n t`ID`,\n t`Subject information`,\n \"\", // empty column for item-action with context menu containing \"Delete CA\" button\n ] as const\n const columnsLength = TABLE_COLUMNS.length\n\n return (\n <div className=\"relative\">\n <Stack className=\"pt-3 pb-2\" distribution=\"end\">\n <Button variant=\"primary\" label={t`Create Certificate Authority`} onClick={toggleCreateCa} />\n </Stack>\n\n {pcas.length === 0 && currentPage === 1 ? (\n <DataGrid columns={columnsLength} className=\"pca\" data-testid=\"no-pcas\">\n <DataGridRow>\n <DataGridCell colSpan={columnsLength}>\n <ContentHeading>\n <Trans>No PCAs found</Trans>\n </ContentHeading>\n <p>\n <Trans>There are no PCAs available for this project.</Trans>\n </p>\n </DataGridCell>\n </DataGridRow>\n </DataGrid>\n ) : (\n <>\n <DataGrid columns={columnsLength}>\n <DataGridRow>\n {TABLE_COLUMNS.map((label) => (\n <DataGridHeadCell key={label}>{label}</DataGridHeadCell>\n ))}\n </DataGridRow>\n {pcas.map((pca) => (\n <PcaTableRow key={pca.id} pca={pca} />\n ))}\n </DataGrid>\n\n {totalPages > 1 && (\n <div className=\"flex justify-center py-4\">\n <Pagination\n variant=\"input\"\n currentPage={currentPage}\n pages={totalPages}\n onPressPrevious={() => goToPage(currentPage - 1)}\n onPressNext={() => goToPage(currentPage + 1)}\n />\n </div>\n )}\n </>\n )}\n\n {createCaOpen && <CreatePcaModal open={createCaOpen} onClose={toggleCreateCa} />}\n </div>\n )\n}\n","import { createFileRoute, redirect } from \"@tanstack/react-router\"\nimport { t } from \"@lingui/core/macro\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { getServiceIndex } from \"@/server/Authentication/helpers\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { ContentHeader } from \"@/client/components/ContentHeader/ContentHeader\"\nimport { canAccessClavisPca } from \"./-components/pcaAccess\"\nimport { PcaListContainer } from \"./-components/-table/PcaListContainer\"\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/services/pca/\")({\n staticData: {\n section: \"services\",\n service: \"pca\",\n analytics: {\n name: \"services.pca.list\",\n },\n sectionCrumb: { labelKey: \"Services\" },\n crumb: { labelKey: \"PCA (Clavis)\" },\n } satisfies RouteInfo,\n head: () => ({ meta: [{ title: t`PCA` }] }),\n beforeLoad: async ({ context, params }) => {\n const availableServices = (await context.trpcClient?.auth.getAvailableServices.query()) || []\n const serviceIndex = getServiceIndex(availableServices)\n\n if (!canAccessClavisPca(serviceIndex, context.enabledServices)) {\n throw redirect({\n to: \"/projects/$projectId\",\n params: { projectId: params.projectId },\n })\n }\n },\n component: RouteComponent,\n})\n\nfunction RouteComponent() {\n const { t } = useLingui()\n const { projectId } = Route.useParams()\n\n return (\n <>\n <ContentHeader title={t`PCA`} projectId={projectId} />\n <PcaListContainer />\n </>\n )\n}\n"],"mappings":"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"}
|
|
@@ -17,9 +17,9 @@ var o = n("/_auth/projects/$projectId/services/pca/")({
|
|
|
17
17
|
params: { projectId: r.projectId }
|
|
18
18
|
});
|
|
19
19
|
},
|
|
20
|
-
component: r(() => import("./pca-
|
|
20
|
+
component: r(() => import("./pca-B60iWWfG.mjs"), "component")
|
|
21
21
|
});
|
|
22
22
|
//#endregion
|
|
23
23
|
export { o as t };
|
|
24
24
|
|
|
25
|
-
//# sourceMappingURL=pca-
|
|
25
|
+
//# sourceMappingURL=pca-D0kKxHp4.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pca-
|
|
1
|
+
{"version":3,"file":"pca-D0kKxHp4.mjs","names":["createFileRoute","redirect","t","getServiceIndex","canAccessClavisPca","Route","staticData","section","service","analytics","name","sectionCrumb","labelKey","crumb","RouteInfo","head","meta","title","beforeLoad","context","params","availableServices","trpcClient","auth","getAvailableServices","query","serviceIndex","enabledServices","to","projectId","component","lazyRouteComponent","$$splitComponentImporter"],"sources":["../../src/client/routes/_auth/projects/$projectId/services/pca/index.tsx"],"sourcesContent":["import { createFileRoute, redirect } from \"@tanstack/react-router\"\nimport { t } from \"@lingui/core/macro\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { getServiceIndex } from \"@/server/Authentication/helpers\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { ContentHeader } from \"@/client/components/ContentHeader/ContentHeader\"\nimport { canAccessClavisPca } from \"./-components/pcaAccess\"\nimport { PcaListContainer } from \"./-components/-table/PcaListContainer\"\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/services/pca/\")({\n staticData: {\n section: \"services\",\n service: \"pca\",\n analytics: {\n name: \"services.pca.list\",\n },\n sectionCrumb: { labelKey: \"Services\" },\n crumb: { labelKey: \"PCA (Clavis)\" },\n } satisfies RouteInfo,\n head: () => ({ meta: [{ title: t`PCA` }] }),\n beforeLoad: async ({ context, params }) => {\n const availableServices = (await context.trpcClient?.auth.getAvailableServices.query()) || []\n const serviceIndex = getServiceIndex(availableServices)\n\n if (!canAccessClavisPca(serviceIndex, context.enabledServices)) {\n throw redirect({\n to: \"/projects/$projectId\",\n params: { projectId: params.projectId },\n })\n }\n },\n component: RouteComponent,\n})\n\nfunction RouteComponent() {\n const { t } = useLingui()\n const { projectId } = Route.useParams()\n\n return (\n <>\n <ContentHeader title={t`PCA`} projectId={projectId} />\n <PcaListContainer />\n </>\n )\n}\n"],"mappings":";;;;AASA,IAAaK,IAAQL,EAAgB,0CAAA,EAA4C;CAC/EM,YAAY;EACVC,SAAS;EACTC,SAAS;EACTC,WAAW,EACTC,MAAM,oBACR;EACAC,cAAc,EAAEC,UAAU,WAAW;EACrCC,OAAO,EAAED,UAAU,eAAe;CACpC;CACAG,aAAa,EAAEC,MAAM,CAAC,EAAEC,OAAOf,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA,EAAM,CAAA,EAAG;CACzCgB,YAAY,OAAO,EAAEC,YAASC,gBAAQ;EAIpC,IAAI,CAAChB,EAFgBD,EADK,MAAOgB,EAAQG,YAAYC,KAAKC,qBAAqBC,MAAAA,KAAY,CAAA,CAGnEC,GAAcP,EAAQQ,eAAe,GAC3D,MAAM1B,EAAS;GACb2B,IAAI;GACJR,QAAQ,EAAES,WAAWT,EAAOS,UAAU;EACxC,CAAA;CAEJ;CACAC,WAASC,sCAAA,WAAA;AACX,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projects-yiK0HGSA.mjs","names":["ProjectsContentProps","search","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/Error/RouteError\"\nimport { TRPCClientError } from \"@trpc/client\"\nimport { Container, ContentHeading, Spinner, Stack } from \"@cloudoperators/juno-ui-components\"\nimport { Trans } 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
|
|
1
|
+
{"version":3,"file":"projects-yiK0HGSA.mjs","names":["ProjectsContentProps","search","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/Error/RouteError\"\nimport { TRPCClientError } from \"@trpc/client\"\nimport { Container, ContentHeading, Spinner, Stack } from \"@cloudoperators/juno-ui-components\"\nimport { Trans } 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 search: string\n}\n\nfunction ProjectsContent({ search }: ProjectsContentProps) {\n const [allProjects] = trpcReact.project.getAuthProjects.useSuspenseQuery()\n\n const normalizedSearch = search.trim().toLowerCase()\n const projects =\n allProjects && normalizedSearch\n ? allProjects.filter(\n (project) =>\n project.name?.toLowerCase().includes(normalizedSearch) ||\n project.description?.toLowerCase().includes(normalizedSearch)\n )\n : allProjects\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\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\n fallback={\n <Stack distribution=\"center\" alignment=\"center\" direction=\"vertical\" className=\"py-12\">\n <Spinner variant=\"primary\" size=\"large\" />\n </Stack>\n }\n >\n <ProjectsContent search={search} />\n </Suspense>\n </div>\n </ErrorBoundary>\n </Container>\n )\n}\n"],"mappings":";;AAiCC,IAAAE,UAPU,gBAAC,KAAA,EAAA,UAAE,qBAAA,CAAA"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { z as e } from "zod";
|
|
2
|
+
var t = e.object({
|
|
3
|
+
labelKey: e.enum([
|
|
4
|
+
"Compute",
|
|
5
|
+
"Network",
|
|
6
|
+
"Storage",
|
|
7
|
+
"Services",
|
|
8
|
+
"Images",
|
|
9
|
+
"Flavors",
|
|
10
|
+
"Security Groups",
|
|
11
|
+
"Floating IPs",
|
|
12
|
+
"PCA (Clavis)"
|
|
13
|
+
]).optional(),
|
|
14
|
+
to: e.string().optional(),
|
|
15
|
+
useParamAsLabel: e.string().optional(),
|
|
16
|
+
useParentTitleAsLabel: e.boolean().optional()
|
|
17
|
+
}), n = e.object({ name: e.string() }), r = e.object({
|
|
18
|
+
section: e.string().optional(),
|
|
19
|
+
service: e.string().optional(),
|
|
20
|
+
isDetail: e.boolean().optional(),
|
|
21
|
+
crumb: t.optional(),
|
|
22
|
+
sectionCrumb: t.optional(),
|
|
23
|
+
intermediateCrumb: t.optional(),
|
|
24
|
+
analytics: n.optional()
|
|
25
|
+
});
|
|
26
|
+
function i(e) {
|
|
27
|
+
return r.safeParse(e).success;
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { i as t };
|
|
31
|
+
|
|
32
|
+
//# sourceMappingURL=routeInfo-CdTRlSxv.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routeInfo-CdTRlSxv.mjs","names":["z","CRUMB_LABEL_KEYS","CrumbSchema","object","labelKey","enum","optional","to","string","useParamAsLabel","useParentTitleAsLabel","boolean","AnalyticsSchema","name","RouteInfoSchema","section","service","isDetail","crumb","sectionCrumb","intermediateCrumb","analytics","isRouteInfo","data","safeParse","success"],"sources":["../../src/client/routes/routeInfo.ts"],"sourcesContent":["import { z } from \"zod\"\n\nexport const CRUMB_LABEL_KEYS = [\n \"Compute\",\n \"Network\",\n \"Storage\",\n \"Services\",\n \"Images\",\n \"Flavors\",\n \"Security Groups\",\n \"Floating IPs\",\n \"PCA (Clavis)\",\n] as const\n\nexport type CrumbLabelKey = (typeof CRUMB_LABEL_KEYS)[number]\n\nconst CrumbSchema = z.object({\n labelKey: z.enum(CRUMB_LABEL_KEYS).optional(),\n to: z.string().optional(),\n useParamAsLabel: z.string().optional(),\n useParentTitleAsLabel: z.boolean().optional(),\n})\n\nconst AnalyticsSchema = z.object({\n name: z.string(),\n})\n\nconst RouteInfoSchema = z.object({\n section: z.string().optional(),\n service: z.string().optional(),\n isDetail: z.boolean().optional(),\n crumb: CrumbSchema.optional(),\n sectionCrumb: CrumbSchema.optional(),\n intermediateCrumb: CrumbSchema.optional(),\n analytics: AnalyticsSchema.optional(),\n})\n\nexport type Crumb = z.infer<typeof CrumbSchema>\nexport type Analytics = z.infer<typeof AnalyticsSchema>\nexport type RouteInfo = z.infer<typeof RouteInfoSchema>\n\nexport function isRouteInfo(data: unknown): data is RouteInfo {\n return RouteInfoSchema.safeParse(data).success\n}\n"],"mappings":";AAgBA,IAAME,IAAcF,EAAEG,OAAO;CAC3BC,UAAUJ,EAAEK,KAAKJ;EAdjB;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CAMiBA,CAAAA,EAAkBK,SAAQ;CAC3CC,IAAIP,EAAEQ,OAAM,EAAGF,SAAQ;CACvBG,iBAAiBT,EAAEQ,OAAM,EAAGF,SAAQ;CACpCI,uBAAuBV,EAAEW,QAAO,EAAGL,SAAQ;AAC7C,CAAA,GAEMM,IAAkBZ,EAAEG,OAAO,EAC/BU,MAAMb,EAAEQ,OAAM,EAChB,CAAA,GAEMM,IAAkBd,EAAEG,OAAO;CAC/BY,SAASf,EAAEQ,OAAM,EAAGF,SAAQ;CAC5BU,SAAShB,EAAEQ,OAAM,EAAGF,SAAQ;CAC5BW,UAAUjB,EAAEW,QAAO,EAAGL,SAAQ;CAC9BY,OAAOhB,EAAYI,SAAQ;CAC3Ba,cAAcjB,EAAYI,SAAQ;CAClCc,mBAAmBlB,EAAYI,SAAQ;CACvCe,WAAWT,EAAgBN,SAAQ;AACrC,CAAA;AAMA,SAAgBgB,EAAYC,GAAa;CACvC,OAAOT,EAAgBU,UAAUD,CAAAA,EAAME;AACzC"}
|
|
@@ -1,27 +1,28 @@
|
|
|
1
|
-
import { B as e, K as t, U as n, Y as r, c as i, tt as a, y as o } from "./build-
|
|
2
|
-
import { n as s } from "./AuthProvider-
|
|
3
|
-
import { t as c } from "./
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
1
|
+
import { B as e, K as t, U as n, Y as r, c as i, tt as a, y as o } from "./build-CRLQyqu2.mjs";
|
|
2
|
+
import { n as s } from "./AuthProvider-CQ6Yppoh.mjs";
|
|
3
|
+
import { t as c } from "./Slot-CWb612-_.mjs";
|
|
4
|
+
import { t as l } from "./routes-CtfnI-aY.mjs";
|
|
5
|
+
import { jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
6
|
+
import { useEffect as f } from "react";
|
|
7
|
+
import { useNavigate as p } from "@tanstack/react-router";
|
|
8
|
+
import { Trans as m } from "@lingui/react";
|
|
8
9
|
//#region src/client/components/Auth/LoginForm.tsx
|
|
9
|
-
function
|
|
10
|
+
function h() {
|
|
10
11
|
let { isLoading: t, error: a, login: c } = s();
|
|
11
|
-
return /*#__PURE__*/
|
|
12
|
+
return /*#__PURE__*/ u("div", {
|
|
12
13
|
className: "mt-8 flex justify-center",
|
|
13
|
-
children: /*#__PURE__*/
|
|
14
|
+
children: /*#__PURE__*/ d("div", {
|
|
14
15
|
className: "border-theme-light relative w-full max-w-md rounded-lg border p-6 shadow-lg",
|
|
15
16
|
children: [
|
|
16
|
-
/*#__PURE__*/
|
|
17
|
+
/*#__PURE__*/ u(r, {
|
|
17
18
|
className: "text-center",
|
|
18
|
-
children: /*#__PURE__*/
|
|
19
|
+
children: /*#__PURE__*/ u(m, { id: "dPj4yB" })
|
|
19
20
|
}),
|
|
20
|
-
/*#__PURE__*/
|
|
21
|
+
/*#__PURE__*/ u("p", {
|
|
21
22
|
className: "mb-6 text-center",
|
|
22
|
-
children: /*#__PURE__*/
|
|
23
|
+
children: /*#__PURE__*/ u(m, { id: "N5vGcw" })
|
|
23
24
|
}),
|
|
24
|
-
/*#__PURE__*/
|
|
25
|
+
/*#__PURE__*/ d("form", {
|
|
25
26
|
className: "space-y-5",
|
|
26
27
|
onSubmit: (e) => {
|
|
27
28
|
e.preventDefault();
|
|
@@ -33,25 +34,25 @@ function m() {
|
|
|
33
34
|
});
|
|
34
35
|
},
|
|
35
36
|
children: [
|
|
36
|
-
a && /*#__PURE__*/
|
|
37
|
+
a && /*#__PURE__*/ u(e, {
|
|
37
38
|
text: a,
|
|
38
39
|
variant: "error"
|
|
39
40
|
}),
|
|
40
|
-
/*#__PURE__*/
|
|
41
|
+
/*#__PURE__*/ u(i, { children: /*#__PURE__*/ u(n, {
|
|
41
42
|
id: "domain",
|
|
42
43
|
name: "domain",
|
|
43
44
|
label: "Domain",
|
|
44
45
|
autoComplete: "domain",
|
|
45
46
|
required: !0
|
|
46
47
|
}) }),
|
|
47
|
-
/*#__PURE__*/
|
|
48
|
+
/*#__PURE__*/ u(i, { children: /*#__PURE__*/ u(n, {
|
|
48
49
|
id: "user",
|
|
49
50
|
name: "user",
|
|
50
51
|
label: "User",
|
|
51
52
|
autoComplete: "user",
|
|
52
53
|
required: !0
|
|
53
54
|
}) }),
|
|
54
|
-
/*#__PURE__*/
|
|
55
|
+
/*#__PURE__*/ u(i, { children: /*#__PURE__*/ u(n, {
|
|
55
56
|
id: "password",
|
|
56
57
|
name: "password",
|
|
57
58
|
type: "password",
|
|
@@ -59,12 +60,12 @@ function m() {
|
|
|
59
60
|
autoComplete: "password",
|
|
60
61
|
required: !0
|
|
61
62
|
}) }),
|
|
62
|
-
/*#__PURE__*/
|
|
63
|
+
/*#__PURE__*/ u(o, {
|
|
63
64
|
type: "submit",
|
|
64
65
|
variant: "primary",
|
|
65
66
|
className: "mt-2 w-full",
|
|
66
67
|
disabled: t,
|
|
67
|
-
children: t ? /*#__PURE__*/
|
|
68
|
+
children: t ? /*#__PURE__*/ u(m, { id: "Z3FXyt" }) : /*#__PURE__*/ u(m, { id: "n1ekoW" })
|
|
68
69
|
})
|
|
69
70
|
]
|
|
70
71
|
})
|
|
@@ -74,32 +75,38 @@ function m() {
|
|
|
74
75
|
}
|
|
75
76
|
//#endregion
|
|
76
77
|
//#region src/client/routes/index.tsx?tsr-split=component
|
|
77
|
-
function
|
|
78
|
+
function g(e) {
|
|
78
79
|
return typeof e == "string" && e.startsWith("/") && !e.startsWith("//");
|
|
79
80
|
}
|
|
80
|
-
function
|
|
81
|
-
let { isLoading: e, isAuthenticated: n } = s(), {
|
|
82
|
-
return
|
|
83
|
-
n && !e &&
|
|
84
|
-
to:
|
|
81
|
+
function _() {
|
|
82
|
+
let { isLoading: e, isAuthenticated: n } = s(), { slots: r } = l.useRouteContext(), { redirect: i } = l.useSearch(), o = p();
|
|
83
|
+
return f(() => {
|
|
84
|
+
n && !e && o({
|
|
85
|
+
to: g(i) ? i : "/projects",
|
|
85
86
|
replace: !0
|
|
86
87
|
});
|
|
87
88
|
}, [
|
|
88
89
|
n,
|
|
89
90
|
e,
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
]), e ? /*#__PURE__*/
|
|
91
|
+
o,
|
|
92
|
+
i
|
|
93
|
+
]), e ? /*#__PURE__*/ d(a, {
|
|
93
94
|
className: "fixed inset-0",
|
|
94
95
|
distribution: "center",
|
|
95
96
|
alignment: "center",
|
|
96
|
-
children: [/*#__PURE__*/
|
|
97
|
+
children: [/*#__PURE__*/ u("div", { className: "absolute inset-0 backdrop-blur-sm" }), /*#__PURE__*/ u(t, {
|
|
97
98
|
variant: "primary",
|
|
98
99
|
size: "large"
|
|
99
100
|
})]
|
|
100
|
-
}) : n ?
|
|
101
|
+
}) : r?.login && !n ? /*#__PURE__*/ u("div", {
|
|
102
|
+
className: "mt-8 flex justify-center",
|
|
103
|
+
children: /*#__PURE__*/ u(c, {
|
|
104
|
+
component: r.login,
|
|
105
|
+
useShadowDOM: !1
|
|
106
|
+
})
|
|
107
|
+
}) : n ? null : /*#__PURE__*/ u(h, {});
|
|
101
108
|
}
|
|
102
109
|
//#endregion
|
|
103
|
-
export {
|
|
110
|
+
export { _ as component };
|
|
104
111
|
|
|
105
|
-
//# sourceMappingURL=routes-
|
|
112
|
+
//# sourceMappingURL=routes-BOf-GDMM.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes-BOf-GDMM.mjs","names":["ContentHeading","Message","Button","FormRow","TextInput","useAuth","LoginForm","isLoading","error","loginError","login","div","className","p","form","onSubmit","e","preventDefault","formData","FormData","currentTarget","domain","String","get","user","password","text","variant","id","name","label","autoComplete","required","type","disabled","useNavigate","Stack","Spinner","useEffect","LoginForm","Slot","useAuth","isSafeRedirect","path","startsWith","Route","LandingPage","isLoading","isAuthenticated","slots","useRouteContext","redirect","searchRedirect","useSearch","navigate","target","to","replace","login","component"],"sources":["../../src/client/components/Auth/LoginForm.tsx","../../src/client/routes/index.tsx?tsr-split=component"],"sourcesContent":["import { ContentHeading, Message, Button, FormRow, TextInput } from \"@cloudoperators/juno-ui-components\"\nimport { Trans } from \"@lingui/react/macro\"\nimport { useAuth } from \"../../store/AuthProvider\"\n\nexport function LoginForm() {\n const { isLoading, error: loginError, login } = useAuth()\n\n return (\n <div className=\"mt-8 flex justify-center\">\n <div className=\"border-theme-light relative w-full max-w-md rounded-lg border p-6 shadow-lg\">\n <ContentHeading className=\"text-center\">\n <Trans>Login to Your Account</Trans>\n </ContentHeading>\n <p className=\"mb-6 text-center\">\n <Trans>Enter your credentials to access your account</Trans>\n </p>\n\n <form\n className=\"space-y-5\"\n onSubmit={(e) => {\n e.preventDefault()\n const formData = new FormData(e.currentTarget)\n login({\n domain: String(formData.get(\"domain\") ?? \"\"),\n user: String(formData.get(\"user\") ?? \"\"),\n password: String(formData.get(\"password\") ?? \"\"),\n })\n }}\n >\n {loginError && <Message text={loginError} variant=\"error\" />}\n <FormRow>\n <TextInput id=\"domain\" name=\"domain\" label=\"Domain\" autoComplete=\"domain\" required />\n </FormRow>\n <FormRow>\n <TextInput id=\"user\" name=\"user\" label=\"User\" autoComplete=\"user\" required />\n </FormRow>\n <FormRow>\n <TextInput\n id=\"password\"\n name=\"password\"\n type=\"password\"\n label=\"Password\"\n autoComplete=\"password\"\n required\n />\n </FormRow>\n\n <Button type=\"submit\" variant=\"primary\" className=\"mt-2 w-full\" disabled={isLoading}>\n {isLoading ? <Trans>Loading...</Trans> : <Trans>Sign In</Trans>}\n </Button>\n </form>\n </div>\n </div>\n )\n}\n","import { createFileRoute, useNavigate } from \"@tanstack/react-router\"\nimport { Stack, Spinner } from \"@cloudoperators/juno-ui-components\"\nimport { z } from \"zod\"\nimport { useEffect } from \"react\"\nimport { LoginForm } from \"../components/Auth/LoginForm\"\nimport { Slot } from \"../components/Slot\"\nimport { useAuth } from \"../store/AuthProvider\"\n\nfunction isSafeRedirect(path: unknown): path is string {\n return typeof path === \"string\" && path.startsWith(\"/\") && !path.startsWith(\"//\")\n}\n\nexport const Route = createFileRoute(\"/\")({\n validateSearch: z.object({\n redirect: z.string().optional().catch(\"\"),\n }),\n component: LandingPage,\n})\n\nfunction LandingPage() {\n const { isLoading, isAuthenticated } = useAuth()\n const { slots } = Route.useRouteContext()\n const { redirect: searchRedirect } = Route.useSearch()\n const navigate = useNavigate()\n\n // Redirect when authenticated\n useEffect(() => {\n if (isAuthenticated && !isLoading) {\n const target = isSafeRedirect(searchRedirect) ? searchRedirect : \"/projects\"\n navigate({ to: target, replace: true })\n }\n }, [isAuthenticated, isLoading, navigate, searchRedirect])\n\n if (isLoading) {\n return (\n <Stack className=\"fixed inset-0\" distribution=\"center\" alignment=\"center\">\n <div className=\"absolute inset-0 backdrop-blur-sm\" />\n <Spinner variant=\"primary\" size=\"large\" />\n </Stack>\n )\n }\n\n if (slots?.login && !isAuthenticated) {\n return (\n <div className=\"mt-8 flex justify-center\">\n <Slot component={slots.login} useShadowDOM={false} />\n </div>\n )\n }\n\n if (!isAuthenticated) {\n return <LoginForm />\n }\n\n // Redirecting...\n return null\n}\n"],"mappings":";;;;;;;;;AAIA,SAAgBM,IAAAA;CACd,IAAM,EAAEC,cAAWC,OAAOC,GAAYC,aAAUL,EAAAA;CAEhD,OACE,gBAACM,OAAAA;EAAIC,WAAU;YACb,gBAACD,OAAAA;GAAIC,WAAU;;IACb,gBAACZ,GAAAA;KAAeY,WAAU;eACxB,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;IAEF,gBAACC,KAAAA;KAAED,WAAU;eACX,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;IAGF,gBAACE,QAAAA;KACCF,WAAU;KACVG,WAAWC,MAAAA;MACTA,EAAEC,eAAc;MAChB,IAAMC,IAAW,IAAIC,SAASH,EAAEI,aAAa;MAC7CV,EAAM;OACJW,QAAQC,OAAOJ,EAASK,IAAI,QAAA,KAAa,EAAA;OACzCC,MAAMF,OAAOJ,EAASK,IAAI,MAAA,KAAW,EAAA;OACrCE,UAAUH,OAAOJ,EAASK,IAAI,UAAA,KAAe,EAAA;MAC/C,CAAA;KACF;;MAECd,KAAc,gBAACR,GAAAA;OAAQyB,MAAMjB;OAAYkB,SAAQ;;MAClD,gBAACxB,GAAAA,EAAAA,UACC,gBAACC,GAAAA;OAAUwB,IAAG;OAASC,MAAK;OAASC,OAAM;OAASC,cAAa;OAASC,UAAQ;;MAEpF,gBAAC7B,GAAAA,EAAAA,UACC,gBAACC,GAAAA;OAAUwB,IAAG;OAAOC,MAAK;OAAOC,OAAM;OAAOC,cAAa;OAAOC,UAAQ;;MAE5E,gBAAC7B,GAAAA,EAAAA,UACC,gBAACC,GAAAA;OACCwB,IAAG;OACHC,MAAK;OACLI,MAAK;OACLH,OAAM;OACNC,cAAa;OACbC,UAAQ;;MAIZ,gBAAC9B,GAAAA;OAAO+B,MAAK;OAASN,SAAQ;OAAUf,WAAU;OAAcsB,UAAU3B;iBACvEA,IAAY,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,IAA4B,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;;;;;;AAMrD;;;AC9CA,SAASmC,EAAeC,GAAa;CACnC,OAAO,OAAOA,KAAS,YAAYA,EAAKC,WAAW,GAAA,KAAQ,CAACD,EAAKC,WAAW,IAAA;AAC9E;AASA,SAASE,IAAAA;CACP,IAAM,EAAEC,cAAWC,uBAAoBP,EAAAA,GACjC,EAAEQ,aAAUJ,EAAMK,gBAAe,GACjC,EAAEC,UAAUC,MAAmBP,EAAMQ,UAAS,GAC9CC,IAAWnB,EAAAA;CAgCjB,OA7BAG,QAAU;EACR,AAAIU,KAAmB,CAACD,KAEtBO,EAAS;GAAEE,IADId,EAAeU,CAAAA,IAAkBA,IAAiB;GAC1CK,SAAS;EAAK,CAAA;CAEzC,GAAG;EAACT;EAAiBD;EAAWO;EAAUF;EAAe,GAErDL,IAEA,gBAAC,GAAA;EAAM,WAAU;EAAgB,cAAa;EAAS,WAAU;aAC/D,gBAAC,OAAA,EAAI,WAAU,oCAAA,CAAA,GACf,gBAAC,GAAA;GAAQ,SAAQ;GAAU,MAAK;;MAKlCE,GAAOS,SAAS,CAACV,IAEjB,gBAAC,OAAA;EAAI,WAAU;YACb,gBAAC,GAAA;GAAK,WAAWC,EAAMS;GAAO,cAAc;;MAK7CV,IAKE,OAJE,gBAAC,GAAA,CAAA,CAAA;AAKZ"}
|
|
@@ -2,9 +2,9 @@ import { createFileRoute as e, lazyRouteComponent as t } from "@tanstack/react-r
|
|
|
2
2
|
import { z as n } from "zod";
|
|
3
3
|
var r = e("/")({
|
|
4
4
|
validateSearch: n.object({ redirect: n.string().optional().catch("") }),
|
|
5
|
-
component: t(() => import("./routes-
|
|
5
|
+
component: t(() => import("./routes-BOf-GDMM.mjs"), "component")
|
|
6
6
|
});
|
|
7
7
|
//#endregion
|
|
8
8
|
export { r as t };
|
|
9
9
|
|
|
10
|
-
//# sourceMappingURL=routes-
|
|
10
|
+
//# sourceMappingURL=routes-CtfnI-aY.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes-CtfnI-aY.mjs","names":["createFileRoute","z","Route","validateSearch","object","redirect","string","optional","catch","component","lazyRouteComponent","$$splitComponentImporter"],"sources":["../../src/client/routes/index.tsx"],"sourcesContent":["import { createFileRoute, useNavigate } from \"@tanstack/react-router\"\nimport { Stack, Spinner } from \"@cloudoperators/juno-ui-components\"\nimport { z } from \"zod\"\nimport { useEffect } from \"react\"\nimport { LoginForm } from \"../components/Auth/LoginForm\"\nimport { Slot } from \"../components/Slot\"\nimport { useAuth } from \"../store/AuthProvider\"\n\nfunction isSafeRedirect(path: unknown): path is string {\n return typeof path === \"string\" && path.startsWith(\"/\") && !path.startsWith(\"//\")\n}\n\nexport const Route = createFileRoute(\"/\")({\n validateSearch: z.object({\n redirect: z.string().optional().catch(\"\"),\n }),\n component: LandingPage,\n})\n\nfunction LandingPage() {\n const { isLoading, isAuthenticated } = useAuth()\n const { slots } = Route.useRouteContext()\n const { redirect: searchRedirect } = Route.useSearch()\n const navigate = useNavigate()\n\n // Redirect when authenticated\n useEffect(() => {\n if (isAuthenticated && !isLoading) {\n const target = isSafeRedirect(searchRedirect) ? searchRedirect : \"/projects\"\n navigate({ to: target, replace: true })\n }\n }, [isAuthenticated, isLoading, navigate, searchRedirect])\n\n if (isLoading) {\n return (\n <Stack className=\"fixed inset-0\" distribution=\"center\" alignment=\"center\">\n <div className=\"absolute inset-0 backdrop-blur-sm\" />\n <Spinner variant=\"primary\" size=\"large\" />\n </Stack>\n )\n }\n\n if (slots?.login && !isAuthenticated) {\n return (\n <div className=\"mt-8 flex justify-center\">\n <Slot component={slots.login} useShadowDOM={false} />\n </div>\n )\n }\n\n if (!isAuthenticated) {\n return <LoginForm />\n }\n\n // Redirecting...\n return null\n}\n"],"mappings":";;AAYA,IAAaE,IAAQF,EAAgB,GAAA,EAAK;CACxCG,gBAAgBF,EAAEG,OAAO,EACvBC,UAAUJ,EAAEK,OAAM,EAAGC,SAAQ,EAAGC,MAAM,EAAA,EACxC,CAAA;CACAC,WAASC,yCAAA,WAAA;AACX,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createFileRoute as e, lazyRouteComponent as t } from "@tanstack/react-router";
|
|
2
|
+
import { i18n as n } from "@lingui/core";
|
|
3
|
+
var r = e("/_auth/projects/$projectId/network/securitygroups/")({
|
|
4
|
+
staticData: {
|
|
5
|
+
section: "network",
|
|
6
|
+
service: "securitygroups",
|
|
7
|
+
analytics: { name: "network.securitygroups.list" },
|
|
8
|
+
sectionCrumb: { labelKey: "Network" },
|
|
9
|
+
crumb: { labelKey: "Security Groups" }
|
|
10
|
+
},
|
|
11
|
+
head: () => ({ meta: [{ title: n._({ id: "4opp4r" }) }] }),
|
|
12
|
+
component: t(() => import("./securitygroups-DRhFle2O.mjs"), "component")
|
|
13
|
+
});
|
|
14
|
+
//#endregion
|
|
15
|
+
export { r as t };
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=securitygroups-B8aLyFK7.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"securitygroups-B8aLyFK7.mjs","names":["createFileRoute","t","Route","staticData","section","service","analytics","name","sectionCrumb","labelKey","crumb","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 { useLingui } from \"@lingui/react/macro\"\nimport { SecurityGroups } from \"./-components/SecurityGroupsList\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { ContentHeading } from \"@cloudoperators/juno-ui-components\"\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 sectionCrumb: { labelKey: \"Network\" },\n crumb: { labelKey: \"Security Groups\" },\n } satisfies RouteInfo,\n head: () => ({ meta: [{ title: t`Security Groups` }] }),\n component: RouteComponent,\n})\n\nfunction RouteComponent() {\n const { t } = useLingui()\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 (\n <>\n <ContentHeading>{t`Security Groups`}</ContentHeading>\n <SecurityGroups project={projectId} />\n </>\n )\n}\n"],"mappings":";;AAOA,IAAaE,IAAQF,EAAgB,oDAAA,EAAsD;CACzFG,YAAY;EACVC,SAAS;EACTC,SAAS;EACTC,WAAW,EACTC,MAAM,8BACR;EACAC,cAAc,EAAEC,UAAU,UAAU;EACpCC,OAAO,EAAED,UAAU,kBAAkB;CACvC;CACAG,aAAa,EAAEC,MAAM,CAAC,EAAEC,OAAOb,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA,EAAkB,CAAA,EAAG;CACrDc,WAASC,iDAAA,WAAA;AACX,CAAA"}
|