Update/misc frontend (#2191)

* update version to 0.3.4

* update release  guide with sdk instructions

* remove comment

* update page styling

* closes #2152, closes #2155, closes #2157

* move marketing site link to description block

* re-arrange setup wizard recovery options

* move divider for update list item

* fix bug in mocks to display lnd as aavailable for update

---------

Co-authored-by: Matt Hill <matthewonthemoon@gmail.com>
This commit is contained in:
Lucy C
2023-03-09 07:02:48 -07:00
committed by GitHub
parent c9fceafc16
commit c8d89f805b
18 changed files with 268 additions and 213 deletions

View File

@@ -9,7 +9,6 @@ import {
import { ApiService } from 'src/app/services/api/embassy-api.service'
import { ActivatedRoute } from '@angular/router'
import { PatchDB } from 'patch-db-client'
import { ServerNameService } from 'src/app/services/server-name.service'
import { combineLatest, firstValueFrom, map, Observable, of } from 'rxjs'
import { ErrorToastService } from '@start9labs/shared'
import { EOSService } from 'src/app/services/eos.service'
@@ -52,7 +51,6 @@ export class ServerShowPage {
private readonly patch: PatchDB<DataModel>,
private readonly eosService: EOSService,
private readonly ClientStorageService: ClientStorageService,
private readonly serverNameService: ServerNameService,
private readonly authService: AuthService,
private readonly toastCtrl: ToastController,
private readonly config: ConfigService,
@@ -60,19 +58,18 @@ export class ServerShowPage {
) {}
async presentModalName(): Promise<void> {
const name = await firstValueFrom(this.serverNameService.name$)
const chosenName = await firstValueFrom(this.patch.watch$('ui', 'name'))
const options: GenericInputOptions = {
title: 'Set Device Name',
message: 'This will be displayed in your browser tab',
label: 'Device Name',
useMask: false,
placeholder: name.default,
placeholder: 'embassyOS',
nullable: true,
initialValue: name.current,
initialValue: chosenName,
buttonText: 'Save',
submitFn: (value: string) =>
this.setDbValue('name', value || name.default),
submitFn: (name: string) => this.setName(name || null),
}
const modal = await this.modalCtrl.create({
@@ -227,14 +224,14 @@ export class ServerShowPage {
}
}
private async setDbValue(key: string, value: string): Promise<void> {
private async setName(value: string | null): Promise<void> {
const loader = await this.loadingCtrl.create({
message: 'Saving...',
})
await loader.present()
try {
await this.embassyApi.setDbValue<string>([key], value)
await this.embassyApi.setDbValue<string | null>(['name'], value)
} finally {
loader.dismiss()
}
@@ -393,8 +390,8 @@ export class ServerShowPage {
disabled$: this.eosService.updatingOrBackingUp$,
},
{
title: 'Set Device Name',
description: 'Give your device a name for easy identification',
title: 'Browser Tab Title',
description: `Customize the display name of your browser tab. This does not affect your server's LAN address.`,
icon: 'pricetag-outline',
action: () => this.presentModalName(),
detail: false,
@@ -429,7 +426,7 @@ export class ServerShowPage {
disabled$: of(false),
},
{
title: 'Sideload Service',
title: 'Sideload a Service',
description: `Manually install a service`,
icon: 'push-outline',
action: () =>

View File

@@ -7,105 +7,127 @@
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding with-widgets">
<ion-content class="with-widgets">
<ion-item-group *ngIf="data$ | async as data">
<ng-container *ngFor="let host of data.hosts">
<ion-item-divider class="header">
<div class="inline">
<h1>{{ host.name }}</h1>
<store-icon [url]="host.url" size="24px"></store-icon>
<div class="header">
<div class="header_items">
<store-icon [url]="host.url" size="48px"></store-icon>
<div class="pl-1">
<h1>{{ host.name }}</h1>
<p>{{ host.url }}</p>
</div>
</div>
</ion-item-divider>
<div class="ion-padding-start ion-padding-bottom">
<ion-item *ngIf="data.errors.includes(host.url)">
<ion-text color="danger">Request Failed</ion-text>
</ion-item>
<ng-container
*ngIf="data.marketplace[host.url]?.packages as packages else loading"
>
<ng-container
*ngIf="packages | filterUpdates : data.localPkgs as updates"
>
<div *ngFor="let pkg of updates" class="item-container">
<ion-item lines="none">
<ng-container *ngIf="data.localPkgs[pkg.manifest.id] as local">
<ion-thumbnail
slot="start"
style="cursor: pointer"
(click)="viewInMarketplace(local)"
>
<img
[src]="'data:image/png;base64,' + pkg.icon | trustUrl"
/>
</ion-thumbnail>
<ion-label>
<h1
(click)="viewInMarketplace(local)"
style="cursor: pointer"
>
{{ pkg.manifest.title }}
</h1>
<h2 class="inline">
<span>{{ local.manifest.version | displayEmver }}</span>
&nbsp;<ion-icon name="arrow-forward"></ion-icon>&nbsp;
<ion-text color="success">
{{ pkg.manifest.version | displayEmver }}
</ion-text>
</h2>
<p
*ngIf="marketplaceService.updateErrors[pkg.manifest.id] as error"
>
<ion-text color="danger">{{ error }}</ion-text>
</p>
</ion-label>
<div slot="end" style="margin-left: 8px">
<round-progress
*ngIf="local.state === PackageState.Updating else notUpdating"
[current]="local['install-progress'] | installProgress"
[max]="100"
[radius]="24"
[stroke]="4"
[rounded]="true"
color="var(--ion-color-primary)"
></round-progress>
<ng-template #notUpdating>
<ion-spinner
*ngIf="marketplaceService.updateQueue[pkg.manifest.id] else updateBtn"
color="dark"
></ion-spinner>
<ng-template #updateBtn>
<ion-button
(click)="tryUpdate(pkg.manifest, host.url, local)"
[color]="marketplaceService.updateErrors[pkg.manifest.id] ? 'danger' : 'dark'"
strong
>
{{ marketplaceService.updateErrors[pkg.manifest.id] ?
'Retry' : 'Update' }}
</ion-button>
</ng-template>
</ng-template>
</div>
</ng-container>
</ion-item>
<div class="notes">
<h5><b>What's New</b></h5>
<p [innerHTML]="pkg.manifest['release-notes'] | markdown"></p>
</div>
</div>
<ion-item *ngIf="!updates.length">
<p>All services are up to date!</p>
</ion-item>
</ng-container>
</ng-container>
<ng-template #loading>
<skeleton-list [showAvatar]="true" [rows]="2"></skeleton-list>
</ng-template>
</div>
<ion-item *ngIf="data.errors.includes(host.url)">
<ion-text color="danger">Request Failed</ion-text>
</ion-item>
<ng-container
*ngIf="data.marketplace[host.url]?.packages as packages else loading"
>
<ng-container
*ngIf="packages | filterUpdates : data.localPkgs as updates"
>
<ion-grid>
<div *ngFor="let pkg of updates">
<ng-container *ngIf="data.localPkgs[pkg.manifest.id] as local">
<ion-row>
<ion-col>
<ion-accordion-group class="accordian-padding">
<ion-accordion class="item-container">
<ion-item slot="header">
<ion-col class="accordian-padding">
<ion-row
(click)="viewInMarketplace(local)"
style="cursor: pointer"
>
<ion-thumbnail class="align-center">
<img
[src]="'data:image/png;base64,' + pkg.icon | trustUrl"
/>
</ion-thumbnail>
<ion-label class="pl-1">
<h1>{{ pkg.manifest.title }}</h1>
<h2 class="inline">
<span>
{{ local.manifest.version | displayEmver }}
</span>
&nbsp;
<ion-icon name="arrow-forward"></ion-icon>
&nbsp;
<ion-text color="success">
{{ pkg.manifest.version | displayEmver }}
</ion-text>
</h2>
<p
*ngIf="marketplaceService.updateErrors[pkg.manifest.id] as error"
>
<ion-text color="danger">
{{ error }}
</ion-text>
</p>
</ion-label>
</ion-row>
</ion-col>
<div class="align-center">
<round-progress
*ngIf="local.state === PackageState.Updating else notUpdating"
[current]="local['install-progress'] | installProgress"
[max]="100"
[radius]="15"
[stroke]="4"
[rounded]="true"
color="var(--ion-color-primary)"
></round-progress>
<ng-template #notUpdating>
<ion-spinner
*ngIf="marketplaceService.updateQueue[pkg.manifest.id] else updateBtn"
color="dark"
></ion-spinner>
<ng-template #updateBtn>
<ion-button
(click)="tryUpdate(pkg.manifest, host.url, local)"
[color]="marketplaceService.updateErrors[pkg.manifest.id] ? 'danger' : 'tertiary'"
strong
size="default"
>
{{
marketplaceService.updateErrors[pkg.manifest.id]
? 'Retry' : 'Update' }}
</ion-button>
</ng-template>
</ng-template>
</div>
</ion-item>
<div class="ion-padding" slot="content">
<div class="notes">
<p
[innerHTML]="pkg.manifest['release-notes'] | markdown"
></p>
</div>
</div>
</ion-accordion>
</ion-accordion-group>
</ion-col>
</ion-row>
</ng-container>
</div>
</ion-grid>
<ion-item
*ngIf="!updates.length"
class="ion-text-center ion-padding"
lines="none"
>
<ion-label>All services are up to date!</ion-label>
</ion-item>
</ng-container>
</ng-container>
<ng-template #loading>
<skeleton-list [showAvatar]="true" [rows]="2"></skeleton-list>
</ng-template>
</ng-container>
</ion-item-group>
</ion-content>

View File

@@ -8,9 +8,57 @@
}
.header {
margin-bottom: 20px;
padding: 1.5rem;
background: var(--ion-color-medium-tint);
&_items {
display: flex;
align-items: center;
flex-direction: row;
}
h1 {
font-weight: bold;
margin: 0 12px 0 0;
font-size: 28px;
letter-spacing: 1px;
margin: 0 0 5px 0;
}
p {
font-size: 14px;
margin: 0;
}
}
img {
height: 85%;
width: 85%;
}
.align-center {
display: flex;
justify-content: center;
align-items: center;
}
.pl-1 {
padding-left: 1rem;
}
p {
font-size: 1rem;
margin-top: 0;
}
ion-item {
--background-hover: none;
}
.accordian-padding {
padding: 0.5rem;
}
@media (max-width: 500px) {
.accordian-padding {
padding: 0.5rem 0 0.5rem 0;
}
}