fix connection failure display monitoring and other style changes (#1573)

* fix connection failure display monitoring and other style chnages

* display updates more clearly in marketplace

* remove scrolling from release notes and long description

* remove unnecessary bangs

Co-authored-by: Matt Hill <matthill@Matt-M1.local>
Co-authored-by: Matt Hill <matthill@Matt-M1.start9.dev>
This commit is contained in:
Matt Hill
2022-06-27 10:44:12 -06:00
committed by GitHub
parent 31952afe1e
commit 0849df524a
34 changed files with 109 additions and 123 deletions

View File

@@ -2,8 +2,10 @@
*ngFor="let cat of categories"
fill="clear"
class="category"
[color]="cat === 'updates' && updatesAvailable ? 'success' : undefined"
[class.category_selected]="cat === category"
(click)="switchCategory(cat)"
>
{{ cat }}
<span *ngIf="cat === 'updates'"> &nbsp; ({{ updatesAvailable }}) </span>
</ion-button>

View File

@@ -22,6 +22,9 @@ export class CategoriesComponent {
@Input()
category = ''
@Input()
updatesAvailable? = 0
@Output()
readonly categoryChange = new EventEmitter<string>()

View File

@@ -1,23 +1,26 @@
<!-- release notes -->
<ion-item-divider>
New in {{ pkg.manifest.version | displayEmver }}
<ion-button routerLink="notes" class="all-notes" fill="clear" color="dark">
All Release Notes
<ion-button
routerLink="notes"
class="all-notes"
fill="clear"
color="dark"
strong
>
Past Release Notes
<ion-icon slot="end" name="arrow-forward"></ion-icon>
</ion-button>
</ion-item-divider>
<ion-item lines="none" color="transparent">
<ion-label>
<div
class="release-notes"
[innerHTML]="pkg.manifest['release-notes'] | markdown"
></div>
<div [innerHTML]="pkg.manifest['release-notes'] | markdown"></div>
</ion-label>
</ion-item>
<!-- description -->
<ion-item-divider>Description</ion-item-divider>
<ion-item lines="none" color="transparent">
<ion-label>
<div class="release-notes">{{ pkg.manifest.description.long }}</div>
{{ pkg.manifest.description.long }}
</ion-label>
</ion-item>

View File

@@ -2,8 +2,3 @@
position: absolute;
right: 10px;
}
.release-notes {
overflow: auto;
max-height: 120px;
}

View File

@@ -33,15 +33,11 @@ export class FilterPackagesPipe implements PipeTransform {
constructor(private readonly emver: Emver) {}
transform(
packages: MarketplacePkg[] | null,
packages: MarketplacePkg[],
query: string,
category: string,
local: Record<string, { manifest: MarketplaceManifest }> = {},
): MarketplacePkg[] | null {
if (!packages) {
return null
}
): MarketplacePkg[] {
if (query) {
const fuse = new Fuse(packages, defaultOps)

View File

@@ -46,7 +46,9 @@
size="large"
color="light"
></ion-icon>
<ion-label>Open</ion-label>
<ion-label>
<b>Open New</b>
</ion-label>
</ion-item>
<br />

View File

@@ -54,8 +54,10 @@
fill="clear"
(click)="presentAlertLogout()"
>
<ion-label>
<ion-text class="montserrat" color="dark"> Log Out </ion-text>
<ion-label class="inline">
<h2>Log Out</h2>
&nbsp;
<ion-icon name="log-out-outline"></ion-icon>
</ion-label>
</ion-item>
</ion-menu-toggle>

View File

@@ -47,6 +47,7 @@ const ICONS = [
'key-outline',
'list-outline',
'lock-closed-outline',
'log-out-outline',
'logo-bitcoin',
'mail-outline',
'map-outline',

View File

@@ -41,7 +41,9 @@
size="large"
color="dark"
></ion-icon>
<ion-label>Open</ion-label>
<ion-label>
<b>Open New</b>
</ion-label>
</ion-item>
<!-- cifs list -->
<ng-container *ngFor="let target of backupService.cifs; let i = index">

View File

@@ -1,13 +1,15 @@
<p
[style.color]="
disconnected ? 'gray' : 'var(--ion-color-' + rendering.color + ')'
(disconnected$ | async)
? 'gray'
: 'var(--ion-color-' + rendering.color + ')'
"
[style.font-size]="size"
[style.font-style]="style"
[style.font-weight]="weight"
>
<span *ngIf="!installProgress">
{{ disconnected ? 'Unknown' : rendering.display }}
{{ (disconnected$ | async) ? 'Unknown' : rendering.display }}
<span *ngIf="rendering.showDots" class="loading-dots"></span>
<span
*ngIf="

View File

@@ -1,4 +1,5 @@
import { Component, Input } from '@angular/core'
import { ConnectionService } from 'src/app/services/connection.service'
import { InstallProgress } from 'src/app/services/patch-db/data-model'
import {
PrimaryRendering,
@@ -19,7 +20,10 @@ export class StatusComponent {
@Input() size?: string
@Input() style?: string = 'regular'
@Input() weight?: string = 'normal'
@Input() disconnected?: boolean = false
@Input() installProgress?: InstallProgress
@Input() sigtermTimeout?: string | null = null
disconnected$ = this.connectionService.watchDisconnected$()
constructor(private readonly connectionService: ConnectionService) {}
}

View File

@@ -13,6 +13,6 @@
color="primary"
></ion-spinner>
<ng-template #bulb>
<div class="bulb" [style.background-color]="color"></div>
<div class="bulb" [style.background-color]="color$ | async"></div>
</ng-template>
</ng-template>

View File

@@ -1,4 +1,6 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
import { map } from 'rxjs/operators'
import { ConnectionService } from 'src/app/services/connection.service'
import { PkgInfo } from 'src/app/util/get-package-info'
@Component({
@@ -11,12 +13,13 @@ export class AppListIconComponent {
@Input()
pkg: PkgInfo
@Input()
connectionFailure = false
get color (): string {
return this.connectionFailure
color$ = this.connectionService.watchDisconnected$().pipe(
map(disconnected => {
return disconnected
? 'var(--ion-color-dark)'
: 'var(--ion-color-' + this.pkg.primaryRendering.color + ')'
}
}),
)
constructor(private readonly connectionService: ConnectionService) {}
}

View File

@@ -1,9 +1,5 @@
<ion-item button detail="false" [routerLink]="['/services', manifest.id]">
<app-list-icon
slot="start"
[pkg]="pkg"
[connectionFailure]="connectionFailure"
></app-list-icon>
<app-list-icon slot="start" [pkg]="pkg"></app-list-icon>
<ion-thumbnail slot="start">
<img alt="" [src]="pkg.entry['static-files'].icon" />
</ion-thumbnail>
@@ -11,7 +7,6 @@
<h2>{{ manifest.title }}</h2>
<p>{{ manifest.version | displayEmver }}</p>
<status
[disconnected]="connectionFailure"
[rendering]="pkg.primaryRendering"
[installProgress]="pkg.entry['install-progress']"
weight="bold"

View File

@@ -15,9 +15,6 @@ export class AppListPkgComponent {
@Input()
pkg: PkgInfo
@Input()
connectionFailure = false
constructor(private readonly launcherService: UiLauncherService) {}
get status(): PackageMainStatus {

View File

@@ -1,11 +1,12 @@
<!-- header -->
<ion-item-divider>
<ion-item-divider class="ion-padding-bottom">
{{ reordering ? 'Reorder' : 'Installed Services' }}
<ion-button
*ngIf="pkgs.length > 1"
slot="end"
fill="clear"
(click)="toggle()"
strong
>
<ion-icon
slot="start"
@@ -24,11 +25,7 @@
*ngIf="item | packageInfo | async as pkg"
class="item"
>
<app-list-icon
slot="start"
[pkg]="pkg"
[connectionFailure]="!!(connectionFailure$ | async)"
></app-list-icon>
<app-list-icon slot="start" [pkg]="pkg"></app-list-icon>
<ion-thumbnail slot="start">
<img alt="" [src]="pkg.entry['static-files'].icon" />
</ion-thumbnail>
@@ -36,7 +33,6 @@
<h2>{{ pkg.entry.manifest.title }}</h2>
<p>{{ pkg.entry.manifest.version | displayEmver }}</p>
<status
[disconnected]="!!(connectionFailure$ | async)"
[rendering]="pkg.primaryRendering"
[installProgress]="pkg.entry['install-progress']"
weight="bold"
@@ -58,7 +54,6 @@
<app-list-pkg
*ngIf="pkg | packageInfo | async as info"
[pkg]="info"
[connectionFailure]="!!(connectionFailure$ | async)"
></app-list-pkg>
</ion-col>
</ion-row>

View File

@@ -7,11 +7,6 @@ import {
} from '@angular/core'
import { ItemReorderEventDetail } from '@ionic/core'
import { PackageDataEntry } from 'src/app/services/patch-db/data-model'
import { map } from 'rxjs/operators'
import {
ConnectionFailure,
ConnectionService,
} from 'src/app/services/connection.service'
@Component({
selector: 'app-list-reorder',
@@ -32,12 +27,6 @@ export class AppListReorderComponent {
@Output()
readonly pkgsChange = new EventEmitter<readonly PackageDataEntry[]>()
readonly connectionFailure$ = this.connectionService
.watchFailure$()
.pipe(map(failure => failure !== ConnectionFailure.None))
constructor(private readonly connectionService: ConnectionService) {}
toggle() {
this.reordering = !this.reordering
this.reorderingChange.emit(this.reordering)

View File

@@ -6,17 +6,15 @@
<!-- ** status ** -->
<app-show-status
[pkg]="pkg"
[connectionFailure]="!!(connectionFailure$ | async)"
[dependencies]="dependencies"
[status]="status"
></app-show-status>
<!-- ** installed && !backing-up ** -->
<ng-container *ngIf="isInstalled(pkg, status)">
<ng-container *ngIf="isInstalled(pkg) && !isBackingUp(status)">
<!-- ** health checks ** -->
<app-show-health-checks
*ngIf="isRunning(status)"
[pkg]="pkg"
[connectionFailure]="!!(connectionFailure$ | async)"
></app-show-health-checks>
<!-- ** dependencies ** -->
<app-show-dependencies

View File

@@ -11,10 +11,6 @@ import {
PackageStatus,
PrimaryStatus,
} from 'src/app/services/pkg-status-rendering.service'
import {
ConnectionFailure,
ConnectionService,
} from 'src/app/services/connection.service'
import { map, startWith, filter } from 'rxjs/operators'
import { ActivatedRoute } from '@angular/router'
import { getPkgId } from '@start9labs/shared'
@@ -66,32 +62,26 @@ export class AppShowPage {
readonly altMarketplaceData$: Observable<UIMarketplaceData | undefined> =
this.marketplaceService.getAltMarketplace()
readonly connectionFailure$ = this.connectionService
.watchFailure$()
.pipe(map(failure => failure !== ConnectionFailure.None))
constructor(
private readonly route: ActivatedRoute,
private readonly navCtrl: NavController,
private readonly patch: PatchDbService,
private readonly connectionService: ConnectionService,
@Inject(AbstractMarketplaceService)
private readonly marketplaceService: MarketplaceService,
) {}
isInstalled(
{ state }: PackageDataEntry,
{ primary }: PackageStatus,
): boolean {
return (
state === PackageState.Installed && primary !== PrimaryStatus.BackingUp
)
isInstalled({ state }: PackageDataEntry): boolean {
return state === PackageState.Installed
}
isRunning({ primary }: PackageStatus): boolean {
return primary === PrimaryStatus.Running
}
isBackingUp({ primary }: PackageStatus): boolean {
return primary === PrimaryStatus.BackingUp
}
showProgress({ state }: PackageDataEntry): boolean {
return STATES.includes(state)
}

View File

@@ -3,7 +3,7 @@
>
<ng-container *ngIf="checks.length">
<ion-item-divider>Health Checks</ion-item-divider>
<ng-container *ngIf="connectionFailure; else connected">
<ng-container *ngIf="disconnected$ | async; else connected">
<ion-item *ngFor="let health of checks">
<ion-avatar slot="start">
<ion-skeleton-text class="avatar"></ion-skeleton-text>

View File

@@ -1,4 +1,5 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
import { ConnectionService } from 'src/app/services/connection.service'
import {
HealthResult,
PackageDataEntry,
@@ -14,11 +15,12 @@ export class AppShowHealthChecksComponent {
@Input()
pkg: PackageDataEntry
@Input()
connectionFailure = false
HealthResult = HealthResult
readonly disconnected$ = this.connectionService.watchDisconnected$()
constructor(private readonly connectionService: ConnectionService) {}
isLoading(result: HealthResult): boolean {
return result === HealthResult.Starting || result === HealthResult.Loading
}

View File

@@ -4,7 +4,6 @@
<status
size="x-large"
weight="500"
[disconnected]="connectionFailure"
[installProgress]="pkg['install-progress']"
[rendering]="PR[status.primary]"
[sigtermTimeout]="pkg.manifest.main['sigterm-timeout']"
@@ -12,7 +11,7 @@
</ion-label>
</ion-item>
<ng-container *ngIf="isInstalled">
<ng-container *ngIf="isInstalled && !(disconnected$ | async)">
<ion-grid>
<ion-row style="padding-left: 12px">
<ion-col>
@@ -32,7 +31,7 @@
</ng-container>
<ion-button
*ngIf="isStopped"
*ngIf="isStopped && pkgStatus?.configured"
class="action-button"
color="success"
(click)="tryStart()"

View File

@@ -12,15 +12,12 @@ import {
Status,
} from 'src/app/services/patch-db/data-model'
import { ErrorToastService } from '@start9labs/shared'
import {
AlertController,
IonicSafeString,
LoadingController,
} from '@ionic/angular'
import { AlertController, LoadingController } from '@ionic/angular'
import { ApiService } from 'src/app/services/api/embassy-api.service'
import { ModalService } from 'src/app/services/modal.service'
import { DependencyInfo } from '../../pipes/to-dependencies.pipe'
import { hasCurrentDeps } from 'src/app/util/has-deps'
import { ConnectionService } from 'src/app/services/connection.service'
@Component({
selector: 'app-show-status',
@@ -32,9 +29,6 @@ export class AppShowStatusComponent {
@Input()
pkg: PackageDataEntry
@Input()
connectionFailure = false
@Input()
status: PackageStatus
@@ -43,6 +37,8 @@ export class AppShowStatusComponent {
PR = PrimaryRendering
disconnected$ = this.connectionService.watchDisconnected$()
constructor(
private readonly alertCtrl: AlertController,
private readonly errToast: ErrorToastService,
@@ -50,6 +46,7 @@ export class AppShowStatusComponent {
private readonly embassyApi: ApiService,
private readonly launcherService: UiLauncherService,
private readonly modalService: ModalService,
private readonly connectionService: ConnectionService,
) {}
get interfaces(): Record<string, InterfaceDef> {
@@ -61,7 +58,7 @@ export class AppShowStatusComponent {
}
get isInstalled(): boolean {
return this.pkg.state === PackageState.Installed && !this.connectionFailure
return this.pkg.state === PackageState.Installed
}
get isRunning(): boolean {
@@ -69,10 +66,7 @@ export class AppShowStatusComponent {
}
get isStopped(): boolean {
return (
this.status.primary === PrimaryStatus.Stopped &&
!!this.pkgStatus?.configured
)
return this.status.primary === PrimaryStatus.Stopped
}
launchUi(): void {
@@ -155,6 +149,7 @@ export class AppShowStatusComponent {
cssClass: 'enter-click',
},
],
cssClass: 'alert-warning-message',
})
await alert.present()

View File

@@ -6,6 +6,7 @@
<marketplace-categories
[categories]="categories"
[category]="category"
[updatesAvailable]="(pkgs | filterPackages: '':'updates':localPkgs).length"
(categoryChange)="onCategoryChange($event)"
></marketplace-categories>

View File

@@ -1,14 +1,14 @@
<ng-container *ngIf="localPkg; else none" [ngSwitch]="localPkg.state">
<ng-container *ngIf="localPkg" [ngSwitch]="localPkg.state">
<div *ngSwitchCase="PackageState.Installed">
<ion-text
*ngIf="(version | compareEmver: localVersion) === 0"
color="success"
*ngIf="(version | compareEmver: localVersion) !== 1"
color="primary"
>
Installed
</ion-text>
<ion-text
*ngIf="(version | compareEmver: localVersion) === 1"
color="warning"
color="success"
>
Update Available
</ion-text>
@@ -29,6 +29,3 @@
</ion-text>
</div>
</ng-container>
<ng-template #none>
<ion-text style="color: var(--ion-color-step-450)">Not Installed</ion-text>
</ng-template>

View File

@@ -0,0 +1,3 @@
ion-text {
font-weight: bold;
}

View File

@@ -7,6 +7,7 @@ import {
@Component({
selector: 'marketplace-status',
templateUrl: 'marketplace-status.component.html',
styleUrls: ['marketplace-status.component.scss'],
})
export class MarketplaceStatusComponent {
@Input()

View File

@@ -67,7 +67,12 @@
<ng-container *ngIf="notifications.length">
<ion-item-group style="margin-bottom: 16px">
<ion-item-divider>
<ion-button slot="end" fill="clear" (click)="presentAlertDeleteAll()">
<ion-button
slot="end"
fill="clear"
(click)="presentAlertDeleteAll()"
strong
>
Delete All
</ion-button>
</ion-item-divider>

View File

@@ -14,7 +14,7 @@
<ion-icon slot="start" name="add" color="dark"></ion-icon>
<ion-label>
<ion-text color="dark">
<b>Add alt marketplace</b>
<b>Add Alt Marketplace</b>
</ion-text>
</ion-label>
</ion-item>

View File

@@ -64,11 +64,10 @@
*ngIf="otherSessions.length"
slot="end"
fill="clear"
color="danger"
strong
(click)="presentAlertKillAll()"
>
Kill All
Log out all
</ion-button>
</ion-item-divider>
<div *ngFor="let session of otherSessions">
@@ -86,10 +85,9 @@
<ion-button
slot="end"
fill="clear"
color="danger"
(click)="presentAlertKill(session.id)"
>
<ion-icon slot="icon-only" name="close"></ion-icon>
<ion-icon slot="icon-only" name="log-out-outline"></ion-icon>
</ion-button>
</ion-item>
</div>

View File

@@ -54,7 +54,7 @@ export class SessionsPage {
const alert = await this.alertCtrl.create({
header: 'Confirm',
message: new IonicSafeString(
`Kill all sessions?<br /><br />Note: you will <b>not</b> be logged out of your current session on this device.`,
`Log out <b>all</b> other web sessions?<br /><br />Note: you will <b>not</b> be logged out of your current session on this device.`,
),
buttons: [
{
@@ -62,7 +62,7 @@ export class SessionsPage {
role: 'cancel',
},
{
text: 'Kill All',
text: 'Log out all',
handler: () => {
this.kill(this.otherSessions.map(s => s.id))
},
@@ -76,14 +76,14 @@ export class SessionsPage {
async presentAlertKill(id: string) {
const alert = await this.alertCtrl.create({
header: 'Confirm',
message: `Kill this session?`,
message: 'Log out other web session?',
buttons: [
{
text: 'Cancel',
role: 'cancel',
},
{
text: 'Kill',
text: 'Log Out',
handler: () => {
this.kill([id])
},
@@ -96,7 +96,7 @@ export class SessionsPage {
async kill(ids: string[]): Promise<void> {
const loader = await this.loadingCtrl.create({
message: 'Killing session...',
message: `Logging out session${ids.length > 1 ? 's' : ''}...`,
})
await loader.present()

View File

@@ -27,7 +27,7 @@
<ion-item button detail="false" (click)="presentModalAdd()">
<ion-icon slot="start" name="add" color="dark"></ion-icon>
<ion-label>
<b>Add new key</b>
<b>Add New Key</b>
</ion-label>
</ion-item>

View File

@@ -165,7 +165,7 @@
<ion-item button detail="false" (click)="presentModalAdd()">
<ion-icon slot="start" name="add" color="dark"></ion-icon>
<ion-label>
<b>Join another network</b>
<b>Join Another Network</b>
</ion-label>
</ion-item>
</ng-container>

View File

@@ -5,8 +5,6 @@ import {
fromEvent,
merge,
Observable,
Subject,
Subscription,
} from 'rxjs'
import { PatchConnection, PatchDbService } from './patch-db/patch-db.service'
import {
@@ -30,7 +28,9 @@ export class ConnectionService {
map(() => navigator.onLine),
)
private readonly connectionFailure$ = new Subject<ConnectionFailure>()
private readonly connectionFailure$ = new BehaviorSubject<ConnectionFailure>(
ConnectionFailure.None,
)
constructor(
private readonly configService: ConfigService,
@@ -41,6 +41,12 @@ export class ConnectionService {
return this.connectionFailure$.asObservable()
}
watchDisconnected$() {
return this.connectionFailure$.pipe(
map(failure => failure !== ConnectionFailure.None),
)
}
start(): Observable<unknown> {
return combineLatest([
// 1