mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 20:14:49 +00:00
fix ui address bug and streamline install flow
This commit is contained in:
committed by
Aiden McClelland
parent
45d945db2e
commit
c5585f7f35
@@ -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
|
||||||
|
|||||||
@@ -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> {
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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 = ''
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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': { },
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
Reference in New Issue
Block a user