mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-31 04:23:40 +00:00
better subscriptions
This commit is contained in:
committed by
Aiden McClelland
parent
aa976e362d
commit
15eb13e156
@@ -5,6 +5,6 @@
|
||||
{{ params.title }}
|
||||
</ion-label>
|
||||
</div>
|
||||
<div class="long-message" [innerHTML]="params.notes | markdown"></div>
|
||||
<div class="long-message" [innerHTML]="params.message | markdown"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -9,8 +9,8 @@ import { Loadable } from '../loadable'
|
||||
})
|
||||
export class AlertComponent implements OnInit, Loadable {
|
||||
@Input() params: {
|
||||
alert: string
|
||||
title: string
|
||||
message: string
|
||||
titleColor: string
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
<div *ngIf="!(loading$ | ngrxPush) && !params.skipCompletionDialogue" class="slide-content">
|
||||
<div *ngIf="!(loading$ | async) && !params.skipCompletionDialogue" class="slide-content">
|
||||
<div style="margin-top: 25px;">
|
||||
<div style="margin: 15px; display: flex; justify-content: center; align-items: center;">
|
||||
<ion-label [color]="$color$ | ngrxPush" style="font-size: xx-large; font-weight: bold;">
|
||||
{{successText}}
|
||||
<ion-label [color]="color$ | async" style="font-size: xx-large; font-weight: bold;">
|
||||
{{ successText }}
|
||||
</ion-label>
|
||||
</div>
|
||||
<div class="long-message">
|
||||
{{summary}}
|
||||
{{ summary }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="loading$ | ngrxPush" class="center-spinner">
|
||||
<div *ngIf="loading$ | async" class="center-spinner">
|
||||
<ion-spinner color="warning" name="lines"></ion-spinner>
|
||||
<ion-label class="long-message">{{label}}</ion-label>
|
||||
</div>
|
||||
@@ -1,42 +1,41 @@
|
||||
<div>
|
||||
<div *ngIf="!(loading$ | ngrxPush)" class="slide-content">
|
||||
<div style="margin-top: 25px;">
|
||||
<div style="margin: 15px; display: flex; justify-content: center; align-items: center;">
|
||||
<ion-label color="warning" style="font-size: xx-large; font-weight: bold;"
|
||||
*ngIf="hasDependentViolation">
|
||||
WARNING
|
||||
</ion-label>
|
||||
<ion-label color="success" style="font-size: x-large; font-weight: bold; text-transform: capitalize;"
|
||||
*ngIf="!hasDependentViolation">
|
||||
READY
|
||||
</ion-label>
|
||||
</div>
|
||||
<div *ngIf="loading$ | async" class="center-spinner">
|
||||
<ion-spinner color="warning" name="lines"></ion-spinner>
|
||||
<ion-label class="long-message">Checking for installed services which depend on {{ params.title }}...</ion-label>
|
||||
</div>
|
||||
|
||||
<div *ngIf="longMessage" class="long-message" >
|
||||
{{longMessage}}
|
||||
</div>
|
||||
<div style="margin: 25px 0px;">
|
||||
<div style="border-width: 0px 0px 1px 0px; font-size: unset; text-align: left; font-weight: bold; margin-left: 13px; border-style: solid; border-color: var(--ion-color-light-tint);"
|
||||
*ngIf="hasDependentViolation"
|
||||
>
|
||||
<ion-text color="warning">Will Stop</ion-text>
|
||||
</div>
|
||||
<ion-item
|
||||
style="--ion-item-background: rgb(0,0,0,0); margin-top: 5px"
|
||||
*ngFor="let dep of dependentBreakages"
|
||||
>
|
||||
<ion-avatar style="position: relative; height: 4vh; width: 4vh" slot="start">
|
||||
<img [src]="dep.iconURL" />
|
||||
</ion-avatar>
|
||||
<ion-label>
|
||||
<h5>{{dep.title}}</h5>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<div *ngIf="!(loading$ | async)" class="slide-content">
|
||||
<div style="margin-top: 25px;">
|
||||
<div style="margin: 15px; display: flex; justify-content: center; align-items: center;">
|
||||
<ion-label color="warning" style="font-size: xx-large; font-weight: bold;"
|
||||
*ngIf="hasDependentViolation">
|
||||
WARNING
|
||||
</ion-label>
|
||||
<ion-label color="success" style="font-size: x-large; font-weight: bold; text-transform: capitalize;"
|
||||
*ngIf="!hasDependentViolation">
|
||||
READY
|
||||
</ion-label>
|
||||
</div>
|
||||
|
||||
<div *ngIf="longMessage" class="long-message" >
|
||||
{{ longMessage }}
|
||||
</div>
|
||||
<div style="margin: 25px 0px;">
|
||||
<div style="border-width: 0px 0px 1px 0px; font-size: unset; text-align: left; font-weight: bold; margin-left: 13px; border-style: solid; border-color: var(--ion-color-light-tint);"
|
||||
*ngIf="hasDependentViolation"
|
||||
>
|
||||
<ion-text color="warning">Will Stop</ion-text>
|
||||
</div>
|
||||
<ion-item
|
||||
style="--ion-item-background: rgb(0,0,0,0); margin-top: 5px"
|
||||
*ngFor="let dep of dependentBreakages | keyvalue"
|
||||
>
|
||||
<ion-avatar style="position: relative; height: 4vh; width: 4vh" slot="start">
|
||||
<img [src]="dep.value.iconURL" />
|
||||
</ion-avatar>
|
||||
<ion-label>
|
||||
<h5>{{ dep.value.title }}</h5>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="loading$ | ngrxPush" class="center-spinner">
|
||||
<ion-spinner color="warning" name="lines"></ion-spinner>
|
||||
<ion-label class="long-message">Checking for installed services which depend on {{params.title}}...</ion-label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2,7 +2,7 @@
|
||||
<ion-toolbar>
|
||||
<ion-label class="toolbar-label text-ellipses">
|
||||
<h1 class="toolbar-title">{{ params.toolbar.title }}</h1>
|
||||
<h3 style="font-size: large; font-style: italic">{{params.toolbar.action}} <ion-text style="font-size: medium;" color="medium">{{ params.toolbar.version | displayEmver }}</ion-text></h3>
|
||||
<h3 style="font-size: large; font-style: italic">{{ params.toolbar.action }} <ion-text style="font-size: medium;" color="medium">{{ params.toolbar.version | displayEmver }}</ion-text></h3>
|
||||
</ion-label>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
@@ -11,14 +11,13 @@
|
||||
<ion-slides *ngIf="!error" id="slide-show" style="--bullet-background: white" pager="false">
|
||||
<ion-slide *ngFor="let def of params.slideDefinitions">
|
||||
<!-- We can pass [transitions]="transitions" into the component if logic within the component needs to trigger a transition (not just bottom bar) -->
|
||||
<dependencies #components *ngIf="def.slide.selector === 'dependencies'" [params]="def.slide.params"></dependencies>
|
||||
<alert #components *ngIf="def.slide.selector === 'alert'" [params]="def.slide.params" style="width: 100%;"></alert>
|
||||
<notes #components *ngIf="def.slide.selector === 'notes'" [params]="def.slide.params" style="width: 100%;"></notes>
|
||||
<dependents #components *ngIf="def.slide.selector === 'dependents'" [params]="def.slide.params" [transitions]="transitions"></dependents>
|
||||
<complete #components *ngIf="def.slide.selector === 'complete'" [params]="def.slide.params" [transitions]="transitions"></complete>
|
||||
</ion-slide>
|
||||
</ion-slides>
|
||||
|
||||
|
||||
<div *ngIf="error" class="slide-content">
|
||||
<div style="margin-top: 25px;">
|
||||
<div style="margin: 15px; display: flex; justify-content: center; align-items: center;">
|
||||
@@ -27,7 +26,7 @@
|
||||
</ion-label>
|
||||
</div>
|
||||
<div class="long-message">
|
||||
{{error}}
|
||||
{{ error }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -38,24 +37,27 @@
|
||||
<ng-container *ngIf="!initializing && !error">
|
||||
|
||||
<!-- cancel button if loading/not loading -->
|
||||
<ion-button slot="start" *ngIf="v.loading && v.bar.cancel.whileLoading as cancel" (click)="transitions.cancel()" class="toolbar-button" fill="outline" color="medium">
|
||||
<ion-text *ngIf="cancel.text" [class.smaller-text]="cancel.text > 16">{{cancel.text}}</ion-text>
|
||||
<ion-button slot="start" *ngIf="(currentSlide.loading$ | async) && currentBottomBar.cancel.whileLoading as cancel" (click)="transitions.cancel()" class="toolbar-button" fill="outline" color="medium">
|
||||
<ion-text *ngIf="cancel.text" [class.smaller-text]="cancel.text > 16">{{ cancel.text }}</ion-text>
|
||||
<ion-icon *ngIf="!cancel.text" name="close-outline"></ion-icon>
|
||||
</ion-button>
|
||||
<ion-button slot="start" *ngIf="!v.loading && v.bar.cancel.afterLoading as cancel" (click)="transitions.cancel()" class="toolbar-button" fill="outline" color="medium">
|
||||
<ion-text *ngIf="cancel.text" [class.smaller-text]="cancel.text > 16">{{cancel.text}}</ion-text>
|
||||
<ion-button slot="start" *ngIf="!(currentSlide.loading$ | async) && currentBottomBar.cancel.afterLoading as cancel" (click)="transitions.cancel()" class="toolbar-button" fill="outline" color="medium">
|
||||
<ion-text *ngIf="cancel.text" [class.smaller-text]="cancel.text > 16">{{ cancel.text }}</ion-text>
|
||||
<ion-icon *ngIf="!cancel.text" name="close-outline"></ion-icon>
|
||||
</ion-button>
|
||||
|
||||
<!-- next button -->
|
||||
<ion-button slot="end" *ngIf="!v.loading && v.bar.next as next" (click)="transitions.next()" fill="outline" class="toolbar-button" color="primary">
|
||||
<ion-text [class.smaller-text]="next.length > 16">{{next}}</ion-text>
|
||||
</ion-button>
|
||||
<!-- next/finish buttons -->
|
||||
<ng-container *ngIf="!(currentSlide.loading$ | async)">
|
||||
<!-- next -->
|
||||
<ion-button slot="end" *ngIf="currentBottomBar.next as next" (click)="transitions.next()" fill="outline" class="toolbar-button" color="primary">
|
||||
<ion-text [class.smaller-text]="next.length > 16">{{ next }}</ion-text>
|
||||
</ion-button>
|
||||
|
||||
<!-- finish button -->
|
||||
<ion-button slot="end" *ngIf="!v.loading && v.bar.finish as finish" (click)="transitions.final()" fill="outline" class="toolbar-button" color="primary">
|
||||
<ion-text [class.smaller-text]="finish.length > 16">{{finish}}</ion-text>
|
||||
</ion-button>
|
||||
<!-- finish -->
|
||||
<ion-button slot="end" *ngIf="currentBottomBar.finish as finish" (click)="transitions.final()" fill="outline" class="toolbar-button" color="primary">
|
||||
<ion-text [class.smaller-text]="finish.length > 16">{{ finish }}</ion-text>
|
||||
</ion-button>
|
||||
</ng-container>
|
||||
|
||||
</ng-container>
|
||||
<ng-container *ngIf="error">
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { InstalledPackageDataEntry } from 'src/app/services/patch-db/data-model'
|
||||
import { PackageDataEntry } from 'src/app/services/patch-db/data-model'
|
||||
import { Breakages } from 'src/app/services/api/api-types'
|
||||
import { exists } from 'src/app/util/misc.util'
|
||||
import { ApiService } from '../../services/api/api.service'
|
||||
import { InstallWizardComponent, SlideDefinition, TopbarParams } from './install-wizard.component'
|
||||
import { WizardAction } from './wizard-types'
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class WizardBaker {
|
||||
@@ -17,10 +16,6 @@ export class WizardBaker {
|
||||
}): InstallWizardComponent['params'] {
|
||||
const { id, title, version, installAlert } = values
|
||||
|
||||
validate(id, exists, 'missing id')
|
||||
validate(title, exists, 'missing title')
|
||||
validate(version, exists, 'missing version')
|
||||
|
||||
const action = 'install'
|
||||
const toolbar: TopbarParams = { action, title, version }
|
||||
|
||||
@@ -29,8 +24,8 @@ export class WizardBaker {
|
||||
slide: {
|
||||
selector: 'alert',
|
||||
params: {
|
||||
alert: installAlert,
|
||||
title: 'Warning',
|
||||
message: installAlert,
|
||||
titleColor: 'warning',
|
||||
},
|
||||
},
|
||||
@@ -62,10 +57,6 @@ export class WizardBaker {
|
||||
}): InstallWizardComponent['params'] {
|
||||
const { id, title, version, installAlert } = values
|
||||
|
||||
validate(id, exists, 'missing id')
|
||||
validate(title, exists, 'missing title')
|
||||
validate(version, exists, 'missing version')
|
||||
|
||||
const action = 'update'
|
||||
const toolbar: TopbarParams = { action, title, version }
|
||||
|
||||
@@ -74,8 +65,8 @@ export class WizardBaker {
|
||||
slide: {
|
||||
selector: 'alert',
|
||||
params: {
|
||||
alert: installAlert,
|
||||
title: 'Warning',
|
||||
message: installAlert,
|
||||
titleColor: 'warning',
|
||||
},
|
||||
},
|
||||
@@ -166,10 +157,6 @@ export class WizardBaker {
|
||||
}): InstallWizardComponent['params'] {
|
||||
const { id, title, version, installAlert } = values
|
||||
|
||||
validate(id, exists, 'missing id')
|
||||
validate(title, exists, 'missing title')
|
||||
validate(version, exists, 'missing version')
|
||||
|
||||
const action = 'downgrade'
|
||||
const toolbar: TopbarParams = { action, title, version }
|
||||
|
||||
@@ -178,8 +165,8 @@ export class WizardBaker {
|
||||
slide: {
|
||||
selector: 'alert',
|
||||
params: {
|
||||
alert: installAlert,
|
||||
title: 'Warning',
|
||||
message: installAlert,
|
||||
titleColor: 'warning',
|
||||
},
|
||||
},
|
||||
@@ -222,11 +209,7 @@ export class WizardBaker {
|
||||
}): InstallWizardComponent['params'] {
|
||||
const { id, title, version, uninstallAlert } = values
|
||||
|
||||
validate(id, exists, 'missing id')
|
||||
validate(title, exists, 'missing title')
|
||||
validate(version, exists, 'missing version')
|
||||
|
||||
const action = 'uninstall' as WizardAction
|
||||
const action = 'uninstall'
|
||||
const toolbar: TopbarParams = { action, title, version }
|
||||
|
||||
const slideDefinitions: SlideDefinition[] = [
|
||||
@@ -234,8 +217,8 @@ export class WizardBaker {
|
||||
slide: {
|
||||
selector: 'alert',
|
||||
params: {
|
||||
alert: uninstallAlert || defaultUninstallationWarning(title),
|
||||
title: 'Warning',
|
||||
message: uninstallAlert || defaultUninstallWarning(title),
|
||||
titleColor: 'warning',
|
||||
},
|
||||
},
|
||||
@@ -248,7 +231,7 @@ export class WizardBaker {
|
||||
action,
|
||||
verb: 'uninstalling',
|
||||
title,
|
||||
fetchBreakages: () => this.apiService.dryRemovePackage({ id }).then(breakages => breakages ),
|
||||
fetchBreakages: () => this.apiService.dryRemovePackage({ id }).then(breakages => breakages),
|
||||
},
|
||||
},
|
||||
bottomBar: { cancel: { whileLoading: { }, afterLoading: { text: 'Cancel' } }, next: 'Uninstall' },
|
||||
@@ -274,10 +257,6 @@ export class WizardBaker {
|
||||
}): InstallWizardComponent['params'] {
|
||||
const { breakages, title, version } = values
|
||||
|
||||
validate(breakages, t => !!t && Array.isArray(t), 'missing breakages')
|
||||
validate(title, exists, 'missing title')
|
||||
validate(version, exists, 'missing version')
|
||||
|
||||
const action = 'stop'
|
||||
const toolbar: TopbarParams = { action, title, version }
|
||||
|
||||
@@ -298,7 +277,7 @@ export class WizardBaker {
|
||||
return { toolbar, slideDefinitions }
|
||||
}
|
||||
|
||||
configure (values: { breakages: Breakages, pkg: InstalledPackageDataEntry }): InstallWizardComponent['params'] {
|
||||
configure (values: { breakages: Breakages, pkg: PackageDataEntry }): InstallWizardComponent['params'] {
|
||||
const { breakages, pkg } = values
|
||||
const { title, version } = pkg.manifest
|
||||
const action = 'configure'
|
||||
@@ -321,12 +300,4 @@ export class WizardBaker {
|
||||
}
|
||||
}
|
||||
|
||||
function validate<T> (t: T, test: (t: T) => Boolean, desc: string) {
|
||||
if (!test(t)) {
|
||||
console.error('failed validation', desc, t)
|
||||
throw new Error(desc)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const defaultUninstallationWarning = serviceName => `Uninstalling ${ serviceName } will result in the deletion of its data.`
|
||||
const defaultUninstallWarning = serviceName => `Uninstalling ${ serviceName } will result in the deletion of its data.`
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<p
|
||||
[style.color]="'var(--ion-color-' + color + ')'"
|
||||
[style.color]="'var(--ion-color-' + rendering.color + ')'"
|
||||
[style.font-size]="size"
|
||||
[style.font-style]="style"
|
||||
[style.font-weight]="weight"
|
||||
>
|
||||
{{ display }}
|
||||
<ion-spinner *ngIf="showDots" class="dots dots-small" name="dots" [color]="color"></ion-spinner>
|
||||
{{ rendering.display }}
|
||||
<ion-spinner *ngIf="rendering.showDots" class="dots dots-small" name="dots" [color]="color"></ion-spinner>
|
||||
</p>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { Component, Input } from '@angular/core'
|
||||
import { combineLatest } from 'rxjs'
|
||||
import { PatchDbModel } from 'src/app/services/patch-db/patch-db.service'
|
||||
import { renderPkgStatus } from 'src/app/services/pkg-status-rendering.service'
|
||||
import { PkgStatusRendering } from 'src/app/services/pkg-status-rendering.service'
|
||||
|
||||
@Component({
|
||||
selector: 'status',
|
||||
@@ -9,36 +7,9 @@ import { renderPkgStatus } from 'src/app/services/pkg-status-rendering.service'
|
||||
styleUrls: ['./status.component.scss'],
|
||||
})
|
||||
export class StatusComponent {
|
||||
@Input() pkgId: string
|
||||
@Input() rendering: PkgStatusRendering
|
||||
@Input() size?: 'small' | 'medium' | 'large' = 'large'
|
||||
@Input() style?: string = 'regular'
|
||||
@Input() weight?: string = 'normal'
|
||||
display = ''
|
||||
color = ''
|
||||
showDots = false
|
||||
subs = []
|
||||
|
||||
constructor (
|
||||
private readonly patch: PatchDbModel,
|
||||
) { }
|
||||
|
||||
ngOnInit () {
|
||||
this.subs = [
|
||||
combineLatest([
|
||||
this.patch.watch$('package-data', this.pkgId, 'state'),
|
||||
this.patch.watch$('package-data', this.pkgId, 'installed', 'status'),
|
||||
])
|
||||
.subscribe(([state, status]) => {
|
||||
const { display, color, showDots } = renderPkgStatus(state, status)
|
||||
this.display = display
|
||||
this.color = color
|
||||
this.showDots = showDots
|
||||
}),
|
||||
]
|
||||
}
|
||||
|
||||
ngOnDestroy () {
|
||||
this.subs.forEach(sub => sub.unsubscribe())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user