feat(appstore,workspace): add App Store upgrade progress tracking and interactive workspace processes
This commit is contained in:
@@ -146,6 +146,7 @@ export class ObViewServices extends DeesElement {
|
||||
accessor appStoreState: appstate.IAppStoreState = {
|
||||
apps: [],
|
||||
upgradeableServices: [],
|
||||
upgradeOperations: [],
|
||||
};
|
||||
|
||||
constructor() {
|
||||
@@ -227,6 +228,7 @@ export class ObViewServices extends DeesElement {
|
||||
appstate.servicesStatePart.dispatchAction(appstate.fetchServicesAction, null),
|
||||
appstate.servicesStatePart.dispatchAction(appstate.fetchPlatformServicesAction, null),
|
||||
appstate.appStoreStatePart.dispatchAction(appstate.fetchUpgradeableAppStoreServicesAction, null),
|
||||
appstate.appStoreStatePart.dispatchAction(appstate.fetchAppStoreUpgradeOperationsAction, null),
|
||||
]);
|
||||
|
||||
// If a platform service was selected from the dashboard, navigate to its detail
|
||||
@@ -471,9 +473,21 @@ export class ObViewServices extends DeesElement {
|
||||
const upgradeInfo = service
|
||||
? this.appStoreState.upgradeableServices.find((u) => u.serviceName === service.name)
|
||||
: null;
|
||||
const upgradeOperation = service
|
||||
? this.appStoreState.upgradeOperations.find((operation) => {
|
||||
return operation.serviceName === service.name && operation.status === 'running';
|
||||
})
|
||||
: null;
|
||||
const latestUpgradeOperation = service
|
||||
? this.appStoreState.upgradeOperations.find((operation) => operation.serviceName === service.name)
|
||||
: null;
|
||||
|
||||
return html`
|
||||
<ob-sectionheading>Service Details</ob-sectionheading>
|
||||
${upgradeOperation ? this.renderUpgradeOperation(upgradeOperation) : ''}
|
||||
${!upgradeOperation && latestUpgradeOperation?.status === 'failed'
|
||||
? this.renderUpgradeOperation(latestUpgradeOperation)
|
||||
: ''}
|
||||
${upgradeInfo ? html`
|
||||
<div style="
|
||||
background: linear-gradient(135deg, rgba(59, 130, 246, 0.1), rgba(139, 92, 246, 0.1));
|
||||
@@ -496,18 +510,14 @@ export class ObViewServices extends DeesElement {
|
||||
<button
|
||||
class="deploy-button"
|
||||
style="padding: 8px 16px; font-size: 13px;"
|
||||
?disabled=${Boolean(upgradeOperation)}
|
||||
@click=${async () => {
|
||||
await appstate.appStoreStatePart.dispatchAction(appstate.upgradeAppStoreServiceAction, {
|
||||
serviceName: upgradeInfo.serviceName,
|
||||
targetVersion: upgradeInfo.latestVersion,
|
||||
});
|
||||
// Refresh service data
|
||||
appstate.servicesStatePart.dispatchAction(appstate.fetchServiceAction, {
|
||||
name: upgradeInfo.serviceName,
|
||||
});
|
||||
appstate.servicesStatePart.dispatchAction(appstate.fetchServicesAction, null);
|
||||
}}
|
||||
>Upgrade</button>
|
||||
>${upgradeOperation ? 'Upgrading...' : 'Upgrade'}</button>
|
||||
</div>
|
||||
` : ''}
|
||||
<sz-service-detail-view
|
||||
@@ -544,6 +554,53 @@ export class ObViewServices extends DeesElement {
|
||||
`;
|
||||
}
|
||||
|
||||
private renderUpgradeOperation(
|
||||
operationArg: interfaces.requests.IAppStoreUpgradeOperation,
|
||||
): TemplateResult {
|
||||
const color = operationArg.status === 'failed' ? '#f87171' : '#60a5fa';
|
||||
return html`
|
||||
<div style="
|
||||
background: var(--ci-shade-1, #09090b);
|
||||
border: 1px solid ${color};
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
margin-bottom: 16px;
|
||||
">
|
||||
<div style="display: flex; justify-content: space-between; gap: 16px; align-items: flex-start;">
|
||||
<div>
|
||||
<div style="font-size: 14px; font-weight: 600; color: var(--ci-shade-7, #e4e4e7);">
|
||||
Upgrade ${operationArg.fromVersion} → ${operationArg.targetVersion}: ${operationArg.step}
|
||||
</div>
|
||||
<div style="font-size: 12px; color: var(--ci-shade-4, #71717a); margin-top: 4px;">
|
||||
${operationArg.status === 'running' ? 'Operation is running in the background.' : operationArg.error || 'Operation finished.'}
|
||||
</div>
|
||||
</div>
|
||||
<span style="font-size: 12px; color: ${color}; text-transform: uppercase; letter-spacing: 0.04em;">
|
||||
${operationArg.status}
|
||||
</span>
|
||||
</div>
|
||||
<div style="
|
||||
margin-top: 12px;
|
||||
padding: 10px 12px;
|
||||
background: var(--ci-shade-0, #030305);
|
||||
border-radius: 6px;
|
||||
color: var(--ci-shade-5, #a1a1aa);
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
max-height: 130px;
|
||||
overflow: auto;
|
||||
white-space: pre-wrap;
|
||||
">${operationArg.progressLines.slice(-8).join('\n')}</div>
|
||||
${operationArg.warnings.length > 0 ? html`
|
||||
<div style="margin-top: 10px; color: #fbbf24; font-size: 12px;">
|
||||
${operationArg.warnings.join(' | ')}
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
private renderBackupsView(): TemplateResult {
|
||||
return html`
|
||||
<ob-sectionheading>Backups</ob-sectionheading>
|
||||
|
||||
Reference in New Issue
Block a user