@cobaltcore-dev/aurora 0.3.1 → 0.5.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/README.md +73 -77
- package/dist/client/AuroraApp.d.ts +15 -0
- package/dist/client/{AuthProvider-D-5Jpa6F.mjs → AuthProvider-Co4d0WzB.mjs} +3 -3
- package/dist/client/{AuthProvider-D-5Jpa6F.mjs.map → AuthProvider-Co4d0WzB.mjs.map} +1 -1
- package/dist/client/{ContentHeader-BXZoN3B9.mjs → ContentHeader-xQVhO2yT.mjs} +20 -20
- package/dist/client/{ContentHeader-BXZoN3B9.mjs.map → ContentHeader-xQVhO2yT.mjs.map} +1 -1
- package/dist/client/{DeleteFlavorModal-BusYn32r.mjs → DeleteFlavorModal-CHTUZ3YV.mjs} +211 -202
- package/dist/client/DeleteFlavorModal-CHTUZ3YV.mjs.map +1 -0
- package/dist/client/{EditSecurityGroupModal-Dl6m7wUe.mjs → EditSecurityGroupModal-CWHHx2Xk.mjs} +22 -22
- package/dist/client/{EditSecurityGroupModal-Dl6m7wUe.mjs.map → EditSecurityGroupModal-CWHHx2Xk.mjs.map} +1 -1
- package/dist/client/{FiltersInput-BgNaHFBt.mjs → FiltersInput-UKJpNFdr.mjs} +11 -11
- package/dist/client/FiltersInput-UKJpNFdr.mjs.map +1 -0
- package/dist/client/{FloatingIpActionModals-By2hXR9m.mjs → FloatingIpActionModals-caXn6bYo.mjs} +54 -54
- package/dist/client/{FloatingIpActionModals-By2hXR9m.mjs.map → FloatingIpActionModals-caXn6bYo.mjs.map} +1 -1
- package/dist/client/{ImageToastNotifications-fHI8jB2j.mjs → ImageToastNotifications-BWimIzu_.mjs} +227 -227
- package/dist/client/{ImageToastNotifications-fHI8jB2j.mjs.map → ImageToastNotifications-BWimIzu_.mjs.map} +1 -1
- package/dist/client/{RouteError-pDEWC_k7.mjs → RouteError-CUj_m3gu.mjs} +6 -6
- package/dist/client/{RouteError-pDEWC_k7.mjs.map → RouteError-CUj_m3gu.mjs.map} +1 -1
- package/dist/client/{SortInput-DXWSqSny.mjs → SortInput-GQlQBlAj.mjs} +6 -6
- package/dist/client/{SortInput-DXWSqSny.mjs.map → SortInput-GQlQBlAj.mjs.map} +1 -1
- package/dist/client/{_auth-CJj1Cnbm.mjs → _auth-DXJkv9QO.mjs} +3 -3
- package/dist/client/{_auth-CJj1Cnbm.mjs.map → _auth-DXJkv9QO.mjs.map} +1 -1
- package/dist/client/_flavorId-C5dc1N_j.mjs +194 -0
- package/dist/client/_flavorId-C5dc1N_j.mjs.map +1 -0
- package/dist/client/{_flavorId-BoNcxYmF.mjs → _flavorId-sUWG0xuy.mjs} +15 -15
- package/dist/client/_flavorId-sUWG0xuy.mjs.map +1 -0
- package/dist/client/{_floatingIpId-BpUfL8Im2.mjs → _floatingIpId-COK_TBrz2.mjs} +42 -42
- package/dist/client/{_floatingIpId-BpUfL8Im2.mjs.map → _floatingIpId-COK_TBrz2.mjs.map} +1 -1
- package/dist/client/{_floatingIpId-CwHiXazi.mjs → _floatingIpId-CT4y-60o.mjs} +3 -3
- package/dist/client/{_floatingIpId-CwHiXazi.mjs.map → _floatingIpId-CT4y-60o.mjs.map} +1 -1
- package/dist/client/_imageId-n3RcnhAR.mjs +534 -0
- package/dist/client/_imageId-n3RcnhAR.mjs.map +1 -0
- package/dist/client/_pcaId-B-f_6kqs.mjs +466 -0
- package/dist/client/_pcaId-B-f_6kqs.mjs.map +1 -0
- package/dist/client/{_pcaId-D1ZEaCdp.mjs → _pcaId-ChnM_t-9.mjs} +3 -3
- package/dist/client/{_pcaId-D1ZEaCdp.mjs.map → _pcaId-ChnM_t-9.mjs.map} +1 -1
- package/dist/client/_projectId-26bw-_rm.mjs +46 -0
- package/dist/client/_projectId-26bw-_rm.mjs.map +1 -0
- package/dist/client/{_projectId-DhLpIalx.mjs → _projectId-BK9UqeYw.mjs} +14 -14
- package/dist/client/{_projectId-DhLpIalx.mjs.map → _projectId-BK9UqeYw.mjs.map} +1 -1
- package/dist/client/{_projectId-D1gGribM.mjs → _projectId-CCtpAQ8m.mjs} +79 -96
- package/dist/client/_projectId-CCtpAQ8m.mjs.map +1 -0
- package/dist/client/{_projectId-OW2xkK43.mjs → _projectId-Dhb4AyBD.mjs} +3 -3
- package/dist/client/{_projectId-OW2xkK43.mjs.map → _projectId-Dhb4AyBD.mjs.map} +1 -1
- package/dist/client/{_securityGroupId-B0llWH9A.mjs → _securityGroupId-CR1mKICQ.mjs} +3 -3
- package/dist/client/{_securityGroupId-B0llWH9A.mjs.map → _securityGroupId-CR1mKICQ.mjs.map} +1 -1
- package/dist/client/{_securityGroupId-gbUnd5Wv.mjs → _securityGroupId-DroYG6cA.mjs} +254 -255
- package/dist/client/{_securityGroupId-gbUnd5Wv.mjs.map → _securityGroupId-DroYG6cA.mjs.map} +1 -1
- package/dist/client/about-969pIiZ9.mjs +92 -0
- package/dist/client/{about-DCe6LsKz.mjs.map → about-969pIiZ9.mjs.map} +1 -1
- package/dist/client/aurora-DDzsst74.mjs +19 -0
- package/dist/client/{aurora-CRcxVUCo.mjs.map → aurora-DDzsst74.mjs.map} +1 -1
- package/dist/client/{build-BJDfnAyi.mjs → build-DracvfrJ.mjs} +5 -5
- package/dist/client/{build-BJDfnAyi.mjs.map → build-DracvfrJ.mjs.map} +1 -1
- package/dist/client/{buildFilterParams-By33pG59.mjs → buildFilterParams-DoZzMKX9.mjs} +1 -1
- package/dist/client/{buildFilterParams-By33pG59.mjs.map → buildFilterParams-DoZzMKX9.mjs.map} +1 -1
- package/dist/client/{cn-C3laVXMm.mjs → cn-DM4Cy3jv.mjs} +1 -1
- package/dist/client/{cn-C3laVXMm.mjs.map → cn-DM4Cy3jv.mjs.map} +1 -1
- package/dist/client/{constants-CAjjRTo_.mjs → constants-4lVQXort.mjs} +22 -22
- package/dist/client/{constants-CAjjRTo_.mjs.map → constants-4lVQXort.mjs.map} +1 -1
- package/dist/client/{containers-NW7RnHTI.mjs → containers-DGY2hoWw.mjs} +3 -3
- package/dist/client/containers-DGY2hoWw.mjs.map +1 -0
- package/dist/client/containers-ZMFTRaQL.mjs +3277 -0
- package/dist/client/containers-ZMFTRaQL.mjs.map +1 -0
- package/dist/client/{containers-Ca5V1EBS.mjs → containers-xfsYgRyf.mjs} +2 -2
- package/dist/client/containers-xfsYgRyf.mjs.map +1 -0
- package/dist/client/{flavors-D8oElC2K.mjs → flavors-C4GtoybP.mjs} +2 -2
- package/dist/client/{flavors-D8oElC2K.mjs.map → flavors-C4GtoybP.mjs.map} +1 -1
- package/dist/client/{flavors-qvgPSI7J.mjs → flavors-CpirO_nr.mjs} +167 -148
- package/dist/client/flavors-CpirO_nr.mjs.map +1 -0
- package/dist/client/{flavors-BXPYAFyQ.mjs → flavors-DWMZ6TuJ.mjs} +2 -2
- package/dist/client/{flavors-BXPYAFyQ.mjs.map → flavors-DWMZ6TuJ.mjs.map} +1 -1
- package/dist/client/{floatingips-Be3zLoaD.mjs → floatingips-BUf_oLRl.mjs} +74 -75
- package/dist/client/{floatingips-Be3zLoaD.mjs.map → floatingips-BUf_oLRl.mjs.map} +1 -1
- package/dist/client/{formatBytes-D6oa0wU9.mjs → formatBytes-CZv_XyCY.mjs} +1 -1
- package/dist/client/{formatBytes-D6oa0wU9.mjs.map → formatBytes-CZv_XyCY.mjs.map} +1 -1
- package/dist/client/{helpers--JWXi40U.mjs → helpers-1PpYf-fC.mjs} +1 -1
- package/dist/client/{helpers--JWXi40U.mjs.map → helpers-1PpYf-fC.mjs.map} +1 -1
- package/dist/client/hooks-dSArr2Ca.mjs +2 -0
- package/dist/client/images-CsonlmFx.mjs +8 -0
- package/dist/client/images-CsonlmFx.mjs.map +1 -0
- package/dist/client/{images-CCYBAphP2.mjs → images-Da1t5KPh.mjs} +509 -536
- package/dist/client/images-Da1t5KPh.mjs.map +1 -0
- package/dist/client/{images-DM9I8G0p.mjs → images-NBf2bV43.mjs} +2 -2
- package/dist/client/images-NBf2bV43.mjs.map +1 -0
- package/dist/client/{images-BiEBENaj.mjs → images-QnWf63uj.mjs} +2 -2
- package/dist/client/{images-BiEBENaj.mjs.map → images-QnWf63uj.mjs.map} +1 -1
- package/dist/client/index.js +232 -236
- package/dist/client/index.js.map +1 -1
- package/dist/client/{md-BivyCkGC.mjs → md-sBiSNVSQ.mjs} +7 -7
- package/dist/client/{md-BivyCkGC.mjs.map → md-sBiSNVSQ.mjs.map} +1 -1
- package/dist/client/{network-nbSbl0X0.mjs → network-DuZm76BZ.mjs} +2 -2
- package/dist/client/{network-nbSbl0X0.mjs.map → network-DuZm76BZ.mjs.map} +1 -1
- package/dist/client/{objects-CU5ws07o.mjs → objects-B89dYCBq.mjs} +3 -3
- package/dist/client/objects-B89dYCBq.mjs.map +1 -0
- package/dist/client/{objects-GmuIOaHd.mjs → objects-CuFLUOe1.mjs} +2 -2
- package/dist/client/objects-CuFLUOe1.mjs.map +1 -0
- package/dist/client/objects-H0NN_Sja.mjs +5460 -0
- package/dist/client/objects-H0NN_Sja.mjs.map +1 -0
- package/dist/client/{pca-x9if8xU-.mjs → pca-C-UFjicP.mjs} +51 -51
- package/dist/client/pca-C-UFjicP.mjs.map +1 -0
- package/dist/client/{pca-DSM71LhW.mjs → pca-CtU6REww.mjs} +2 -2
- package/dist/client/{pca-DSM71LhW.mjs.map → pca-CtU6REww.mjs.map} +1 -1
- package/dist/client/{projects-B6BPo2Ar.mjs → projects-C-sjd9T5.mjs} +3 -3
- package/dist/client/{projects-B6BPo2Ar.mjs.map → projects-C-sjd9T5.mjs.map} +1 -1
- package/dist/client/{projects-CnmZIB2Q.mjs → projects-DNXsDnJM.mjs} +29 -25
- package/dist/client/projects-DNXsDnJM.mjs.map +1 -0
- package/dist/client/{projects-Bt0XptpG.mjs → projects-dhnQkuvV.mjs} +2 -2
- package/dist/client/{projects-Bt0XptpG.mjs.map → projects-dhnQkuvV.mjs.map} +1 -1
- package/dist/client/{projects-BilrmHLu.mjs → projects-yiK0HGSA.mjs} +2 -2
- package/dist/client/{projects-BilrmHLu.mjs.map → projects-yiK0HGSA.mjs.map} +1 -1
- package/dist/client/{securitygroups-BdzieS7Z.mjs → securitygroups-wHdrxZXd.mjs} +72 -73
- package/dist/client/{securitygroups-BdzieS7Z.mjs.map → securitygroups-wHdrxZXd.mjs.map} +1 -1
- package/dist/client/{trpcClient-BxguzNYF.mjs → trpcClient-BzPUgiM2.mjs} +1 -1
- package/dist/client/{trpcClient-BxguzNYF.mjs.map → trpcClient-BzPUgiM2.mjs.map} +1 -1
- package/dist/client/{useErrorTranslation-TZVwIAzq.mjs → useErrorTranslation-Dc0eE8Zt.mjs} +1 -1
- package/dist/client/{useErrorTranslation-TZVwIAzq.mjs.map → useErrorTranslation-Dc0eE8Zt.mjs.map} +1 -1
- package/dist/client/useListWithFiltering-DrgUwXef.mjs +157 -0
- package/dist/client/useListWithFiltering-DrgUwXef.mjs.map +1 -0
- package/dist/client/{useModal-DxxlilRm.mjs → useModal-DCs1OJh7.mjs} +1 -1
- package/dist/client/{useModal-DxxlilRm.mjs.map → useModal-DCs1OJh7.mjs.map} +1 -1
- package/dist/client/{useProjectId-CgOTejka.mjs → useProjectId-DBc5lpoU.mjs} +1 -1
- package/dist/client/{useProjectId-CgOTejka.mjs.map → useProjectId-DBc5lpoU.mjs.map} +1 -1
- package/dist/server/index.d.ts +7 -1
- package/dist/server/index.js +1363 -453
- package/package.json +7 -7
- package/dist/client/DeleteFlavorModal-BusYn32r.mjs.map +0 -1
- package/dist/client/FiltersInput-BgNaHFBt.mjs.map +0 -1
- package/dist/client/ListToolbar-BvtCo8dk.mjs +0 -129
- package/dist/client/ListToolbar-BvtCo8dk.mjs.map +0 -1
- package/dist/client/_flavorId-BRonXvCo.mjs +0 -188
- package/dist/client/_flavorId-BRonXvCo.mjs.map +0 -1
- package/dist/client/_flavorId-BoNcxYmF.mjs.map +0 -1
- package/dist/client/_imageId-CdOOJjw0.mjs +0 -527
- package/dist/client/_imageId-CdOOJjw0.mjs.map +0 -1
- package/dist/client/_pcaId-CwlH1Kvl.mjs +0 -369
- package/dist/client/_pcaId-CwlH1Kvl.mjs.map +0 -1
- package/dist/client/_projectId-D1gGribM.mjs.map +0 -1
- package/dist/client/_projectId-Dj_InfSc.mjs +0 -26
- package/dist/client/_projectId-Dj_InfSc.mjs.map +0 -1
- package/dist/client/about-DCe6LsKz.mjs +0 -92
- package/dist/client/aurora-CRcxVUCo.mjs +0 -19
- package/dist/client/containers-BuXUVb1N.mjs +0 -3031
- package/dist/client/containers-BuXUVb1N.mjs.map +0 -1
- package/dist/client/containers-Ca5V1EBS.mjs.map +0 -1
- package/dist/client/containers-NW7RnHTI.mjs.map +0 -1
- package/dist/client/flavors-qvgPSI7J.mjs.map +0 -1
- package/dist/client/hooks-D0krAKvo.mjs +0 -2
- package/dist/client/images-CCYBAphP2.mjs.map +0 -1
- package/dist/client/images-DM9I8G0p.mjs.map +0 -1
- package/dist/client/objects-CU5ws07o.mjs.map +0 -1
- package/dist/client/objects-FXN0VWLI.mjs +0 -4760
- package/dist/client/objects-FXN0VWLI.mjs.map +0 -1
- package/dist/client/objects-GmuIOaHd.mjs.map +0 -1
- package/dist/client/overview-B3gdnWTG.mjs +0 -15
- package/dist/client/overview-B3gdnWTG.mjs.map +0 -1
- package/dist/client/overview-DzYBiNfD.mjs +0 -15
- package/dist/client/overview-DzYBiNfD.mjs.map +0 -1
- package/dist/client/overview-EhfPY8Je.mjs +0 -15
- package/dist/client/overview-EhfPY8Je.mjs.map +0 -1
- package/dist/client/overview-XueZI4LQ.mjs +0 -173
- package/dist/client/overview-XueZI4LQ.mjs.map +0 -1
- package/dist/client/pca-x9if8xU-.mjs.map +0 -1
- package/dist/client/projects-CnmZIB2Q.mjs.map +0 -1
- package/dist/client/useListWithFiltering-CqQbAjEe.mjs +0 -32
- package/dist/client/useListWithFiltering-CqQbAjEe.mjs.map +0 -1
- package/permission_policies/compute.yaml +0 -975
- package/permission_policies/image.yaml +0 -71
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"objects-GmuIOaHd.mjs","names":["Trans","SplitNotFoundComponent","notFoundComponent"],"sources":["../../src/client/routes/_auth/projects/$projectId/storage/$provider/containers/$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 { ObjectBrowserView } 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 containerName: string\n }\n) => {\n const { provider, projectId, 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\n if (provider !== \"swift\" && provider !== \"ceph\") {\n if (!fallbackProvider) {\n throw redirect({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n throw redirect({\n to: \"/projects/$projectId/storage/$provider/containers/$containerName/objects\",\n params: { projectId, provider: fallbackProvider, 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/containers/$containerName/objects\",\n params: { projectId, provider: \"ceph\", 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/containers/$containerName/objects\",\n params: { projectId, provider: \"swift\", containerName },\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(\"/_auth/projects/$projectId/storage/$provider/containers/$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/containers\" },\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)\n\nfunction ObjectsDashboard() {\n const { project, provider, containerName } = useParams({\n from: \"/_auth/projects/$projectId/storage/$provider/containers/$containerName/objects/\",\n select: (params) => ({\n project: params.projectId,\n provider: params.provider,\n containerName: params.containerName,\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 />\n case \"ceph\":\n return <ObjectBrowserView 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":";;;AA0FA,IAAAC,UA0BQ,kBAAC,KAAA,EAAA,UACC,kBAAA,GAAA,EAAA,IAAA,UAAA,CAAA,EAAA,CAAA"}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { j as e } from "./build-BJDfnAyi.mjs";
|
|
2
|
-
import { Fragment as t, jsx as n, jsxs as r } from "react/jsx-runtime";
|
|
3
|
-
import { Trans as i, useLingui as a } from "@lingui/react";
|
|
4
|
-
//#region src/client/routes/_auth/projects/$projectId/network/overview.tsx?tsr-split=component
|
|
5
|
-
function o() {
|
|
6
|
-
let { i18n: o, _: s } = a();
|
|
7
|
-
return /* @__PURE__ */ r(t, { children: [/* @__PURE__ */ n(e, { children: o._({ id: "vcXmqy" }) }), /* @__PURE__ */ n("div", {
|
|
8
|
-
className: "p-4 text-center",
|
|
9
|
-
children: /* @__PURE__ */ n(i, { id: "vcXmqy" })
|
|
10
|
-
})] });
|
|
11
|
-
}
|
|
12
|
-
//#endregion
|
|
13
|
-
export { o as component };
|
|
14
|
-
|
|
15
|
-
//# sourceMappingURL=overview-B3gdnWTG.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"overview-B3gdnWTG.mjs","names":["useLingui","Trans","ContentHeading","RouteComponent","t","component"],"sources":["../../src/client/routes/_auth/projects/$projectId/network/overview.tsx?tsr-split=component"],"sourcesContent":["import { createFileRoute } from \"@tanstack/react-router\"\nimport { t } from \"@lingui/core/macro\"\nimport { useLingui, Trans } from \"@lingui/react/macro\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { ContentHeading } from \"@cloudoperators/juno-ui-components\"\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/network/overview\")({\n staticData: { section: \"network\", service: \"overview\", crumb: { labelKey: \"Network\" } } satisfies RouteInfo,\n head: () => ({ meta: [{ title: t`Network Overview` }] }),\n component: RouteComponent,\n})\n\nfunction RouteComponent() {\n const { t } = useLingui()\n return (\n <>\n <ContentHeading>{t`Network Overview`}</ContentHeading>\n <div className=\"p-4 text-center\">\n <Trans>Network Overview</Trans>\n </div>\n </>\n )\n}\n"],"mappings":";;;;AAYA,SAASG,IAAAA;CACP,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQH,GAAAA;AACd,QACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAA,EAAA,UAAgBI,EAAAA,EAAC,EAAA,IAAA,UAAA,CAAA,EAAA,CAAA,EAClB,kBAAC,OAAA;EAAI,WAAU;YACb,kBAAA,GAAA,EAAA,IAAA,UAAA,CAAA"}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { j as e } from "./build-BJDfnAyi.mjs";
|
|
2
|
-
import { Fragment as t, jsx as n, jsxs as r } from "react/jsx-runtime";
|
|
3
|
-
import { Trans as i, useLingui as a } from "@lingui/react";
|
|
4
|
-
//#region src/client/routes/_auth/projects/$projectId/services/overview.tsx?tsr-split=component
|
|
5
|
-
function o() {
|
|
6
|
-
let { i18n: o, _: s } = a();
|
|
7
|
-
return /* @__PURE__ */ r(t, { children: [/* @__PURE__ */ n(e, { children: o._({ id: "rvT6l1" }) }), /* @__PURE__ */ n("div", {
|
|
8
|
-
className: "p-4 text-center",
|
|
9
|
-
children: /* @__PURE__ */ n(i, { id: "rvT6l1" })
|
|
10
|
-
})] });
|
|
11
|
-
}
|
|
12
|
-
//#endregion
|
|
13
|
-
export { o as component };
|
|
14
|
-
|
|
15
|
-
//# sourceMappingURL=overview-DzYBiNfD.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"overview-DzYBiNfD.mjs","names":["useLingui","Trans","ContentHeading","RouteComponent","t","component"],"sources":["../../src/client/routes/_auth/projects/$projectId/services/overview.tsx?tsr-split=component"],"sourcesContent":["import { createFileRoute } from \"@tanstack/react-router\"\nimport { t } from \"@lingui/core/macro\"\nimport { useLingui, Trans } from \"@lingui/react/macro\"\nimport { ContentHeading } from \"@cloudoperators/juno-ui-components\"\nimport { RouteInfo } from \"@/client/routes/routeInfo\"\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/services/overview\")({\n staticData: { section: \"services\", service: \"overview\", crumb: { labelKey: \"Services\" } } satisfies RouteInfo,\n head: () => ({ meta: [{ title: t`Services Overview` }] }),\n component: RouteComponent,\n})\n\nfunction RouteComponent() {\n const { t } = useLingui()\n return (\n <>\n <ContentHeading>{t`Services Overview`}</ContentHeading>\n <div className=\"p-4 text-center\">\n <Trans>Services Overview</Trans>\n </div>\n </>\n )\n}\n"],"mappings":";;;;AAYA,SAASG,IAAAA;CACP,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQH,GAAAA;AACd,QACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAA,EAAA,UAAgBI,EAAAA,EAAC,EAAA,IAAA,UAAA,CAAA,EAAA,CAAA,EAClB,kBAAC,OAAA;EAAI,WAAU;YACb,kBAAA,GAAA,EAAA,IAAA,UAAA,CAAA"}
|
|
@@ -1,15 +0,0 @@
|
|
|
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/compute/overview")({
|
|
4
|
-
staticData: {
|
|
5
|
-
section: "compute",
|
|
6
|
-
service: "overview",
|
|
7
|
-
crumb: { labelKey: "Compute" }
|
|
8
|
-
},
|
|
9
|
-
head: () => ({ meta: [{ title: n._({ id: "grs4+e" }) }] }),
|
|
10
|
-
component: t(() => import("./overview-XueZI4LQ.mjs"), "component")
|
|
11
|
-
});
|
|
12
|
-
//#endregion
|
|
13
|
-
export { r as t };
|
|
14
|
-
|
|
15
|
-
//# sourceMappingURL=overview-EhfPY8Je.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"overview-EhfPY8Je.mjs","names":["createFileRoute","t","Route","staticData","section","service","crumb","labelKey","RouteInfo","head","meta","title","component","lazyRouteComponent","$$splitComponentImporter"],"sources":["../../src/client/routes/_auth/projects/$projectId/compute/overview.tsx"],"sourcesContent":["import { createFileRoute } from \"@tanstack/react-router\"\nimport { t } from \"@lingui/core/macro\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { Overview } from \"./-components/Overview\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { ContentHeading } from \"@cloudoperators/juno-ui-components\"\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/compute/overview\")({\n staticData: { section: \"compute\", service: \"overview\", crumb: { labelKey: \"Compute\" } } satisfies RouteInfo,\n head: () => ({ meta: [{ title: t`Compute Overview` }] }),\n component: RouteComponent,\n})\n\nfunction RouteComponent() {\n const { t } = useLingui()\n const { projectId } = Route.useParams()\n const { trpcClient } = Route.useRouteContext()\n return (\n <>\n <ContentHeading>{t`Compute Overview`}</ContentHeading>\n <Overview project={projectId} client={trpcClient!} />\n </>\n )\n}\n"],"mappings":";;AAOA,IAAaE,IAAQF,EAAgB,8CAAA,CAA+C;CAClFG,YAAY;EAAEC,SAAS;EAAWC,SAAS;EAAYC,OAAO,EAAEC,UAAU,WAAU;EAAE;CACtFE,aAAa,EAAEC,MAAM,CAAC,EAAEC,OAAOV,EAAAA,EAAC,EAAA,IAAA,UAAA,CAAA,EAAmB,CAAC,EAAE;CACtDW,WAASC,2CAAA,YAAA;CACX,CAAA"}
|
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
import { j as e, nt as t } from "./build-BJDfnAyi.mjs";
|
|
2
|
-
import { t as n } from "./overview-EhfPY8Je.mjs";
|
|
3
|
-
import { Fragment as r, jsx as i, jsxs as a } from "react/jsx-runtime";
|
|
4
|
-
import { Suspense as o, use as s } from "react";
|
|
5
|
-
import { Trans as c, useLingui as l } from "@lingui/react";
|
|
6
|
-
//#region src/client/routes/_auth/projects/$projectId/compute/-components/ActivitySummary.tsx
|
|
7
|
-
var u = ({ progress: e, color: t, size: n = 100, strokeWidth: r = 8, label: o, value: s }) => {
|
|
8
|
-
let c = n / 2, l = c - r / 2, u = l * 2 * Math.PI, d = u - e / 100 * u;
|
|
9
|
-
return /* @__PURE__ */ a("div", {
|
|
10
|
-
className: "flex flex-col items-center justify-center",
|
|
11
|
-
children: [/* @__PURE__ */ a("div", {
|
|
12
|
-
style: {
|
|
13
|
-
position: "relative",
|
|
14
|
-
width: n,
|
|
15
|
-
height: n
|
|
16
|
-
},
|
|
17
|
-
children: [/* @__PURE__ */ a("svg", {
|
|
18
|
-
height: n,
|
|
19
|
-
width: n,
|
|
20
|
-
style: { transform: "rotate(-90deg)" },
|
|
21
|
-
children: [/* @__PURE__ */ i("circle", {
|
|
22
|
-
stroke: `${t}33`,
|
|
23
|
-
fill: "transparent",
|
|
24
|
-
strokeWidth: r,
|
|
25
|
-
r: l,
|
|
26
|
-
cx: c,
|
|
27
|
-
cy: c
|
|
28
|
-
}), /* @__PURE__ */ i("circle", {
|
|
29
|
-
stroke: t,
|
|
30
|
-
fill: "transparent",
|
|
31
|
-
strokeWidth: r,
|
|
32
|
-
strokeDasharray: u + " " + u,
|
|
33
|
-
style: { strokeDashoffset: d },
|
|
34
|
-
r: l,
|
|
35
|
-
cx: c,
|
|
36
|
-
cy: c,
|
|
37
|
-
strokeLinecap: "round"
|
|
38
|
-
})]
|
|
39
|
-
}), /* @__PURE__ */ i("div", {
|
|
40
|
-
style: {
|
|
41
|
-
position: "absolute",
|
|
42
|
-
top: "50%",
|
|
43
|
-
left: "50%",
|
|
44
|
-
transform: "translate(-50%, -50%)",
|
|
45
|
-
textAlign: "center"
|
|
46
|
-
},
|
|
47
|
-
children: /* @__PURE__ */ i("div", {
|
|
48
|
-
className: "text-xl font-bold text-gray-200",
|
|
49
|
-
children: s
|
|
50
|
-
})
|
|
51
|
-
})]
|
|
52
|
-
}), /* @__PURE__ */ i("div", {
|
|
53
|
-
className: "mt-2 text-sm text-gray-300",
|
|
54
|
-
children: o
|
|
55
|
-
})]
|
|
56
|
-
});
|
|
57
|
-
};
|
|
58
|
-
function d({ activityData: n }) {
|
|
59
|
-
return /* @__PURE__ */ a(t, {
|
|
60
|
-
distribution: "center",
|
|
61
|
-
alignment: "center",
|
|
62
|
-
direction: "vertical",
|
|
63
|
-
children: [/* @__PURE__ */ i(e, {
|
|
64
|
-
className: "my-6 text-xl font-semibold",
|
|
65
|
-
children: "Activity Summary"
|
|
66
|
-
}), /* @__PURE__ */ a("div", {
|
|
67
|
-
className: "flex flex-wrap justify-start gap-16",
|
|
68
|
-
children: [
|
|
69
|
-
/* @__PURE__ */ i(u, {
|
|
70
|
-
progress: n.instances.current / n.instances.quota * 100,
|
|
71
|
-
color: n.instances.color,
|
|
72
|
-
label: "Instances",
|
|
73
|
-
value: `${n.instances.current}/${n.instances.total}`,
|
|
74
|
-
size: 120
|
|
75
|
-
}),
|
|
76
|
-
/* @__PURE__ */ i(u, {
|
|
77
|
-
progress: n.cpu.percentage,
|
|
78
|
-
color: n.cpu.color,
|
|
79
|
-
label: "CPU",
|
|
80
|
-
value: `${n.cpu.percentage}%`,
|
|
81
|
-
size: 120
|
|
82
|
-
}),
|
|
83
|
-
/* @__PURE__ */ i(u, {
|
|
84
|
-
progress: n.memory.percentage,
|
|
85
|
-
color: n.memory.color,
|
|
86
|
-
label: "Memory",
|
|
87
|
-
value: `${n.memory.percentage}%`,
|
|
88
|
-
size: 120
|
|
89
|
-
}),
|
|
90
|
-
/* @__PURE__ */ i(u, {
|
|
91
|
-
progress: n.storage.percentage,
|
|
92
|
-
color: n.storage.color,
|
|
93
|
-
label: "Storage",
|
|
94
|
-
value: `${n.storage.percentage}%`,
|
|
95
|
-
size: 120
|
|
96
|
-
})
|
|
97
|
-
]
|
|
98
|
-
})]
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
//#endregion
|
|
102
|
-
//#region src/client/routes/_auth/projects/$projectId/compute/-components/Overview.tsx
|
|
103
|
-
var f = ({ getDataPromise: e }) => {
|
|
104
|
-
let [t, n] = s(e), r = n.images;
|
|
105
|
-
if (!t && !r) return /* @__PURE__ */ i("div", {
|
|
106
|
-
className: "p-4 text-center",
|
|
107
|
-
children: "No data found"
|
|
108
|
-
});
|
|
109
|
-
let a = t?.filter((e) => e.status === "ACTIVE")?.length || 0, o = t?.length || 0, c = Math.max(10, Math.ceil(o * 1.5)), l = 0, u = 0, f = 0;
|
|
110
|
-
t?.forEach((e) => {
|
|
111
|
-
if (e.flavor && e.flavor.vcpus) l += e.flavor.vcpus;
|
|
112
|
-
else {
|
|
113
|
-
let t = e.name?.includes("small") || e.name?.includes("micro");
|
|
114
|
-
l += t ? 1 : 2;
|
|
115
|
-
}
|
|
116
|
-
e.flavor && e.flavor.ram ? u += e.flavor.ram : u += 1024, e.flavor && e.flavor.disk ? f += e.flavor.disk : f += 20;
|
|
117
|
-
});
|
|
118
|
-
let p = r?.filter((e) => e.status === "active")?.length || 0, m = r?.length || 0, h = Math.min(100, Math.round(l / 32 * 100)), g = Math.min(100, Math.round(u / 131072 * 100)), _ = Math.min(100, Math.round(f / 1024 * 100));
|
|
119
|
-
return /* @__PURE__ */ i("div", {
|
|
120
|
-
className: "h-full",
|
|
121
|
-
children: /* @__PURE__ */ i(d, { activityData: {
|
|
122
|
-
instances: {
|
|
123
|
-
current: a,
|
|
124
|
-
total: o,
|
|
125
|
-
quota: c,
|
|
126
|
-
color: "#FF5733"
|
|
127
|
-
},
|
|
128
|
-
cpu: {
|
|
129
|
-
percentage: h,
|
|
130
|
-
cores: l,
|
|
131
|
-
color: "#33A1FD"
|
|
132
|
-
},
|
|
133
|
-
memory: {
|
|
134
|
-
percentage: g,
|
|
135
|
-
usedMB: u,
|
|
136
|
-
color: "#9B59B6"
|
|
137
|
-
},
|
|
138
|
-
storage: {
|
|
139
|
-
percentage: _,
|
|
140
|
-
sizeGB: f,
|
|
141
|
-
color: "#4CAF50"
|
|
142
|
-
},
|
|
143
|
-
images: {
|
|
144
|
-
active: p,
|
|
145
|
-
total: m,
|
|
146
|
-
color: "#F1C40F"
|
|
147
|
-
}
|
|
148
|
-
} })
|
|
149
|
-
});
|
|
150
|
-
};
|
|
151
|
-
function p({ client: e, project: t }) {
|
|
152
|
-
let n = Promise.all([e.compute.getServersByProjectId.query({ project_id: t }), e.compute.listImagesWithSearch.query({ project_id: t })]);
|
|
153
|
-
return /* @__PURE__ */ i(o, {
|
|
154
|
-
fallback: /* @__PURE__ */ i("div", {
|
|
155
|
-
className: "p-4 text-center",
|
|
156
|
-
children: /* @__PURE__ */ i(c, { id: "Z3FXyt" })
|
|
157
|
-
}),
|
|
158
|
-
children: /* @__PURE__ */ i(f, { getDataPromise: n })
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
//#endregion
|
|
162
|
-
//#region src/client/routes/_auth/projects/$projectId/compute/overview.tsx?tsr-split=component
|
|
163
|
-
function m() {
|
|
164
|
-
let { i18n: t, _: o } = l(), { projectId: s } = n.useParams(), { trpcClient: c } = n.useRouteContext();
|
|
165
|
-
return /* @__PURE__ */ a(r, { children: [/* @__PURE__ */ i(e, { children: t._({ id: "grs4+e" }) }), /* @__PURE__ */ i(p, {
|
|
166
|
-
project: s,
|
|
167
|
-
client: c
|
|
168
|
-
})] });
|
|
169
|
-
}
|
|
170
|
-
//#endregion
|
|
171
|
-
export { m as component };
|
|
172
|
-
|
|
173
|
-
//# sourceMappingURL=overview-XueZI4LQ.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"overview-XueZI4LQ.mjs","names":["ContentHeading","Stack","React","ActivityRing","progress","color","size","strokeWidth","label","value","radius","normalizedRadius","circumference","Math","PI","strokeDashoffset","div","className","style","position","width","height","svg","transform","circle","stroke","fill","r","cx","cy","strokeDasharray","strokeLinecap","top","left","textAlign","ActivitySummary","activityData","distribution","alignment","direction","instances","current","quota","total","cpu","percentage","memory","storage","ActivitySummary","Suspense","use","OverviewContainer","getDataPromise","servers","imagesResponse","images","div","className","activeServers","filter","server","status","length","totalServers","estimatedServerQuota","Math","max","ceil","totalCores","usedMemoryMB","totalDiskGB","forEach","flavor","vcpus","smallestSize","name","includes","ram","disk","activeImages","image","totalImages","cpuPercentage","min","round","memoryPercentage","storagePercentage","activityData","instances","current","total","quota","color","cpu","percentage","cores","memory","usedMB","storage","sizeGB","active","Overview","client","project","Promise","all","compute","getServersByProjectId","query","project_id","listImagesWithSearch","fallback","useLingui","Overview","ContentHeading","Route","RouteComponent","t","projectId","useParams","trpcClient","useRouteContext","component"],"sources":["../../src/client/routes/_auth/projects/$projectId/compute/-components/ActivitySummary.tsx","../../src/client/routes/_auth/projects/$projectId/compute/-components/Overview.tsx","../../src/client/routes/_auth/projects/$projectId/compute/overview.tsx?tsr-split=component"],"sourcesContent":["import { ContentHeading, Stack } from \"@cloudoperators/juno-ui-components/index\"\nimport React from \"react\"\n\ninterface ActivityRingProps {\n progress: number // Progress percentage (0-100)\n color: string // Color of the ring\n size?: number // Size of the ring (default: 100)\n strokeWidth?: number // Width of the stroke (default: 8)\n label: string // Label for the ring\n value: string // Value to display inside the ring\n}\n// Activity ring component inspired by Apple's activity rings\nconst ActivityRing = ({ progress, color, size = 100, strokeWidth = 8, label, value }: ActivityRingProps) => {\n const radius = size / 2\n const normalizedRadius = radius - strokeWidth / 2\n const circumference = normalizedRadius * 2 * Math.PI\n const strokeDashoffset = circumference - (progress / 100) * circumference\n\n return (\n <div className=\"flex flex-col items-center justify-center\">\n <div style={{ position: \"relative\", width: size, height: size }}>\n <svg height={size} width={size} style={{ transform: \"rotate(-90deg)\" }}>\n {/* Background circle */}\n <circle\n stroke={`${color}33`}\n fill=\"transparent\"\n strokeWidth={strokeWidth}\n r={normalizedRadius}\n cx={radius}\n cy={radius}\n />\n {/* Progress circle */}\n <circle\n stroke={color}\n fill=\"transparent\"\n strokeWidth={strokeWidth}\n strokeDasharray={circumference + \" \" + circumference}\n style={{ strokeDashoffset }}\n r={normalizedRadius}\n cx={radius}\n cy={radius}\n strokeLinecap=\"round\"\n />\n </svg>\n <div\n style={{\n position: \"absolute\",\n top: \"50%\",\n left: \"50%\",\n transform: \"translate(-50%, -50%)\",\n textAlign: \"center\",\n }}\n >\n <div className=\"text-xl font-bold text-gray-200\">{value}</div>\n </div>\n </div>\n <div className=\"mt-2 text-sm text-gray-300\">{label}</div>\n </div>\n )\n}\n\n// Interface for activity data props\ninterface ActivityData {\n instances: {\n current: number\n total: number\n quota: number\n color: string\n }\n cpu: {\n percentage: number\n cores: number\n color: string\n }\n memory: {\n percentage: number\n usedMB: number\n color: string\n }\n storage: {\n percentage: number\n sizeGB: number\n color: string\n }\n images: {\n active: number\n total: number\n color: string\n }\n}\n\nexport function ActivitySummary({ activityData }: { activityData: ActivityData }) {\n return (\n <Stack distribution=\"center\" alignment=\"center\" direction=\"vertical\">\n <ContentHeading className=\"my-6 text-xl font-semibold\">Activity Summary</ContentHeading>\n <div className=\"flex flex-wrap justify-start gap-16\">\n <ActivityRing\n progress={(activityData.instances.current / activityData.instances.quota) * 100}\n color={activityData.instances.color}\n label=\"Instances\"\n value={`${activityData.instances.current}/${activityData.instances.total}`}\n size={120}\n />\n <ActivityRing\n progress={activityData.cpu.percentage}\n color={activityData.cpu.color}\n label=\"CPU\"\n value={`${activityData.cpu.percentage}%`}\n size={120}\n />\n <ActivityRing\n progress={activityData.memory.percentage}\n color={activityData.memory.color}\n label=\"Memory\"\n value={`${activityData.memory.percentage}%`}\n size={120}\n />\n <ActivityRing\n progress={activityData.storage.percentage}\n color={activityData.storage.color}\n label=\"Storage\"\n value={`${activityData.storage.percentage}%`}\n size={120}\n />\n </div>\n </Stack>\n )\n}\n","import { ActivitySummary } from \"./ActivitySummary\"\nimport { Suspense, use } from \"react\"\nimport { Server } from \"@/server/Compute/types/server\"\nimport { ImagesPaginatedResponse } from \"@/server/Compute/types/image\"\nimport { TrpcClient } from \"@/client/trpcClient\"\nimport { Trans } from \"@lingui/react/macro\"\n\ninterface OverviewContainerProps {\n getDataPromise: Promise<[Server[] | undefined, ImagesPaginatedResponse]>\n}\nconst OverviewContainer = ({ getDataPromise }: OverviewContainerProps) => {\n const [servers, imagesResponse] = use(getDataPromise)\n const images = imagesResponse.images\n if (!servers && !images) return <div className=\"p-4 text-center\">No data found</div>\n\n // Calculate server statistics\n const activeServers = servers?.filter((server) => server.status === \"ACTIVE\")?.length || 0\n const totalServers = servers?.length || 0\n const estimatedServerQuota = Math.max(10, Math.ceil(totalServers * 1.5))\n\n // Calculate resource usage based on server flavors\n let totalCores = 0\n let usedMemoryMB = 0\n let totalDiskGB = 0\n\n // Process server data to extract resource usage\n servers?.forEach((server) => {\n // Extract core count from flavor if available\n if (server.flavor && server.flavor.vcpus) {\n totalCores += server.flavor.vcpus\n } else {\n // Fallback estimate based on server name or other heuristics\n const smallestSize = server.name?.includes(\"small\") || server.name?.includes(\"micro\")\n totalCores += smallestSize ? 1 : 2\n }\n\n // Extract memory usage from flavor if available\n if (server.flavor && server.flavor.ram) {\n usedMemoryMB += server.flavor.ram\n } else {\n // Fallback estimate\n usedMemoryMB += 1024 // Assume 1GB per instance as fallback\n }\n\n // Extract disk usage from flavor if available\n if (server.flavor && server.flavor.disk) {\n totalDiskGB += server.flavor.disk\n } else {\n // Fallback estimate\n totalDiskGB += 20 // Assume 20GB per instance as fallback\n }\n })\n\n // Calculate image statistics\n const activeImages = images?.filter((image) => image.status === \"active\")?.length || 0\n const totalImages = images?.length || 0\n\n // Calculate resource percentage utilizations\n const cpuPercentage = Math.min(100, Math.round((totalCores / 32) * 100))\n const memoryPercentage = Math.min(100, Math.round((usedMemoryMB / 131072) * 100))\n const storagePercentage = Math.min(100, Math.round((totalDiskGB / 1024) * 100))\n\n // Prepare data to pass to ActivitySummary\n const activityData = {\n instances: {\n current: activeServers,\n total: totalServers,\n quota: estimatedServerQuota,\n color: \"#FF5733\",\n },\n cpu: {\n percentage: cpuPercentage,\n cores: totalCores,\n color: \"#33A1FD\",\n },\n memory: {\n percentage: memoryPercentage,\n usedMB: usedMemoryMB,\n color: \"#9B59B6\", // Purple color for memory\n },\n storage: {\n percentage: storagePercentage,\n sizeGB: totalDiskGB,\n color: \"#4CAF50\",\n },\n images: {\n active: activeImages,\n total: totalImages,\n color: \"#F1C40F\", // Yellow color for images if you want to use it\n },\n }\n\n return (\n <div className=\"h-full\">\n <ActivitySummary activityData={activityData} />\n </div>\n )\n}\n\ninterface OverviewProps {\n client: TrpcClient\n project: string\n}\n\nexport function Overview({ client, project }: OverviewProps) {\n const getDataPromise = Promise.all([\n client.compute.getServersByProjectId.query({ project_id: project }),\n client.compute.listImagesWithSearch.query({ project_id: project }),\n ])\n\n return (\n <Suspense\n fallback={\n <div className=\"p-4 text-center\">\n <Trans>Loading...</Trans>\n </div>\n }\n >\n <OverviewContainer getDataPromise={getDataPromise} />\n </Suspense>\n )\n}\n","import { createFileRoute } from \"@tanstack/react-router\"\nimport { t } from \"@lingui/core/macro\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { Overview } from \"./-components/Overview\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { ContentHeading } from \"@cloudoperators/juno-ui-components\"\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/compute/overview\")({\n staticData: { section: \"compute\", service: \"overview\", crumb: { labelKey: \"Compute\" } } satisfies RouteInfo,\n head: () => ({ meta: [{ title: t`Compute Overview` }] }),\n component: RouteComponent,\n})\n\nfunction RouteComponent() {\n const { t } = useLingui()\n const { projectId } = Route.useParams()\n const { trpcClient } = Route.useRouteContext()\n return (\n <>\n <ContentHeading>{t`Compute Overview`}</ContentHeading>\n <Overview project={projectId} client={trpcClient!} />\n </>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pca-x9if8xU-.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","Modal","Form","FormSection","Spinner","TextInput","Message","trpcReact","useProjectId","csrRegex","isValidCommonName","value","test","CreatePcaModal","open","onClose","useLingui","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","mutateAsync","project_id","configuration","subject","handleClose","reset","size","title","onCancel","cancelButtonLabel","confirmButtonLabel","onConfirm","handleSubmit","disableConfirmButton","error","dismissible","variant","className","div","span","id","e","preventDefault","Field","name","children","field","state","onBlur","handleBlur","onChange","handleChange","target","label","placeholder","helptext","errortext","meta","errors","map","join","disabled","Stack","Spinner","DataGrid","DataGridRow","DataGridCell","ContentHeading","DataGridHeadCell","Button","trpcReact","useProjectId","TABLE_COLUMNS","PcaTableRow","useModal","CreatePcaModal","PcaListContainer","useLingui","projectId","columns","createCaOpen","toggleCreateCa","data","pcas","isLoading","isError","error","services","pca","list","useQuery","project_id","className","distribution","alignment","direction","variant","size","message","t","length","data-testid","colSpan","p","div","label","onClick","map","id","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`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 } from \"@tanstack/react-form\"\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 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 await createPcaMutation.mutateAsync({\n project_id: projectId,\n configuration: {\n subject: { common_name: value.common_name },\n },\n })\n handleClose()\n },\n })\n\n const handleClose = () => {\n if (isPending) return\n\n form.reset()\n createPcaMutation.reset()\n onClose()\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}\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 {\n Stack,\n Spinner,\n DataGrid,\n DataGridRow,\n DataGridCell,\n ContentHeading,\n DataGridHeadCell,\n Button,\n} from \"@cloudoperators/juno-ui-components\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { useProjectId } from \"@/client/hooks\"\nimport { TABLE_COLUMNS } from \"./-table/constants\"\nimport { PcaTableRow } from \"./-table/PcaTableRow\"\nimport { useModal } from \"@/client/utils/useModal\"\nimport { CreatePcaModal } from \"./-modals/CreatePcaModal\"\n\nexport const PcaListContainer = () => {\n const { t } = useLingui()\n const projectId = useProjectId()\n const columns = TABLE_COLUMNS()\n const [createCaOpen, toggleCreateCa] = useModal(false)\n\n // Check filtering, sorting and search API compatibility with OpenStack -> implement with <ListToolbar />\n const { data: pcas = [], isLoading, isError, error } = trpcReact.services.pca.list.useQuery({ project_id: projectId })\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) {\n return (\n <DataGrid columns={columns.length} className=\"pca\" data-testid=\"no-pcas\">\n <DataGridRow>\n <DataGridCell colSpan={columns.length}>\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 <Button variant=\"primary\" label={t`Create Certificate Authority`} onClick={toggleCreateCa} />\n <DataGrid columns={columns.length}>\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 {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 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"projects-CnmZIB2Q.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","ContentHeading","ProjectCard","project","navigate","padding","onClick","to","params","projectId","id","className","div","name","p","description","ProjectCardView","projects","length","map","ProjectsOverviewNavBar","ProjectCardView","Container","ContentHeading","Trans","Route","ProjectsOverview","projects","useLoaderData","search","useSearch","navigate","useNavigate","handleSearch","value","replace","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, ContentHeading } 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=\"min-h-50\"\n >\n <div className=\"w-full\">\n <ContentHeading className=\"text-theme-accent\">{project.name}</ContentHeading>\n <p className=\"mt-4 line-clamp-3 pr-4 leading-relaxed\">{project.description}</p>\n </div>\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 { 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>\n <ContentHeading>\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":";;;;;;;AASA,SAAgBI,EAAuB,EAAEC,aAAUC,gBAAa,MAAiC;CAC/F,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,GAAAA,EACRC,IAAWP,EAA6C,KAAA,EACxDQ,IAAkBR,EAAO,GAAA,EACzB,CAACS,GAAYC,KAAiBT,EAASI,EAAAA;AAiC7C,QA/BAN,QAAU;AACR,EAAI,CAACS,EAAgBG,WAAW,CAACJ,EAASI,WAAWN,MAAeI,KAClEC,EAAcL,EAAAA;IAEf,CAACA,EAAW,CAAA,EAEfN,cACS;AACL,EAAIQ,EAASI,WAASC,aAAaL,EAASI,QAAO;IAEpD,EAAE,CAAA,EAsBH,kBAACT,GAAAA;EACCiB,WAAU;EACVC,MAAK;EACLC,aAAaC,EAAAA,EAAC,EAAA,IAAA,UAAU,CAAA;EACxBC,WAxBwBT,MAAAA;GAC1B,IAAMC,IAAQD,EAAEE,OAAOD;AAGvBR,GAFAG,EAAcK,EAAAA,EACVR,EAASI,WAASC,aAAaL,EAASI,QAAO,EACnDJ,EAASI,UAAUM,iBAAW;AAE5Bb,IADAG,EAASI,UAAU,MACnBP,EAASW,EAAAA;MACR,IAAA;;EAkBDS,eAAS;AACPhB,KAAgBG,UAAU;;EAE5Bc,cAAQ;AACNjB,KAAgBG,UAAU;;EAE5Be,eArBgB;AAMlBtB,GALA,AAEEG,EAASI,aADTC,aAAaL,EAASI,QAAO,EACV,OAErBD,EAAc,GAAA,EACdN,EAAS,GAAA;;EAgBPW,OAAON;;;;;AC/Cb,SAAgBqB,EAAY,EAAEC,cAA2B;CACvD,IAAMC,IAAWL,GAAAA;AACjB,QACE,kBAACC,GAAAA;EACCK,SAAO;EACPC,eAAeF,EAAS;GAAEG,IAAI;GAAwBC,QAAQ,EAAEC,WAAWN,EAAQO,IAAG;GAAE,CAAA;EACxFC,WAAU;YAEV,kBAACC,OAAAA;GAAID,WAAU;cACb,kBAACV,GAAAA;IAAeU,WAAU;cAAqBR,EAAQU;OACvD,kBAACC,KAAAA;IAAEH,WAAU;cAA0CR,EAAQY;;;;;AAMvE,SAAgBC,EAAgB,EAAEC,eAAgC;AAChE,QACE,kBAACL,OAAAA;EAAID,WAAU;YACb,kBAACC,OAAAA;GAAID,WAAU;aACZM,GAAUC,SACTD,EAASE,KAAKhB,MAAY,kBAACD,GAAAA,EAAsCC,YAAAA,EAArBA,EAAQO,GAAE,CAAA,GAEtD,kBAACI,KAAAA;IAAEH,WAAU;cACX,kBAAA,GAAA,EAAA,IAAA,UAAA,CAAA;;;;;;;ACMZ,SAASe,IAAAA;CACP,IAAM,EAAEC,gBAAaF,EAAMG,eAAa,EAClC,EAAEC,YAAS,OAAOJ,EAAMK,WAAS,EACjCC,IAAWN,EAAMO,aAAW;AAMlC,QACE,kBAAC,GAAA,EAAA,UAAA;EACC,kBAAC,GAAA,EAAA,UACC,kBAAA,GAAA,EAAA,IAAA,UAAA,CAAA,EAAA,CAAA;EAEF,kBAAC,GAAA;GAAuB,YAAYH;GAAQ,WAT1BK,MAAAA;AACpBH,MAAS;KAAEF,QAAQ,EAAEA,QAAQK,GAAM;KAAGC,SAAS;KAAK,CAAA;;;EASlD,kBAAC,OAAA;GAAI,WAAU;aACb,kBAAC,GAAA,EAA0BR,aAAAA,CAAAA"}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { startTransition as e, useState as t } from "react";
|
|
2
|
-
//#region src/client/utils/useListWithFiltering.ts
|
|
3
|
-
function n({ defaultSortKey: n, defaultSortDir: r, sortOptions: i, filterSettings: a }) {
|
|
4
|
-
let [o, s] = t(""), c = (t) => {
|
|
5
|
-
let n = typeof t == "string" ? t : "";
|
|
6
|
-
e(() => s(n));
|
|
7
|
-
}, [l, u] = t({
|
|
8
|
-
options: i,
|
|
9
|
-
sortBy: n,
|
|
10
|
-
sortDirection: r
|
|
11
|
-
}), d = (e) => {
|
|
12
|
-
u({
|
|
13
|
-
options: e.options ?? l.options,
|
|
14
|
-
sortBy: e.sortBy?.toString() || n,
|
|
15
|
-
sortDirection: e.sortDirection || r
|
|
16
|
-
});
|
|
17
|
-
}, [f, p] = t(a);
|
|
18
|
-
return {
|
|
19
|
-
searchTerm: o,
|
|
20
|
-
sortSettings: l,
|
|
21
|
-
filterSettings: f,
|
|
22
|
-
handleSearchChange: c,
|
|
23
|
-
handleSortChange: d,
|
|
24
|
-
handleFilterChange: (t) => {
|
|
25
|
-
e(() => p(t));
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
//#endregion
|
|
30
|
-
export { n as t };
|
|
31
|
-
|
|
32
|
-
//# sourceMappingURL=useListWithFiltering-CqQbAjEe.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useListWithFiltering-CqQbAjEe.mjs","names":["startTransition","useState","useListWithFiltering","defaultSortKey","defaultSortDir","sortOptions","filterSettings","initialFilterSettings","searchTerm","setSearchTerm","handleSearchChange","term","searchValue","sortSettings","setSortSettings","options","sortBy","sortDirection","handleSortChange","newSortSettings","settings","toString","setFilterSettings","handleFilterChange","newFilterSettings"],"sources":["../../src/client/utils/useListWithFiltering.ts"],"sourcesContent":["import { startTransition, useState } from \"react\"\nimport { FilterSettings, SortOption, SortSettings } from \"@/client/components/ListToolbar/types\"\n\n/**\n * Sort direction enumeration\n * Used across all sort-enabled list views\n */\nexport type SortDirection = \"asc\" | \"desc\"\n\n/**\n * Generic required sort settings with guaranteed non-optional properties\n * Used by components to maintain a fully-defined sort state\n *\n * Type parameter K is the sort key type (string literal union of allowed sort fields)\n *\n * @example\n * // For floating IPs\n * type FloatingIpListSortSettings = ListSortConfig<FloatingIpsSortKey>\n *\n * // For security groups\n * type SecurityGroupListSortSettings = ListSortConfig<\"name\" | \"project_id\">\n */\nexport type ListSortConfig<T extends string = string> = {\n /**\n * Array of available sort options to display in the UI\n */\n options: SortOption[]\n /**\n * The currently selected sort field (guaranteed to be one of the available options)\n */\n sortBy: T\n /**\n * The currently active sort direction (guaranteed to be either \"asc\" or \"desc\")\n */\n sortDirection: SortDirection\n}\n\n/**\n * Configuration options for the useListWithFiltering hook\n */\nexport interface UseListWithFilteringOptions<T extends string> {\n /** Default sort key to use on initial render */\n defaultSortKey: T\n /** Default sort direction to use on initial render */\n defaultSortDir: SortDirection\n /** Available sort options to display in the sort dropdown */\n sortOptions: Array<{ label: string; value: string }>\n /** Initial filter settings configuration */\n filterSettings: FilterSettings\n}\n\n/**\n * Return value from the useListWithFiltering hook\n */\nexport interface UseListWithFilteringReturn<T extends string> {\n // State\n searchTerm: string\n sortSettings: ListSortConfig<T>\n filterSettings: FilterSettings\n\n // Handlers\n handleSearchChange: (term: string | number | string[] | undefined) => void\n handleSortChange: (newSortSettings: SortSettings) => void\n handleFilterChange: (newFilterSettings: FilterSettings) => void\n}\n\n/**\n * Custom hook to manage common list view state: search, sort, and filter\n *\n * Extracts shared logic from list components to ensure consistent behavior\n * across all list pages and reduce code duplication.\n *\n * @example\n * ```tsx\n * const listState = useListWithFiltering({\n * defaultSortKey: \"name\",\n * defaultSortDir: \"asc\",\n * sortOptions: [\n * { label: t`Name`, value: \"name\" },\n * { label: t`Created`, value: \"created_at\" },\n * ],\n * filterSettings: {\n * filters: [\n * { displayName: t`Status`, filterName: \"status\", values: [\"active\", \"inactive\"] }\n * ]\n * }\n * })\n * ```\n */\nexport function useListWithFiltering<T extends string>({\n defaultSortKey,\n defaultSortDir,\n sortOptions,\n filterSettings: initialFilterSettings,\n}: UseListWithFilteringOptions<T>): UseListWithFilteringReturn<T> {\n // Search\n const [searchTerm, setSearchTerm] = useState(\"\")\n const handleSearchChange = (term: string | number | string[] | undefined) => {\n const searchValue = typeof term === \"string\" ? term : \"\"\n startTransition(() => setSearchTerm(searchValue))\n }\n\n // Sort\n const [sortSettings, setSortSettings] = useState<ListSortConfig<T>>({\n options: sortOptions,\n sortBy: defaultSortKey,\n sortDirection: defaultSortDir,\n })\n const handleSortChange = (newSortSettings: SortSettings) => {\n const settings: ListSortConfig<T> = {\n options: newSortSettings.options ?? sortSettings.options,\n sortBy: (newSortSettings.sortBy?.toString() as T) || defaultSortKey,\n sortDirection: (newSortSettings.sortDirection as SortDirection) || defaultSortDir,\n }\n setSortSettings(settings)\n }\n\n // Filter\n const [filterSettings, setFilterSettings] = useState<FilterSettings>(initialFilterSettings)\n const handleFilterChange = (newFilterSettings: FilterSettings) => {\n startTransition(() => setFilterSettings(newFilterSettings))\n }\n\n return {\n searchTerm,\n sortSettings,\n filterSettings,\n handleSearchChange,\n handleSortChange,\n handleFilterChange,\n }\n}\n"],"mappings":";;AAyFA,SAAgBE,EAAuC,EACrDC,mBACAC,mBACAC,gBACAC,gBAAgBC,KACe;CAE/B,IAAM,CAACC,GAAYC,KAAiBR,EAAS,GAAA,EACvCS,KAAsBC,MAAAA;EAC1B,IAAMC,IAAc,OAAOD,KAAS,WAAWA,IAAO;AACtDX,UAAsBS,EAAcG,EAAAA,CAAAA;IAIhC,CAACC,GAAcC,KAAmBb,EAA4B;EAClEc,SAASV;EACTW,QAAQb;EACRc,eAAeb;EACjB,CAAA,EACMc,KAAoBC,MAAAA;AAMxBL,IALoC;GAClCC,SAASI,EAAgBJ,WAAWF,EAAaE;GACjDC,QAAQ,EAAiBA,QAAQK,UAAAA,IAAoBlB;GACrDc,eAAe,EAAiBA,iBAAmCb;GACrE,CACgBgB;IAIZ,CAACd,GAAgBgB,KAAqBrB,EAAyBM,EAAAA;AAKrE,QAAO;EACLC;EACAK;EACAP;EACAI;EACAQ;EACAK,qBAV0BC,MAAAA;AAC1BxB,WAAsBsB,EAAkBE,EAAAA,CAAAA;;EAU1C"}
|