mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 20:14:49 +00:00
fin
This commit is contained in:
committed by
Aiden McClelland
parent
7acfd2da5b
commit
6da3c7e326
@@ -11,22 +11,22 @@
|
|||||||
</ion-header>
|
</ion-header>
|
||||||
|
|
||||||
<ion-content class="ion-padding-bottom" *ngIf="{
|
<ion-content class="ion-padding-bottom" *ngIf="{
|
||||||
id: app$.id | async,
|
id: $app$.id | async,
|
||||||
status: app$.status | async,
|
status: $app$.status | async,
|
||||||
title: app$.title | async,
|
title: $app$.title | async,
|
||||||
versionInstalled: app$.versionInstalled | async,
|
versionInstalled: $app$.versionInstalled | async,
|
||||||
versionViewing: app$.versionViewing | async,
|
versionViewing: $app$.versionViewing | async,
|
||||||
descriptionLong: app$.descriptionLong | async,
|
descriptionLong: $app$.descriptionLong | async,
|
||||||
serviceRequirements: app$.serviceRequirements | async,
|
serviceRequirements: $app$.serviceRequirements | async,
|
||||||
iconURL: app$.iconURL | async,
|
iconURL: $app$.iconURL | async,
|
||||||
releaseNotes: app$.releaseNotes | async
|
releaseNotes: $app$.releaseNotes | async
|
||||||
} as vars"
|
} as vars"
|
||||||
>
|
>
|
||||||
<ion-spinner *ngIf="($loading$ | async)" class="center" name="lines" color="warning"></ion-spinner>
|
<ion-spinner *ngIf="($loading$ | async)" class="center" name="lines" color="warning"></ion-spinner>
|
||||||
|
|
||||||
<error-message [$error$]="$error$" [dismissable]="vars.id"></error-message>
|
<error-message [$error$]="$error$" [dismissable]="vars.id"></error-message>
|
||||||
|
|
||||||
<ng-container *ngIf="!($loading$ | async) && vars.id && (app$ | compareInstalledAndViewing | async) as installedStatus">
|
<ng-container *ngIf="!($loading$ | async) && vars.id && ($app$ | compareInstalledAndViewing | async) as installedStatus">
|
||||||
<ion-item-group>
|
<ion-item-group>
|
||||||
<ion-item lines="none">
|
<ion-item lines="none">
|
||||||
<ion-avatar slot="start">
|
<ion-avatar slot="start">
|
||||||
@@ -91,10 +91,10 @@
|
|||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<ion-item-divider>Release Notes</ion-item-divider>
|
<ion-item-divider>Release Notes</ion-item-divider>
|
||||||
<ion-item lines="none" button details="true" [disabled]="" (click)="presentModalReleaseNotes()" [disabled]="$versionSpecificLoading$ | async">
|
<ion-item lines="none" button details="true" [disabled]="" (click)="presentModalReleaseNotes()" [disabled]="$newVersionLoading$ | async">
|
||||||
<ion-icon slot="start" name="newspaper-outline" color="medium"></ion-icon>
|
<ion-icon slot="start" name="newspaper-outline" color="medium"></ion-icon>
|
||||||
<ion-label *ngIf="!($versionSpecificLoading$ | async)"><ion-text color="medium">New in {{ vars.versionViewing | displayEmver }}</ion-text></ion-label>
|
<ion-label *ngIf="!($newVersionLoading$ | async)"><ion-text color="medium">New in {{ vars.versionViewing | displayEmver }}</ion-text></ion-label>
|
||||||
<ion-spinner style="display: block; margin: auto;" name="lines" color="dark" *ngIf="$versionSpecificLoading$ | async"></ion-spinner>
|
<ion-spinner style="display: block; margin: auto;" name="lines" color="dark" *ngIf="$newVersionLoading$ | async"></ion-spinner>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<ng-container *ngIf="(vars.serviceRequirements)?.length">
|
<ng-container *ngIf="(vars.serviceRequirements)?.length">
|
||||||
@@ -103,7 +103,7 @@
|
|||||||
<ion-icon name="help-circle-outline"></ion-icon>
|
<ion-icon name="help-circle-outline"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-item-divider>
|
</ion-item-divider>
|
||||||
<dependency-list [$loading$]="$versionSpecificLoading$" [hostApp]="app$ | peekProperties" [dependencies]="vars.serviceRequirements"></dependency-list>
|
<dependency-list [$loading$]="$dependenciesLoading$" [hostApp]="$app$ | peekProperties" [dependencies]="vars.serviceRequirements"></dependency-list>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ion-item-divider></ion-item-divider>
|
<ion-item-divider></ion-item-divider>
|
||||||
<ion-item lines="none" button (click)="presentAlertVersions()">
|
<ion-item lines="none" button (click)="presentAlertVersions()">
|
||||||
|
|||||||
@@ -25,9 +25,14 @@ import { displayEmver } from 'src/app/pipes/emver.pipe'
|
|||||||
})
|
})
|
||||||
export class AppAvailableShowPage extends Cleanup {
|
export class AppAvailableShowPage extends Cleanup {
|
||||||
$loading$ = new BehaviorSubject(true)
|
$loading$ = new BehaviorSubject(true)
|
||||||
$versionSpecificLoading$ = new BehaviorSubject(false)
|
|
||||||
|
// When a new version is selected
|
||||||
|
$newVersionLoading$ = new BehaviorSubject(false)
|
||||||
|
// When dependencies are refreshing
|
||||||
|
$dependenciesLoading$ = new BehaviorSubject(false)
|
||||||
|
|
||||||
$error$ = new BehaviorSubject(undefined)
|
$error$ = new BehaviorSubject(undefined)
|
||||||
app$: PropertySubject<AppAvailableFull> = { } as any
|
$app$: PropertySubject<AppAvailableFull> = { } as any
|
||||||
appId: string
|
appId: string
|
||||||
|
|
||||||
openRecommendation = false
|
openRecommendation = false
|
||||||
@@ -58,26 +63,18 @@ export class AppAvailableShowPage extends Cleanup {
|
|||||||
this.cleanup(
|
this.cleanup(
|
||||||
markAsLoadingDuring$(this.$loading$,
|
markAsLoadingDuring$(this.$loading$,
|
||||||
from(this.apiService.getAvailableApp(this.appId)).pipe(
|
from(this.apiService.getAvailableApp(this.appId)).pipe(
|
||||||
tap(app => this.app$ = initPropertySubject(app)),
|
tap(app => this.$app$ = initPropertySubject(app)),
|
||||||
concatMap(() => this.fetchRecommendation()),
|
concatMap(() => this.fetchRecommendation()),
|
||||||
),
|
),
|
||||||
).pipe(
|
).pipe(
|
||||||
concatMap(() => this.syncWhenDependencyInstalls()), //must be final in stack
|
concatMap(() => this.syncWhenDependencyInstalls()), //must be final in stack
|
||||||
catchError(e => of(this.setError(e))),
|
catchError(e => of(this.setError(e))),
|
||||||
).subscribe(),
|
).subscribe(),
|
||||||
merge(this.$loading$, this.$versionSpecificLoading$).pipe(concatMap(l => {
|
|
||||||
if (l) {
|
|
||||||
this.showMoreReleaseNotes = false
|
|
||||||
}
|
|
||||||
return pauseFor(125)
|
|
||||||
})).subscribe(
|
|
||||||
() => this.setMoreReleaseNotes(),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
ionViewDidEnter () {
|
ionViewDidEnter () {
|
||||||
markAsLoadingDuring$(this.$versionSpecificLoading$, this.fetchAppVersionInfo()).subscribe({
|
markAsLoadingDuring$(this.$dependenciesLoading$, this.syncVersionSpecificInfo()).subscribe({
|
||||||
error: e => this.setError(e),
|
error: e => this.setError(e),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -96,25 +93,25 @@ export class AppAvailableShowPage extends Cleanup {
|
|||||||
return await popover.present()
|
return await popover.present()
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchAppVersionInfo (versionSpec?: string): Observable<any> {
|
syncVersionSpecificInfo (versionSpec?: string): Observable<any> {
|
||||||
if (!this.app$.versionViewing) return of({ })
|
if (!this.$app$.versionViewing) return of({ })
|
||||||
const specToFetch = versionSpec || `=${this.app$.versionViewing.getValue()}`
|
const specToFetch = versionSpec || `=${this.$app$.versionViewing.getValue()}`
|
||||||
return from(this.apiService.getAvailableAppVersionSpecificInfo(this.appId, specToFetch)).pipe(
|
return from(this.apiService.getAvailableAppVersionSpecificInfo(this.appId, specToFetch)).pipe(
|
||||||
tap(versionInfo => this.syncVersionSpecificInfo(versionInfo)),
|
tap(versionInfo => this.mergeInfo(versionInfo)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private syncVersionSpecificInfo (versionSpecificInfo: AppAvailableVersionSpecificInfo) {
|
private mergeInfo (versionSpecificInfo: AppAvailableVersionSpecificInfo) {
|
||||||
this.zone.run(() => {
|
this.zone.run(() => {
|
||||||
Object.entries(versionSpecificInfo).forEach( ([k, v]) => {
|
Object.entries(versionSpecificInfo).forEach( ([k, v]) => {
|
||||||
if (!this.app$[k]) this.app$[k] = new BehaviorSubject(undefined)
|
if (!this.$app$[k]) this.$app$[k] = new BehaviorSubject(undefined)
|
||||||
if (v !== this.app$[k].getValue()) this.app$[k].next(v)
|
if (v !== this.$app$[k].getValue()) this.$app$[k].next(v)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async presentAlertVersions () {
|
async presentAlertVersions () {
|
||||||
const app = peekProperties(this.app$)
|
const app = peekProperties(this.$app$)
|
||||||
const alert = await this.alertCtrl.create({
|
const alert = await this.alertCtrl.create({
|
||||||
header: 'Versions',
|
header: 'Versions',
|
||||||
backdropDismiss: false,
|
backdropDismiss: false,
|
||||||
@@ -133,13 +130,15 @@ export class AppAvailableShowPage extends Cleanup {
|
|||||||
}, {
|
}, {
|
||||||
text: 'Ok',
|
text: 'Ok',
|
||||||
handler: (version: string) => {
|
handler: (version: string) => {
|
||||||
const previousVersion = this.app$.versionViewing.getValue()
|
const previousVersion = this.$app$.versionViewing.getValue()
|
||||||
this.app$.versionViewing.next(version)
|
this.$app$.versionViewing.next(version)
|
||||||
markAsLoadingDuring$(this.$versionSpecificLoading$, this.fetchAppVersionInfo(`=${version}`))
|
markAsLoadingDuring$(
|
||||||
|
this.$newVersionLoading$, this.syncVersionSpecificInfo(`=${version}`)
|
||||||
|
)
|
||||||
.subscribe({
|
.subscribe({
|
||||||
error: e => {
|
error: e => {
|
||||||
this.setError(e)
|
this.setError(e)
|
||||||
this.app$.versionViewing.next(previousVersion)
|
this.$app$.versionViewing.next(previousVersion)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -151,7 +150,7 @@ export class AppAvailableShowPage extends Cleanup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async install () {
|
async install () {
|
||||||
const app = peekProperties(this.app$)
|
const app = peekProperties(this.$app$)
|
||||||
const { cancelled } = await wizardModal(
|
const { cancelled } = await wizardModal(
|
||||||
this.modalCtrl,
|
this.modalCtrl,
|
||||||
this.wizardBaker.install({
|
this.wizardBaker.install({
|
||||||
@@ -166,7 +165,7 @@ export class AppAvailableShowPage extends Cleanup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async update (action: 'update' | 'downgrade') {
|
async update (action: 'update' | 'downgrade') {
|
||||||
const app = peekProperties(this.app$)
|
const app = peekProperties(this.$app$)
|
||||||
|
|
||||||
const value = {
|
const value = {
|
||||||
id: app.id,
|
id: app.id,
|
||||||
@@ -190,7 +189,7 @@ export class AppAvailableShowPage extends Cleanup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async presentModalReleaseNotes () {
|
async presentModalReleaseNotes () {
|
||||||
const { releaseNotes, versionViewing } = peekProperties(this.app$)
|
const { releaseNotes, versionViewing } = peekProperties(this.$app$)
|
||||||
|
|
||||||
const modal = await this.modalCtrl.create({
|
const modal = await this.modalCtrl.create({
|
||||||
component: AppReleaseNotesPage,
|
component: AppReleaseNotesPage,
|
||||||
@@ -207,17 +206,17 @@ export class AppAvailableShowPage extends Cleanup {
|
|||||||
this.recommendation = history.state && history.state.installationRecommendation
|
this.recommendation = history.state && history.state.installationRecommendation
|
||||||
|
|
||||||
if (this.recommendation) {
|
if (this.recommendation) {
|
||||||
return from(this.fetchAppVersionInfo(this.recommendation.versionSpec))
|
return from(this.syncVersionSpecificInfo(this.recommendation.versionSpec))
|
||||||
} else {
|
} else {
|
||||||
return of({ })
|
return of({ })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private syncWhenDependencyInstalls (): Observable<void> {
|
private syncWhenDependencyInstalls (): Observable<void> {
|
||||||
return this.app$.serviceRequirements.pipe(
|
return this.$app$.serviceRequirements.pipe(
|
||||||
filter(deps => !!deps),
|
filter(deps => !!deps),
|
||||||
switchMap(deps => this.appModel.watchForInstallations(deps)),
|
switchMap(deps => this.appModel.watchForInstallations(deps)),
|
||||||
concatMap(() => markAsLoadingDuring$(this.$versionSpecificLoading$, this.fetchAppVersionInfo())),
|
concatMap(() => markAsLoadingDuring$(this.$dependenciesLoading$, this.syncVersionSpecificInfo())),
|
||||||
catchError(e => of(console.error(e))),
|
catchError(e => of(console.error(e))),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -226,24 +225,4 @@ export class AppAvailableShowPage extends Cleanup {
|
|||||||
console.error(e)
|
console.error(e)
|
||||||
this.$error$.next(e.message)
|
this.$error$.next(e.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
private setMoreReleaseNotes () {
|
|
||||||
const releaseNotes = document.getElementById(`release-notes-${this.appId}`)
|
|
||||||
if (releaseNotes) {
|
|
||||||
this.showMoreReleaseNotes = isTextOverflow(releaseNotes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@HostListener('window:resize', ['$event'])
|
|
||||||
onResize () {
|
|
||||||
this.setMoreReleaseNotes()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isTextOverflow (elem: any): boolean {
|
|
||||||
if (elem) {
|
|
||||||
return (elem.offsetWidth < elem.scrollWidth)
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<ion-header *ngIf="{appLoading: $appLoading$ | async} as vars">
|
||||||
|
<ion-toolbar>
|
||||||
|
<ion-buttons style="margin: 0px 15px" slot="start">
|
||||||
|
<img class="bulb" *ngIf="status$ | async | displayBulb: 'green'" src="assets/img/green-bulb.png"/>
|
||||||
|
<img class="bulb" *ngIf="status$ | async | displayBulb: 'red'" src="assets/img/red-bulb.png"/>
|
||||||
|
<img class="bulb" *ngIf="status$ | async | displayBulb: 'yellow'" src="assets/img/yellow-bulb.png"/>
|
||||||
|
<img class="bulb" *ngIf="status$ | async | displayBulb: 'off'" src="assets/img/black-bulb.png"/>
|
||||||
|
</ion-buttons>
|
||||||
|
<ion-title>{{$app$.title | async}}</ion-title>
|
||||||
|
<ion-buttons slot="end" *ngIf="">
|
||||||
|
<ion-spinner *ngIf="vars.appLoading" name="dots" color="medium"></ion-spinner>
|
||||||
|
<ion-button *ngIf="!vars.appLoading" (click)=presentPopoverMenu($event)>
|
||||||
|
<ion-icon name="ellipsis-vertical"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
|
</ion-buttons>
|
||||||
|
</ion-toolbar>
|
||||||
|
</ion-header>
|
||||||
|
|
||||||
|
<ion-content style="--overflow: hidden;" *ngIf="{isRunning: isRunning$ | async, status: status$ | async, appLoading: $appLoading$ | async, iframeLoading: $iframeLoading$ | async } as vars">
|
||||||
|
<ion-spinner *ngIf="vars.appLoading || vars.iframeLoading" style="position: absolute; width: 4vh; left: calc(50% - 2vh); height: 100%;" name="lines" color="warning"></ion-spinner>
|
||||||
|
<iframe (load)="iframeLoaded()" *ngIf="!vars.appLoading && vars.isRunning" [id]="appId + '-ui'" src="http://localhost:8100" width="100%" height="100%" style="border:1px solid black;"></iframe>
|
||||||
|
<div *ngIf="!vars.appLoading && !vars.isRunning" class="flex-center" style="border:1px solid black; color: white">
|
||||||
|
<ion-label style="margin:10px">{{$app$.title | async}} is not running.</ion-label>
|
||||||
|
<ion-button fill="outline" (click)="toServiceShow()">View</ion-button>
|
||||||
|
</div>
|
||||||
|
</ion-content>
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"useMocks": false
|
"useMocks": true
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user