@terasky/backstage-plugin-vcf-automation 0.0.1 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/README.md +36 -0
  2. package/dist/api/VcfAutomationClient.esm.js +90 -0
  3. package/dist/api/VcfAutomationClient.esm.js.map +1 -0
  4. package/dist/components/VCFAutomationDeploymentDetails.esm.js +186 -0
  5. package/dist/components/VCFAutomationDeploymentDetails.esm.js.map +1 -0
  6. package/dist/components/VCFAutomationDeploymentOverview.esm.js +102 -0
  7. package/dist/components/VCFAutomationDeploymentOverview.esm.js.map +1 -0
  8. package/dist/components/VCFAutomationGenericResourceDetails.esm.js +52 -0
  9. package/dist/components/VCFAutomationGenericResourceDetails.esm.js.map +1 -0
  10. package/dist/components/VCFAutomationGenericResourceOverview.esm.js +40 -0
  11. package/dist/components/VCFAutomationGenericResourceOverview.esm.js.map +1 -0
  12. package/dist/components/VCFAutomationProjectDetails.esm.js +184 -0
  13. package/dist/components/VCFAutomationProjectDetails.esm.js.map +1 -0
  14. package/dist/components/VCFAutomationProjectOverview.esm.js +109 -0
  15. package/dist/components/VCFAutomationProjectOverview.esm.js.map +1 -0
  16. package/dist/components/VCFAutomationVSphereVMDetails.esm.js +116 -0
  17. package/dist/components/VCFAutomationVSphereVMDetails.esm.js.map +1 -0
  18. package/dist/components/VCFAutomationVSphereVMOverview.esm.js +116 -0
  19. package/dist/components/VCFAutomationVSphereVMOverview.esm.js.map +1 -0
  20. package/dist/index.d.ts +10 -11
  21. package/dist/index.esm.js +11 -881
  22. package/dist/index.esm.js.map +1 -1
  23. package/dist/plugin.esm.js +82 -0
  24. package/dist/plugin.esm.js.map +1 -0
  25. package/dist/routes.esm.js +20 -0
  26. package/dist/routes.esm.js.map +1 -0
  27. package/package.json +21 -14
package/README.md CHANGED
@@ -248,6 +248,42 @@ metadata:
248
248
  - **Project Administration**: Manage VCF project settings and resources
249
249
  - **Permission Integration**: Built-in support for Backstage's permission framework
250
250
 
251
+ ## Usage
252
+
253
+ Once installed and configured, the VCF Automation plugin provides comprehensive views for different VCF entity types:
254
+
255
+ ### Project (Domain) Views
256
+ The project overview provides a high-level summary of your VCF project:
257
+ ![Project Overview](../../images/vcf-proj-overview.png)
258
+
259
+ Detailed project information is available as well:
260
+ ![Project Details 1](../../images/vcf-proj-details-1.png)
261
+ ![Project Details 2](../../images/vcf-proj-details-2.png)
262
+ ![Project Details 3](../../images/vcf-proj-details-3.png)
263
+
264
+ ### Deployment Views
265
+ Get a quick overview of your VCF deployments:
266
+ ![Deployment Overview](../../images/vcf-deploy-overview.png)
267
+
268
+ Access detailed deployment information:
269
+ ![Deployment Details 1](../../images/vcf-deploy-details-1.png)
270
+ ![Deployment Details 2](../../images/vcf-deploy-details-2.png)
271
+
272
+ ### VSphere VM Views
273
+ Monitor your VSphere VMs with the overview card:
274
+ ![VM Overview](../../images/vcf-vm-overview.png)
275
+
276
+ Dive deep into VM configurations and status:
277
+ ![VM Details 1](../../images/vcf-vm-details-1.png)
278
+ ![VM Details 2](../../images/vcf-vm-details-2.png)
279
+
280
+ ### Generic Resource Views
281
+ View resource summaries in the overview:
282
+ ![Resource Overview](../../images/vcf-resource-overview.png)
283
+
284
+ Access detailed resource information:
285
+ ![Resource Details](../../images/vcf-resource-details.png)
286
+
251
287
  ## Contributing
252
288
 
253
289
  Contributions are welcome! Please open an issue or submit a pull request on GitHub.
@@ -0,0 +1,90 @@
1
+ import { createApiRef } from '@backstage/core-plugin-api';
2
+
3
+ const vcfAutomationApiRef = createApiRef({
4
+ id: "plugin.vcf-automation.service"
5
+ });
6
+ class VcfAutomationClient {
7
+ discoveryApi;
8
+ identityApi;
9
+ constructor(options) {
10
+ this.discoveryApi = options.discoveryApi;
11
+ this.identityApi = options.identityApi;
12
+ }
13
+ async getAuthHeaders() {
14
+ const token = await this.identityApi.getCredentials();
15
+ return {
16
+ "Content-Type": "application/json",
17
+ ...token?.token ? { Authorization: `Bearer ${token.token}` } : {}
18
+ };
19
+ }
20
+ async getDeploymentEvents(deploymentId) {
21
+ const baseUrl = await this.discoveryApi.getBaseUrl("vcf-automation");
22
+ const headers = await this.getAuthHeaders();
23
+ const response = await fetch(`${baseUrl}/deployments/${deploymentId}/events`, {
24
+ headers
25
+ });
26
+ if (!response.ok) {
27
+ throw new Error(`Failed to fetch deployment events: ${response.statusText}`);
28
+ }
29
+ return await response.json();
30
+ }
31
+ async getVSphereVMDetails(deploymentId, resourceId) {
32
+ const baseUrl = await this.discoveryApi.getBaseUrl("vcf-automation");
33
+ const headers = await this.getAuthHeaders();
34
+ const response = await fetch(`${baseUrl}/deployments/${deploymentId}/resources/${resourceId}`, {
35
+ headers
36
+ });
37
+ if (!response.ok) {
38
+ throw new Error(`Failed to fetch resource details: ${response.statusText}`);
39
+ }
40
+ return await response.json();
41
+ }
42
+ async getGenericResourceDetails(deploymentId, resourceId) {
43
+ const baseUrl = await this.discoveryApi.getBaseUrl("vcf-automation");
44
+ const headers = await this.getAuthHeaders();
45
+ const response = await fetch(
46
+ `${baseUrl}/deployments/${deploymentId}/resources/${resourceId}`,
47
+ {
48
+ headers: {
49
+ "Content-Type": "application/json",
50
+ ...headers
51
+ }
52
+ }
53
+ );
54
+ if (!response.ok) {
55
+ throw new Error(`Failed to fetch resource details: ${response.statusText}`);
56
+ }
57
+ return await response.json();
58
+ }
59
+ async getDeploymentDetails(deploymentId) {
60
+ const baseUrl = await this.discoveryApi.getBaseUrl("vcf-automation");
61
+ const headers = await this.getAuthHeaders();
62
+ const response = await fetch(
63
+ `${baseUrl}/deployments/${deploymentId}`,
64
+ {
65
+ headers: {
66
+ "Content-Type": "application/json",
67
+ ...headers
68
+ }
69
+ }
70
+ );
71
+ if (!response.ok) {
72
+ throw new Error(`Failed to fetch deployment details: ${response.statusText}`);
73
+ }
74
+ return await response.json();
75
+ }
76
+ async getProjectDetails(projectId) {
77
+ const baseUrl = await this.discoveryApi.getBaseUrl("vcf-automation");
78
+ const headers = await this.getAuthHeaders();
79
+ const response = await fetch(`${baseUrl}/projects/${projectId}`, {
80
+ headers
81
+ });
82
+ if (!response.ok) {
83
+ throw new Error(`Failed to fetch project details: ${response.statusText}`);
84
+ }
85
+ return await response.json();
86
+ }
87
+ }
88
+
89
+ export { VcfAutomationClient, vcfAutomationApiRef };
90
+ //# sourceMappingURL=VcfAutomationClient.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VcfAutomationClient.esm.js","sources":["../../src/api/VcfAutomationClient.ts"],"sourcesContent":["import { createApiRef, DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api';\nimport { VcfProject as VcfProjectType } from '../types';\n\nexport interface VcfDeploymentEvent {\n timestamp: string;\n status: string;\n operation: string;\n user: string;\n details: string;\n}\n\nexport interface VcfDeploymentConfig {\n key: string;\n value: string;\n}\n\nexport interface VcfDeploymentResponse {\n content: any;\n pageable: any;\n config: VcfDeploymentConfig[];\n history: VcfDeploymentEvent[];\n}\n\nexport interface VcfVSphereVM {\n id: string;\n name: string;\n type: string;\n properties: {\n resourceId: string;\n moref: string;\n resourceDescLink: string;\n powerState: string;\n zone: string;\n environmentName: string;\n hasSnapshots: string;\n computeHostType: string;\n id: string;\n memoryGB: string;\n cpuCount: number;\n image: string;\n totalMemoryMB: number;\n endpointType: string;\n resourceName: string;\n tags: string[];\n softwareName: string;\n name: string;\n resourceLink: string;\n region: string;\n hostName: string;\n storage: {\n disks: Array<{\n vm: string;\n name: string;\n type: string;\n shares?: string;\n vcUuid: string;\n diskFile?: string;\n bootOrder?: number;\n encrypted: boolean;\n limitIops?: string;\n capacityGb: number;\n persistent: boolean;\n independent?: string;\n sharesLevel?: string;\n endpointType: string;\n resourceLink: string;\n vmFolderPath?: string;\n controllerKey: string;\n diskPlacementRef?: string;\n existingResource: string;\n provisioningType?: string;\n controllerUnitNumber: string;\n }>;\n };\n networks: Array<{\n id: string;\n name: string;\n address: string;\n network: string;\n assignment: string;\n deviceIndex: number;\n external_id: string;\n mac_address: string;\n resourceName: string;\n ipv6Addresses?: string[];\n }>;\n areVMActionsDisabled: string;\n providerId: string;\n osType: string;\n instanceUUID: string;\n componentType: string;\n address: string;\n endpointId: string;\n externalId: string;\n datacenter: string;\n datastoreName: string;\n coreCount: string;\n primaryMAC: string;\n computeHostRef: string;\n snapshotCount: string;\n accounts: string[];\n vmFolderPath: string;\n account: string;\n vcUuid: string;\n };\n createdAt: string;\n syncStatus: string;\n expense: {\n totalExpense: number;\n computeExpense: number;\n storageExpense: number;\n additionalExpense: number;\n unit: string;\n lastUpdatedTime: string;\n };\n origin: string;\n dependsOn: string[];\n state: string;\n}\n\nexport type VcfProject = VcfProjectType;\n\nexport interface VcfAutomationApi {\n getDeploymentEvents(deploymentId: string): Promise<VcfDeploymentResponse>;\n getVSphereVMDetails(deploymentId: string, resourceId: string): Promise<VcfVSphereVM>;\n getProjectDetails(projectId: string): Promise<VcfProject>;\n getGenericResourceDetails(deploymentId: string, resourceId: string): Promise<any>;\n getDeploymentDetails(deploymentId: string): Promise<any>;\n}\n\nexport const vcfAutomationApiRef = createApiRef<VcfAutomationApi>({\n id: 'plugin.vcf-automation.service',\n});\n\nexport class VcfAutomationClient implements VcfAutomationApi {\n private readonly discoveryApi: DiscoveryApi;\n private readonly identityApi: IdentityApi;\n\n constructor(options: { discoveryApi: DiscoveryApi; identityApi: IdentityApi }) {\n this.discoveryApi = options.discoveryApi;\n this.identityApi = options.identityApi;\n }\n\n private async getAuthHeaders(): Promise<HeadersInit> {\n const token = await this.identityApi.getCredentials();\n return {\n 'Content-Type': 'application/json',\n ...(token?.token ? { Authorization: `Bearer ${token.token}` } : {}),\n };\n }\n\n async getDeploymentEvents(deploymentId: string): Promise<VcfDeploymentResponse> {\n const baseUrl = await this.discoveryApi.getBaseUrl('vcf-automation');\n const headers = await this.getAuthHeaders();\n const response = await fetch(`${baseUrl}/deployments/${deploymentId}/events`, {\n headers,\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch deployment events: ${response.statusText}`);\n }\n return await response.json();\n }\n\n async getVSphereVMDetails(deploymentId: string, resourceId: string): Promise<VcfVSphereVM> {\n const baseUrl = await this.discoveryApi.getBaseUrl('vcf-automation');\n const headers = await this.getAuthHeaders();\n const response = await fetch(`${baseUrl}/deployments/${deploymentId}/resources/${resourceId}`, {\n headers,\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch resource details: ${response.statusText}`);\n }\n return await response.json();\n }\n\n async getGenericResourceDetails(deploymentId: string, resourceId: string): Promise<any> {\n const baseUrl = await this.discoveryApi.getBaseUrl('vcf-automation');\n const headers = await this.getAuthHeaders();\n \n const response = await fetch(`${baseUrl}/deployments/${deploymentId}/resources/${resourceId}`,\n {\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n },\n );\n\n if (!response.ok) {\n throw new Error(`Failed to fetch resource details: ${response.statusText}`);\n }\n\n return await response.json();\n }\n\n async getDeploymentDetails(deploymentId: string): Promise<any> {\n const baseUrl = await this.discoveryApi.getBaseUrl('vcf-automation');\n const headers = await this.getAuthHeaders();\n \n const response = await fetch(`${baseUrl}/deployments/${deploymentId}`,\n {\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n },\n );\n\n if (!response.ok) {\n throw new Error(`Failed to fetch deployment details: ${response.statusText}`);\n }\n\n return await response.json();\n }\n\n async getProjectDetails(projectId: string): Promise<VcfProject> {\n const baseUrl = await this.discoveryApi.getBaseUrl('vcf-automation');\n const headers = await this.getAuthHeaders();\n const response = await fetch(`${baseUrl}/projects/${projectId}`, {\n headers,\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch project details: ${response.statusText}`);\n }\n return await response.json();\n }\n} "],"names":[],"mappings":";;AAkIO,MAAM,sBAAsB,YAA+B,CAAA;AAAA,EAChE,EAAI,EAAA;AACN,CAAC;AAEM,MAAM,mBAAgD,CAAA;AAAA,EAC1C,YAAA;AAAA,EACA,WAAA;AAAA,EAEjB,YAAY,OAAmE,EAAA;AAC7E,IAAA,IAAA,CAAK,eAAe,OAAQ,CAAA,YAAA;AAC5B,IAAA,IAAA,CAAK,cAAc,OAAQ,CAAA,WAAA;AAAA;AAC7B,EAEA,MAAc,cAAuC,GAAA;AACnD,IAAA,MAAM,KAAQ,GAAA,MAAM,IAAK,CAAA,WAAA,CAAY,cAAe,EAAA;AACpD,IAAO,OAAA;AAAA,MACL,cAAgB,EAAA,kBAAA;AAAA,MAChB,GAAI,KAAO,EAAA,KAAA,GAAQ,EAAE,aAAA,EAAe,UAAU,KAAM,CAAA,KAAK,CAAG,CAAA,EAAA,GAAI;AAAC,KACnE;AAAA;AACF,EAEA,MAAM,oBAAoB,YAAsD,EAAA;AAC9E,IAAA,MAAM,OAAU,GAAA,MAAM,IAAK,CAAA,YAAA,CAAa,WAAW,gBAAgB,CAAA;AACnE,IAAM,MAAA,OAAA,GAAU,MAAM,IAAA,CAAK,cAAe,EAAA;AAC1C,IAAA,MAAM,WAAW,MAAM,KAAA,CAAM,GAAG,OAAO,CAAA,aAAA,EAAgB,YAAY,CAAW,OAAA,CAAA,EAAA;AAAA,MAC5E;AAAA,KACD,CAAA;AACD,IAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,MAAA,MAAM,IAAI,KAAA,CAAM,CAAsC,mCAAA,EAAA,QAAA,CAAS,UAAU,CAAE,CAAA,CAAA;AAAA;AAE7E,IAAO,OAAA,MAAM,SAAS,IAAK,EAAA;AAAA;AAC7B,EAEA,MAAM,mBAAoB,CAAA,YAAA,EAAsB,UAA2C,EAAA;AACzF,IAAA,MAAM,OAAU,GAAA,MAAM,IAAK,CAAA,YAAA,CAAa,WAAW,gBAAgB,CAAA;AACnE,IAAM,MAAA,OAAA,GAAU,MAAM,IAAA,CAAK,cAAe,EAAA;AAC1C,IAAM,MAAA,QAAA,GAAW,MAAM,KAAM,CAAA,CAAA,EAAG,OAAO,CAAgB,aAAA,EAAA,YAAY,CAAc,WAAA,EAAA,UAAU,CAAI,CAAA,EAAA;AAAA,MAC7F;AAAA,KACD,CAAA;AACD,IAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,MAAA,MAAM,IAAI,KAAA,CAAM,CAAqC,kCAAA,EAAA,QAAA,CAAS,UAAU,CAAE,CAAA,CAAA;AAAA;AAE5E,IAAO,OAAA,MAAM,SAAS,IAAK,EAAA;AAAA;AAC7B,EAEA,MAAM,yBAA0B,CAAA,YAAA,EAAsB,UAAkC,EAAA;AACtF,IAAA,MAAM,OAAU,GAAA,MAAM,IAAK,CAAA,YAAA,CAAa,WAAW,gBAAgB,CAAA;AACnE,IAAM,MAAA,OAAA,GAAU,MAAM,IAAA,CAAK,cAAe,EAAA;AAExC,IAAA,MAAM,WAAW,MAAM,KAAA;AAAA,MAAM,CAAG,EAAA,OAAO,CAAgB,aAAA,EAAA,YAAY,cAAc,UAAU,CAAA,CAAA;AAAA,MAC3F;AAAA,QACE,OAAS,EAAA;AAAA,UACP,cAAgB,EAAA,kBAAA;AAAA,UAChB,GAAG;AAAA;AACL;AACF,KACF;AAEA,IAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,MAAA,MAAM,IAAI,KAAA,CAAM,CAAqC,kCAAA,EAAA,QAAA,CAAS,UAAU,CAAE,CAAA,CAAA;AAAA;AAG5E,IAAO,OAAA,MAAM,SAAS,IAAK,EAAA;AAAA;AAC7B,EAEA,MAAM,qBAAqB,YAAoC,EAAA;AAC7D,IAAA,MAAM,OAAU,GAAA,MAAM,IAAK,CAAA,YAAA,CAAa,WAAW,gBAAgB,CAAA;AACnE,IAAM,MAAA,OAAA,GAAU,MAAM,IAAA,CAAK,cAAe,EAAA;AAExC,IAAA,MAAM,WAAW,MAAM,KAAA;AAAA,MAAM,CAAA,EAAG,OAAO,CAAA,aAAA,EAAgB,YAAY,CAAA,CAAA;AAAA,MACnE;AAAA,QACE,OAAS,EAAA;AAAA,UACP,cAAgB,EAAA,kBAAA;AAAA,UAChB,GAAG;AAAA;AACL;AACF,KACF;AAEA,IAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,MAAA,MAAM,IAAI,KAAA,CAAM,CAAuC,oCAAA,EAAA,QAAA,CAAS,UAAU,CAAE,CAAA,CAAA;AAAA;AAG9E,IAAO,OAAA,MAAM,SAAS,IAAK,EAAA;AAAA;AAC7B,EAEA,MAAM,kBAAkB,SAAwC,EAAA;AAC9D,IAAA,MAAM,OAAU,GAAA,MAAM,IAAK,CAAA,YAAA,CAAa,WAAW,gBAAgB,CAAA;AACnE,IAAM,MAAA,OAAA,GAAU,MAAM,IAAA,CAAK,cAAe,EAAA;AAC1C,IAAA,MAAM,WAAW,MAAM,KAAA,CAAM,GAAG,OAAO,CAAA,UAAA,EAAa,SAAS,CAAI,CAAA,EAAA;AAAA,MAC/D;AAAA,KACD,CAAA;AACD,IAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,MAAA,MAAM,IAAI,KAAA,CAAM,CAAoC,iCAAA,EAAA,QAAA,CAAS,UAAU,CAAE,CAAA,CAAA;AAAA;AAE3E,IAAO,OAAA,MAAM,SAAS,IAAK,EAAA;AAAA;AAE/B;;;;"}
@@ -0,0 +1,186 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { useEntity, catalogApiRef } from '@backstage/plugin-catalog-react';
3
+ import { useApi } from '@backstage/core-plugin-api';
4
+ import { vcfAutomationApiRef } from '../api/VcfAutomationClient.esm.js';
5
+ import { InfoCard, Progress, ResponseErrorPanel, StructuredMetadataTable, Table, Link } from '@backstage/core-components';
6
+ import { Typography, Grid } from '@material-ui/core';
7
+ import useAsync from 'react-use/lib/useAsync';
8
+ import { usePermission } from '@backstage/plugin-permission-react';
9
+ import { viewDeploymentHistoryPermission } from '@terasky/backstage-plugin-vcf-automation-common';
10
+
11
+ const eventColumns = [
12
+ {
13
+ title: "Operation",
14
+ field: "name"
15
+ },
16
+ {
17
+ title: "Status",
18
+ field: "status"
19
+ },
20
+ {
21
+ title: "User",
22
+ field: "requestedBy"
23
+ },
24
+ {
25
+ title: "Created",
26
+ field: "createdAt",
27
+ render: (row) => new Date(row.createdAt).toLocaleString()
28
+ },
29
+ {
30
+ title: "Last Updated",
31
+ field: "updatedAt",
32
+ render: (row) => new Date(row.updatedAt).toLocaleString()
33
+ },
34
+ {
35
+ title: "Details",
36
+ field: "details"
37
+ }
38
+ ];
39
+ const resourceColumns = [
40
+ {
41
+ title: "Name",
42
+ field: "title",
43
+ render: (row) => /* @__PURE__ */ jsx(Link, { to: `/catalog/${row.namespace}/${row.kind.toLowerCase()}/${row.name}`, children: row.title || row.name })
44
+ },
45
+ {
46
+ title: "Type",
47
+ field: "type"
48
+ }
49
+ ];
50
+ const getEntityType = (entity) => {
51
+ const type = entity.spec?.type;
52
+ if (typeof type === "string") {
53
+ return type;
54
+ }
55
+ if (typeof type === "object" && type !== null) {
56
+ return JSON.stringify(type);
57
+ }
58
+ return String(type || "N/A");
59
+ };
60
+ const VCFAutomationDeploymentDetails = () => {
61
+ const { entity } = useEntity();
62
+ const api = useApi(vcfAutomationApiRef);
63
+ const catalogApi = useApi(catalogApiRef);
64
+ const deploymentId = entity.metadata.name;
65
+ const { allowed: hasViewPermission, loading: permissionLoading } = usePermission({
66
+ permission: viewDeploymentHistoryPermission
67
+ });
68
+ const { value: deploymentDetails, loading: detailsLoading, error: detailsError } = useAsync(async () => {
69
+ if (!deploymentId || !hasViewPermission) {
70
+ return void 0;
71
+ }
72
+ return await api.getDeploymentDetails(deploymentId);
73
+ }, [deploymentId, hasViewPermission]);
74
+ const { value: eventsResponse, loading: eventsLoading, error: eventsError } = useAsync(async () => {
75
+ if (!deploymentId || !hasViewPermission) {
76
+ return void 0;
77
+ }
78
+ const response = await api.getDeploymentEvents(deploymentId);
79
+ return response;
80
+ }, [deploymentId, hasViewPermission]);
81
+ const { value: resources, loading: resourcesLoading, error: resourcesError } = useAsync(async () => {
82
+ if (!deploymentId) {
83
+ return void 0;
84
+ }
85
+ const components = await catalogApi.getEntities({
86
+ filter: {
87
+ kind: "Component",
88
+ "spec.system": deploymentId
89
+ }
90
+ });
91
+ const resources2 = await catalogApi.getEntities({
92
+ filter: {
93
+ kind: "Resource",
94
+ "spec.system": deploymentId
95
+ }
96
+ });
97
+ const allResources = [
98
+ ...components.items.map((component) => ({
99
+ name: component.metadata.name,
100
+ title: component.metadata.title || component.metadata.name,
101
+ kind: component.kind,
102
+ type: getEntityType(component),
103
+ namespace: component.metadata.namespace || "default"
104
+ })),
105
+ ...resources2.items.map((resource) => ({
106
+ name: resource.metadata.name,
107
+ title: resource.metadata.title || resource.metadata.name,
108
+ kind: resource.kind,
109
+ type: getEntityType(resource),
110
+ namespace: resource.metadata.namespace || "default"
111
+ }))
112
+ ];
113
+ return allResources;
114
+ }, [deploymentId]);
115
+ if (!deploymentId) {
116
+ return /* @__PURE__ */ jsx(InfoCard, { title: "VCF Automation Deployment", children: /* @__PURE__ */ jsx(Typography, { children: "No deployment ID found for this entity." }) });
117
+ }
118
+ if (detailsLoading || eventsLoading || permissionLoading || resourcesLoading) {
119
+ return /* @__PURE__ */ jsx(InfoCard, { title: "VCF Automation Deployment", children: /* @__PURE__ */ jsx(Progress, {}) });
120
+ }
121
+ if (!hasViewPermission) {
122
+ return /* @__PURE__ */ jsx(InfoCard, { title: "VCF Automation Deployment", children: /* @__PURE__ */ jsx(Typography, { children: "You don't have permission to view deployment information." }) });
123
+ }
124
+ if (detailsError || eventsError || resourcesError) {
125
+ return /* @__PURE__ */ jsx(ResponseErrorPanel, { error: detailsError ?? eventsError ?? resourcesError ?? new Error("Unknown error") });
126
+ }
127
+ const metadata = {
128
+ "Basic Information": {
129
+ Name: deploymentDetails?.name,
130
+ Description: deploymentDetails?.description || "No description",
131
+ Status: deploymentDetails?.status,
132
+ "Owner Type": deploymentDetails?.ownerType,
133
+ "Owned By": deploymentDetails?.ownedBy,
134
+ "Project ID": deploymentDetails?.projectId,
135
+ "Blueprint ID": deploymentDetails?.blueprintId,
136
+ "Organization ID": deploymentDetails?.orgId
137
+ },
138
+ "Timing Information": {
139
+ "Created By": deploymentDetails?.createdBy,
140
+ "Created At": deploymentDetails?.createdAt ? new Date(deploymentDetails.createdAt).toLocaleString() : "",
141
+ "Last Updated By": deploymentDetails?.lastUpdatedBy,
142
+ "Last Updated At": deploymentDetails?.lastUpdatedAt ? new Date(deploymentDetails.lastUpdatedAt).toLocaleString() : "",
143
+ "Lease Grace Period (Days)": deploymentDetails?.leaseGracePeriodDays
144
+ },
145
+ "Expense Information": deploymentDetails?.expense ? {
146
+ "Total Expense": `${deploymentDetails.expense.totalExpense} ${deploymentDetails.expense.unit}`,
147
+ "Compute Expense": `${deploymentDetails.expense.computeExpense} ${deploymentDetails.expense.unit}`,
148
+ "Storage Expense": `${deploymentDetails.expense.storageExpense} ${deploymentDetails.expense.unit}`,
149
+ "Additional Expense": `${deploymentDetails.expense.additionalExpense} ${deploymentDetails.expense.unit}`,
150
+ "Last Updated": new Date(deploymentDetails.expense.lastUpdatedTime).toLocaleString()
151
+ } : {},
152
+ "Input Parameters": deploymentDetails?.inputs || {}
153
+ };
154
+ return /* @__PURE__ */ jsxs(Grid, { container: true, spacing: 3, children: [
155
+ /* @__PURE__ */ jsx(Grid, { item: true, xs: 12, children: /* @__PURE__ */ jsx(InfoCard, { title: "Deployment Details", children: /* @__PURE__ */ jsx(StructuredMetadataTable, { metadata }) }) }),
156
+ /* @__PURE__ */ jsx(Grid, { item: true, xs: 12, children: /* @__PURE__ */ jsx(InfoCard, { title: "Deployment Resources", children: resources && resources.length > 0 ? /* @__PURE__ */ jsx(
157
+ Table,
158
+ {
159
+ columns: resourceColumns,
160
+ data: resources,
161
+ options: {
162
+ search: true,
163
+ paging: true,
164
+ pageSize: 10,
165
+ padding: "dense"
166
+ }
167
+ }
168
+ ) : /* @__PURE__ */ jsx(Typography, { children: "No resources found for this deployment." }) }) }),
169
+ /* @__PURE__ */ jsx(Grid, { item: true, xs: 12, children: /* @__PURE__ */ jsx(InfoCard, { title: "Deployment Events", children: eventsResponse?.content && eventsResponse.content.length > 0 ? /* @__PURE__ */ jsx(
170
+ Table,
171
+ {
172
+ columns: eventColumns,
173
+ data: eventsResponse.content,
174
+ options: {
175
+ search: true,
176
+ paging: true,
177
+ pageSize: eventsResponse.pageable?.pageSize || 10,
178
+ padding: "dense"
179
+ }
180
+ }
181
+ ) : /* @__PURE__ */ jsx(Typography, { children: "No deployment events available." }) }) })
182
+ ] });
183
+ };
184
+
185
+ export { VCFAutomationDeploymentDetails };
186
+ //# sourceMappingURL=VCFAutomationDeploymentDetails.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VCFAutomationDeploymentDetails.esm.js","sources":["../../src/components/VCFAutomationDeploymentDetails.tsx"],"sourcesContent":["import { useEntity } from '@backstage/plugin-catalog-react';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { vcfAutomationApiRef } from '../api/VcfAutomationClient';\nimport {\n InfoCard,\n Progress,\n ResponseErrorPanel,\n Table,\n TableColumn,\n StructuredMetadataTable,\n Link,\n} from '@backstage/core-components';\nimport { Grid, Typography } from '@material-ui/core';\nimport useAsync from 'react-use/lib/useAsync';\nimport { usePermission } from '@backstage/plugin-permission-react';\nimport { viewDeploymentHistoryPermission } from '@terasky/backstage-plugin-vcf-automation-common';\nimport { catalogApiRef } from '@backstage/plugin-catalog-react';\nimport { Entity } from '@backstage/catalog-model';\n\ntype DeploymentEvent = {\n id: string;\n name: string;\n status: string;\n requestedBy: string;\n createdAt: string;\n updatedAt: string;\n details: string;\n requestId: string;\n resourceIds: string[];\n};\n\ntype DeploymentResource = {\n name: string;\n title: string;\n kind: string;\n type: string;\n namespace: string;\n};\n\nconst eventColumns: TableColumn<DeploymentEvent>[] = [\n {\n title: 'Operation',\n field: 'name',\n },\n {\n title: 'Status',\n field: 'status',\n },\n {\n title: 'User',\n field: 'requestedBy',\n },\n {\n title: 'Created',\n field: 'createdAt',\n render: (row: DeploymentEvent) => new Date(row.createdAt).toLocaleString(),\n },\n {\n title: 'Last Updated',\n field: 'updatedAt',\n render: (row: DeploymentEvent) => new Date(row.updatedAt).toLocaleString(),\n },\n {\n title: 'Details',\n field: 'details',\n },\n];\n\nconst resourceColumns: TableColumn<DeploymentResource>[] = [\n {\n title: 'Name',\n field: 'title',\n render: (row: DeploymentResource) => (\n <Link to={`/catalog/${row.namespace}/${row.kind.toLowerCase()}/${row.name}`}>\n {row.title || row.name}\n </Link>\n ),\n },\n {\n title: 'Type',\n field: 'type',\n },\n];\n\nconst getEntityType = (entity: Entity): string => {\n const type = entity.spec?.type;\n if (typeof type === 'string') {\n return type;\n }\n if (typeof type === 'object' && type !== null) {\n return JSON.stringify(type);\n }\n return String(type || 'N/A');\n};\n\nexport const VCFAutomationDeploymentDetails = () => {\n const { entity } = useEntity();\n const api = useApi(vcfAutomationApiRef);\n const catalogApi = useApi(catalogApiRef);\n const deploymentId = entity.metadata.name;\n\n const { allowed: hasViewPermission, loading: permissionLoading } = usePermission({\n permission: viewDeploymentHistoryPermission,\n });\n\n const { value: deploymentDetails, loading: detailsLoading, error: detailsError } = useAsync(async () => {\n if (!deploymentId || !hasViewPermission) {\n return undefined;\n }\n return await api.getDeploymentDetails(deploymentId);\n }, [deploymentId, hasViewPermission]);\n\n const { value: eventsResponse, loading: eventsLoading, error: eventsError } = useAsync(async () => {\n if (!deploymentId || !hasViewPermission) {\n return undefined;\n }\n const response = await api.getDeploymentEvents(deploymentId);\n return response;\n }, [deploymentId, hasViewPermission]);\n\n const { value: resources, loading: resourcesLoading, error: resourcesError } = useAsync(async () => {\n if (!deploymentId) {\n return undefined;\n }\n\n // Get all components that belong to this system\n const components = await catalogApi.getEntities({\n filter: {\n kind: 'Component',\n 'spec.system': deploymentId,\n },\n });\n\n // Get all resources that belong to this system\n const resources = await catalogApi.getEntities({\n filter: {\n kind: 'Resource',\n 'spec.system': deploymentId,\n },\n });\n\n // Combine and format the results\n const allResources: DeploymentResource[] = [\n ...components.items.map((component: Entity) => ({\n name: component.metadata.name,\n title: component.metadata.title || component.metadata.name,\n kind: component.kind,\n type: getEntityType(component),\n namespace: component.metadata.namespace || 'default',\n })),\n ...resources.items.map((resource: Entity) => ({\n name: resource.metadata.name,\n title: resource.metadata.title || resource.metadata.name,\n kind: resource.kind,\n type: getEntityType(resource),\n namespace: resource.metadata.namespace || 'default',\n })),\n ];\n\n return allResources;\n }, [deploymentId]);\n\n if (!deploymentId) {\n return (\n <InfoCard title=\"VCF Automation Deployment\">\n <Typography>No deployment ID found for this entity.</Typography>\n </InfoCard>\n );\n }\n\n if (detailsLoading || eventsLoading || permissionLoading || resourcesLoading) {\n return (\n <InfoCard title=\"VCF Automation Deployment\">\n <Progress />\n </InfoCard>\n );\n }\n\n if (!hasViewPermission) {\n return (\n <InfoCard title=\"VCF Automation Deployment\">\n <Typography>You don't have permission to view deployment information.</Typography>\n </InfoCard>\n );\n }\n\n if (detailsError || eventsError || resourcesError) {\n return <ResponseErrorPanel error={detailsError ?? eventsError ?? resourcesError ?? new Error('Unknown error')} />;\n }\n\n const metadata: Record<string, any> = {\n 'Basic Information': {\n Name: deploymentDetails?.name,\n Description: deploymentDetails?.description || 'No description',\n Status: deploymentDetails?.status,\n 'Owner Type': deploymentDetails?.ownerType,\n 'Owned By': deploymentDetails?.ownedBy,\n 'Project ID': deploymentDetails?.projectId,\n 'Blueprint ID': deploymentDetails?.blueprintId,\n 'Organization ID': deploymentDetails?.orgId,\n },\n 'Timing Information': {\n 'Created By': deploymentDetails?.createdBy,\n 'Created At': deploymentDetails?.createdAt ? new Date(deploymentDetails.createdAt).toLocaleString() : '',\n 'Last Updated By': deploymentDetails?.lastUpdatedBy,\n 'Last Updated At': deploymentDetails?.lastUpdatedAt ? new Date(deploymentDetails.lastUpdatedAt).toLocaleString() : '',\n 'Lease Grace Period (Days)': deploymentDetails?.leaseGracePeriodDays,\n },\n 'Expense Information': deploymentDetails?.expense ? {\n 'Total Expense': `${deploymentDetails.expense.totalExpense} ${deploymentDetails.expense.unit}`,\n 'Compute Expense': `${deploymentDetails.expense.computeExpense} ${deploymentDetails.expense.unit}`,\n 'Storage Expense': `${deploymentDetails.expense.storageExpense} ${deploymentDetails.expense.unit}`,\n 'Additional Expense': `${deploymentDetails.expense.additionalExpense} ${deploymentDetails.expense.unit}`,\n 'Last Updated': new Date(deploymentDetails.expense.lastUpdatedTime).toLocaleString(),\n } : {},\n 'Input Parameters': deploymentDetails?.inputs || {},\n };\n\n return (\n <Grid container spacing={3}>\n <Grid item xs={12}>\n <InfoCard title=\"Deployment Details\">\n <StructuredMetadataTable metadata={metadata} />\n </InfoCard>\n </Grid>\n <Grid item xs={12}>\n <InfoCard title=\"Deployment Resources\">\n {resources && resources.length > 0 ? (\n <Table\n columns={resourceColumns}\n data={resources}\n options={{\n search: true,\n paging: true,\n pageSize: 10,\n padding: 'dense',\n }}\n />\n ) : (\n <Typography>No resources found for this deployment.</Typography>\n )}\n </InfoCard>\n </Grid>\n <Grid item xs={12}>\n <InfoCard title=\"Deployment Events\">\n {eventsResponse?.content && eventsResponse.content.length > 0 ? (\n <Table\n columns={eventColumns}\n data={eventsResponse.content}\n options={{\n search: true,\n paging: true,\n pageSize: eventsResponse.pageable?.pageSize || 10,\n padding: 'dense',\n }}\n />\n ) : (\n <Typography>No deployment events available.</Typography>\n )}\n </InfoCard>\n </Grid>\n </Grid>\n );\n}; "],"names":["resources"],"mappings":";;;;;;;;;;AAuCA,MAAM,YAA+C,GAAA;AAAA,EACnD;AAAA,IACE,KAAO,EAAA,WAAA;AAAA,IACP,KAAO,EAAA;AAAA,GACT;AAAA,EACA;AAAA,IACE,KAAO,EAAA,QAAA;AAAA,IACP,KAAO,EAAA;AAAA,GACT;AAAA,EACA;AAAA,IACE,KAAO,EAAA,MAAA;AAAA,IACP,KAAO,EAAA;AAAA,GACT;AAAA,EACA;AAAA,IACE,KAAO,EAAA,SAAA;AAAA,IACP,KAAO,EAAA,WAAA;AAAA,IACP,MAAA,EAAQ,CAAC,GAAyB,KAAA,IAAI,KAAK,GAAI,CAAA,SAAS,EAAE,cAAe;AAAA,GAC3E;AAAA,EACA;AAAA,IACE,KAAO,EAAA,cAAA;AAAA,IACP,KAAO,EAAA,WAAA;AAAA,IACP,MAAA,EAAQ,CAAC,GAAyB,KAAA,IAAI,KAAK,GAAI,CAAA,SAAS,EAAE,cAAe;AAAA,GAC3E;AAAA,EACA;AAAA,IACE,KAAO,EAAA,SAAA;AAAA,IACP,KAAO,EAAA;AAAA;AAEX,CAAA;AAEA,MAAM,eAAqD,GAAA;AAAA,EACzD;AAAA,IACE,KAAO,EAAA,MAAA;AAAA,IACP,KAAO,EAAA,OAAA;AAAA,IACP,MAAA,EAAQ,CAAC,GACP,qBAAA,GAAA,CAAC,QAAK,EAAI,EAAA,CAAA,SAAA,EAAY,IAAI,SAAS,CAAA,CAAA,EAAI,IAAI,IAAK,CAAA,WAAA,EAAa,CAAI,CAAA,EAAA,GAAA,CAAI,IAAI,CACtE,CAAA,EAAA,QAAA,EAAA,GAAA,CAAI,KAAS,IAAA,GAAA,CAAI,IACpB,EAAA;AAAA,GAEJ;AAAA,EACA;AAAA,IACE,KAAO,EAAA,MAAA;AAAA,IACP,KAAO,EAAA;AAAA;AAEX,CAAA;AAEA,MAAM,aAAA,GAAgB,CAAC,MAA2B,KAAA;AAChD,EAAM,MAAA,IAAA,GAAO,OAAO,IAAM,EAAA,IAAA;AAC1B,EAAI,IAAA,OAAO,SAAS,QAAU,EAAA;AAC5B,IAAO,OAAA,IAAA;AAAA;AAET,EAAA,IAAI,OAAO,IAAA,KAAS,QAAY,IAAA,IAAA,KAAS,IAAM,EAAA;AAC7C,IAAO,OAAA,IAAA,CAAK,UAAU,IAAI,CAAA;AAAA;AAE5B,EAAO,OAAA,MAAA,CAAO,QAAQ,KAAK,CAAA;AAC7B,CAAA;AAEO,MAAM,iCAAiC,MAAM;AAClD,EAAM,MAAA,EAAE,MAAO,EAAA,GAAI,SAAU,EAAA;AAC7B,EAAM,MAAA,GAAA,GAAM,OAAO,mBAAmB,CAAA;AACtC,EAAM,MAAA,UAAA,GAAa,OAAO,aAAa,CAAA;AACvC,EAAM,MAAA,YAAA,GAAe,OAAO,QAAS,CAAA,IAAA;AAErC,EAAA,MAAM,EAAE,OAAS,EAAA,iBAAA,EAAmB,OAAS,EAAA,iBAAA,KAAsB,aAAc,CAAA;AAAA,IAC/E,UAAY,EAAA;AAAA,GACb,CAAA;AAED,EAAM,MAAA,EAAE,OAAO,iBAAmB,EAAA,OAAA,EAAS,gBAAgB,KAAO,EAAA,YAAA,EAAiB,GAAA,QAAA,CAAS,YAAY;AACtG,IAAI,IAAA,CAAC,YAAgB,IAAA,CAAC,iBAAmB,EAAA;AACvC,MAAO,OAAA,KAAA,CAAA;AAAA;AAET,IAAO,OAAA,MAAM,GAAI,CAAA,oBAAA,CAAqB,YAAY,CAAA;AAAA,GACjD,EAAA,CAAC,YAAc,EAAA,iBAAiB,CAAC,CAAA;AAEpC,EAAM,MAAA,EAAE,OAAO,cAAgB,EAAA,OAAA,EAAS,eAAe,KAAO,EAAA,WAAA,EAAgB,GAAA,QAAA,CAAS,YAAY;AACjG,IAAI,IAAA,CAAC,YAAgB,IAAA,CAAC,iBAAmB,EAAA;AACvC,MAAO,OAAA,KAAA,CAAA;AAAA;AAET,IAAA,MAAM,QAAW,GAAA,MAAM,GAAI,CAAA,mBAAA,CAAoB,YAAY,CAAA;AAC3D,IAAO,OAAA,QAAA;AAAA,GACN,EAAA,CAAC,YAAc,EAAA,iBAAiB,CAAC,CAAA;AAEpC,EAAM,MAAA,EAAE,OAAO,SAAW,EAAA,OAAA,EAAS,kBAAkB,KAAO,EAAA,cAAA,EAAmB,GAAA,QAAA,CAAS,YAAY;AAClG,IAAA,IAAI,CAAC,YAAc,EAAA;AACjB,MAAO,OAAA,KAAA,CAAA;AAAA;AAIT,IAAM,MAAA,UAAA,GAAa,MAAM,UAAA,CAAW,WAAY,CAAA;AAAA,MAC9C,MAAQ,EAAA;AAAA,QACN,IAAM,EAAA,WAAA;AAAA,QACN,aAAe,EAAA;AAAA;AACjB,KACD,CAAA;AAGD,IAAMA,MAAAA,UAAAA,GAAY,MAAM,UAAA,CAAW,WAAY,CAAA;AAAA,MAC7C,MAAQ,EAAA;AAAA,QACN,IAAM,EAAA,UAAA;AAAA,QACN,aAAe,EAAA;AAAA;AACjB,KACD,CAAA;AAGD,IAAA,MAAM,YAAqC,GAAA;AAAA,MACzC,GAAG,UAAA,CAAW,KAAM,CAAA,GAAA,CAAI,CAAC,SAAuB,MAAA;AAAA,QAC9C,IAAA,EAAM,UAAU,QAAS,CAAA,IAAA;AAAA,QACzB,KAAO,EAAA,SAAA,CAAU,QAAS,CAAA,KAAA,IAAS,UAAU,QAAS,CAAA,IAAA;AAAA,QACtD,MAAM,SAAU,CAAA,IAAA;AAAA,QAChB,IAAA,EAAM,cAAc,SAAS,CAAA;AAAA,QAC7B,SAAA,EAAW,SAAU,CAAA,QAAA,CAAS,SAAa,IAAA;AAAA,OAC3C,CAAA,CAAA;AAAA,MACF,GAAGA,UAAAA,CAAU,KAAM,CAAA,GAAA,CAAI,CAAC,QAAsB,MAAA;AAAA,QAC5C,IAAA,EAAM,SAAS,QAAS,CAAA,IAAA;AAAA,QACxB,KAAO,EAAA,QAAA,CAAS,QAAS,CAAA,KAAA,IAAS,SAAS,QAAS,CAAA,IAAA;AAAA,QACpD,MAAM,QAAS,CAAA,IAAA;AAAA,QACf,IAAA,EAAM,cAAc,QAAQ,CAAA;AAAA,QAC5B,SAAA,EAAW,QAAS,CAAA,QAAA,CAAS,SAAa,IAAA;AAAA,OAC1C,CAAA;AAAA,KACJ;AAEA,IAAO,OAAA,YAAA;AAAA,GACT,EAAG,CAAC,YAAY,CAAC,CAAA;AAEjB,EAAA,IAAI,CAAC,YAAc,EAAA;AACjB,IAAA,2BACG,QAAS,EAAA,EAAA,KAAA,EAAM,6BACd,QAAC,kBAAA,GAAA,CAAA,UAAA,EAAA,EAAW,qDAAuC,CACrD,EAAA,CAAA;AAAA;AAIJ,EAAI,IAAA,cAAA,IAAkB,aAAiB,IAAA,iBAAA,IAAqB,gBAAkB,EAAA;AAC5E,IAAA,2BACG,QAAS,EAAA,EAAA,KAAA,EAAM,2BACd,EAAA,QAAA,kBAAA,GAAA,CAAC,YAAS,CACZ,EAAA,CAAA;AAAA;AAIJ,EAAA,IAAI,CAAC,iBAAmB,EAAA;AACtB,IAAA,2BACG,QAAS,EAAA,EAAA,KAAA,EAAM,6BACd,QAAC,kBAAA,GAAA,CAAA,UAAA,EAAA,EAAW,uEAAyD,CACvE,EAAA,CAAA;AAAA;AAIJ,EAAI,IAAA,YAAA,IAAgB,eAAe,cAAgB,EAAA;AACjD,IAAO,uBAAA,GAAA,CAAC,sBAAmB,KAAO,EAAA,YAAA,IAAgB,eAAe,cAAkB,IAAA,IAAI,KAAM,CAAA,eAAe,CAAG,EAAA,CAAA;AAAA;AAGjH,EAAA,MAAM,QAAgC,GAAA;AAAA,IACpC,mBAAqB,EAAA;AAAA,MACnB,MAAM,iBAAmB,EAAA,IAAA;AAAA,MACzB,WAAA,EAAa,mBAAmB,WAAe,IAAA,gBAAA;AAAA,MAC/C,QAAQ,iBAAmB,EAAA,MAAA;AAAA,MAC3B,cAAc,iBAAmB,EAAA,SAAA;AAAA,MACjC,YAAY,iBAAmB,EAAA,OAAA;AAAA,MAC/B,cAAc,iBAAmB,EAAA,SAAA;AAAA,MACjC,gBAAgB,iBAAmB,EAAA,WAAA;AAAA,MACnC,mBAAmB,iBAAmB,EAAA;AAAA,KACxC;AAAA,IACA,oBAAsB,EAAA;AAAA,MACpB,cAAc,iBAAmB,EAAA,SAAA;AAAA,MACjC,YAAA,EAAc,mBAAmB,SAAY,GAAA,IAAI,KAAK,iBAAkB,CAAA,SAAS,CAAE,CAAA,cAAA,EAAmB,GAAA,EAAA;AAAA,MACtG,mBAAmB,iBAAmB,EAAA,aAAA;AAAA,MACtC,iBAAA,EAAmB,mBAAmB,aAAgB,GAAA,IAAI,KAAK,iBAAkB,CAAA,aAAa,CAAE,CAAA,cAAA,EAAmB,GAAA,EAAA;AAAA,MACnH,6BAA6B,iBAAmB,EAAA;AAAA,KAClD;AAAA,IACA,qBAAA,EAAuB,mBAAmB,OAAU,GAAA;AAAA,MAClD,eAAA,EAAiB,GAAG,iBAAkB,CAAA,OAAA,CAAQ,YAAY,CAAI,CAAA,EAAA,iBAAA,CAAkB,QAAQ,IAAI,CAAA,CAAA;AAAA,MAC5F,iBAAA,EAAmB,GAAG,iBAAkB,CAAA,OAAA,CAAQ,cAAc,CAAI,CAAA,EAAA,iBAAA,CAAkB,QAAQ,IAAI,CAAA,CAAA;AAAA,MAChG,iBAAA,EAAmB,GAAG,iBAAkB,CAAA,OAAA,CAAQ,cAAc,CAAI,CAAA,EAAA,iBAAA,CAAkB,QAAQ,IAAI,CAAA,CAAA;AAAA,MAChG,oBAAA,EAAsB,GAAG,iBAAkB,CAAA,OAAA,CAAQ,iBAAiB,CAAI,CAAA,EAAA,iBAAA,CAAkB,QAAQ,IAAI,CAAA,CAAA;AAAA,MACtG,gBAAgB,IAAI,IAAA,CAAK,kBAAkB,OAAQ,CAAA,eAAe,EAAE,cAAe;AAAA,QACjF,EAAC;AAAA,IACL,kBAAA,EAAoB,iBAAmB,EAAA,MAAA,IAAU;AAAC,GACpD;AAEA,EAAA,uBACG,IAAA,CAAA,IAAA,EAAA,EAAK,SAAS,EAAA,IAAA,EAAC,SAAS,CACvB,EAAA,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,IAAK,EAAA,EAAA,IAAA,EAAI,IAAC,EAAA,EAAA,EAAI,EACb,EAAA,QAAA,kBAAA,GAAA,CAAC,QAAS,EAAA,EAAA,KAAA,EAAM,oBACd,EAAA,QAAA,kBAAA,GAAA,CAAC,uBAAwB,EAAA,EAAA,QAAA,EAAoB,GAC/C,CACF,EAAA,CAAA;AAAA,oBACC,GAAA,CAAA,IAAA,EAAA,EAAK,IAAI,EAAA,IAAA,EAAC,EAAI,EAAA,EAAA,EACb,QAAC,kBAAA,GAAA,CAAA,QAAA,EAAA,EAAS,KAAM,EAAA,sBAAA,EACb,QAAa,EAAA,SAAA,IAAA,SAAA,CAAU,SAAS,CAC/B,mBAAA,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,OAAS,EAAA,eAAA;AAAA,QACT,IAAM,EAAA,SAAA;AAAA,QACN,OAAS,EAAA;AAAA,UACP,MAAQ,EAAA,IAAA;AAAA,UACR,MAAQ,EAAA,IAAA;AAAA,UACR,QAAU,EAAA,EAAA;AAAA,UACV,OAAS,EAAA;AAAA;AACX;AAAA,KAGF,mBAAA,GAAA,CAAC,UAAW,EAAA,EAAA,QAAA,EAAA,yCAAA,EAAuC,GAEvD,CACF,EAAA,CAAA;AAAA,oBACC,GAAA,CAAA,IAAA,EAAA,EAAK,IAAI,EAAA,IAAA,EAAC,IAAI,EACb,EAAA,QAAA,kBAAA,GAAA,CAAC,QAAS,EAAA,EAAA,KAAA,EAAM,qBACb,QAAgB,EAAA,cAAA,EAAA,OAAA,IAAW,cAAe,CAAA,OAAA,CAAQ,SAAS,CAC1D,mBAAA,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,OAAS,EAAA,YAAA;AAAA,QACT,MAAM,cAAe,CAAA,OAAA;AAAA,QACrB,OAAS,EAAA;AAAA,UACP,MAAQ,EAAA,IAAA;AAAA,UACR,MAAQ,EAAA,IAAA;AAAA,UACR,QAAA,EAAU,cAAe,CAAA,QAAA,EAAU,QAAY,IAAA,EAAA;AAAA,UAC/C,OAAS,EAAA;AAAA;AACX;AAAA,KAGF,mBAAA,GAAA,CAAC,UAAW,EAAA,EAAA,QAAA,EAAA,iCAAA,EAA+B,GAE/C,CACF,EAAA;AAAA,GACF,EAAA,CAAA;AAEJ;;;;"}
@@ -0,0 +1,102 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { useEntity } from '@backstage/plugin-catalog-react';
3
+ import { useApi } from '@backstage/core-plugin-api';
4
+ import { vcfAutomationApiRef } from '../api/VcfAutomationClient.esm.js';
5
+ import { InfoCard, Progress, ResponseErrorPanel } from '@backstage/core-components';
6
+ import { Typography, Grid } from '@material-ui/core';
7
+ import useAsync from 'react-use/lib/useAsync';
8
+ import { usePermission } from '@backstage/plugin-permission-react';
9
+ import { viewDeploymentHistoryPermission } from '@terasky/backstage-plugin-vcf-automation-common';
10
+
11
+ const VCFAutomationDeploymentOverview = () => {
12
+ const { entity } = useEntity();
13
+ const api = useApi(vcfAutomationApiRef);
14
+ const deploymentId = entity.metadata.name;
15
+ const { allowed: hasViewPermission, loading: permissionLoading } = usePermission({
16
+ permission: viewDeploymentHistoryPermission
17
+ });
18
+ const { value: deploymentDetails, loading, error } = useAsync(async () => {
19
+ if (!deploymentId || !hasViewPermission) {
20
+ return void 0;
21
+ }
22
+ return await api.getDeploymentDetails(deploymentId);
23
+ }, [deploymentId, hasViewPermission]);
24
+ if (!deploymentId) {
25
+ return /* @__PURE__ */ jsx(InfoCard, { title: "VCF Automation Deployment", children: /* @__PURE__ */ jsx(Typography, { children: "No deployment ID found for this entity." }) });
26
+ }
27
+ if (loading || permissionLoading) {
28
+ return /* @__PURE__ */ jsx(InfoCard, { title: "VCF Automation Deployment", children: /* @__PURE__ */ jsx(Progress, {}) });
29
+ }
30
+ if (!hasViewPermission) {
31
+ return /* @__PURE__ */ jsx(InfoCard, { title: "VCF Automation Deployment", children: /* @__PURE__ */ jsx(Typography, { children: "You don't have permission to view deployment details." }) });
32
+ }
33
+ if (error) {
34
+ return /* @__PURE__ */ jsx(ResponseErrorPanel, { error });
35
+ }
36
+ if (!deploymentDetails) {
37
+ return /* @__PURE__ */ jsx(InfoCard, { title: "VCF Automation Deployment", children: /* @__PURE__ */ jsx(Typography, { children: "No deployment details available." }) });
38
+ }
39
+ return /* @__PURE__ */ jsx(InfoCard, { title: "VCF Automation Deployment", children: /* @__PURE__ */ jsxs(Grid, { container: true, spacing: 2, children: [
40
+ /* @__PURE__ */ jsx(Grid, { item: true, xs: 12, children: /* @__PURE__ */ jsx(Typography, { variant: "h6", children: "Deployment Information" }) }),
41
+ /* @__PURE__ */ jsxs(Grid, { item: true, xs: 6, children: [
42
+ /* @__PURE__ */ jsx(Typography, { variant: "subtitle2", children: "Name" }),
43
+ /* @__PURE__ */ jsx(Typography, { children: deploymentDetails.name })
44
+ ] }),
45
+ /* @__PURE__ */ jsxs(Grid, { item: true, xs: 6, children: [
46
+ /* @__PURE__ */ jsx(Typography, { variant: "subtitle2", children: "Status" }),
47
+ /* @__PURE__ */ jsx(Typography, { children: deploymentDetails.status })
48
+ ] }),
49
+ /* @__PURE__ */ jsxs(Grid, { item: true, xs: 6, children: [
50
+ /* @__PURE__ */ jsx(Typography, { variant: "subtitle2", children: "Created By" }),
51
+ /* @__PURE__ */ jsx(Typography, { children: deploymentDetails.createdBy })
52
+ ] }),
53
+ /* @__PURE__ */ jsxs(Grid, { item: true, xs: 6, children: [
54
+ /* @__PURE__ */ jsx(Typography, { variant: "subtitle2", children: "Created At" }),
55
+ /* @__PURE__ */ jsx(Typography, { children: new Date(deploymentDetails.createdAt).toLocaleString() })
56
+ ] }),
57
+ /* @__PURE__ */ jsxs(Grid, { item: true, xs: 6, children: [
58
+ /* @__PURE__ */ jsx(Typography, { variant: "subtitle2", children: "Last Updated By" }),
59
+ /* @__PURE__ */ jsx(Typography, { children: deploymentDetails.lastUpdatedBy })
60
+ ] }),
61
+ /* @__PURE__ */ jsxs(Grid, { item: true, xs: 6, children: [
62
+ /* @__PURE__ */ jsx(Typography, { variant: "subtitle2", children: "Last Updated At" }),
63
+ /* @__PURE__ */ jsx(Typography, { children: new Date(deploymentDetails.lastUpdatedAt).toLocaleString() })
64
+ ] }),
65
+ /* @__PURE__ */ jsx(Grid, { item: true, xs: 12, children: /* @__PURE__ */ jsx(Typography, { variant: "h6", children: "Expenses" }) }),
66
+ /* @__PURE__ */ jsxs(Grid, { item: true, xs: 3, children: [
67
+ /* @__PURE__ */ jsx(Typography, { variant: "subtitle2", children: "Total" }),
68
+ /* @__PURE__ */ jsxs(Typography, { children: [
69
+ deploymentDetails.expense?.totalExpense || "N/A",
70
+ " ",
71
+ deploymentDetails.expense?.unit || ""
72
+ ] })
73
+ ] }),
74
+ /* @__PURE__ */ jsxs(Grid, { item: true, xs: 3, children: [
75
+ /* @__PURE__ */ jsx(Typography, { variant: "subtitle2", children: "Compute" }),
76
+ /* @__PURE__ */ jsxs(Typography, { children: [
77
+ deploymentDetails.expense?.computeExpense || "N/A",
78
+ " ",
79
+ deploymentDetails.expense?.unit || ""
80
+ ] })
81
+ ] }),
82
+ /* @__PURE__ */ jsxs(Grid, { item: true, xs: 3, children: [
83
+ /* @__PURE__ */ jsx(Typography, { variant: "subtitle2", children: "Storage" }),
84
+ /* @__PURE__ */ jsxs(Typography, { children: [
85
+ deploymentDetails.expense?.storageExpense || "N/A",
86
+ " ",
87
+ deploymentDetails.expense?.unit || ""
88
+ ] })
89
+ ] }),
90
+ /* @__PURE__ */ jsxs(Grid, { item: true, xs: 3, children: [
91
+ /* @__PURE__ */ jsx(Typography, { variant: "subtitle2", children: "Additional" }),
92
+ /* @__PURE__ */ jsxs(Typography, { children: [
93
+ deploymentDetails.expense?.additionalExpense || "N/A",
94
+ " ",
95
+ deploymentDetails.expense?.unit || ""
96
+ ] })
97
+ ] })
98
+ ] }) });
99
+ };
100
+
101
+ export { VCFAutomationDeploymentOverview };
102
+ //# sourceMappingURL=VCFAutomationDeploymentOverview.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VCFAutomationDeploymentOverview.esm.js","sources":["../../src/components/VCFAutomationDeploymentOverview.tsx"],"sourcesContent":["import { useEntity } from '@backstage/plugin-catalog-react';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { vcfAutomationApiRef } from '../api/VcfAutomationClient';\nimport {\n InfoCard,\n Progress,\n ResponseErrorPanel,\n} from '@backstage/core-components';\nimport { Grid, Typography } from '@material-ui/core';\nimport useAsync from 'react-use/lib/useAsync';\nimport { usePermission } from '@backstage/plugin-permission-react';\nimport { viewDeploymentHistoryPermission } from '@terasky/backstage-plugin-vcf-automation-common';\n\nexport const VCFAutomationDeploymentOverview = () => {\n const { entity } = useEntity();\n const api = useApi(vcfAutomationApiRef);\n const deploymentId = entity.metadata.name;\n\n const { allowed: hasViewPermission, loading: permissionLoading } = usePermission({\n permission: viewDeploymentHistoryPermission,\n });\n\n const { value: deploymentDetails, loading, error } = useAsync(async () => {\n if (!deploymentId || !hasViewPermission) {\n return undefined;\n }\n return await api.getDeploymentDetails(deploymentId);\n }, [deploymentId, hasViewPermission]);\n\n if (!deploymentId) {\n return (\n <InfoCard title=\"VCF Automation Deployment\">\n <Typography>No deployment ID found for this entity.</Typography>\n </InfoCard>\n );\n }\n\n if (loading || permissionLoading) {\n return (\n <InfoCard title=\"VCF Automation Deployment\">\n <Progress />\n </InfoCard>\n );\n }\n\n if (!hasViewPermission) {\n return (\n <InfoCard title=\"VCF Automation Deployment\">\n <Typography>You don't have permission to view deployment details.</Typography>\n </InfoCard>\n );\n }\n\n if (error) {\n return <ResponseErrorPanel error={error} />;\n }\n\n if (!deploymentDetails) {\n return (\n <InfoCard title=\"VCF Automation Deployment\">\n <Typography>No deployment details available.</Typography>\n </InfoCard>\n );\n }\n\n return (\n <InfoCard title=\"VCF Automation Deployment\">\n <Grid container spacing={2}>\n <Grid item xs={12}>\n <Typography variant=\"h6\">Deployment Information</Typography>\n </Grid>\n <Grid item xs={6}>\n <Typography variant=\"subtitle2\">Name</Typography>\n <Typography>{deploymentDetails.name}</Typography>\n </Grid>\n <Grid item xs={6}>\n <Typography variant=\"subtitle2\">Status</Typography>\n <Typography>{deploymentDetails.status}</Typography>\n </Grid>\n <Grid item xs={6}>\n <Typography variant=\"subtitle2\">Created By</Typography>\n <Typography>{deploymentDetails.createdBy}</Typography>\n </Grid>\n <Grid item xs={6}>\n <Typography variant=\"subtitle2\">Created At</Typography>\n <Typography>\n {new Date(deploymentDetails.createdAt).toLocaleString()}\n </Typography>\n </Grid>\n <Grid item xs={6}>\n <Typography variant=\"subtitle2\">Last Updated By</Typography>\n <Typography>{deploymentDetails.lastUpdatedBy}</Typography>\n </Grid>\n <Grid item xs={6}>\n <Typography variant=\"subtitle2\">Last Updated At</Typography>\n <Typography>\n {new Date(deploymentDetails.lastUpdatedAt).toLocaleString()}\n </Typography>\n </Grid>\n <Grid item xs={12}>\n <Typography variant=\"h6\">Expenses</Typography>\n </Grid>\n <Grid item xs={3}>\n <Typography variant=\"subtitle2\">Total</Typography>\n <Typography>\n {deploymentDetails.expense?.totalExpense || 'N/A'} {deploymentDetails.expense?.unit || ''}\n </Typography>\n </Grid>\n <Grid item xs={3}>\n <Typography variant=\"subtitle2\">Compute</Typography>\n <Typography>\n {deploymentDetails.expense?.computeExpense || 'N/A'} {deploymentDetails.expense?.unit || ''}\n </Typography>\n </Grid>\n <Grid item xs={3}>\n <Typography variant=\"subtitle2\">Storage</Typography>\n <Typography>\n {deploymentDetails.expense?.storageExpense || 'N/A'} {deploymentDetails.expense?.unit || ''}\n </Typography>\n </Grid>\n <Grid item xs={3}>\n <Typography variant=\"subtitle2\">Additional</Typography>\n <Typography>\n {deploymentDetails.expense?.additionalExpense || 'N/A'} {deploymentDetails.expense?.unit || ''}\n </Typography>\n </Grid>\n </Grid>\n </InfoCard>\n );\n}; "],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { useEntity } from '@backstage/plugin-catalog-react';
3
+ import { ResponseErrorPanel, Progress, InfoCard, StructuredMetadataTable } from '@backstage/core-components';
4
+ import useAsync from 'react-use/lib/useAsync';
5
+ import { useApi } from '@backstage/core-plugin-api';
6
+ import { vcfAutomationApiRef } from '../api/VcfAutomationClient.esm.js';
7
+
8
+ const formatValue = (value) => {
9
+ if (value === null) return "null";
10
+ if (typeof value === "undefined") return "undefined";
11
+ if (typeof value === "object") {
12
+ if (Array.isArray(value)) {
13
+ return value.map(formatValue);
14
+ }
15
+ const formattedObj = {};
16
+ Object.entries(value).forEach(([key, val]) => {
17
+ formattedObj[key] = formatValue(val);
18
+ });
19
+ return formattedObj;
20
+ }
21
+ if (typeof value === "string" && value.match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/)) {
22
+ return new Date(value).toLocaleString();
23
+ }
24
+ return value;
25
+ };
26
+ const VCFAutomationGenericResourceDetails = () => {
27
+ const { entity } = useEntity();
28
+ const vcfAutomationApi = useApi(vcfAutomationApiRef);
29
+ const deploymentId = entity.spec?.system || "";
30
+ const resourceId = entity.metadata.name;
31
+ const { value: resourceData, loading, error } = useAsync(async () => {
32
+ if (!deploymentId || !resourceId) return void 0;
33
+ return await vcfAutomationApi.getGenericResourceDetails(deploymentId, resourceId);
34
+ }, [deploymentId, resourceId]);
35
+ if (error) {
36
+ return /* @__PURE__ */ jsx(ResponseErrorPanel, { error });
37
+ }
38
+ if (loading) {
39
+ return /* @__PURE__ */ jsx(Progress, {});
40
+ }
41
+ if (!deploymentId || !resourceId) {
42
+ return /* @__PURE__ */ jsx(InfoCard, { title: "No Resource Information", children: "This entity is not associated with a VCF resource." });
43
+ }
44
+ if (!resourceData) {
45
+ return /* @__PURE__ */ jsx(InfoCard, { title: "No Data", children: "No resource details available." });
46
+ }
47
+ const formattedData = formatValue(resourceData);
48
+ return /* @__PURE__ */ jsx(InfoCard, { title: "Resource Details", children: /* @__PURE__ */ jsx(StructuredMetadataTable, { metadata: formattedData }) });
49
+ };
50
+
51
+ export { VCFAutomationGenericResourceDetails };
52
+ //# sourceMappingURL=VCFAutomationGenericResourceDetails.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VCFAutomationGenericResourceDetails.esm.js","sources":["../../src/components/VCFAutomationGenericResourceDetails.tsx"],"sourcesContent":["import { useEntity } from '@backstage/plugin-catalog-react';\nimport {\n InfoCard,\n Progress,\n ResponseErrorPanel,\n StructuredMetadataTable,\n} from '@backstage/core-components';\nimport useAsync from 'react-use/lib/useAsync';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { vcfAutomationApiRef } from '../api/VcfAutomationClient';\n\nconst formatValue = (value: any): any => {\n if (value === null) return 'null';\n if (typeof value === 'undefined') return 'undefined';\n if (typeof value === 'object') {\n if (Array.isArray(value)) {\n return value.map(formatValue);\n }\n const formattedObj: Record<string, any> = {};\n Object.entries(value).forEach(([key, val]) => {\n formattedObj[key] = formatValue(val);\n });\n return formattedObj;\n }\n if (typeof value === 'string' && value.match(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}/)) {\n return new Date(value).toLocaleString();\n }\n return value;\n};\n\nexport const VCFAutomationGenericResourceDetails = () => {\n const { entity } = useEntity();\n const vcfAutomationApi = useApi(vcfAutomationApiRef);\n const deploymentId = entity.spec?.system || '';\n const resourceId = entity.metadata.name;\n\n const { value: resourceData, loading, error } = useAsync(async () => {\n if (!deploymentId || !resourceId) return undefined;\n return await vcfAutomationApi.getGenericResourceDetails(deploymentId as string, resourceId as string);\n }, [deploymentId, resourceId]);\n\n if (error) {\n return <ResponseErrorPanel error={error} />;\n }\n\n if (loading) {\n return <Progress />;\n }\n\n if (!deploymentId || !resourceId) {\n return (\n <InfoCard title=\"No Resource Information\">\n This entity is not associated with a VCF resource.\n </InfoCard>\n );\n }\n\n if (!resourceData) {\n return <InfoCard title=\"No Data\">No resource details available.</InfoCard>;\n }\n\n // Format all data for display\n const formattedData = formatValue(resourceData);\n\n return (\n <InfoCard title=\"Resource Details\">\n <StructuredMetadataTable metadata={formattedData} />\n </InfoCard>\n );\n}; "],"names":[],"mappings":";;;;;;;AAWA,MAAM,WAAA,GAAc,CAAC,KAAoB,KAAA;AACvC,EAAI,IAAA,KAAA,KAAU,MAAa,OAAA,MAAA;AAC3B,EAAI,IAAA,OAAO,KAAU,KAAA,WAAA,EAAoB,OAAA,WAAA;AACzC,EAAI,IAAA,OAAO,UAAU,QAAU,EAAA;AAC7B,IAAI,IAAA,KAAA,CAAM,OAAQ,CAAA,KAAK,CAAG,EAAA;AACxB,MAAO,OAAA,KAAA,CAAM,IAAI,WAAW,CAAA;AAAA;AAE9B,IAAA,MAAM,eAAoC,EAAC;AAC3C,IAAO,MAAA,CAAA,OAAA,CAAQ,KAAK,CAAE,CAAA,OAAA,CAAQ,CAAC,CAAC,GAAA,EAAK,GAAG,CAAM,KAAA;AAC5C,MAAa,YAAA,CAAA,GAAG,CAAI,GAAA,WAAA,CAAY,GAAG,CAAA;AAAA,KACpC,CAAA;AACD,IAAO,OAAA,YAAA;AAAA;AAET,EAAA,IAAI,OAAO,KAAU,KAAA,QAAA,IAAY,KAAM,CAAA,KAAA,CAAM,sCAAsC,CAAG,EAAA;AACpF,IAAA,OAAO,IAAI,IAAA,CAAK,KAAK,CAAA,CAAE,cAAe,EAAA;AAAA;AAExC,EAAO,OAAA,KAAA;AACT,CAAA;AAEO,MAAM,sCAAsC,MAAM;AACvD,EAAM,MAAA,EAAE,MAAO,EAAA,GAAI,SAAU,EAAA;AAC7B,EAAM,MAAA,gBAAA,GAAmB,OAAO,mBAAmB,CAAA;AACnD,EAAM,MAAA,YAAA,GAAe,MAAO,CAAA,IAAA,EAAM,MAAU,IAAA,EAAA;AAC5C,EAAM,MAAA,UAAA,GAAa,OAAO,QAAS,CAAA,IAAA;AAEnC,EAAA,MAAM,EAAE,KAAO,EAAA,YAAA,EAAc,SAAS,KAAM,EAAA,GAAI,SAAS,YAAY;AACnE,IAAA,IAAI,CAAC,YAAA,IAAgB,CAAC,UAAA,EAAmB,OAAA,KAAA,CAAA;AACzC,IAAA,OAAO,MAAM,gBAAA,CAAiB,yBAA0B,CAAA,YAAA,EAAwB,UAAoB,CAAA;AAAA,GACnG,EAAA,CAAC,YAAc,EAAA,UAAU,CAAC,CAAA;AAE7B,EAAA,IAAI,KAAO,EAAA;AACT,IAAO,uBAAA,GAAA,CAAC,sBAAmB,KAAc,EAAA,CAAA;AAAA;AAG3C,EAAA,IAAI,OAAS,EAAA;AACX,IAAA,2BAAQ,QAAS,EAAA,EAAA,CAAA;AAAA;AAGnB,EAAI,IAAA,CAAC,YAAgB,IAAA,CAAC,UAAY,EAAA;AAChC,IAAA,uBACG,GAAA,CAAA,QAAA,EAAA,EAAS,KAAM,EAAA,yBAAA,EAA0B,QAE1C,EAAA,oDAAA,EAAA,CAAA;AAAA;AAIJ,EAAA,IAAI,CAAC,YAAc,EAAA;AACjB,IAAA,uBAAQ,GAAA,CAAA,QAAA,EAAA,EAAS,KAAM,EAAA,SAAA,EAAU,QAA8B,EAAA,gCAAA,EAAA,CAAA;AAAA;AAIjE,EAAM,MAAA,aAAA,GAAgB,YAAY,YAAY,CAAA;AAE9C,EACE,uBAAA,GAAA,CAAC,YAAS,KAAM,EAAA,kBAAA,EACd,8BAAC,uBAAwB,EAAA,EAAA,QAAA,EAAU,eAAe,CACpD,EAAA,CAAA;AAEJ;;;;"}
@@ -0,0 +1,40 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { useEntity } from '@backstage/plugin-catalog-react';
3
+ import { ResponseErrorPanel, Progress, InfoCard, StructuredMetadataTable } from '@backstage/core-components';
4
+ import useAsync from 'react-use/lib/useAsync';
5
+ import { useApi } from '@backstage/core-plugin-api';
6
+ import { vcfAutomationApiRef } from '../api/VcfAutomationClient.esm.js';
7
+
8
+ const VCFAutomationGenericResourceOverview = () => {
9
+ const { entity } = useEntity();
10
+ const vcfAutomationApi = useApi(vcfAutomationApiRef);
11
+ const deploymentId = entity.spec?.system || "";
12
+ const resourceId = entity.metadata.name;
13
+ const { value: resourceData, loading, error } = useAsync(async () => {
14
+ if (!deploymentId || !resourceId) return void 0;
15
+ return await vcfAutomationApi.getGenericResourceDetails(deploymentId, resourceId);
16
+ }, [deploymentId, resourceId]);
17
+ if (error) {
18
+ return /* @__PURE__ */ jsx(ResponseErrorPanel, { error });
19
+ }
20
+ if (loading) {
21
+ return /* @__PURE__ */ jsx(Progress, {});
22
+ }
23
+ if (!deploymentId || !resourceId) {
24
+ return /* @__PURE__ */ jsx(InfoCard, { title: "No Resource Information", children: "This entity is not associated with a VCF resource." });
25
+ }
26
+ if (!resourceData) {
27
+ return /* @__PURE__ */ jsx(InfoCard, { title: "No Data", children: "No resource details available." });
28
+ }
29
+ const overviewData = {};
30
+ if (resourceData.name) overviewData["Name"] = resourceData.name;
31
+ if (resourceData.type) overviewData["Type"] = resourceData.type;
32
+ if (resourceData.createdAt) overviewData["Created At"] = new Date(resourceData.createdAt).toLocaleString();
33
+ if (resourceData.syncStatus) overviewData["Sync Status"] = resourceData.syncStatus;
34
+ if (resourceData.origin) overviewData["Origin"] = resourceData.origin;
35
+ if (resourceData.status) overviewData["Status"] = resourceData.status;
36
+ return /* @__PURE__ */ jsx(InfoCard, { title: "Resource Overview", children: /* @__PURE__ */ jsx(StructuredMetadataTable, { metadata: overviewData }) });
37
+ };
38
+
39
+ export { VCFAutomationGenericResourceOverview };
40
+ //# sourceMappingURL=VCFAutomationGenericResourceOverview.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VCFAutomationGenericResourceOverview.esm.js","sources":["../../src/components/VCFAutomationGenericResourceOverview.tsx"],"sourcesContent":["import { useEntity } from '@backstage/plugin-catalog-react';\nimport {\n InfoCard,\n Progress,\n ResponseErrorPanel,\n StructuredMetadataTable,\n} from '@backstage/core-components';\nimport useAsync from 'react-use/lib/useAsync';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { vcfAutomationApiRef } from '../api/VcfAutomationClient';\n\nexport const VCFAutomationGenericResourceOverview = () => {\n const { entity } = useEntity();\n const vcfAutomationApi = useApi(vcfAutomationApiRef);\n const deploymentId = entity.spec?.system || '';\n const resourceId = entity.metadata.name;\n\n const { value: resourceData, loading, error } = useAsync(async () => {\n if (!deploymentId || !resourceId) return undefined;\n return await vcfAutomationApi.getGenericResourceDetails(deploymentId as string, resourceId as string);\n }, [deploymentId, resourceId]);\n\n if (error) {\n return <ResponseErrorPanel error={error} />;\n }\n\n if (loading) {\n return <Progress />;\n }\n\n if (!deploymentId || !resourceId) {\n return (\n <InfoCard title=\"No Resource Information\">\n This entity is not associated with a VCF resource.\n </InfoCard>\n );\n }\n\n if (!resourceData) {\n return <InfoCard title=\"No Data\">No resource details available.</InfoCard>;\n }\n\n // Extract the overview fields if they exist\n const overviewData: Record<string, any> = {};\n \n if (resourceData.name) overviewData['Name'] = resourceData.name;\n if (resourceData.type) overviewData['Type'] = resourceData.type;\n if (resourceData.createdAt) overviewData['Created At'] = new Date(resourceData.createdAt).toLocaleString();\n if (resourceData.syncStatus) overviewData['Sync Status'] = resourceData.syncStatus;\n if (resourceData.origin) overviewData['Origin'] = resourceData.origin;\n if (resourceData.status) overviewData['Status'] = resourceData.status;\n\n return (\n <InfoCard title=\"Resource Overview\">\n <StructuredMetadataTable metadata={overviewData} />\n </InfoCard>\n );\n}; "],"names":[],"mappings":";;;;;;;AAWO,MAAM,uCAAuC,MAAM;AACxD,EAAM,MAAA,EAAE,MAAO,EAAA,GAAI,SAAU,EAAA;AAC7B,EAAM,MAAA,gBAAA,GAAmB,OAAO,mBAAmB,CAAA;AACnD,EAAM,MAAA,YAAA,GAAe,MAAO,CAAA,IAAA,EAAM,MAAU,IAAA,EAAA;AAC5C,EAAM,MAAA,UAAA,GAAa,OAAO,QAAS,CAAA,IAAA;AAEnC,EAAA,MAAM,EAAE,KAAO,EAAA,YAAA,EAAc,SAAS,KAAM,EAAA,GAAI,SAAS,YAAY;AACnE,IAAA,IAAI,CAAC,YAAA,IAAgB,CAAC,UAAA,EAAmB,OAAA,KAAA,CAAA;AACzC,IAAA,OAAO,MAAM,gBAAA,CAAiB,yBAA0B,CAAA,YAAA,EAAwB,UAAoB,CAAA;AAAA,GACnG,EAAA,CAAC,YAAc,EAAA,UAAU,CAAC,CAAA;AAE7B,EAAA,IAAI,KAAO,EAAA;AACT,IAAO,uBAAA,GAAA,CAAC,sBAAmB,KAAc,EAAA,CAAA;AAAA;AAG3C,EAAA,IAAI,OAAS,EAAA;AACX,IAAA,2BAAQ,QAAS,EAAA,EAAA,CAAA;AAAA;AAGnB,EAAI,IAAA,CAAC,YAAgB,IAAA,CAAC,UAAY,EAAA;AAChC,IAAA,uBACG,GAAA,CAAA,QAAA,EAAA,EAAS,KAAM,EAAA,yBAAA,EAA0B,QAE1C,EAAA,oDAAA,EAAA,CAAA;AAAA;AAIJ,EAAA,IAAI,CAAC,YAAc,EAAA;AACjB,IAAA,uBAAQ,GAAA,CAAA,QAAA,EAAA,EAAS,KAAM,EAAA,SAAA,EAAU,QAA8B,EAAA,gCAAA,EAAA,CAAA;AAAA;AAIjE,EAAA,MAAM,eAAoC,EAAC;AAE3C,EAAA,IAAI,YAAa,CAAA,IAAA,EAAmB,YAAA,CAAA,MAAM,IAAI,YAAa,CAAA,IAAA;AAC3D,EAAA,IAAI,YAAa,CAAA,IAAA,EAAmB,YAAA,CAAA,MAAM,IAAI,YAAa,CAAA,IAAA;AAC3D,EAAI,IAAA,YAAA,CAAa,SAAW,EAAA,YAAA,CAAa,YAAY,CAAA,GAAI,IAAI,IAAK,CAAA,YAAA,CAAa,SAAS,CAAA,CAAE,cAAe,EAAA;AACzG,EAAA,IAAI,YAAa,CAAA,UAAA,EAAyB,YAAA,CAAA,aAAa,IAAI,YAAa,CAAA,UAAA;AACxE,EAAA,IAAI,YAAa,CAAA,MAAA,EAAqB,YAAA,CAAA,QAAQ,IAAI,YAAa,CAAA,MAAA;AAC/D,EAAA,IAAI,YAAa,CAAA,MAAA,EAAqB,YAAA,CAAA,QAAQ,IAAI,YAAa,CAAA,MAAA;AAE/D,EACE,uBAAA,GAAA,CAAC,YAAS,KAAM,EAAA,mBAAA,EACd,8BAAC,uBAAwB,EAAA,EAAA,QAAA,EAAU,cAAc,CACnD,EAAA,CAAA;AAEJ;;;;"}