mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 10:21:52 +00:00
login error fix (#1013)
* login error fix * loading gone * fix type erros Co-authored-by: Drew Ansbacher <drew.ansbacher@spiredigital.com> Co-authored-by: Matt Hill <matthewonthemoon@gmail.com>
This commit is contained in:
committed by
Aiden McClelland
parent
e0f8a0894d
commit
1203cf8d09
@@ -10,7 +10,7 @@
|
||||
<ion-content class="ion-padding">
|
||||
<!-- loading -->
|
||||
<text-spinner
|
||||
*ngIf="loading else data"
|
||||
*ngIf="!patch.loaded else data"
|
||||
text="Connecting to Embassy"
|
||||
></text-spinner>
|
||||
|
||||
|
||||
@@ -18,13 +18,12 @@ export class AppListPage {
|
||||
pkgs: readonly PackageDataEntry[] = []
|
||||
recoveredPkgs: readonly RecoveredInfo[] = []
|
||||
order: readonly string[] = []
|
||||
loading = true
|
||||
reordering = false
|
||||
|
||||
constructor (
|
||||
private readonly api: ApiService,
|
||||
private readonly patch: PatchDbService,
|
||||
private readonly destroy$: DestroyService,
|
||||
public readonly patch: PatchDbService,
|
||||
) { }
|
||||
|
||||
get empty (): boolean {
|
||||
@@ -42,7 +41,6 @@ export class AppListPage {
|
||||
this.pkgs = pkgs
|
||||
this.recoveredPkgs = recoveredPkgs
|
||||
this.order = order
|
||||
this.loading = false
|
||||
|
||||
// set order in UI DB if there were unknown packages
|
||||
if (order.length < pkgs.length) {
|
||||
|
||||
@@ -7,127 +7,136 @@
|
||||
</ion-header>
|
||||
|
||||
<ion-content class="ion-padding">
|
||||
<h1 style="font-family: 'Montserrat'; font-size: 42px; margin: 32px 0;" class="ion-text-center">Embassy Marketplace</h1>
|
||||
|
||||
<ion-grid style="padding-bottom: 32px;">
|
||||
<ion-row>
|
||||
<ion-col sizeSm="8" offset-sm="2">
|
||||
<ion-toolbar color="transparent">
|
||||
<ion-searchbar
|
||||
enterkeyhint="search"
|
||||
color="dark"
|
||||
debounce="250"
|
||||
[(ngModel)]="query"
|
||||
(ionChange)="search()"
|
||||
></ion-searchbar>
|
||||
</ion-toolbar>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
|
||||
<!-- loading -->
|
||||
<ng-container *ngIf="loading; else pageLoaded">
|
||||
<div class="scrollable ion-text-center">
|
||||
<ion-button *ngFor="let cat of ['', '', '', '', '', '', '']" fill="clear">
|
||||
<ion-skeleton-text animated style="width: 80px; border-radius: 0;"></ion-skeleton-text>
|
||||
</ion-button>
|
||||
</div>
|
||||
<text-spinner
|
||||
*ngIf="!patch.loaded else data"
|
||||
text="Connecting to Embassy"
|
||||
></text-spinner>
|
||||
|
||||
<div class="divider" style="margin: 24px 0;"></div>
|
||||
</ng-container>
|
||||
<!-- not loading -->
|
||||
<ng-template #data>
|
||||
<h1 style="font-family: 'Montserrat'; font-size: 42px; margin: 32px 0;" class="ion-text-center">Embassy Marketplace</h1>
|
||||
|
||||
<!-- loaded -->
|
||||
<ng-template #pageLoaded>
|
||||
<div class="scrollable ion-text-center">
|
||||
<ion-button
|
||||
*ngFor="let cat of categories"
|
||||
fill="clear"
|
||||
[class]="cat === category ? 'selected' : 'dim'"
|
||||
(click)="switchCategory(cat)"
|
||||
<ion-grid style="padding-bottom: 32px;">
|
||||
<ion-row>
|
||||
<ion-col sizeSm="8" offset-sm="2">
|
||||
<ion-toolbar color="transparent">
|
||||
<ion-searchbar
|
||||
enterkeyhint="search"
|
||||
color="dark"
|
||||
debounce="250"
|
||||
[(ngModel)]="query"
|
||||
(ionChange)="search()"
|
||||
></ion-searchbar>
|
||||
</ion-toolbar>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
|
||||
<!-- loading -->
|
||||
<ng-container *ngIf="loading; else pageLoaded">
|
||||
<div class="scrollable ion-text-center">
|
||||
<ion-button *ngFor="let cat of ['', '', '', '', '', '', '']" fill="clear">
|
||||
<ion-skeleton-text animated style="width: 80px; border-radius: 0;"></ion-skeleton-text>
|
||||
</ion-button>
|
||||
</div>
|
||||
|
||||
<div class="divider" style="margin: 24px 0;"></div>
|
||||
</ng-container>
|
||||
|
||||
<!-- loaded -->
|
||||
<ng-template #pageLoaded>
|
||||
<div class="scrollable ion-text-center">
|
||||
<ion-button
|
||||
*ngFor="let cat of categories"
|
||||
fill="clear"
|
||||
[class]="cat === category ? 'selected' : 'dim'"
|
||||
(click)="switchCategory(cat)"
|
||||
>
|
||||
{{ cat }}
|
||||
</ion-button>
|
||||
</div>
|
||||
|
||||
<div class="divider" style="margin: 24px;"></div>
|
||||
</ng-template>
|
||||
|
||||
<!-- loading -->
|
||||
<ng-container *ngIf="loading; else pkgsLoaded">
|
||||
<ion-grid>
|
||||
<ion-row>
|
||||
<ion-col *ngFor="let pkg of ['', '', '', '']" sizeXs="12" sizeSm="12" sizeMd="6">
|
||||
<ion-item>
|
||||
<ion-thumbnail slot="start">
|
||||
<ion-skeleton-text style="border-radius: 100%;" animated></ion-skeleton-text>
|
||||
</ion-thumbnail>
|
||||
<ion-label>
|
||||
<ion-skeleton-text animated style="width: 150px; height: 18px; margin-bottom: 8px;"></ion-skeleton-text>
|
||||
<ion-skeleton-text animated style="width: 400px;"></ion-skeleton-text>
|
||||
<ion-skeleton-text animated style="width: 100px;"></ion-skeleton-text>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
</ng-container>
|
||||
|
||||
<!-- packages loaded -->
|
||||
<ng-template #pkgsLoaded>
|
||||
<div
|
||||
class="ion-padding"
|
||||
*ngIf="!pkgs.length && category ==='updates'"
|
||||
style="text-align: center;"
|
||||
>
|
||||
{{ cat }}
|
||||
</ion-button>
|
||||
</div>
|
||||
|
||||
<div class="divider" style="margin: 24px;"></div>
|
||||
</ng-template>
|
||||
|
||||
<!-- loading -->
|
||||
<ng-container *ngIf="loading; else pkgsLoaded">
|
||||
<ion-grid>
|
||||
<ion-row>
|
||||
<ion-col *ngFor="let pkg of ['', '', '', '']" sizeXs="12" sizeSm="12" sizeMd="6">
|
||||
<ion-item>
|
||||
<ion-thumbnail slot="start">
|
||||
<ion-skeleton-text style="border-radius: 100%;" animated></ion-skeleton-text>
|
||||
</ion-thumbnail>
|
||||
<ion-label>
|
||||
<ion-skeleton-text animated style="width: 150px; height: 18px; margin-bottom: 8px;"></ion-skeleton-text>
|
||||
<ion-skeleton-text animated style="width: 400px;"></ion-skeleton-text>
|
||||
<ion-skeleton-text animated style="width: 100px;"></ion-skeleton-text>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
</ng-container>
|
||||
|
||||
<!-- packages loaded -->
|
||||
<ng-template #pkgsLoaded>
|
||||
<div
|
||||
class="ion-padding"
|
||||
*ngIf="!pkgs.length && category ==='updates'"
|
||||
style="text-align: center;"
|
||||
>
|
||||
<h1>All services are up to date!</h1>
|
||||
</div>
|
||||
<ion-grid>
|
||||
<ion-row>
|
||||
<ion-col *ngIf="marketplaceService.eosUpdateAvailable && category === 'featured'" sizeXs="12" sizeSm="12" sizeMd="6">
|
||||
<ion-item button class="eos-item" (click)="updateEos()">
|
||||
<ion-thumbnail slot="start">
|
||||
<img src="assets/img/icon.png" />
|
||||
</ion-thumbnail>
|
||||
<ion-label>
|
||||
<h3>Now Available...</h3>
|
||||
<h2>Embassy OS {{ marketplaceService.eos.version }}</h2>
|
||||
<p>{{ marketplaceService.eos.headline }}</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ion-col>
|
||||
<ion-col *ngFor="let pkg of pkgs" sizeXs="12" sizeSm="12" sizeMd="6">
|
||||
<ion-item [routerLink]="['/marketplace', pkg.manifest.id]">
|
||||
<ion-thumbnail slot="start">
|
||||
<img [src]="'/marketplace' + pkg.icon" />
|
||||
</ion-thumbnail>
|
||||
<ion-label>
|
||||
<h2 style="font-family: 'Montserrat'; font-weight: bold;">{{ pkg.manifest.title }}</h2>
|
||||
<h3>{{ pkg.manifest.description.short }}</h3>
|
||||
<ng-container *ngIf="localPkgs[pkg.manifest.id] as localPkg; else none">
|
||||
<p *ngIf="localPkg.state === PackageState.Installed">
|
||||
<ion-text *ngIf="(pkg.manifest.version | compareEmver : localPkg.manifest.version) === 0" color="success">Installed</ion-text>
|
||||
<ion-text *ngIf="(pkg.manifest.version | compareEmver : localPkg.manifest.version) === 1" color="warning">Update Available</ion-text>
|
||||
</p>
|
||||
<p *ngIf="[PackageState.Installing, PackageState.Updating] | includes : localPkg.state">
|
||||
<ion-text color="primary" *ngIf="(localPkg['install-progress'] | installState) as progress">
|
||||
Installing
|
||||
<span class="loading-dots"></span>{{ progress.totalProgress < 99 ? progress.totalProgress + '%' : 'finalizing' }}
|
||||
</ion-text>
|
||||
</p>
|
||||
<p *ngIf="localPkg.state === PackageState.Removing">
|
||||
<ion-text color="danger">
|
||||
Removing
|
||||
<span class="loading-dots"></span>
|
||||
</ion-text>
|
||||
</p>
|
||||
</ng-container>
|
||||
<ng-template #none>
|
||||
<p>Not Installed</p>
|
||||
</ng-template>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
<h1>All services are up to date!</h1>
|
||||
</div>
|
||||
<ion-grid>
|
||||
<ion-row>
|
||||
<ion-col *ngIf="marketplaceService.eosUpdateAvailable && category === 'featured'" sizeXs="12" sizeSm="12" sizeMd="6">
|
||||
<ion-item button class="eos-item" (click)="updateEos()">
|
||||
<ion-thumbnail slot="start">
|
||||
<img src="assets/img/icon.png" />
|
||||
</ion-thumbnail>
|
||||
<ion-label>
|
||||
<h3>Now Available...</h3>
|
||||
<h2>Embassy OS {{ marketplaceService.eos.version }}</h2>
|
||||
<p>{{ marketplaceService.eos.headline }}</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ion-col>
|
||||
<ion-col *ngFor="let pkg of pkgs" sizeXs="12" sizeSm="12" sizeMd="6">
|
||||
<ion-item [routerLink]="['/marketplace', pkg.manifest.id]">
|
||||
<ion-thumbnail slot="start">
|
||||
<img [src]="'/marketplace' + pkg.icon" />
|
||||
</ion-thumbnail>
|
||||
<ion-label>
|
||||
<h2 style="font-family: 'Montserrat'; font-weight: bold;">{{ pkg.manifest.title }}</h2>
|
||||
<h3>{{ pkg.manifest.description.short }}</h3>
|
||||
<ng-container *ngIf="localPkgs[pkg.manifest.id] as localPkg; else none">
|
||||
<p *ngIf="localPkg.state === PackageState.Installed">
|
||||
<ion-text *ngIf="(pkg.manifest.version | compareEmver : localPkg.manifest.version) === 0" color="success">Installed</ion-text>
|
||||
<ion-text *ngIf="(pkg.manifest.version | compareEmver : localPkg.manifest.version) === 1" color="warning">Update Available</ion-text>
|
||||
</p>
|
||||
<p *ngIf="[PackageState.Installing, PackageState.Updating] | includes : localPkg.state">
|
||||
<ion-text color="primary" *ngIf="(localPkg['install-progress'] | installState) as progress">
|
||||
Installing
|
||||
<span class="loading-dots"></span>{{ progress.totalProgress < 99 ? progress.totalProgress + '%' : 'finalizing' }}
|
||||
</ion-text>
|
||||
</p>
|
||||
<p *ngIf="localPkg.state === PackageState.Removing">
|
||||
<ion-text color="danger">
|
||||
Removing
|
||||
<span class="loading-dots"></span>
|
||||
</ion-text>
|
||||
</p>
|
||||
</ng-container>
|
||||
<ng-template #none>
|
||||
<p>Not Installed</p>
|
||||
</ng-template>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
</ion-content>
|
||||
|
||||
@@ -9,8 +9,9 @@ import { ErrorToastService } from 'src/app/services/error-toast.service'
|
||||
import { MarketplaceService } from '../marketplace.service'
|
||||
import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
|
||||
import Fuse from 'fuse.js/dist/fuse.min.js'
|
||||
import { isEmptyObject } from 'src/app/util/misc.util'
|
||||
import { exists, isEmptyObject } from 'src/app/util/misc.util'
|
||||
import { Router } from '@angular/router'
|
||||
import { filter, first } from 'rxjs/operators'
|
||||
|
||||
const defaultOps = {
|
||||
isCaseSensitive: false,
|
||||
@@ -57,15 +58,18 @@ export class MarketplaceListPage {
|
||||
private readonly modalCtrl: ModalController,
|
||||
private readonly errToast: ErrorToastService,
|
||||
private readonly wizardBaker: WizardBaker,
|
||||
private readonly patch: PatchDbService,
|
||||
private readonly alertCtrl: AlertController,
|
||||
private readonly router: Router,
|
||||
public readonly patch: PatchDbService,
|
||||
public readonly marketplaceService: MarketplaceService,
|
||||
) { }
|
||||
|
||||
async ngOnInit () {
|
||||
this.subs = [
|
||||
this.patch.watch$('package-data').subscribe(pkgs => {
|
||||
this.patch.watch$('package-data')
|
||||
.pipe(
|
||||
filter((data) => exists(data) && !isEmptyObject(data)),
|
||||
).subscribe(pkgs => {
|
||||
this.localPkgs = pkgs
|
||||
Object.values(this.localPkgs).forEach(pkg => {
|
||||
pkg['install-progress'] = { ...pkg['install-progress'] }
|
||||
@@ -76,23 +80,30 @@ export class MarketplaceListPage {
|
||||
}),
|
||||
]
|
||||
|
||||
try {
|
||||
if (!this.marketplaceService.pkgs.length) {
|
||||
await this.marketplaceService.load()
|
||||
this.patch.watch$('server-info')
|
||||
.pipe(
|
||||
filter((data) => exists(data) && !isEmptyObject(data)),
|
||||
first(),
|
||||
).subscribe(async _ => {
|
||||
try {
|
||||
if (!this.marketplaceService.pkgs.length) {
|
||||
await this.marketplaceService.load()
|
||||
}
|
||||
|
||||
// category should start as first item in array
|
||||
// remove here then add at beginning
|
||||
const filterdCategories = this.marketplaceService.data.categories.filter(cat => this.category !== cat)
|
||||
this.categories = [this.category, 'updates'].concat(filterdCategories).concat(['all'])
|
||||
|
||||
this.filterPkgs()
|
||||
|
||||
} catch (e) {
|
||||
this.errToast.present(e)
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
})
|
||||
|
||||
// category should start as first item in array
|
||||
// remove here then add at beginning
|
||||
const filterdCategories = this.marketplaceService.data.categories.filter(cat => this.category !== cat)
|
||||
this.categories = [this.category, 'updates'].concat(filterdCategories).concat(['all'])
|
||||
|
||||
this.filterPkgs()
|
||||
|
||||
} catch (e) {
|
||||
this.errToast.present(e)
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
}
|
||||
|
||||
ngAfterViewInit () {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>{{ patch.data.ui.name || "Embassy-" + patch.data['server-info'].id }}</ion-title>
|
||||
<ion-title *ngIf="!patch.loaded">Loading<span class="loading-dots"></span></ion-title>
|
||||
<ion-title *ngIf="patch.loaded">{{ patch.data.ui.name || "Embassy-" + patch.data['server-info'].id }}</ion-title>
|
||||
<ion-buttons slot="end">
|
||||
<badge-menu-button></badge-menu-button>
|
||||
</ion-buttons>
|
||||
@@ -8,29 +9,38 @@
|
||||
</ion-header>
|
||||
|
||||
<ion-content class="ion-padding">
|
||||
<ion-item-group>
|
||||
<div *ngFor="let cat of settings | keyvalue : asIsOrder">
|
||||
<ion-item-divider><ion-text color="dark">{{ cat.key }}</ion-text></ion-item-divider>
|
||||
<ion-item button *ngFor="let button of cat.value" [detail]="button.detail" [disabled]="button.disabled | async" (click)="button.action()">
|
||||
<ion-icon slot="start" [name]="button.icon"></ion-icon>
|
||||
<ion-label>
|
||||
<h2>{{ button.title }}</h2>
|
||||
<p *ngIf="button.description">{{ button.description }}</p>
|
||||
<p *ngIf="button.title === 'Create Backup'">
|
||||
<ng-container *ngIf="patch.data['server-info'].status as status">
|
||||
<ion-text color="warning" *ngIf="status === ServerStatus.Running">
|
||||
Last Backup: {{ patch.data['server-info']['last-backup'] ? (patch.data['server-info']['last-backup'] | date: 'short') : 'never' }}
|
||||
</ion-text>
|
||||
<span *ngIf="status === ServerStatus.BackingUp" class="inline">
|
||||
<ion-spinner color="success" style="height: 12px; width: 12px; margin-right: 6px;"></ion-spinner>
|
||||
<ion-text color="success">
|
||||
Backing up
|
||||
<!-- loading -->
|
||||
<text-spinner
|
||||
*ngIf="!patch.loaded else data"
|
||||
text="Connecting to Embassy"
|
||||
></text-spinner>
|
||||
|
||||
<!-- not loading -->
|
||||
<ng-template #data>
|
||||
<ion-item-group>
|
||||
<div *ngFor="let cat of settings | keyvalue : asIsOrder">
|
||||
<ion-item-divider><ion-text color="dark">{{ cat.key }}</ion-text></ion-item-divider>
|
||||
<ion-item button *ngFor="let button of cat.value" [detail]="button.detail" [disabled]="button.disabled | async" (click)="button.action()">
|
||||
<ion-icon slot="start" [name]="button.icon"></ion-icon>
|
||||
<ion-label>
|
||||
<h2>{{ button.title }}</h2>
|
||||
<p *ngIf="button.description">{{ button.description }}</p>
|
||||
<p *ngIf="button.title === 'Create Backup'">
|
||||
<ng-container *ngIf="patch.data['server-info'].status as status">
|
||||
<ion-text color="warning" *ngIf="status === ServerStatus.Running">
|
||||
Last Backup: {{ patch.data['server-info']['last-backup'] ? (patch.data['server-info']['last-backup'] | date: 'short') : 'never' }}
|
||||
</ion-text>
|
||||
</span>
|
||||
</ng-container>
|
||||
</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</div>
|
||||
</ion-item-group>
|
||||
<span *ngIf="status === ServerStatus.BackingUp" class="inline">
|
||||
<ion-spinner color="success" style="height: 12px; width: 12px; margin-right: 6px;"></ion-spinner>
|
||||
<ion-text color="success">
|
||||
Backing up
|
||||
</ion-text>
|
||||
</span>
|
||||
</ng-container>
|
||||
</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</div>
|
||||
</ion-item-group>
|
||||
</ng-template>
|
||||
</ion-content>
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
tap,
|
||||
withLatestFrom,
|
||||
} from 'rxjs/operators'
|
||||
import { pauseFor } from 'src/app/util/misc.util'
|
||||
import { isEmptyObject, pauseFor } from 'src/app/util/misc.util'
|
||||
import { ApiService } from '../api/embassy-api.service'
|
||||
import { AuthService } from '../auth.service'
|
||||
import { DataModel } from './data-model'
|
||||
@@ -48,6 +48,10 @@ export class PatchDbService {
|
||||
return this.patchDb.store.cache.data
|
||||
}
|
||||
|
||||
get loaded (): boolean {
|
||||
return this.patchDb?.store?.cache?.data && !isEmptyObject(this.patchDb.store.cache.data)
|
||||
}
|
||||
|
||||
constructor (
|
||||
@Inject(PATCH_SOURCE) private readonly wsSource: Source<DataModel>,
|
||||
@Inject(PATCH_SOURCE) private readonly pollSource: Source<DataModel>,
|
||||
|
||||
Reference in New Issue
Block a user