mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 20:14:49 +00:00
rework status display in service show
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
<pwa-back-button></pwa-back-button>
|
<pwa-back-button></pwa-back-button>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
<ion-title>Properties</ion-title>
|
<ion-title>Properties</ion-title>
|
||||||
<ion-buttons slot="end">
|
<ion-buttons *ngIf="!loading" slot="end">
|
||||||
<ion-button (click)="refresh()">
|
<ion-button (click)="refresh()">
|
||||||
<ion-icon slot="start" name="refresh"></ion-icon>
|
<ion-icon slot="start" name="refresh"></ion-icon>
|
||||||
Refresh
|
Refresh
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
<ion-button *ngIf="prop.value.masked" fill="clear" (click)="toggleMask(prop.key)">
|
<ion-button *ngIf="prop.value.masked" fill="clear" (click)="toggleMask(prop.key)">
|
||||||
<ion-icon slot="icon-only" [name]="unmasked[prop.key] ? 'eye-off-outline' : 'eye-outline'" [color]="unmasked[prop.key] ? 'danger' : 'dark'" size="small"></ion-icon>
|
<ion-icon slot="icon-only" [name]="unmasked[prop.key] ? 'eye-off-outline' : 'eye-outline'" [color]="unmasked[prop.key] ? 'danger' : 'dark'" size="small"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
<ion-button *ngIf="prop.value.qr" fill="clear" (click)="showQR(prop.value.value, $event)">
|
<ion-button *ngIf="prop.value.qr" fill="clear" (click)="showQR(prop.value.value)">
|
||||||
<ion-icon slot="icon-only" name="qr-code-outline" size="small"></ion-icon>
|
<ion-icon slot="icon-only" name="qr-code-outline" size="small"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
<ion-button *ngIf="prop.value.copyable" fill="clear" (click)="copy(prop.value.value)">
|
<ion-button *ngIf="prop.value.copyable" fill="clear" (click)="copy(prop.value.value)">
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { ActivatedRoute } from '@angular/router'
|
|||||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||||
import { Subscription } from 'rxjs'
|
import { Subscription } from 'rxjs'
|
||||||
import { copyToClipboard } from 'src/app/util/web.util'
|
import { copyToClipboard } from 'src/app/util/web.util'
|
||||||
import { AlertController, IonContent, NavController, PopoverController, ToastController } from '@ionic/angular'
|
import { AlertController, IonContent, ModalController, NavController, ToastController } from '@ionic/angular'
|
||||||
import { PackageProperties } from 'src/app/util/properties.util'
|
import { PackageProperties } from 'src/app/util/properties.util'
|
||||||
import { QRComponent } from 'src/app/components/qr/qr.component'
|
import { QRComponent } from 'src/app/components/qr/qr.component'
|
||||||
import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
|
import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
|
||||||
@@ -34,7 +34,7 @@ export class AppPropertiesPage {
|
|||||||
private readonly errToast: ErrorToastService,
|
private readonly errToast: ErrorToastService,
|
||||||
private readonly alertCtrl: AlertController,
|
private readonly alertCtrl: AlertController,
|
||||||
private readonly toastCtrl: ToastController,
|
private readonly toastCtrl: ToastController,
|
||||||
private readonly popoverCtrl: PopoverController,
|
private readonly modalCtrl: ModalController,
|
||||||
private readonly navCtrl: NavController,
|
private readonly navCtrl: NavController,
|
||||||
private readonly patch: PatchDbService,
|
private readonly patch: PatchDbService,
|
||||||
) { }
|
) { }
|
||||||
@@ -100,16 +100,15 @@ export class AppPropertiesPage {
|
|||||||
await toast.present()
|
await toast.present()
|
||||||
}
|
}
|
||||||
|
|
||||||
async showQR (text: string, ev: any): Promise<void> {
|
async showQR (text: string): Promise<void> {
|
||||||
const popover = await this.popoverCtrl.create({
|
const modal = await this.modalCtrl.create({
|
||||||
component: QRComponent,
|
component: QRComponent,
|
||||||
cssClass: 'qr-popover',
|
|
||||||
event: ev,
|
|
||||||
componentProps: {
|
componentProps: {
|
||||||
text,
|
text,
|
||||||
},
|
},
|
||||||
|
cssClass: 'qr-modal',
|
||||||
})
|
})
|
||||||
return await popover.present()
|
await modal.present()
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleMask (key: string) {
|
toggleMask (key: string) {
|
||||||
|
|||||||
@@ -19,19 +19,11 @@
|
|||||||
|
|
||||||
<ion-content>
|
<ion-content>
|
||||||
<ion-item-group>
|
<ion-item-group>
|
||||||
<!-- ** always ** -->
|
<!-- ** status ** -->
|
||||||
<ion-item-divider>Status</ion-item-divider>
|
<ion-item-divider>Status</ion-item-divider>
|
||||||
<ion-item>
|
<ion-item>
|
||||||
<ion-label style="overflow: visible;">
|
<ion-label style="overflow: visible;">
|
||||||
<status [disconnected]="connectionFailure" size="x-large" weight="500" [rendering]="PR[statuses.primary]"></status>
|
<status [disconnected]="connectionFailure" size="x-large" weight="500" [rendering]="PR[statuses.primary]"></status>
|
||||||
<span *ngIf="statuses.dependency">
|
|
||||||
Dependencies:
|
|
||||||
<status [disconnected]="connectionFailure" size="medium" weight="500" [rendering]="DR[statuses.dependency]"></status>
|
|
||||||
</span>
|
|
||||||
<span *ngIf="statuses.health">
|
|
||||||
Health:
|
|
||||||
<status [disconnected]="connectionFailure" size="medium" weight="500" [rendering]="HR[statuses.health]"></status>
|
|
||||||
</span>
|
|
||||||
</ion-label>
|
</ion-label>
|
||||||
<ng-container *ngIf="pkg.state === PackageState.Installed && !connectionFailure">
|
<ng-container *ngIf="pkg.state === PackageState.Installed && !connectionFailure">
|
||||||
<ion-button slot="end" class="action-button" *ngIf="pkg.manifest.interfaces | hasUi" [disabled]="!(pkg.state | isLaunchable : pkg.installed.status.main.status : pkg.manifest.interfaces)" (click)="launchUi()">
|
<ion-button slot="end" class="action-button" *ngIf="pkg.manifest.interfaces | hasUi" [disabled]="!(pkg.state | isLaunchable : pkg.installed.status.main.status : pkg.manifest.interfaces)" (click)="launchUi()">
|
||||||
@@ -44,15 +36,11 @@
|
|||||||
<ion-button slot="end" class="action-button" *ngIf="statuses.primary === PS.Running" color="danger" (click)="stop()">
|
<ion-button slot="end" class="action-button" *ngIf="statuses.primary === PS.Running" color="danger" (click)="stop()">
|
||||||
Stop
|
Stop
|
||||||
</ion-button>
|
</ion-button>
|
||||||
<ion-button slot="end" class="action-button" *ngIf="statuses.dependency && status.dependency !== DS.Satisfied" (click)="scrollToRequirements()">
|
<ion-button slot="end" class="action-button" *ngIf="statuses.primary === PS.Stopped && pkg.installed.status.configured && statuses.dependency !== DS.Critical" color="success" (click)="tryStart()">
|
||||||
Fix
|
|
||||||
</ion-button>
|
|
||||||
<ion-button slot="end" class="action-button" *ngIf="statuses.primary === PS.Stopped && statuses.dependency !== DS.Critical" color="success" (click)="tryStart()">
|
|
||||||
Start
|
Start
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<!-- ** installed ** -->
|
<!-- ** installed ** -->
|
||||||
<ng-container *ngIf="pkg.state === PackageState.Installed">
|
<ng-container *ngIf="pkg.state === PackageState.Installed">
|
||||||
<!-- ** !restoring/backing-up ** -->
|
<!-- ** !restoring/backing-up ** -->
|
||||||
@@ -87,55 +75,32 @@
|
|||||||
</ion-item>
|
</ion-item>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
<!-- ** dependencies ** -->
|
||||||
|
<ng-container *ngIf="!(dependencies | empty)">
|
||||||
|
<ion-item-divider>Dependencies</ion-item-divider>
|
||||||
|
<!-- dependencies are a subset of the pkg.manifest.dependencies that are currently required as determined by the service config -->
|
||||||
|
<ion-item button *ngFor="let dep of dependencies | keyvalue" (click)="dep.value.action()">
|
||||||
|
<ion-thumbnail slot="start">
|
||||||
|
<img [src]="dep.value.icon" />
|
||||||
|
</ion-thumbnail>
|
||||||
|
<ion-label>
|
||||||
|
<h2 style="font-family: 'Montserrat'">{{ dep.value.title }}</h2>
|
||||||
|
<p>{{ dep.value.version | displayEmver }}</p>
|
||||||
|
<p><ion-text [color]="!!dep.value.errorText ? 'warning' : 'success'">{{ dep.value.errorText || 'satisfied' }}</ion-text></p>
|
||||||
|
</ion-label>
|
||||||
|
<ion-spinner *ngIf="dep.value.spinnerColor" slot="end" [color]="dep.value.spinnerColor" style="height: 3vh; width: 3vh"></ion-spinner>
|
||||||
|
<ion-button *ngIf="dep.value.actionText" slot="end" fill="clear">
|
||||||
|
{{ dep.value.actionText }}
|
||||||
|
<ion-icon slot="end" name="arrow-forward"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
|
</ion-item>
|
||||||
|
</ng-container>
|
||||||
<!-- ** menu ** -->
|
<!-- ** menu ** -->
|
||||||
<ion-item-divider>Menu</ion-item-divider>
|
<ion-item-divider>Menu</ion-item-divider>
|
||||||
<ion-item button detail *ngFor="let button of buttons" (click)="button.action()">
|
<ion-item button detail *ngFor="let button of buttons" (click)="button.action()">
|
||||||
<ion-icon slot="start" [name]="button.icon"></ion-icon>
|
<ion-icon slot="start" [name]="button.icon"></ion-icon>
|
||||||
<ion-label>{{ button.title }}</ion-label>
|
<ion-label>{{ button.title }}</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<!-- ** dependencies ** -->
|
|
||||||
<ng-container *ngIf="!(currentDependencies | empty)">
|
|
||||||
<ion-item-divider id="dependencies">Dependencies</ion-item-divider>
|
|
||||||
<!-- A current-dependency is a subset of the pkg.manifest.dependencies that is currently required as determined by the service config. -->
|
|
||||||
<ion-item *ngFor="let dep of currentDependencies | keyvalue">
|
|
||||||
<ion-thumbnail slot="start">
|
|
||||||
<img [src]="pkg.installed['dependency-info'][dep.key].icon" />
|
|
||||||
</ion-thumbnail>
|
|
||||||
<ion-label>
|
|
||||||
<h2 style="font-family: 'Montserrat'">{{ pkg.installed['dependency-info'][dep.key].manifest.title }}</h2>
|
|
||||||
<p>{{ pkg.manifest.dependencies[dep.key].version | displayEmver }}</p>
|
|
||||||
<p><ion-text [color]="pkg.installed.status['dependency-errors'][dep.key] ? 'warning' : 'success'">{{ pkg.installed.status['dependency-errors'][dep.key] ? pkg.installed.status['dependency-errors'][dep.key].type : 'satisfied' }}</ion-text></p>
|
|
||||||
</ion-label>
|
|
||||||
|
|
||||||
<ion-button *ngIf="!pkg.installed.status['dependency-errors'][dep.key] || (pkg.installed.status['dependency-errors'][dep.key] && [DependencyErrorType.InterfaceHealthChecksFailed, DependencyErrorType.HealthChecksFailed] | includes : pkg.installed.status['dependency-errors'][dep.key].type)" slot="end" size="small" [routerLink]="['/services', dep.key]">
|
|
||||||
View
|
|
||||||
</ion-button>
|
|
||||||
|
|
||||||
<ng-container *ngIf="pkg.installed.status['dependency-errors'][dep.key]">
|
|
||||||
<ion-button *ngIf="!patch.data['package-data'][dep.key]" slot="end" size="small" (click)="fixDep('install', dep.key)">
|
|
||||||
Install
|
|
||||||
</ion-button>
|
|
||||||
|
|
||||||
<ng-container *ngIf="patch.data['package-data'][dep.key] && patch.data['package-data'][dep.key].state === PackageState.Installed">
|
|
||||||
<ion-button *ngIf="pkg.installed.status['dependency-errors'][dep.key].type === DependencyErrorType.NotRunning" slot="end" size="small" [routerLink]="['/services', dep.key]">
|
|
||||||
Start
|
|
||||||
</ion-button>
|
|
||||||
<ion-button *ngIf="pkg.installed.status['dependency-errors'][dep.key].type === DependencyErrorType.IncorrectVersion" slot="end" size="small" (click)="fixDep('update', dep.key)">
|
|
||||||
Update
|
|
||||||
</ion-button>
|
|
||||||
<ion-button *ngIf="pkg.installed.status['dependency-errors'][dep.key].type === DependencyErrorType.ConfigUnsatisfied" slot="end" size="small" (click)="fixDep('configure', dep.key)">
|
|
||||||
Configure
|
|
||||||
</ion-button>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<div *ngIf="patch.data['package-data'][dep.key] && patch.data['package-data'][dep.key].state !== PackageState.Installed" slot="end">
|
|
||||||
<ion-spinner [color]="patch.data['package-data'][dep.key].state === PackageState.Removing ? 'danger' : 'primary'" style="height: 3vh; width: 3vh" name="dots"></ion-spinner>
|
|
||||||
</div>
|
|
||||||
</ng-container>
|
|
||||||
</ion-item>
|
|
||||||
</ng-container>
|
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<!-- @TODO better maintenance messaging -->
|
<!-- @TODO better maintenance messaging -->
|
||||||
<ng-template #maintenance>
|
<ng-template #maintenance>
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import { wizardModal } from 'src/app/components/install-wizard/install-wizard.co
|
|||||||
import { WizardBaker } from 'src/app/components/install-wizard/prebaked-wizards'
|
import { WizardBaker } from 'src/app/components/install-wizard/prebaked-wizards'
|
||||||
import { ConfigService } from 'src/app/services/config.service'
|
import { ConfigService } from 'src/app/services/config.service'
|
||||||
import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
|
import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
|
||||||
import { CurrentDependencyInfo, DependencyErrorConfigUnsatisfied, DependencyErrorType, HealthCheckResult, PackageDataEntry, PackageMainStatus, PackageState } from 'src/app/services/patch-db/data-model'
|
import { DependencyErrorConfigUnsatisfied, DependencyErrorType, HealthCheckResult, PackageDataEntry, PackageMainStatus, PackageState } from 'src/app/services/patch-db/data-model'
|
||||||
import { DependencyRendering, DependencyStatus, HealthRendering, HealthStatus, PrimaryRendering, PrimaryStatus, renderPkgStatus } from 'src/app/services/pkg-status-rendering.service'
|
import { DependencyStatus, HealthStatus, PrimaryRendering, PrimaryStatus, renderPkgStatus } from 'src/app/services/pkg-status-rendering.service'
|
||||||
import { ConnectionFailure, ConnectionService } from 'src/app/services/connection.service'
|
import { ConnectionFailure, ConnectionService } from 'src/app/services/connection.service'
|
||||||
import { ErrorToastService } from 'src/app/services/error-toast.service'
|
import { ErrorToastService } from 'src/app/services/error-toast.service'
|
||||||
import { AppConfigPage } from 'src/app/modals/app-config/app-config.page'
|
import { AppConfigPage } from 'src/app/modals/app-config/app-config.page'
|
||||||
@@ -27,16 +27,14 @@ export class AppShowPage {
|
|||||||
Math = Math
|
Math = Math
|
||||||
PS = PrimaryStatus
|
PS = PrimaryStatus
|
||||||
DS = DependencyStatus
|
DS = DependencyStatus
|
||||||
HS = HealthStatus
|
|
||||||
PR = PrimaryRendering
|
PR = PrimaryRendering
|
||||||
DR = DependencyRendering
|
|
||||||
HR = HealthRendering
|
|
||||||
|
|
||||||
pkgId: string
|
pkgId: string
|
||||||
pkg: PackageDataEntry
|
pkg: PackageDataEntry
|
||||||
hideLAN: boolean
|
hideLAN: boolean
|
||||||
buttons: Button[] = []
|
buttons: Button[] = []
|
||||||
currentDependencies: { [id: string]: CurrentDependencyInfo }
|
// currentDependencies: { [id: string]: CurrentDependencyInfo }
|
||||||
|
dependencies: { [id: string]: DependencyInfo } = { }
|
||||||
statuses: {
|
statuses: {
|
||||||
primary: PrimaryStatus
|
primary: PrimaryStatus
|
||||||
dependency: DependencyStatus
|
dependency: DependencyStatus
|
||||||
@@ -61,19 +59,19 @@ export class AppShowPage {
|
|||||||
private readonly wizardBaker: WizardBaker,
|
private readonly wizardBaker: WizardBaker,
|
||||||
private readonly config: ConfigService,
|
private readonly config: ConfigService,
|
||||||
private readonly packageLoadingService: PackageLoadingService,
|
private readonly packageLoadingService: PackageLoadingService,
|
||||||
public readonly patch: PatchDbService,
|
private readonly patch: PatchDbService,
|
||||||
public readonly connectionService: ConnectionService,
|
private readonly connectionService: ConnectionService,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
async ngOnInit () {
|
async ngOnInit () {
|
||||||
this.pkgId = this.route.snapshot.paramMap.get('pkgId')
|
this.pkgId = this.route.snapshot.paramMap.get('pkgId')
|
||||||
this.setValues(this.patch.data['package-data'][this.pkgId])
|
this.setValues(this.patch.data['package-data'])
|
||||||
|
|
||||||
this.subs = [
|
this.subs = [
|
||||||
// 1
|
// 1
|
||||||
this.patch.watch$('package-data', this.pkgId)
|
this.patch.watch$('package-data')
|
||||||
.subscribe(pkg => {
|
.subscribe(pkgs => {
|
||||||
this.setValues(pkg)
|
this.setValues(pkgs)
|
||||||
}),
|
}),
|
||||||
// 2
|
// 2
|
||||||
this.connectionService.watchFailure$()
|
this.connectionService.watchFailure$()
|
||||||
@@ -148,13 +146,6 @@ export class AppShowPage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scrollToRequirements () {
|
|
||||||
const el = document.getElementById('dependencies')
|
|
||||||
if (!el) return
|
|
||||||
let y = el.offsetTop
|
|
||||||
return this.content.scrollToPoint(0, y, 1000)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fixDep (action: 'install' | 'update' | 'configure', id: string): Promise<void> {
|
async fixDep (action: 'install' | 'update' | 'configure', id: string): Promise<void> {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case 'install':
|
case 'install':
|
||||||
@@ -175,22 +166,87 @@ export class AppShowPage {
|
|||||||
await modal.present()
|
await modal.present()
|
||||||
}
|
}
|
||||||
|
|
||||||
private setValues (pkg: PackageDataEntry): void {
|
private setValues (pkgs: { [id: string]: PackageDataEntry }): void {
|
||||||
this.pkg = pkg
|
this.pkg = pkgs[this.pkgId]
|
||||||
this.installProgress = !isEmptyObject(pkg['install-progress']) ? this.packageLoadingService.transform(pkg['install-progress']) : undefined
|
this.installProgress = !isEmptyObject(this.pkg['install-progress']) ? this.packageLoadingService.transform(this.pkg['install-progress']) : undefined
|
||||||
// we can safely ignore any current dependencies that are not defined in the service manifest
|
this.statuses = renderPkgStatus(this.pkg)
|
||||||
this.currentDependencies = { }
|
|
||||||
Object.entries(pkg.installed?.['current-dependencies'] || { }).forEach(([id, value]) => {
|
if (!this.pkg.installed) {
|
||||||
if (pkg.manifest.dependencies[id]) {
|
this.dependencies = { }
|
||||||
this.currentDependencies[id] = value
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (pkg.installed?.status.main.status === PackageMainStatus.Running) {
|
|
||||||
this.healthChecks = { ...pkg.installed.status.main.health }
|
|
||||||
} else {
|
|
||||||
this.healthChecks = { }
|
this.healthChecks = { }
|
||||||
|
} else {
|
||||||
|
// ** dependencies
|
||||||
|
Object.keys(this.pkg.installed['current-dependencies'] || { })
|
||||||
|
.forEach(id => {
|
||||||
|
// we can safely ignore any current dependencies that are not defined in the service manifest
|
||||||
|
const manifestDep = this.pkg.manifest.dependencies[id]
|
||||||
|
if (manifestDep) {
|
||||||
|
let errorText = ''
|
||||||
|
let spinnerColor = ''
|
||||||
|
let actionText = 'View'
|
||||||
|
let action: () => any = () => this.navCtrl.navigateForward(`/services/${id}`)
|
||||||
|
|
||||||
|
const error = this.pkg.installed.status['dependency-errors'][id] || null
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
const localDep = pkgs[id]
|
||||||
|
// health checks failed
|
||||||
|
if ([DependencyErrorType.InterfaceHealthChecksFailed, DependencyErrorType.HealthChecksFailed].includes(error.type)) {
|
||||||
|
errorText = 'Health Check Failed'
|
||||||
|
// not fully installed (same as !localDep?.installed)
|
||||||
|
} else if (error.type === DependencyErrorType.NotInstalled) {
|
||||||
|
if (localDep) {
|
||||||
|
errorText = localDep.state // 'Installing' | 'Removing'
|
||||||
|
} else {
|
||||||
|
errorText = 'Not Installed'
|
||||||
|
actionText = 'Install'
|
||||||
|
action = () => this.fixDep('install', id)
|
||||||
|
}
|
||||||
|
// incorrect version
|
||||||
|
} else if (error.type === DependencyErrorType.IncorrectVersion) {
|
||||||
|
if (localDep) {
|
||||||
|
errorText = localDep.state // 'Updating' | 'Removing'
|
||||||
|
} else {
|
||||||
|
errorText = 'Incorrect Version'
|
||||||
|
actionText = 'Update'
|
||||||
|
action = () => this.fixDep('update', id)
|
||||||
|
}
|
||||||
|
// not running
|
||||||
|
} else if (error.type === DependencyErrorType.NotRunning) {
|
||||||
|
errorText = 'Not Running'
|
||||||
|
actionText = 'Start'
|
||||||
|
// config unsatisfied
|
||||||
|
} else if (error.type === DependencyErrorType.ConfigUnsatisfied) {
|
||||||
|
errorText = 'Config Not Satisfied'
|
||||||
|
actionText = 'Auto Config'
|
||||||
|
action = () => this.fixDep('configure', id)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (localDep && localDep.state !== PackageState.Installed) {
|
||||||
|
spinnerColor = localDep.state === PackageState.Removing ? 'danger' : 'primary'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.dependencies[id]) this.dependencies[id] = { } as any
|
||||||
|
|
||||||
|
const depInfo = this.pkg.installed['dependency-info'][id]
|
||||||
|
|
||||||
|
this.dependencies[id].title = depInfo.manifest.title
|
||||||
|
this.dependencies[id].icon = depInfo.icon
|
||||||
|
this.dependencies[id].version = manifestDep.version
|
||||||
|
this.dependencies[id].errorText = errorText
|
||||||
|
this.dependencies[id].actionText = actionText
|
||||||
|
this.dependencies[id].spinnerColor = spinnerColor
|
||||||
|
this.dependencies[id].action = action
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// ** health
|
||||||
|
if (this.pkg.installed.status.main.status === PackageMainStatus.Running) {
|
||||||
|
this.healthChecks = { ...this.pkg.installed.status.main.health }
|
||||||
|
} else {
|
||||||
|
this.healthChecks = { }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.statuses = renderPkgStatus(pkg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async installDep (depId: string): Promise<void> {
|
private async installDep (depId: string): Promise<void> {
|
||||||
@@ -334,6 +390,16 @@ export class AppShowPage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface DependencyInfo {
|
||||||
|
title: string
|
||||||
|
icon: string
|
||||||
|
version: string
|
||||||
|
errorText: string
|
||||||
|
spinnerColor: string
|
||||||
|
actionText: string
|
||||||
|
action: () => any
|
||||||
|
}
|
||||||
|
|
||||||
interface Button {
|
interface Button {
|
||||||
title: string
|
title: string
|
||||||
icon: string
|
icon: string
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<ion-buttons slot="start">
|
<ion-buttons slot="start">
|
||||||
<pwa-back-button></pwa-back-button>
|
<pwa-back-button></pwa-back-button>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
<ion-title>Listing</ion-title>
|
<ion-title>Marketplace Listing</ion-title>
|
||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
|
|
||||||
|
|||||||
@@ -6,13 +6,14 @@ export function renderPkgStatus (pkg: PackageDataEntry): {
|
|||||||
dependency: DependencyStatus | null,
|
dependency: DependencyStatus | null,
|
||||||
health: HealthStatus | null
|
health: HealthStatus | null
|
||||||
} {
|
} {
|
||||||
|
console.log('PKGPKG', pkg)
|
||||||
let primary: PrimaryStatus
|
let primary: PrimaryStatus
|
||||||
let dependency: DependencyStatus | null = null
|
let dependency: DependencyStatus | null = null
|
||||||
let health: HealthStatus | null = null
|
let health: HealthStatus | null = null
|
||||||
|
|
||||||
if (pkg.state === PackageState.Installed) {
|
if (pkg.state === PackageState.Installed) {
|
||||||
primary = pkg.installed.status.main.status as string as PrimaryStatus
|
primary = pkg.installed.status.main.status as string as PrimaryStatus
|
||||||
dependency = getDependencyStatus(pkg.installed)
|
dependency = getDependencyStatus(pkg)
|
||||||
health = getHealthStatus(pkg.installed.status)
|
health = getHealthStatus(pkg.installed.status)
|
||||||
} else {
|
} else {
|
||||||
primary = pkg.state as string as PrimaryStatus
|
primary = pkg.state as string as PrimaryStatus
|
||||||
@@ -21,11 +22,11 @@ export function renderPkgStatus (pkg: PackageDataEntry): {
|
|||||||
return { primary, dependency, health }
|
return { primary, dependency, health }
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDependencyStatus (pkg: InstalledPackageDataEntry): DependencyStatus {
|
function getDependencyStatus (pkg: PackageDataEntry): DependencyStatus {
|
||||||
console.log('pkg', pkg)
|
const installed = pkg.installed
|
||||||
if (isEmptyObject(pkg['current-dependencies'])) return null
|
if (isEmptyObject(installed['current-dependencies'])) return null
|
||||||
|
|
||||||
const pkgIds = Object.keys(pkg.status['dependency-errors'])
|
const pkgIds = Object.keys(installed.status['dependency-errors'])
|
||||||
|
|
||||||
for (let pkgId of pkgIds) {
|
for (let pkgId of pkgIds) {
|
||||||
if (pkg.manifest.dependencies[pkgId].critical) {
|
if (pkg.manifest.dependencies[pkgId].critical) {
|
||||||
@@ -92,8 +93,8 @@ export const PrimaryRendering: { [key: string]: StatusRendering } = {
|
|||||||
[PrimaryStatus.Installing]: { display: 'Installing', color: 'primary', showDots: true },
|
[PrimaryStatus.Installing]: { display: 'Installing', color: 'primary', showDots: true },
|
||||||
[PrimaryStatus.Updating]: { display: 'Updating', color: 'primary', showDots: true },
|
[PrimaryStatus.Updating]: { display: 'Updating', color: 'primary', showDots: true },
|
||||||
[PrimaryStatus.Removing]: { display: 'Removing', color: 'warning', showDots: true },
|
[PrimaryStatus.Removing]: { display: 'Removing', color: 'warning', showDots: true },
|
||||||
[PrimaryStatus.Stopping]: { display: 'Stopping', color: 'dark', showDots: true },
|
[PrimaryStatus.Stopping]: { display: 'Stopping', color: 'dark-shade', showDots: true },
|
||||||
[PrimaryStatus.Stopped]: { display: 'Stopped', color: 'dark', showDots: false },
|
[PrimaryStatus.Stopped]: { display: 'Stopped', color: 'dark-shade', showDots: false },
|
||||||
[PrimaryStatus.BackingUp]: { display: 'Backing Up', color: 'warning', showDots: true },
|
[PrimaryStatus.BackingUp]: { display: 'Backing Up', color: 'warning', showDots: true },
|
||||||
[PrimaryStatus.Restoring]: { display: 'Restoring', color: 'primary', showDots: true },
|
[PrimaryStatus.Restoring]: { display: 'Restoring', color: 'primary', showDots: true },
|
||||||
[PrimaryStatus.Running]: { display: 'Running', color: 'success', showDots: false },
|
[PrimaryStatus.Running]: { display: 'Running', color: 'success', showDots: false },
|
||||||
|
|||||||
@@ -174,6 +174,15 @@ ion-button {
|
|||||||
box-shadow: 0 0 70px 70px black;
|
box-shadow: 0 0 70px 70px black;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.qr-modal {
|
||||||
|
.modal-wrapper {
|
||||||
|
width: 400px !important;
|
||||||
|
height: 400px !important;
|
||||||
|
top: unset !important;
|
||||||
|
left: unset !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.modal-wrapper {
|
.modal-wrapper {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
height: 90% !important;
|
height: 90% !important;
|
||||||
@@ -236,11 +245,6 @@ ion-slides {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.qr-popover {
|
|
||||||
--width: auto;
|
|
||||||
--background: transparent !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
ion-item-divider {
|
ion-item-divider {
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
--padding-top: 24px;
|
--padding-top: 24px;
|
||||||
|
|||||||
Reference in New Issue
Block a user