@cobaltcore-dev/aurora 0.8.1 → 0.10.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.
Files changed (98) hide show
  1. package/README.md +47 -13
  2. package/dist/client/AuroraApp.d.ts +14 -0
  3. package/dist/client/ContentHeader-D4jlOG-9.mjs +96 -0
  4. package/dist/client/ContentHeader-D4jlOG-9.mjs.map +1 -0
  5. package/dist/client/DeleteVersionsModal-CyYZfB8d.mjs +331 -0
  6. package/dist/client/DeleteVersionsModal-CyYZfB8d.mjs.map +1 -0
  7. package/dist/client/Slot-CWb612-_.mjs +28 -0
  8. package/dist/client/Slot-CWb612-_.mjs.map +1 -0
  9. package/dist/client/{SortInput-VK7IYqQv.mjs → SortInput-DLcusjGZ.mjs} +8 -8
  10. package/dist/client/SortInput-DLcusjGZ.mjs.map +1 -0
  11. package/dist/client/_auth-DXJkv9QO.mjs.map +1 -1
  12. package/dist/client/{_flavorId-iZE2j210.mjs → _flavorId-DsD2VTKA.mjs} +3 -3
  13. package/dist/client/{_flavorId-iZE2j210.mjs.map → _flavorId-DsD2VTKA.mjs.map} +1 -1
  14. package/dist/client/{_flavorId-DU4gcFna.mjs → _flavorId-Dy7EYQum.mjs} +2 -2
  15. package/dist/client/{_flavorId-DU4gcFna.mjs.map → _flavorId-Dy7EYQum.mjs.map} +1 -1
  16. package/dist/client/{_floatingIpId-B5GMSLeQ.mjs → _floatingIpId-BjVbeNw_.mjs} +2 -2
  17. package/dist/client/{_floatingIpId-B5GMSLeQ.mjs.map → _floatingIpId-BjVbeNw_.mjs.map} +1 -1
  18. package/dist/client/{_floatingIpId-C2-BeRmF.mjs → _floatingIpId-j17rCQqG2.mjs} +2 -2
  19. package/dist/client/_floatingIpId-j17rCQqG2.mjs.map +1 -0
  20. package/dist/client/{_imageId-zmaSymWe.mjs → _imageId-BjfhqAje.mjs} +2 -2
  21. package/dist/client/{_imageId-zmaSymWe.mjs.map → _imageId-BjfhqAje.mjs.map} +1 -1
  22. package/dist/client/{_pcaId-BwTvJJgh.mjs → _pcaId-Bo7yHkNW.mjs} +3 -3
  23. package/dist/client/{_pcaId-BwTvJJgh.mjs.map → _pcaId-Bo7yHkNW.mjs.map} +1 -1
  24. package/dist/client/{_pcaId-DUHQd0rB.mjs → _pcaId-CKkCVC7b.mjs} +2 -2
  25. package/dist/client/{_pcaId-DUHQd0rB.mjs.map → _pcaId-CKkCVC7b.mjs.map} +1 -1
  26. package/dist/client/_projectId-B_2sZKk-.mjs.map +1 -1
  27. package/dist/client/_projectId-CARHuZTU.mjs +106 -0
  28. package/dist/client/_projectId-CARHuZTU.mjs.map +1 -0
  29. package/dist/client/_projectId-CY8W0IF6.mjs +27 -0
  30. package/dist/client/_projectId-CY8W0IF6.mjs.map +1 -0
  31. package/dist/client/_projectId-Dbck_MFa.mjs +290 -0
  32. package/dist/client/_projectId-Dbck_MFa.mjs.map +1 -0
  33. package/dist/client/{_securityGroupId-DYxmXUOP.mjs → _securityGroupId-CkN0CGVg.mjs} +3 -3
  34. package/dist/client/{_securityGroupId-DYxmXUOP.mjs.map → _securityGroupId-CkN0CGVg.mjs.map} +1 -1
  35. package/dist/client/{_securityGroupId-fhK1CuZh.mjs → _securityGroupId-gSEZbBII.mjs} +2 -2
  36. package/dist/client/{_securityGroupId-fhK1CuZh.mjs.map → _securityGroupId-gSEZbBII.mjs.map} +1 -1
  37. package/dist/client/{_storageType-CepuevDG.mjs → _storageType-6k8lUnQo.mjs} +2 -2
  38. package/dist/client/{_storageType-CepuevDG.mjs.map → _storageType-6k8lUnQo.mjs.map} +1 -1
  39. package/dist/client/_storageType-CLTxXjQZ.mjs +3048 -0
  40. package/dist/client/_storageType-CLTxXjQZ.mjs.map +1 -0
  41. package/dist/client/{constants-J5nm9hbP.mjs → constants-PMXUGI4Q.mjs} +2 -2
  42. package/dist/client/{constants-J5nm9hbP.mjs.map → constants-PMXUGI4Q.mjs.map} +1 -1
  43. package/dist/client/{flavors-8bZVlzzb.mjs → flavors-BclEwobO.mjs} +2 -2
  44. package/dist/client/{flavors-8bZVlzzb.mjs.map → flavors-BclEwobO.mjs.map} +1 -1
  45. package/dist/client/{flavors-BfsEBUE-.mjs → flavors-p2TKcqP-.mjs} +4 -4
  46. package/dist/client/{flavors-BfsEBUE-.mjs.map → flavors-p2TKcqP-.mjs.map} +1 -1
  47. package/dist/client/{floatingips-Dq4DXQYb.mjs → floatingips-ph0ZxJw8.mjs} +3 -3
  48. package/dist/client/{floatingips-Dq4DXQYb.mjs.map → floatingips-ph0ZxJw8.mjs.map} +1 -1
  49. package/dist/client/{images-BPnTuKFO2.mjs → images-BblnyWJq.mjs} +4 -4
  50. package/dist/client/images-BblnyWJq.mjs.map +1 -0
  51. package/dist/client/{images-8FOgju2f.mjs → images-CXdghaMW.mjs} +2 -2
  52. package/dist/client/{images-8FOgju2f.mjs.map → images-CXdghaMW.mjs.map} +1 -1
  53. package/dist/client/index.js +261 -247
  54. package/dist/client/index.js.map +1 -1
  55. package/dist/client/{md-CYTrL5dq.mjs → md-CyCflQee.mjs} +10 -28
  56. package/dist/client/{md-CYTrL5dq.mjs.map → md-CyCflQee.mjs.map} +1 -1
  57. package/dist/client/{objects-DKWp9RtR.mjs → objects-B9Jh3SMG.mjs} +4 -3
  58. package/dist/client/objects-B9Jh3SMG.mjs.map +1 -0
  59. package/dist/client/objects-Bw25cE1m.mjs +5970 -0
  60. package/dist/client/objects-Bw25cE1m.mjs.map +1 -0
  61. package/dist/client/objects-o2Cj_ndZ.mjs.map +1 -1
  62. package/dist/client/{pca-5wOBf_KI.mjs → pca-CiLPHmK7.mjs} +4 -4
  63. package/dist/client/{pca-5wOBf_KI.mjs.map → pca-CiLPHmK7.mjs.map} +1 -1
  64. package/dist/client/{pca-dhrOFfrE.mjs → pca-DUrQ_tIg.mjs} +2 -2
  65. package/dist/client/{pca-dhrOFfrE.mjs.map → pca-DUrQ_tIg.mjs.map} +1 -1
  66. package/dist/client/{projects-B_PPyZD1.mjs → projects-B5topuei.mjs} +2 -2
  67. package/dist/client/projects-B5topuei.mjs.map +1 -0
  68. package/dist/client/projects-CHYn7L5e.mjs.map +1 -1
  69. package/dist/client/projects-DNd3UTas.mjs +110 -0
  70. package/dist/client/projects-DNd3UTas.mjs.map +1 -0
  71. package/dist/client/projects-yiK0HGSA.mjs.map +1 -1
  72. package/dist/client/routeInfo-Dy9l-wFB.mjs +31 -0
  73. package/dist/client/routeInfo-Dy9l-wFB.mjs.map +1 -0
  74. package/dist/client/{securitygroups-CNFLu9zS.mjs → securitygroups-CcA2TpAt.mjs} +2 -2
  75. package/dist/client/{securitygroups-CNFLu9zS.mjs.map → securitygroups-CcA2TpAt.mjs.map} +1 -1
  76. package/dist/client/{useListWithFiltering-v2A0-SZb.mjs → useListWithFiltering-CVzhMyEA.mjs} +2 -2
  77. package/dist/client/{useListWithFiltering-v2A0-SZb.mjs.map → useListWithFiltering-CVzhMyEA.mjs.map} +1 -1
  78. package/dist/server/index.js +282 -48
  79. package/package.json +3 -3
  80. package/dist/client/ContentHeader-C51H95X8.mjs +0 -85
  81. package/dist/client/ContentHeader-C51H95X8.mjs.map +0 -1
  82. package/dist/client/SortInput-VK7IYqQv.mjs.map +0 -1
  83. package/dist/client/_floatingIpId-C2-BeRmF.mjs.map +0 -1
  84. package/dist/client/_projectId-C8BaEHUj.mjs +0 -273
  85. package/dist/client/_projectId-C8BaEHUj.mjs.map +0 -1
  86. package/dist/client/_projectId-COt93OEF.mjs +0 -84
  87. package/dist/client/_projectId-COt93OEF.mjs.map +0 -1
  88. package/dist/client/_storageType-B-qGcGUQ.mjs +0 -3244
  89. package/dist/client/_storageType-B-qGcGUQ.mjs.map +0 -1
  90. package/dist/client/images-BPnTuKFO2.mjs.map +0 -1
  91. package/dist/client/objects-DKWp9RtR.mjs.map +0 -1
  92. package/dist/client/objects-DaCuy_CB.mjs +0 -5708
  93. package/dist/client/objects-DaCuy_CB.mjs.map +0 -1
  94. package/dist/client/projects-B_PPyZD1.mjs.map +0 -1
  95. package/dist/client/projects-Dmewygrp.mjs +0 -105
  96. package/dist/client/projects-Dmewygrp.mjs.map +0 -1
  97. package/dist/client/routeInfo-CHiJfum5.mjs +0 -73
  98. package/dist/client/routeInfo-CHiJfum5.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"objects-o2Cj_ndZ.mjs","names":["Trans","SplitNotFoundComponent","notFoundComponent"],"sources":["../../src/client/routes/_auth/projects/$projectId/storage/$provider/$storageType/$containerName/objects/index.tsx?tsr-split=notFoundComponent"],"sourcesContent":["import { createFileRoute, redirect, useParams } from \"@tanstack/react-router\"\nimport { getServiceIndex } from \"@/server/Authentication/helpers\"\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\"\n\nexport const checkServiceAvailability = (\n availableServices: {\n type: string\n name: string\n }[],\n params: {\n projectId: string\n provider: string\n storageType: string\n containerName: string\n }\n) => {\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\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(),\n sortDirection: z.enum([\"asc\", \"desc\"]).optional(),\n search: z.string().optional(),\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 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 { project, provider, containerName } = useParams({\n from: \"/_auth/projects/$projectId/storage/$provider/$storageType/$containerName/objects/\",\n select: (params) => ({\n project: params.projectId,\n provider: params.provider,\n containerName: params.containerName,\n storageType: params.storageType,\n }),\n })\n\n const { prefix, sortBy, sortDirection, search } = Route.useSearch()\n\n return (\n <div>\n {project ? (\n <ErrorBoundary\n resetKeys={[project, 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"],"mappings":";;;AA2GA,IAAAC,UA2BM,gBAAC,KAAA,EAAA,UACC,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,EAAA,CAAA"}
1
+ {"version":3,"file":"objects-o2Cj_ndZ.mjs","names":["Trans","SplitNotFoundComponent","notFoundComponent"],"sources":["../../src/client/routes/_auth/projects/$projectId/storage/$provider/$storageType/$containerName/objects/index.tsx?tsr-split=notFoundComponent"],"sourcesContent":["import { createFileRoute, redirect, useParams } from \"@tanstack/react-router\"\nimport { getServiceIndex } from \"@/server/Authentication/helpers\"\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 { ContentHeader } from \"@/client/components/ContentHeader/ContentHeader\"\n\nexport const checkServiceAvailability = (\n availableServices: {\n type: string\n name: string\n }[],\n params: {\n projectId: string\n provider: string\n storageType: string\n containerName: string\n }\n) => {\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\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(),\n sortDirection: z.enum([\"asc\", \"desc\"]).optional(),\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 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 { project, provider, containerName } = useParams({\n from: \"/_auth/projects/$projectId/storage/$provider/$storageType/$containerName/objects/\",\n select: (params) => ({\n project: params.projectId,\n provider: params.provider,\n containerName: params.containerName,\n storageType: params.storageType,\n }),\n })\n\n const { prefix, sortBy, sortDirection, search } = Route.useSearch()\n\n // For Ceph buckets, we need to show ContentHeader\n // For Swift containers, the component handles its own header\n const showContentHeader = provider === \"ceph\"\n\n return (\n <>\n {showContentHeader && <ContentHeader title={containerName} projectId={project} />}\n <div>\n {project ? (\n <ErrorBoundary\n resetKeys={[project, 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":";;;AA4GA,IAAAC,UA4BM,gBAAC,KAAA,EAAA,UACC,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,EAAA,CAAA"}
@@ -1,11 +1,11 @@
1
1
  import { D as e, E as t, G as n, H as r, J as i, L as a, N as o, Q as s, Y as c, _ as l, ct as u, et as d, k as f, m as p, ot as m, p as h, x as g } from "./build-BdRRmNf5.mjs";
2
2
  import { r as _ } from "./trpcClient-BzPUgiM2.mjs";
3
- import { t as v } from "./pca-dhrOFfrE.mjs";
4
- import { t as y } from "./ContentHeader-C51H95X8.mjs";
3
+ import { t as v } from "./pca-DUrQ_tIg.mjs";
4
+ import { t as y } from "./ContentHeader-D4jlOG-9.mjs";
5
5
  import { t as b } from "./useModal-DCs1OJh7.mjs";
6
6
  import { t as x } from "./useProjectId-DBc5lpoU.mjs";
7
7
  import "./hooks-dSArr2Ca.mjs";
8
- import { n as S, r as C, t as w } from "./constants-J5nm9hbP.mjs";
8
+ import { n as S, r as C, t as w } from "./constants-PMXUGI4Q.mjs";
9
9
  import { Fragment as T, jsx as E, jsxs as D } from "react/jsx-runtime";
10
10
  import { useState as O } from "react";
11
11
  import { useNavigate as k } from "@tanstack/react-router";
@@ -199,4 +199,4 @@ function V() {
199
199
  //#endregion
200
200
  export { V as component };
201
201
 
202
- //# sourceMappingURL=pca-5wOBf_KI.mjs.map
202
+ //# sourceMappingURL=pca-CiLPHmK7.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"pca-5wOBf_KI.mjs","names":["useNavigate","DataGridCell","DataGridRow","PopupMenu","PopupMenuItem","PopupMenuOptions","useModal","useProjectId","DeletePcaModal","STATE_CONFIG","PcaTableRow","pca","useLingui","navigate","projectId","deletePcaModalOpen","toggleDeletePcaModal","navigateToDetailsPage","to","params","pcaId","id","data-testid","onClick","div","className","state","icon","text","configuration","subject","common_name","e","stopPropagation","label","t","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","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","TABLE_COLUMNS","PcaTableRow","CreatePcaModal","ITEMS_PER_PAGE","PcaListContainer","useLingui","projectId","columns","columnsLength","length","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","goToPage","page","prev","updated","className","distribution","alignment","direction","variant","size","message","t","data-testid","colSpan","p","div","label","onClick","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/PcaListContainer.tsx","../../src/client/routes/_auth/projects/$projectId/services/pca/index.tsx?tsr-split=component"],"sourcesContent":["import { 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\"\nimport { STATE_CONFIG } from \"./constants\"\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 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.configuration?.subject?.common_name || \"—\"}</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\nexport interface CreateCaModalProps {\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 }: CreateCaModalProps) => {\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: { common_name: value.common_name },\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 { TABLE_COLUMNS } from \"./-table/constants\"\nimport { PcaTableRow } from \"./-table/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 columns = TABLE_COLUMNS()\n const columnsLength = columns.length\n const [createCaOpen, toggleCreateCa] = useModal(false)\n const [pageMarkers, setPageMarkers] = useState<(string | undefined)[]>([undefined])\n const [currentPage, setCurrentPage] = useState(1)\n\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 if (pcas.length === 0 && currentPage === 1) {\n return (\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\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 <DataGrid columns={columnsLength}>\n <DataGridRow>\n {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 {createCaOpen && <CreatePcaModal open={createCaOpen} onClose={toggleCreateCa} />}\n </div>\n )\n}\n","import { createFileRoute } from \"@tanstack/react-router\"\nimport { t } from \"@lingui/core/macro\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { ContentHeader } from \"@/client/components/ContentHeader/ContentHeader\"\nimport { PcaListContainer } from \"./-components/PcaListContainer\"\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/services/pca/\")({\n staticData: {\n section: \"services\",\n service: \"pca\",\n sectionCrumb: { labelKey: \"Services\" },\n crumb: { labelKey: \"PCA (Clavis)\" },\n } satisfies RouteInfo,\n head: () => ({ meta: [{ title: t`PCA` }] }),\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-CiLPHmK7.mjs","names":["useNavigate","DataGridCell","DataGridRow","PopupMenu","PopupMenuItem","PopupMenuOptions","useModal","useProjectId","DeletePcaModal","STATE_CONFIG","PcaTableRow","pca","useLingui","navigate","projectId","deletePcaModalOpen","toggleDeletePcaModal","navigateToDetailsPage","to","params","pcaId","id","data-testid","onClick","div","className","state","icon","text","configuration","subject","common_name","e","stopPropagation","label","t","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","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","TABLE_COLUMNS","PcaTableRow","CreatePcaModal","ITEMS_PER_PAGE","PcaListContainer","useLingui","projectId","columns","columnsLength","length","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","goToPage","page","prev","updated","className","distribution","alignment","direction","variant","size","message","t","data-testid","colSpan","p","div","label","onClick","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/PcaListContainer.tsx","../../src/client/routes/_auth/projects/$projectId/services/pca/index.tsx?tsr-split=component"],"sourcesContent":["import { 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\"\nimport { STATE_CONFIG } from \"./constants\"\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 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.configuration?.subject?.common_name || \"—\"}</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\nexport interface CreateCaModalProps {\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 }: CreateCaModalProps) => {\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: { common_name: value.common_name },\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 { TABLE_COLUMNS } from \"./-table/constants\"\nimport { PcaTableRow } from \"./-table/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 columns = TABLE_COLUMNS()\n const columnsLength = columns.length\n const [createCaOpen, toggleCreateCa] = useModal(false)\n const [pageMarkers, setPageMarkers] = useState<(string | undefined)[]>([undefined])\n const [currentPage, setCurrentPage] = useState(1)\n\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 if (pcas.length === 0 && currentPage === 1) {\n return (\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\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 <DataGrid columns={columnsLength}>\n <DataGridRow>\n {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 {createCaOpen && <CreatePcaModal open={createCaOpen} onClose={toggleCreateCa} />}\n </div>\n )\n}\n","import { createFileRoute } from \"@tanstack/react-router\"\nimport { t } from \"@lingui/core/macro\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { ContentHeader } from \"@/client/components/ContentHeader/ContentHeader\"\nimport { PcaListContainer } from \"./-components/PcaListContainer\"\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/services/pca/\")({\n staticData: {\n section: \"services\",\n service: \"pca\",\n sectionCrumb: { labelKey: \"Services\" },\n crumb: { labelKey: \"PCA (Clavis)\" },\n } satisfies RouteInfo,\n head: () => ({ meta: [{ title: t`PCA` }] }),\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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"}
@@ -8,9 +8,9 @@ var r = e("/_auth/projects/$projectId/services/pca/")({
8
8
  crumb: { labelKey: "PCA (Clavis)" }
9
9
  },
10
10
  head: () => ({ meta: [{ title: n._({ id: "ffw//c" }) }] }),
11
- component: t(() => import("./pca-5wOBf_KI.mjs"), "component")
11
+ component: t(() => import("./pca-CiLPHmK7.mjs"), "component")
12
12
  });
13
13
  //#endregion
14
14
  export { r as t };
15
15
 
16
- //# sourceMappingURL=pca-dhrOFfrE.mjs.map
16
+ //# sourceMappingURL=pca-DUrQ_tIg.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"pca-dhrOFfrE.mjs","names":["createFileRoute","t","Route","staticData","section","service","sectionCrumb","labelKey","crumb","RouteInfo","head","meta","title","component","lazyRouteComponent","$$splitComponentImporter"],"sources":["../../src/client/routes/_auth/projects/$projectId/services/pca/index.tsx"],"sourcesContent":["import { createFileRoute } from \"@tanstack/react-router\"\nimport { t } from \"@lingui/core/macro\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { ContentHeader } from \"@/client/components/ContentHeader/ContentHeader\"\nimport { PcaListContainer } from \"./-components/PcaListContainer\"\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/services/pca/\")({\n staticData: {\n section: \"services\",\n service: \"pca\",\n sectionCrumb: { labelKey: \"Services\" },\n crumb: { labelKey: \"PCA (Clavis)\" },\n } satisfies RouteInfo,\n head: () => ({ meta: [{ title: t`PCA` }] }),\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":";;AAOA,IAAaE,IAAQF,EAAgB,0CAAA,EAA4C;CAC/EG,YAAY;EACVC,SAAS;EACTC,SAAS;EACTC,cAAc,EAAEC,UAAU,WAAW;EACrCC,OAAO,EAAED,UAAU,eAAe;CACpC;CACAG,aAAa,EAAEC,MAAM,CAAC,EAAEC,OAAOX,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA,EAAM,CAAA,EAAG;CACzCY,WAASC,sCAAA,WAAA;AACX,CAAA"}
1
+ {"version":3,"file":"pca-DUrQ_tIg.mjs","names":["createFileRoute","t","Route","staticData","section","service","sectionCrumb","labelKey","crumb","RouteInfo","head","meta","title","component","lazyRouteComponent","$$splitComponentImporter"],"sources":["../../src/client/routes/_auth/projects/$projectId/services/pca/index.tsx"],"sourcesContent":["import { createFileRoute } from \"@tanstack/react-router\"\nimport { t } from \"@lingui/core/macro\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { ContentHeader } from \"@/client/components/ContentHeader/ContentHeader\"\nimport { PcaListContainer } from \"./-components/PcaListContainer\"\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/services/pca/\")({\n staticData: {\n section: \"services\",\n service: \"pca\",\n sectionCrumb: { labelKey: \"Services\" },\n crumb: { labelKey: \"PCA (Clavis)\" },\n } satisfies RouteInfo,\n head: () => ({ meta: [{ title: t`PCA` }] }),\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":";;AAOA,IAAaE,IAAQF,EAAgB,0CAAA,EAA4C;CAC/EG,YAAY;EACVC,SAAS;EACTC,SAAS;EACTC,cAAc,EAAEC,UAAU,WAAW;EACrCC,OAAO,EAAED,UAAU,eAAe;CACpC;CACAG,aAAa,EAAEC,MAAM,CAAC,EAAEC,OAAOX,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA,EAAM,CAAA,EAAG;CACzCY,WAASC,sCAAA,WAAA;AACX,CAAA"}
@@ -1,7 +1,7 @@
1
1
  import { createFileRoute as e, lazyRouteComponent as t } from "@tanstack/react-router";
2
2
  import { z as n } from "zod";
3
3
  //#region src/client/routes/_auth/projects/index.tsx
4
- var r = () => import("./projects-yiK0HGSA.mjs"), i = () => import("./projects-CHYn7L5e.mjs"), a = () => import("./projects-Dmewygrp.mjs"), o = n.object({ search: n.string().optional() }), s = e("/_auth/projects/")({
4
+ var r = () => import("./projects-yiK0HGSA.mjs"), i = () => import("./projects-CHYn7L5e.mjs"), a = () => import("./projects-DNd3UTas.mjs"), o = n.object({ search: n.string().optional() }), s = e("/_auth/projects/")({
5
5
  component: t(a, "component"),
6
6
  errorComponent: t(i, "errorComponent"),
7
7
  notFoundComponent: t(r, "notFoundComponent"),
@@ -19,4 +19,4 @@ var r = () => import("./projects-yiK0HGSA.mjs"), i = () => import("./projects-CH
19
19
  //#endregion
20
20
  export { s as t };
21
21
 
22
- //# sourceMappingURL=projects-B_PPyZD1.mjs.map
22
+ //# sourceMappingURL=projects-B5topuei.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projects-B5topuei.mjs","names":["createFileRoute","z","searchSchema","object","search","string","optional","Route","component","lazyRouteComponent","$$splitComponentImporter","errorComponent","$$splitErrorComponentImporter","notFoundComponent","$$splitNotFoundComponentImporter","validateSearch","loaderDeps","loader","context","deps","allProjects","trpcClient","project","getAuthProjects","query","projects","trim","searchTermLower","toLowerCase","filter","name","includes","description"],"sources":["../../src/client/routes/_auth/projects/index.tsx"],"sourcesContent":["import { createFileRoute } from \"@tanstack/react-router\"\nimport { 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 } from \"@cloudoperators/juno-ui-components\"\nimport { Trans } from \"@lingui/react/macro\"\nimport { z } from \"zod\"\nimport { Slot } from \"@/client/components/Slot\"\n\nconst searchSchema = z.object({\n search: z.string().optional(),\n})\n\nexport const Route = createFileRoute(\"/_auth/projects/\")({\n component: ProjectsOverview,\n errorComponent: ({ error }) => (\n <RouteError error={error} safeErrorMessage={error instanceof TRPCClientError ? error.message : undefined} />\n ),\n notFoundComponent: () => {\n return <p>Projects not found</p>\n },\n validateSearch: searchSchema,\n loaderDeps: ({ search }) => ({\n search: search.search || \"\",\n }),\n loader: async ({ context, deps }) => {\n const allProjects = await context.trpcClient?.project.getAuthProjects.query()\n\n let projects = allProjects\n if (deps.search && deps.search.trim() !== \"\") {\n const searchTermLower = deps.search.toLowerCase()\n projects = allProjects?.filter(\n (project) =>\n project.name?.toLowerCase().includes(searchTermLower) ||\n project.description?.toLowerCase().includes(searchTermLower)\n )\n }\n\n return { projects }\n },\n})\n\nfunction ProjectsOverview() {\n const { projects } = Route.useLoaderData()\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: { search: value }, replace: true })\n }\n\n return (\n <Container py>\n <ContentHeading className=\"pb-4\">\n <Trans>Projects</Trans>\n </ContentHeading>\n {slots?.projectsBanner && <Slot component={slots.projectsBanner} useShadowDOM={false} />}\n <ProjectsOverviewNavBar searchTerm={search} onSearch={handleSearch} />\n <div className=\"pt-5\">\n <ProjectCardView projects={projects} />\n </div>\n </Container>\n )\n}\n"],"mappings":";;;2IAWME,IAAeD,EAAEE,OAAO,EAC5BC,QAAQH,EAAEI,OAAM,EAAGC,SAAQ,EAC7B,CAAA,GAEaC,IAAQP,EAAgB,kBAAA,EAAoB;CACvDQ,WAASC,EAAAC,GAAA,WAAA;CACTC,gBAAcF,EAAAG,GAAA,gBAAA;CAGdC,mBAAiBJ,EAAAK,GAAA,mBAAA;CAGjBC,gBAAgBb;CAChBc,aAAa,EAAEZ,iBAAc,EAC3BA,QAAQA,EAAOA,UAAU,GAC3B;CACAa,QAAQ,OAAO,EAAEC,YAASC,cAAM;EAC9B,IAAMC,IAAc,MAAMF,EAAQG,YAAYC,QAAQC,gBAAgBC,MAAAA,GAElEC,IAAWL;EACf,IAAID,EAAKf,UAAUe,EAAKf,OAAOsB,KAAI,MAAO,IAAI;GAC5C,IAAMC,IAAkBR,EAAKf,OAAOwB,YAAW;GAC/CH,IAAWL,GAAaS,QACrBP,MACCA,EAAQQ,MAAMF,YAAAA,EAAcG,SAASJ,CAAAA,KACrCL,EAAQU,aAAaJ,YAAAA,EAAcG,SAASJ,CAAAA,CAAAA;EAElD;EAEA,OAAO,EAAEF,YAAS;CACpB;AACF,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"projects-CHYn7L5e.mjs","names":["RouteError","TRPCClientError","SplitErrorComponent","error","message","undefined","errorComponent"],"sources":["../../src/client/routes/_auth/projects/index.tsx?tsr-split=errorComponent"],"sourcesContent":["import { createFileRoute } 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 } from \"@cloudoperators/juno-ui-components\"\nimport { Trans } from \"@lingui/react/macro\"\nimport { z } from \"zod\"\n\nconst searchSchema = z.object({\n search: z.string().optional(),\n})\n\nexport const Route = createFileRoute(\"/_auth/projects/\")({\n component: ProjectsOverview,\n errorComponent: ({ error }) => (\n <RouteError error={error} safeErrorMessage={error instanceof TRPCClientError ? error.message : undefined} />\n ),\n notFoundComponent: () => {\n return <p>Projects not found</p>\n },\n validateSearch: searchSchema,\n loaderDeps: ({ search }) => ({\n search: search.search || \"\",\n }),\n loader: async ({ context, deps }) => {\n const allProjects = await context.trpcClient?.project.getAuthProjects.query()\n\n let projects = allProjects\n if (deps.search && deps.search.trim() !== \"\") {\n const searchTermLower = deps.search.toLowerCase()\n projects = allProjects?.filter(\n (project) =>\n project.name?.toLowerCase().includes(searchTermLower) ||\n project.description?.toLowerCase().includes(searchTermLower)\n )\n }\n\n return { projects }\n },\n})\n\nfunction ProjectsOverview() {\n const { projects } = Route.useLoaderData()\n const { search = \"\" } = Route.useSearch()\n const navigate = Route.useNavigate()\n\n const handleSearch = (value: string) => {\n navigate({ search: { search: value }, replace: true })\n }\n\n return (\n <Container py>\n <ContentHeading className=\"pb-4\">\n <Trans>Projects</Trans>\n </ContentHeading>\n <ProjectsOverviewNavBar searchTerm={search} onSearch={handleSearch} />\n <div className=\"pt-5\">\n <ProjectCardView projects={projects} />\n </div>\n </Container>\n )\n}\n"],"mappings":";;;;AAI8C,IAAAE,KAW3B,EAAEC,eACjB,gBAAC,GAAA;CAAkBA;CAAO,kBAAkBA,aAAiBF,IAAkBE,EAAMC,UAAUC,KAAAA"}
1
+ {"version":3,"file":"projects-CHYn7L5e.mjs","names":["RouteError","TRPCClientError","SplitErrorComponent","error","message","undefined","errorComponent"],"sources":["../../src/client/routes/_auth/projects/index.tsx?tsr-split=errorComponent"],"sourcesContent":["import { createFileRoute } from \"@tanstack/react-router\"\nimport { 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 } from \"@cloudoperators/juno-ui-components\"\nimport { Trans } from \"@lingui/react/macro\"\nimport { z } from \"zod\"\nimport { Slot } from \"@/client/components/Slot\"\n\nconst searchSchema = z.object({\n search: z.string().optional(),\n})\n\nexport const Route = createFileRoute(\"/_auth/projects/\")({\n component: ProjectsOverview,\n errorComponent: ({ error }) => (\n <RouteError error={error} safeErrorMessage={error instanceof TRPCClientError ? error.message : undefined} />\n ),\n notFoundComponent: () => {\n return <p>Projects not found</p>\n },\n validateSearch: searchSchema,\n loaderDeps: ({ search }) => ({\n search: search.search || \"\",\n }),\n loader: async ({ context, deps }) => {\n const allProjects = await context.trpcClient?.project.getAuthProjects.query()\n\n let projects = allProjects\n if (deps.search && deps.search.trim() !== \"\") {\n const searchTermLower = deps.search.toLowerCase()\n projects = allProjects?.filter(\n (project) =>\n project.name?.toLowerCase().includes(searchTermLower) ||\n project.description?.toLowerCase().includes(searchTermLower)\n )\n }\n\n return { projects }\n },\n})\n\nfunction ProjectsOverview() {\n const { projects } = Route.useLoaderData()\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: { search: value }, replace: true })\n }\n\n return (\n <Container py>\n <ContentHeading className=\"pb-4\">\n <Trans>Projects</Trans>\n </ContentHeading>\n {slots?.projectsBanner && <Slot component={slots.projectsBanner} useShadowDOM={false} />}\n <ProjectsOverviewNavBar searchTerm={search} onSearch={handleSearch} />\n <div className=\"pt-5\">\n <ProjectCardView projects={projects} />\n </div>\n </Container>\n )\n}\n"],"mappings":";;;;AAK8C,IAAAE,KAY3B,EAAEC,eACjB,gBAAC,GAAA;CAAkBA;CAAO,kBAAkBA,aAAiBF,IAAkBE,EAAMC,UAAUC,KAAAA"}
@@ -0,0 +1,110 @@
1
+ import { O as e, Q as t, V as n, u as r } from "./build-BdRRmNf5.mjs";
2
+ import { t as i } from "./Slot-CWb612-_.mjs";
3
+ import { t as a } from "./projects-B5topuei.mjs";
4
+ import { jsx as o, jsxs as s } from "react/jsx-runtime";
5
+ import { useEffect as c, useRef as l, useState as u } from "react";
6
+ import { useNavigate as d, useRouteContext as f } from "@tanstack/react-router";
7
+ import { Trans as p, useLingui as m } from "@lingui/react";
8
+ //#region src/client/routes/_auth/projects/-components/ProjectOverviewNavBar.tsx
9
+ function h({ onSearch: e, searchTerm: t = "" }) {
10
+ let { i18n: r, _: i } = m(), a = l(null), s = l(!1), [d, f] = u(t);
11
+ return c(() => {
12
+ !s.current && !a.current && t !== d && f(t);
13
+ }, [t]), c(() => () => {
14
+ a.current && clearTimeout(a.current);
15
+ }, []), /*#__PURE__*/ o(n, {
16
+ className: "w-full",
17
+ type: "text",
18
+ placeholder: r._({ id: "YIix5Y" }),
19
+ onChange: (t) => {
20
+ let n = t.target.value;
21
+ f(n), a.current && clearTimeout(a.current), a.current = setTimeout(() => {
22
+ a.current = null, e(n);
23
+ }, 300);
24
+ },
25
+ onFocus: () => {
26
+ s.current = !0;
27
+ },
28
+ onBlur: () => {
29
+ s.current = !1;
30
+ },
31
+ onClear: () => {
32
+ a.current &&= (clearTimeout(a.current), null), f(""), e("");
33
+ },
34
+ value: d
35
+ });
36
+ }
37
+ //#endregion
38
+ //#region src/client/routes/_auth/projects/-components/ProjectCardView.tsx
39
+ function g({ project: e }) {
40
+ let t = d();
41
+ return /*#__PURE__*/ s(r, {
42
+ padding: !0,
43
+ onClick: () => t({
44
+ to: "/projects/$projectId",
45
+ params: { projectId: e.id }
46
+ }),
47
+ className: "flex flex-col gap-4",
48
+ children: [/*#__PURE__*/ s("div", {
49
+ className: "flex min-w-0 flex-col",
50
+ children: [/*#__PURE__*/ o("p", {
51
+ className: "text-theme-light text-xs leading-5 font-normal",
52
+ children: e.domain_name ?? e.domain_id ?? /*#__PURE__*/ o(p, { id: "ZkxxiR" })
53
+ }), /*#__PURE__*/ o("p", {
54
+ "data-testid": "project-name",
55
+ className: "text-theme-high text-lg leading-7 font-bold",
56
+ children: e.name
57
+ })]
58
+ }), e.description && /*#__PURE__*/ o("p", {
59
+ className: "text-theme-default line-clamp-2 text-sm font-normal",
60
+ children: e.description
61
+ })]
62
+ });
63
+ }
64
+ function _({ projects: e }) {
65
+ return /*#__PURE__*/ o("div", {
66
+ className: "w-full",
67
+ children: /*#__PURE__*/ o("div", {
68
+ className: "grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4",
69
+ children: e?.length ? e.map((e) => /*#__PURE__*/ o(g, { project: e }, e.id)) : /*#__PURE__*/ o("p", {
70
+ className: "text-center",
71
+ children: /*#__PURE__*/ o(p, { id: "Zgp2Sm" })
72
+ })
73
+ })
74
+ });
75
+ }
76
+ //#endregion
77
+ //#region src/client/routes/_auth/projects/index.tsx?tsr-split=component
78
+ function v() {
79
+ let { projects: n } = a.useLoaderData(), { search: r = "" } = a.useSearch(), c = a.useNavigate(), { slots: l } = f({ strict: !1 });
80
+ return /*#__PURE__*/ s(e, {
81
+ py: !0,
82
+ children: [
83
+ /*#__PURE__*/ o(t, {
84
+ className: "pb-4",
85
+ children: /*#__PURE__*/ o(p, { id: "+0B+ue" })
86
+ }),
87
+ l?.projectsBanner && /*#__PURE__*/ o(i, {
88
+ component: l.projectsBanner,
89
+ useShadowDOM: !1
90
+ }),
91
+ /*#__PURE__*/ o(h, {
92
+ searchTerm: r,
93
+ onSearch: (e) => {
94
+ c({
95
+ search: { search: e },
96
+ replace: !0
97
+ });
98
+ }
99
+ }),
100
+ /*#__PURE__*/ o("div", {
101
+ className: "pt-5",
102
+ children: /*#__PURE__*/ o(_, { projects: n })
103
+ })
104
+ ]
105
+ });
106
+ }
107
+ //#endregion
108
+ export { v as component };
109
+
110
+ //# sourceMappingURL=projects-DNd3UTas.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projects-DNd3UTas.mjs","names":["useEffect","useRef","useState","SearchInput","ProjectsOverviewNavBar","onSearch","searchTerm","useLingui","timerRef","inputFocusedRef","inputValue","setInputValue","current","clearTimeout","handleSearchChange","e","value","target","setTimeout","handleClear","className","type","placeholder","t","onChange","onFocus","onBlur","onClear","useNavigate","Card","ProjectCard","project","navigate","padding","onClick","to","params","projectId","id","className","div","p","domain_name","domain_id","data-testid","name","description","ProjectCardView","projects","length","map","useRouteContext","ProjectsOverviewNavBar","ProjectCardView","Container","ContentHeading","Trans","Slot","Route","ProjectsOverview","projects","useLoaderData","search","useSearch","navigate","useNavigate","slots","strict","handleSearch","value","replace","projectsBanner","component"],"sources":["../../src/client/routes/_auth/projects/-components/ProjectOverviewNavBar.tsx","../../src/client/routes/_auth/projects/-components/ProjectCardView.tsx","../../src/client/routes/_auth/projects/index.tsx?tsr-split=component"],"sourcesContent":["import { ChangeEvent, useEffect, useRef, useState } from \"react\"\nimport { SearchInput } from \"@cloudoperators/juno-ui-components\"\nimport { useLingui } from \"@lingui/react/macro\"\n\ntype ProjectsOverviewNavBarProps = {\n searchTerm?: string\n onSearch: (value: string) => void\n}\n\nexport function ProjectsOverviewNavBar({ onSearch, searchTerm = \"\" }: ProjectsOverviewNavBarProps) {\n const { t } = useLingui()\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const inputFocusedRef = useRef(false)\n const [inputValue, setInputValue] = useState(searchTerm)\n\n useEffect(() => {\n if (!inputFocusedRef.current && !timerRef.current && searchTerm !== inputValue) {\n setInputValue(searchTerm)\n }\n }, [searchTerm])\n\n useEffect(() => {\n return () => {\n if (timerRef.current) clearTimeout(timerRef.current)\n }\n }, [])\n\n const handleSearchChange = (e: ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value\n setInputValue(value)\n if (timerRef.current) clearTimeout(timerRef.current)\n timerRef.current = setTimeout(() => {\n timerRef.current = null\n onSearch(value)\n }, 300)\n }\n\n const handleClear = () => {\n if (timerRef.current) {\n clearTimeout(timerRef.current)\n timerRef.current = null\n }\n setInputValue(\"\")\n onSearch(\"\")\n }\n\n return (\n <SearchInput\n className=\"w-full\"\n type=\"text\"\n placeholder={t`Search...`}\n onChange={handleSearchChange}\n onFocus={() => {\n inputFocusedRef.current = true\n }}\n onBlur={() => {\n inputFocusedRef.current = false\n }}\n onClear={handleClear}\n value={inputValue}\n />\n )\n}\n","import { useNavigate } from \"@tanstack/react-router\"\nimport { Project } from \"@/server/Project/types/models\"\nimport { Card } from \"@cloudoperators/juno-ui-components\"\nimport { Trans } from \"@lingui/react/macro\"\n\ntype ProjectCardProps = {\n project: Project\n}\ntype ProjectCardViewProps = {\n projects: Project[] | undefined\n}\n\nexport function ProjectCard({ project }: ProjectCardProps) {\n const navigate = useNavigate()\n return (\n <Card\n padding\n onClick={() => navigate({ to: \"/projects/$projectId\", params: { projectId: project.id } })}\n className=\"flex flex-col gap-4\"\n >\n <div className=\"flex min-w-0 flex-col\">\n <p className=\"text-theme-light text-xs leading-5 font-normal\">\n {project.domain_name ?? project.domain_id ?? <Trans>Unknown domain</Trans>}\n </p>\n <p data-testid=\"project-name\" className=\"text-theme-high text-lg leading-7 font-bold\">\n {project.name}\n </p>\n </div>\n {project.description && (\n <p className=\"text-theme-default line-clamp-2 text-sm font-normal\">{project.description}</p>\n )}\n </Card>\n )\n}\n\nexport function ProjectCardView({ projects }: ProjectCardViewProps) {\n return (\n <div className=\"w-full\">\n <div className=\"grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4\">\n {projects?.length ? (\n projects.map((project) => <ProjectCard key={project.id} project={project} />)\n ) : (\n <p className=\"text-center\">\n <Trans>No projects available.</Trans>\n </p>\n )}\n </div>\n </div>\n )\n}\n","import { createFileRoute } from \"@tanstack/react-router\"\nimport { 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 } from \"@cloudoperators/juno-ui-components\"\nimport { Trans } from \"@lingui/react/macro\"\nimport { z } from \"zod\"\nimport { Slot } from \"@/client/components/Slot\"\n\nconst searchSchema = z.object({\n search: z.string().optional(),\n})\n\nexport const Route = createFileRoute(\"/_auth/projects/\")({\n component: ProjectsOverview,\n errorComponent: ({ error }) => (\n <RouteError error={error} safeErrorMessage={error instanceof TRPCClientError ? error.message : undefined} />\n ),\n notFoundComponent: () => {\n return <p>Projects not found</p>\n },\n validateSearch: searchSchema,\n loaderDeps: ({ search }) => ({\n search: search.search || \"\",\n }),\n loader: async ({ context, deps }) => {\n const allProjects = await context.trpcClient?.project.getAuthProjects.query()\n\n let projects = allProjects\n if (deps.search && deps.search.trim() !== \"\") {\n const searchTermLower = deps.search.toLowerCase()\n projects = allProjects?.filter(\n (project) =>\n project.name?.toLowerCase().includes(searchTermLower) ||\n project.description?.toLowerCase().includes(searchTermLower)\n )\n }\n\n return { projects }\n },\n})\n\nfunction ProjectsOverview() {\n const { projects } = Route.useLoaderData()\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: { search: value }, replace: true })\n }\n\n return (\n <Container py>\n <ContentHeading className=\"pb-4\">\n <Trans>Projects</Trans>\n </ContentHeading>\n {slots?.projectsBanner && <Slot component={slots.projectsBanner} useShadowDOM={false} />}\n <ProjectsOverviewNavBar searchTerm={search} onSearch={handleSearch} />\n <div className=\"pt-5\">\n <ProjectCardView projects={projects} />\n </div>\n </Container>\n )\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"projects-yiK0HGSA.mjs","names":["SplitNotFoundComponent","notFoundComponent"],"sources":["../../src/client/routes/_auth/projects/index.tsx?tsr-split=notFoundComponent"],"sourcesContent":["import { createFileRoute } 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 } from \"@cloudoperators/juno-ui-components\"\nimport { Trans } from \"@lingui/react/macro\"\nimport { z } from \"zod\"\n\nconst searchSchema = z.object({\n search: z.string().optional(),\n})\n\nexport const Route = createFileRoute(\"/_auth/projects/\")({\n component: ProjectsOverview,\n errorComponent: ({ error }) => (\n <RouteError error={error} safeErrorMessage={error instanceof TRPCClientError ? error.message : undefined} />\n ),\n notFoundComponent: () => {\n return <p>Projects not found</p>\n },\n validateSearch: searchSchema,\n loaderDeps: ({ search }) => ({\n search: search.search || \"\",\n }),\n loader: async ({ context, deps }) => {\n const allProjects = await context.trpcClient?.project.getAuthProjects.query()\n\n let projects = allProjects\n if (deps.search && deps.search.trim() !== \"\") {\n const searchTermLower = deps.search.toLowerCase()\n projects = allProjects?.filter(\n (project) =>\n project.name?.toLowerCase().includes(searchTermLower) ||\n project.description?.toLowerCase().includes(searchTermLower)\n )\n }\n\n return { projects }\n },\n})\n\nfunction ProjectsOverview() {\n const { projects } = Route.useLoaderData()\n const { search = \"\" } = Route.useSearch()\n const navigate = Route.useNavigate()\n\n const handleSearch = (value: string) => {\n navigate({ search: { search: value }, replace: true })\n }\n\n return (\n <Container py>\n <ContentHeading className=\"pb-4\">\n <Trans>Projects</Trans>\n </ContentHeading>\n <ProjectsOverviewNavBar searchTerm={search} onSearch={handleSearch} />\n <div className=\"pt-5\">\n <ProjectCardView projects={projects} />\n </div>\n </Container>\n )\n}\n"],"mappings":";;cAmBW,gBAAC,KAAA,EAAA,UAAE,qBAAA,CAAA"}
1
+ {"version":3,"file":"projects-yiK0HGSA.mjs","names":["SplitNotFoundComponent","notFoundComponent"],"sources":["../../src/client/routes/_auth/projects/index.tsx?tsr-split=notFoundComponent"],"sourcesContent":["import { createFileRoute } from \"@tanstack/react-router\"\nimport { 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 } from \"@cloudoperators/juno-ui-components\"\nimport { Trans } from \"@lingui/react/macro\"\nimport { z } from \"zod\"\nimport { Slot } from \"@/client/components/Slot\"\n\nconst searchSchema = z.object({\n search: z.string().optional(),\n})\n\nexport const Route = createFileRoute(\"/_auth/projects/\")({\n component: ProjectsOverview,\n errorComponent: ({ error }) => (\n <RouteError error={error} safeErrorMessage={error instanceof TRPCClientError ? error.message : undefined} />\n ),\n notFoundComponent: () => {\n return <p>Projects not found</p>\n },\n validateSearch: searchSchema,\n loaderDeps: ({ search }) => ({\n search: search.search || \"\",\n }),\n loader: async ({ context, deps }) => {\n const allProjects = await context.trpcClient?.project.getAuthProjects.query()\n\n let projects = allProjects\n if (deps.search && deps.search.trim() !== \"\") {\n const searchTermLower = deps.search.toLowerCase()\n projects = allProjects?.filter(\n (project) =>\n project.name?.toLowerCase().includes(searchTermLower) ||\n project.description?.toLowerCase().includes(searchTermLower)\n )\n }\n\n return { projects }\n },\n})\n\nfunction ProjectsOverview() {\n const { projects } = Route.useLoaderData()\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: { search: value }, replace: true })\n }\n\n return (\n <Container py>\n <ContentHeading className=\"pb-4\">\n <Trans>Projects</Trans>\n </ContentHeading>\n {slots?.projectsBanner && <Slot component={slots.projectsBanner} useShadowDOM={false} />}\n <ProjectsOverviewNavBar searchTerm={search} onSearch={handleSearch} />\n <div className=\"pt-5\">\n <ProjectCardView projects={projects} />\n </div>\n </Container>\n )\n}\n"],"mappings":";;cAqBW,gBAAC,KAAA,EAAA,UAAE,qBAAA,CAAA"}
@@ -0,0 +1,31 @@
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({
18
+ section: e.string(),
19
+ service: e.string().optional(),
20
+ isDetail: e.boolean().optional(),
21
+ crumb: t.optional(),
22
+ sectionCrumb: t.optional(),
23
+ intermediateCrumb: t.optional()
24
+ });
25
+ function r(e) {
26
+ return n.safeParse(e).success;
27
+ }
28
+ //#endregion
29
+ export { r as t };
30
+
31
+ //# sourceMappingURL=routeInfo-Dy9l-wFB.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routeInfo-Dy9l-wFB.mjs","names":["z","CRUMB_LABEL_KEYS","CrumbSchema","object","labelKey","enum","optional","to","string","useParamAsLabel","useParentTitleAsLabel","boolean","RouteInfoSchema","section","service","isDetail","crumb","sectionCrumb","intermediateCrumb","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 RouteInfoSchema = z.object({\n section: z.string(),\n service: z.string().optional(),\n isDetail: z.boolean().optional(),\n crumb: CrumbSchema.optional(),\n sectionCrumb: CrumbSchema.optional(),\n intermediateCrumb: CrumbSchema.optional(),\n})\n\nexport type Crumb = z.infer<typeof CrumbSchema>\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;CAC/BU,SAASb,EAAEQ,OAAM;CACjBM,SAASd,EAAEQ,OAAM,EAAGF,SAAQ;CAC5BS,UAAUf,EAAEW,QAAO,EAAGL,SAAQ;CAC9BU,OAAOd,EAAYI,SAAQ;CAC3BW,cAAcf,EAAYI,SAAQ;CAClCY,mBAAmBhB,EAAYI,SAAQ;AACzC,CAAA;AAKA,SAAgBa,EAAYC,GAAa;CACvC,OAAOR,EAAgBS,UAAUD,CAAAA,EAAME;AACzC"}
@@ -2,7 +2,7 @@ import { D as e, G as t, H as n, J as r, L as i, N as a, Q as o, S as s, U as c,
2
2
  import { r as x } from "./trpcClient-BzPUgiM2.mjs";
3
3
  import { t as S } from "./useProjectId-DBc5lpoU.mjs";
4
4
  import "./hooks-dSArr2Ca.mjs";
5
- import { n as C, t as w } from "./useListWithFiltering-v2A0-SZb.mjs";
5
+ import { n as C, t as w } from "./useListWithFiltering-CVzhMyEA.mjs";
6
6
  import { t as T } from "./buildFilterParams-DoZzMKX9.mjs";
7
7
  import { t as E } from "./EditSecurityGroupModal-DKusxfta.mjs";
8
8
  import { Fragment as D, jsx as O, jsxs as k } from "react/jsx-runtime";
@@ -437,4 +437,4 @@ function U() {
437
437
  //#endregion
438
438
  export { U as component };
439
439
 
440
- //# sourceMappingURL=securitygroups-CNFLu9zS.mjs.map
440
+ //# sourceMappingURL=securitygroups-CcA2TpAt.mjs.map