fix ui address bug and streamline install flow

This commit is contained in:
Matt Hill
2021-09-08 21:51:01 -06:00
committed by Aiden McClelland
parent 45d945db2e
commit c5585f7f35
12 changed files with 78 additions and 82 deletions

View File

@@ -11,50 +11,6 @@ export class WizardBaker {
private readonly embassyApi: ApiService, private readonly embassyApi: ApiService,
) { } ) { }
install (values: {
id: string
title: string
version: string
installAlert?: string
}): InstallWizardComponent['params'] {
const { id, title, version, installAlert } = values
const action = 'install'
const toolbar: TopbarParams = { action, title, version }
const slideDefinitions: SlideDefinition[] = [
installAlert ? {
slide: {
selector: 'alert',
params: {
title: 'Warning',
message: installAlert,
titleColor: 'warning',
},
},
bottomBar: {
cancel: { afterLoading: { text: 'Cancel' } }, next: 'Next',
},
} : undefined,
{
slide: {
selector: 'complete',
params: {
action,
verb: 'beginning installation for',
title,
executeAction: () => this.embassyApi.installPackage({ id, version }),
},
},
bottomBar: {
cancel: { whileLoading: { } },
finish: 'Dismiss',
},
},
]
return { toolbar, slideDefinitions: slideDefinitions.filter(exists) }
}
update (values: { update (values: {
id: string id: string
title: string title: string

View File

@@ -33,7 +33,6 @@ export class GenericFormPage {
text: '', text: '',
handler: () => Promise.resolve(true), handler: () => Promise.resolve(true),
} }
console.log(this.submitBtn)
} }
async dismiss (): Promise<void> { async dismiss (): Promise<void> {

View File

@@ -11,13 +11,13 @@
<ion-item-group> <ion-item-group>
<!-- iff ui --> <!-- iff ui -->
<ng-container *ngIf="ui"> <ng-container *ngIf="ui">
<ion-item-divider>Web User Interface</ion-item-divider> <ion-item-divider>User Interface</ion-item-divider>
<app-interfaces-item [interface]="ui"></app-interfaces-item> <app-interfaces-item [interface]="ui"></app-interfaces-item>
</ng-container> </ng-container>
<!-- other interface --> <!-- other interface -->
<ng-container *ngIf="other.length"> <ng-container *ngIf="other.length">
<ion-item-divider>Other Interfaces</ion-item-divider> <ion-item-divider>Machine Interfaces</ion-item-divider>
<div *ngFor="let interface of other" style="margin-bottom: 30px;"> <div *ngFor="let interface of other" style="margin-bottom: 30px;">
<app-interfaces-item [interface]="interface"></app-interfaces-item> <app-interfaces-item [interface]="interface"></app-interfaces-item>
</div> </div>

View File

@@ -1,6 +1,7 @@
import { Component, Input, ViewChild } from '@angular/core' import { Component, Input, ViewChild } from '@angular/core'
import { ActivatedRoute } from '@angular/router' import { ActivatedRoute } from '@angular/router'
import { IonContent, ToastController } from '@ionic/angular' import { IonContent, ToastController } from '@ionic/angular'
import { getUiInterfaceKey } from 'src/app/services/config.service'
import { InstalledPackageDataEntry, InterfaceDef } from 'src/app/services/patch-db/data-model' import { InstalledPackageDataEntry, InterfaceDef } from 'src/app/services/patch-db/data-model'
import { PatchDbService } from 'src/app/services/patch-db/patch-db.service' import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
import { copyToClipboard } from 'src/app/util/web.util' import { copyToClipboard } from 'src/app/util/web.util'
@@ -29,13 +30,14 @@ export class AppInterfacesPage {
const pkgId = this.route.snapshot.paramMap.get('pkgId') const pkgId = this.route.snapshot.paramMap.get('pkgId')
const pkg = this.patch.data['package-data'][pkgId] const pkg = this.patch.data['package-data'][pkgId]
const interfaces = pkg.manifest.interfaces const interfaces = pkg.manifest.interfaces
const addressesMap = pkg.installed['interface-addresses'] const uiKey = getUiInterfaceKey(interfaces)
const ui = interfaces['ui']
if (ui) { const addressesMap = pkg.installed['interface-addresses']
const uiAddresses = addressesMap['ui']
if (uiKey) {
const uiAddresses = addressesMap[uiKey]
this.ui = { this.ui = {
def: ui, def: interfaces[uiKey],
addresses: { addresses: {
'lan-address': uiAddresses['lan-address'] ? 'https://' + uiAddresses['lan-address'] : null, 'lan-address': uiAddresses['lan-address'] ? 'https://' + uiAddresses['lan-address'] : null,
'tor-address': uiAddresses['tor-address'] ? 'http://' + uiAddresses['tor-address'] : null, 'tor-address': uiAddresses['tor-address'] ? 'http://' + uiAddresses['tor-address'] : null,
@@ -44,7 +46,7 @@ export class AppInterfacesPage {
} }
this.other = Object.keys(interfaces) this.other = Object.keys(interfaces)
.filter(key => key !== 'ui') .filter(key => key !== uiKey)
.map(key => { .map(key => {
const addresses = addressesMap[key] const addresses = addressesMap[key]
return { return {

View File

@@ -50,7 +50,6 @@ export class AppListPage {
}), }),
) )
.subscribe(pkgs => { .subscribe(pkgs => {
console.log('PACKAGES LIST', pkgs)
this.loading = false this.loading = false
const ids = Object.keys(pkgs) const ids = Object.keys(pkgs)
@@ -77,7 +76,6 @@ export class AppListPage {
} }
// subscribe to pkg // subscribe to pkg
this.pkgs[id].sub = this.patch.watch$('package-data', id).subscribe(pkg => { this.pkgs[id].sub = this.patch.watch$('package-data', id).subscribe(pkg => {
console.log('SOLO PKG', id, pkg)
if (!pkg) return if (!pkg) return
let bulbClass = 'bulb-on' let bulbClass = 'bulb-on'
let img = '' let img = ''

View File

@@ -49,17 +49,17 @@
</ion-col> </ion-col>
<ion-col sizeXl="3" sizeLg="3" sizeMd="3" sizeSm="12" sizeXs="12" class="ion-align-self-center"> <ion-col sizeXl="3" sizeLg="3" sizeMd="3" sizeSm="12" sizeXs="12" class="ion-align-self-center">
<!-- no localPkg --> <!-- no localPkg -->
<ion-button *ngIf="!localPkg; else localPkg2" expand="block" (click)="install()"> <ion-button *ngIf="!localPkg; else localPkg2" expand="block" (click)="tryInstall()">
Install Install
</ion-button> </ion-button>
<!-- localPkg --> <!-- localPkg -->
<ng-template #localPkg2> <ng-template #localPkg2>
<!-- not installing, updating, or removing --> <!-- not installing, updating, or removing -->
<ng-container *ngIf="localPkg.state === PackageState.Installed"> <ng-container *ngIf="localPkg.state === PackageState.Installed">
<ion-button *ngIf="(localPkg.manifest.version | compareEmver : pkg.manifest.version) === -1" expand="block" (click)="update('update')"> <ion-button *ngIf="(localPkg.manifest.version | compareEmver : pkg.manifest.version) === -1" expand="block" (click)="presentModal('update')">
Update Update
</ion-button> </ion-button>
<ion-button *ngIf="(localPkg.manifest.version | compareEmver : pkg.manifest.version) === 1" expand="block" color="warning" (click)="update('downgrade')"> <ion-button *ngIf="(localPkg.manifest.version | compareEmver : pkg.manifest.version) === 1" expand="block" color="warning" (click)="presentModal('downgrade')">
Downgrade Downgrade
</ion-button> </ion-button>
</ng-container> </ng-container>

View File

@@ -1,6 +1,6 @@
import { Component, ViewChild } from '@angular/core' import { Component, ViewChild } from '@angular/core'
import { ActivatedRoute } from '@angular/router' import { ActivatedRoute } from '@angular/router'
import { AlertController, IonContent, ModalController, NavController } from '@ionic/angular' import { AlertController, IonContent, LoadingController, ModalController, NavController } from '@ionic/angular'
import { wizardModal } from 'src/app/components/install-wizard/install-wizard.component' import { wizardModal } from 'src/app/components/install-wizard/install-wizard.component'
import { WizardBaker } from 'src/app/components/install-wizard/prebaked-wizards' import { WizardBaker } from 'src/app/components/install-wizard/prebaked-wizards'
import { Emver } from 'src/app/services/emver.service' import { Emver } from 'src/app/services/emver.service'
@@ -12,6 +12,7 @@ import { PackageDataEntry, PackageState } from 'src/app/services/patch-db/data-m
import { MarketplaceService } from '../marketplace.service' import { MarketplaceService } from '../marketplace.service'
import { Subscription } from 'rxjs' import { Subscription } from 'rxjs'
import { MarkdownPage } from 'src/app/modals/markdown/markdown.page' import { MarkdownPage } from 'src/app/modals/markdown/markdown.page'
import { ApiService } from 'src/app/services/api/embassy-api.service'
@Component({ @Component({
selector: 'marketplace-show', selector: 'marketplace-show',
@@ -33,11 +34,13 @@ export class MarketplaceShowPage {
private readonly route: ActivatedRoute, private readonly route: ActivatedRoute,
private readonly alertCtrl: AlertController, private readonly alertCtrl: AlertController,
private readonly modalCtrl: ModalController, private readonly modalCtrl: ModalController,
private readonly loadingCtrl: LoadingController,
private readonly errToast: ErrorToastService, private readonly errToast: ErrorToastService,
private readonly wizardBaker: WizardBaker, private readonly wizardBaker: WizardBaker,
private readonly navCtrl: NavController, private readonly navCtrl: NavController,
private readonly emver: Emver, private readonly emver: Emver,
private readonly patch: PatchDbService, private readonly patch: PatchDbService,
private readonly embassyApi: ApiService,
public readonly marketplaceService: MarketplaceService, public readonly marketplaceService: MarketplaceService,
) { } ) { }
@@ -121,21 +124,34 @@ export class MarketplaceShowPage {
await modal.present() await modal.present()
} }
async install () { async tryInstall () {
const { id, title, version, alerts } = this.marketplaceService.pkgs[this.pkgId].manifest const { id, title, version, alerts } = this.marketplaceService.pkgs[this.pkgId].manifest
const { cancelled } = await wizardModal(
this.modalCtrl, if (!alerts.install) {
this.wizardBaker.install({ await this.install(id, version)
id, } else {
title, const alert = await this.alertCtrl.create({
version, header: title,
installAlert: alerts.install, subHeader: version,
}), message: alerts.install,
) buttons: [
if (cancelled) return {
text: 'Cancel',
role: 'cancel',
},
{
text: 'Install',
handler: () => {
this.install(id, version)
},
},
],
})
await alert.present()
}
} }
async update (action: 'update' | 'downgrade') { async presentModal (action: 'update' | 'downgrade') {
const { id, title, version, dependencies, alerts } = this.marketplaceService.pkgs[this.pkgId].manifest const { id, title, version, dependencies, alerts } = this.marketplaceService.pkgs[this.pkgId].manifest
const value = { const value = {
id, id,
@@ -160,4 +176,21 @@ export class MarketplaceShowPage {
dismissRec () { dismissRec () {
this.showRec = false this.showRec = false
} }
private async install (id: string, version?: string): Promise<void> {
const loader = await this.loadingCtrl.create({
spinner: 'lines',
message: 'Beginning Installation',
cssClass: 'loader',
})
loader.present()
try {
await this.embassyApi.installPackage({ id, version })
} catch (e) {
this.errToast.present(e)
} finally {
loader.dismiss()
}
}
} }

View File

@@ -7,7 +7,6 @@ import { InstallProgress } from '../services/patch-db/data-model'
export class InstallState implements PipeTransform { export class InstallState implements PipeTransform {
transform (loadData: InstallProgress): ProgressData { transform (loadData: InstallProgress): ProgressData {
console.log('LOAD DATA', loadData)
let { downloaded, validated, unpacked, size, 'download-complete': downloadComplete, 'validation-complete': validationComplete, 'unpack-complete': unpackComplete } = loadData let { downloaded, validated, unpacked, size, 'download-complete': downloadComplete, 'validation-complete': validationComplete, 'unpack-complete': unpackComplete } = loadData
downloaded = downloadComplete ? size : downloaded downloaded = downloadComplete ? size : downloaded
validated = validationComplete ? size : validated validated = validationComplete ? size : validated

View File

@@ -366,7 +366,7 @@ export module Mock {
rpc: { rpc: {
name: 'RPC interface', name: 'RPC interface',
description: 'Good for connecting to your node at a distance.', description: 'Good for connecting to your node at a distance.',
ui: true, ui: false,
'tor-config': { 'tor-config': {
'port-mapping': { }, 'port-mapping': { },
}, },

View File

@@ -77,7 +77,6 @@ export class MockApiService extends ApiService {
await pauseFor(2000) await pauseFor(2000)
let entries let entries
if (Math.random() < .2) { if (Math.random() < .2) {
console.log('last page')
entries = Mock.ServerLogs entries = Mock.ServerLogs
} else { } else {
const arrLength = params.limit ? Math.ceil(params.limit / Mock.ServerLogs.length) : 10 const arrLength = params.limit ? Math.ceil(params.limit / Mock.ServerLogs.length) : 10
@@ -324,7 +323,6 @@ export class MockApiService extends ApiService {
await pauseFor(2000) await pauseFor(2000)
let entries let entries
if (Math.random() < .2) { if (Math.random() < .2) {
console.log('last page')
entries = Mock.PackageLogs entries = Mock.PackageLogs
} else { } else {
const arrLength = params.limit ? Math.ceil(params.limit / Mock.PackageLogs.length) : 10 const arrLength = params.limit ? Math.ceil(params.limit / Mock.PackageLogs.length) : 10

View File

@@ -67,31 +67,43 @@ export class ConfigService {
} }
export function hasTorUi (interfaces: { [id: string]: InterfaceDef }): boolean { export function hasTorUi (interfaces: { [id: string]: InterfaceDef }): boolean {
return !!Object.values(interfaces).find(i => i.ui && i['tor-config']) const int = getUiInterfaceValue(interfaces)
return !!int?.['tor-config']
} }
export function hasLanUi (interfaces: { [id: string]: InterfaceDef }): boolean { export function hasLanUi (interfaces: { [id: string]: InterfaceDef }): boolean {
return !!Object.values(interfaces).find(i => i.ui && i['lan-config']) const int = getUiInterfaceValue(interfaces)
return !!int?.['lan-config']
} }
export function torUiAddress (pkg: PackageDataEntry): string { export function torUiAddress (pkg: PackageDataEntry): string {
return pkg.installed?.['interface-addresses']?.ui?.['tor-address'] const key = getUiInterfaceKey(pkg.manifest.interfaces)
return pkg.installed['interface-addresses'][key]['tor-address']
} }
export function lanUiAddress (pkg: PackageDataEntry): string { export function lanUiAddress (pkg: PackageDataEntry): string {
return pkg.installed?.['interface-addresses']?.ui?.['lan-address'] const key = getUiInterfaceKey(pkg.manifest.interfaces)
return pkg.installed['interface-addresses'][key]['lan-address']
} }
export function hasUi (interfaces: { [id: string]: InterfaceDef }): boolean { export function hasUi (interfaces: { [id: string]: InterfaceDef }): boolean {
return hasTorUi(interfaces) || hasLanUi(interfaces) return hasTorUi(interfaces) || hasLanUi(interfaces)
} }
function removeProtocol (str: string): string { export function removeProtocol (str: string): string {
if (str.startsWith('http://')) return str.slice(7) if (str.startsWith('http://')) return str.slice(7)
if (str.startsWith('https://')) return str.slice(8) if (str.startsWith('https://')) return str.slice(8)
return str return str
} }
function removePort (str: string): string { export function removePort (str: string): string {
return str.split(':')[0] return str.split(':')[0]
} }
export function getUiInterfaceKey (interfaces: { [id: string]: InterfaceDef }): string {
return Object.keys(interfaces).find(key => interfaces[key].ui)
}
export function getUiInterfaceValue (interfaces: { [id: string]: InterfaceDef }): InterfaceDef {
return Object.values(interfaces).find(i => i.ui)
}

View File

@@ -79,7 +79,6 @@ export class HttpService {
case Method.PATCH: req = this.http.patch(url, httpOpts.body, options) as any; break case Method.PATCH: req = this.http.patch(url, httpOpts.body, options) as any; break
case Method.DELETE: req = this.http.delete(url, options) as any; break case Method.DELETE: req = this.http.delete(url, options) as any; break
} }
console.log('REQUEST', options)
return (httpOpts.timeout ? withTimeout(req, httpOpts.timeout) : req) return (httpOpts.timeout ? withTimeout(req, httpOpts.timeout) : req)
.toPromise() .toPromise()