diff --git a/changelog.md b/changelog.md index ae5702a..4e7bd56 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,16 @@ ## Pending +- remove redundant card wrappers around Cloudly tables (ui) + - Lets `dees-table` provide its own card shell in service, image, and task history views. + - Moves the live deployment refresh action into the table header actions. + +### Fixes + +- remove redundant wrappers around Cloudly tables (ui) + - Let dees-table provide its own card shell in service, image, and task history views. + - Move the live deployments refresh action into the deployments table header actions. + - Bump @types/node to ^25.9.1. ## 2026-05-26 - 6.3.0 diff --git a/package.json b/package.json index cbaf393..663d0c3 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "@git.zone/tstest": "^3.6.6", "@git.zone/tswatch": "^3.3.5", "@push.rocks/smartnetwork": "^4.7.1", - "@types/node": "^25.9.0" + "@types/node": "^25.9.1" }, "dependencies": { "@api.global/typedrequest": "3.3.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f85066f..a9363c7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -178,8 +178,8 @@ importers: specifier: ^4.7.1 version: 4.7.1 '@types/node': - specifier: ^25.9.0 - version: 25.9.0 + specifier: ^25.9.1 + version: 25.9.1 packages: @@ -2308,11 +2308,11 @@ packages: '@types/node@18.19.130': resolution: {integrity: sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==} - '@types/node@22.19.18': - resolution: {integrity: sha512-9v00a+dn2yWVsYDEunWC4g/TcRKVq3r8N5FuZp7u0SGrPvdN9c2yXI9bBuf5Fl0hNCb+QTIePTn5pJs2pwBOQQ==} + '@types/node@22.19.19': + resolution: {integrity: sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew==} - '@types/node@25.9.0': - resolution: {integrity: sha512-AOQwYUNolgy3VosiRqXrACUXTN8nJUtPl7FJXMqZVyxiiCLhQuG3jXKvCS1ALr+Y2OmZhzzLVlYPEqJaiqkaJQ==} + '@types/node@25.9.1': + resolution: {integrity: sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==} '@types/randomatic@3.1.5': resolution: {integrity: sha512-VCwCTw6qh1pRRw+5rNTAwqPmf6A+hdrkdM7dBpZVmhl7g+em3ONXlYK/bWPVKqVGMWgP0d1bog8Vc/X6zRwRRQ==} @@ -5735,7 +5735,7 @@ snapshots: '@happy-dom/global-registrator@20.9.0': dependencies: - '@types/node': 25.9.0 + '@types/node': 25.9.1 happy-dom: 20.9.0 transitivePeerDependencies: - bufferutil @@ -5855,7 +5855,7 @@ snapshots: '@inquirer/figures': 1.0.15 '@inquirer/type': 2.0.0 '@types/mute-stream': 0.0.4 - '@types/node': 22.19.18 + '@types/node': 22.19.19 '@types/wrap-ansi': 3.0.0 ansi-escapes: 4.3.2 cli-width: 4.1.0 @@ -7915,7 +7915,7 @@ snapshots: '@types/clean-css@4.2.11': dependencies: - '@types/node': 25.9.0 + '@types/node': 25.9.1 source-map: 0.6.1 '@types/debug@4.1.13': @@ -7931,7 +7931,7 @@ snapshots: '@types/fs-extra@11.0.4': dependencies: '@types/jsonfile': 6.1.4 - '@types/node': 25.9.0 + '@types/node': 25.9.1 '@types/hast@3.0.4': dependencies: @@ -7947,12 +7947,12 @@ snapshots: '@types/jsonfile@6.1.4': dependencies: - '@types/node': 25.9.0 + '@types/node': 25.9.1 '@types/jsonwebtoken@9.0.10': dependencies: '@types/ms': 2.1.0 - '@types/node': 25.9.0 + '@types/node': 25.9.1 '@types/linkify-it@5.0.0': {} @@ -7973,16 +7973,16 @@ snapshots: '@types/mute-stream@0.0.4': dependencies: - '@types/node': 25.9.0 + '@types/node': 25.9.1 '@types/node-fetch@2.6.13': dependencies: - '@types/node': 25.9.0 + '@types/node': 25.9.1 form-data: 4.0.5 '@types/node-forge@1.3.14': dependencies: - '@types/node': 25.9.0 + '@types/node': 25.9.1 '@types/node@16.9.1': {} @@ -7990,11 +7990,11 @@ snapshots: dependencies: undici-types: 5.26.5 - '@types/node@22.19.18': + '@types/node@22.19.19': dependencies: undici-types: 6.21.0 - '@types/node@25.9.0': + '@types/node@25.9.1': dependencies: undici-types: 7.24.6 @@ -8012,7 +8012,7 @@ snapshots: '@types/through2@2.0.41': dependencies: - '@types/node': 25.9.0 + '@types/node': 25.9.1 '@types/trusted-types@2.0.7': {} @@ -8040,11 +8040,11 @@ snapshots: '@types/ws@8.18.1': dependencies: - '@types/node': 25.9.0 + '@types/node': 25.9.1 '@types/yauzl@2.10.3': dependencies: - '@types/node': 25.9.0 + '@types/node': 25.9.1 optional: true '@ungap/structured-clone@1.3.1': {} @@ -8780,7 +8780,7 @@ snapshots: happy-dom@20.9.0: dependencies: - '@types/node': 25.9.0 + '@types/node': 25.9.1 '@types/whatwg-mimetype': 3.0.2 '@types/ws': 8.18.1 entities: 7.0.1 diff --git a/ts_web/elements/views/images/index.ts b/ts_web/elements/views/images/index.ts index 1d62ed7..187114e 100644 --- a/ts_web/elements/views/images/index.ts +++ b/ts_web/elements/views/images/index.ts @@ -42,8 +42,8 @@ export class CloudlyViewImages extends DeesElement { .detail-title { margin: 0; font-size: 26px; font-weight: 700; color: var(--ci-shade-7, #e4e4e7); } .detail-subtitle { margin-top: 6px; color: var(--ci-shade-4, #71717a); font-size: 14px; overflow-wrap: anywhere; } .back-button { border: 1px solid var(--ci-shade-2, #27272a); border-radius: 7px; padding: 9px 13px; font-size: 13px; cursor: pointer; background: var(--ci-shade-1, #09090b); color: var(--ci-shade-7, #e4e4e7); } - .summary-card, .detail-card { background: var(--ci-shade-1, #09090b); border: 1px solid var(--ci-shade-2, #27272a); border-radius: 9px; padding: 16px; } - .spaced-card { margin-top: 14px; } + .detail-card { background: var(--ci-shade-1, #09090b); border: 1px solid var(--ci-shade-2, #27272a); border-radius: 9px; padding: 16px; } + .spaced-table, .spaced-card { margin-top: 14px; } .details-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-top: 14px; } .section-title { font-size: 14px; font-weight: 700; color: var(--ci-shade-7, #e4e4e7); margin-bottom: 10px; } .kv-list { display: grid; gap: 8px; } @@ -172,43 +172,43 @@ export class CloudlyViewImages extends DeesElement { -
-
Versions
+ ({ + Version: versionArg.versionString, + Source: this.renderSourceBadge(versionArg.source), + Size: this.formatBytes(versionArg.size), + Digest: versionArg.digest || '-', + Repository: versionArg.registryRepository || '-', + Tag: versionArg.registryTag || '-', + Storage: versionArg.storagePath || '-', + Created: this.formatDate(versionArg.createdAt), + })} + > + + ${servicesUsingImage.length ? html` ({ - Version: versionArg.versionString, - Source: this.renderSourceBadge(versionArg.source), - Size: this.formatBytes(versionArg.size), - Digest: versionArg.digest || '-', - Repository: versionArg.registryRepository || '-', - Tag: versionArg.registryTag || '-', - Storage: versionArg.storagePath || '-', - Created: this.formatDate(versionArg.createdAt), + class="spaced-table" + .heading1=${'Service Usage'} + .heading2=${'Services currently configured with this image ID'} + .data=${servicesUsingImage} + .displayFunction=${(serviceArg: plugins.interfaces.data.IService) => ({ + Name: serviceArg.data.name, + Version: serviceArg.data.imageVersion || '-', + Category: serviceArg.data.serviceCategory || 'workload', + Strategy: serviceArg.data.deploymentStrategy || 'custom', + Domains: serviceArg.data.domains?.map((domainArg) => domainArg.name).join(', ') || '-', + Deployments: serviceArg.data.deploymentIds?.length || 0, })} > -
- -
-
Services Using This Image
- ${servicesUsingImage.length ? html` - ({ - Name: serviceArg.data.name, - Version: serviceArg.data.imageVersion || '-', - Category: serviceArg.data.serviceCategory || 'workload', - Strategy: serviceArg.data.deploymentStrategy || 'custom', - Domains: serviceArg.data.domains?.map((domainArg) => domainArg.name).join(', ') || '-', - Deployments: serviceArg.data.deploymentIds?.length || 0, - })} - > - ` : html`
No services currently reference this image.
`} -
+ ` : html` +
+
Services Using This Image
+
No services currently reference this image.
+
+ `}
diff --git a/ts_web/elements/views/services/index.ts b/ts_web/elements/views/services/index.ts index 68c1d76..0ac42d8 100644 --- a/ts_web/elements/views/services/index.ts +++ b/ts_web/elements/views/services/index.ts @@ -368,66 +368,65 @@ export class CloudlyViewServices extends DeesElement {
-
-
-
-
Deployments
-
Container-level runtime actions happen here.
-
- -
- ${this.deploymentsLoading ? html`
Loading deployments...
` : html` - ({ - Status: this.renderStatusBadge(deploymentArg.status), - Node: deploymentArg.nodeName || deploymentArg.nodeId || '-', - Slot: deploymentArg.slot || '-', - Version: deploymentArg.version || service.data.imageVersion, - Container: deploymentArg.containerId ? deploymentArg.containerId.slice(0, 12) : '-', - CPU: deploymentArg.resourceUsage ? `${deploymentArg.resourceUsage.cpuUsagePercent.toFixed(1)}%` : '-', - Memory: deploymentArg.resourceUsage ? `${deploymentArg.resourceUsage.memoryUsedMB} MB` : '-', - Updated: deploymentArg.updatedAt ? new Date(deploymentArg.updatedAt).toLocaleString() : '-', - })} - .dataActions=${[ - { - name: 'Details', - iconName: 'lucide:Eye', - type: ['contextmenu', 'inRow', 'doubleClick'], - actionFunc: async (actionDataArg: any) => { - await this.showDeploymentDetailsModal(actionDataArg.item); - }, + ${this.deploymentsLoading ? html`
Loading deployments...
` : html` + ({ + Status: this.renderStatusBadge(deploymentArg.status), + Node: deploymentArg.nodeName || deploymentArg.nodeId || '-', + Slot: deploymentArg.slot || '-', + Version: deploymentArg.version || service.data.imageVersion, + Container: deploymentArg.containerId ? deploymentArg.containerId.slice(0, 12) : '-', + CPU: deploymentArg.resourceUsage ? `${deploymentArg.resourceUsage.cpuUsagePercent.toFixed(1)}%` : '-', + Memory: deploymentArg.resourceUsage ? `${deploymentArg.resourceUsage.memoryUsedMB} MB` : '-', + Updated: deploymentArg.updatedAt ? new Date(deploymentArg.updatedAt).toLocaleString() : '-', + })} + .dataActions=${[ + { + name: 'Refresh', + iconName: 'refresh-cw', + type: ['header'], + actionFunc: async () => { + await this.loadDeploymentsForService(service); }, - { - name: 'Open IDE', - iconName: 'terminal', - type: ['contextmenu', 'inRow'], - actionFunc: async (actionDataArg: any) => { - await this.openDeploymentWorkspace(actionDataArg.item); - }, + }, + { + name: 'Details', + iconName: 'lucide:Eye', + type: ['contextmenu', 'inRow', 'doubleClick'], + actionFunc: async (actionDataArg: any) => { + await this.showDeploymentDetailsModal(actionDataArg.item); }, - { - name: 'Restart', - iconName: 'refresh-cw', - type: ['contextmenu', 'inRow'], - actionFunc: async (actionDataArg: any) => { - await this.restartDeployment(actionDataArg.item); - }, + }, + { + name: 'Open IDE', + iconName: 'terminal', + type: ['contextmenu', 'inRow'], + actionFunc: async (actionDataArg: any) => { + await this.openDeploymentWorkspace(actionDataArg.item); }, - { - name: 'Kill Container', - iconName: 'skull', - type: ['contextmenu', 'inRow'], - actionFunc: async (actionDataArg: any) => { - await this.confirmKillDeployment(actionDataArg.item); - }, + }, + { + name: 'Restart', + iconName: 'refresh-cw', + type: ['contextmenu', 'inRow'], + actionFunc: async (actionDataArg: any) => { + await this.restartDeployment(actionDataArg.item); }, - ] as plugins.deesCatalog.ITableAction[]} - > - `} -
+ }, + { + name: 'Kill Container', + iconName: 'skull', + type: ['contextmenu', 'inRow'], + actionFunc: async (actionDataArg: any) => { + await this.confirmKillDeployment(actionDataArg.item); + }, + }, + ] as plugins.deesCatalog.ITableAction[]} + > + `}
diff --git a/ts_web/elements/views/tasks/index.ts b/ts_web/elements/views/tasks/index.ts index 3b6dc0f..cb71918 100644 --- a/ts_web/elements/views/tasks/index.ts +++ b/ts_web/elements/views/tasks/index.ts @@ -266,32 +266,30 @@ export class CloudlyViewTasks extends DeesElement { Execution History - - { - return { - Task: itemArg.data.taskName, - Status: html`${itemArg.data.status}`, - 'Started At': formatDate(itemArg.data.startedAt), - Duration: itemArg.data.duration ? formatDuration(itemArg.data.duration) : '-', - 'Triggered By': itemArg.data.triggeredBy, - Logs: itemArg.data.logs?.length || 0, - } as any; - }} - .actionFunction=${async (itemArg: plugins.interfaces.data.ITaskExecution) => { - const actions: any[] = [ - { name: 'View Details', iconName: 'lucide:Eye', type: ['inRow'], actionFunc: async () => { this.selectedExecution = itemArg; } } - ]; - if (itemArg.data.status === 'running') { - actions.push({ name: 'Cancel', iconName: 'lucide:SquareX', type: ['inRow'], actionFunc: async () => { await appstate.dataState.dispatchAction(appstate.taskActions.cancelTask, { executionId: itemArg.id }); await this.loadExecutionsWithFilter(); } }); - } - return actions; - }} - > - + { + return { + Task: itemArg.data.taskName, + Status: html`${itemArg.data.status}`, + 'Started At': formatDate(itemArg.data.startedAt), + Duration: itemArg.data.duration ? formatDuration(itemArg.data.duration) : '-', + 'Triggered By': itemArg.data.triggeredBy, + Logs: itemArg.data.logs?.length || 0, + } as any; + }} + .actionFunction=${async (itemArg: plugins.interfaces.data.ITaskExecution) => { + const actions: any[] = [ + { name: 'View Details', iconName: 'lucide:Eye', type: ['inRow'], actionFunc: async () => { this.selectedExecution = itemArg; } } + ]; + if (itemArg.data.status === 'running') { + actions.push({ name: 'Cancel', iconName: 'lucide:SquareX', type: ['inRow'], actionFunc: async () => { await appstate.dataState.dispatchAction(appstate.taskActions.cancelTask, { executionId: itemArg.id }); await this.loadExecutionsWithFilter(); } }); + } + return actions; + }} + > ${this.selectedExecution ? html` Execution Details