config could take a while

This commit is contained in:
Drew Ansbacher
2022-02-10 13:06:07 -07:00
committed by Aiden McClelland
parent d82092c5a5
commit ed6ad25565

View File

@@ -1,5 +1,11 @@
import { Component, Input, ViewChild } from '@angular/core' import { Component, Input, ViewChild } from '@angular/core'
import { AlertController, ModalController, IonContent, LoadingController, IonicSafeString } from '@ionic/angular' import {
AlertController,
ModalController,
IonContent,
LoadingController,
IonicSafeString,
} from '@ionic/angular'
import { ApiService } from 'src/app/services/api/embassy-api.service' import { ApiService } from 'src/app/services/api/embassy-api.service'
import { DependentInfo, isEmptyObject, isObject } from 'src/app/util/misc.util' import { DependentInfo, isEmptyObject, isObject } from 'src/app/util/misc.util'
import { wizardModal } from 'src/app/components/install-wizard/install-wizard.component' import { wizardModal } from 'src/app/components/install-wizard/install-wizard.component'
@@ -7,9 +13,15 @@ import { WizardBaker } from 'src/app/components/install-wizard/prebaked-wizards'
import { ConfigSpec } from 'src/app/pkg-config/config-types' import { ConfigSpec } from 'src/app/pkg-config/config-types'
import { PackageDataEntry } from 'src/app/services/patch-db/data-model' import { PackageDataEntry } 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 { ErrorToastService, getErrorMessage } from 'src/app/services/error-toast.service' import {
ErrorToastService,
getErrorMessage,
} from 'src/app/services/error-toast.service'
import { FormGroup } from '@angular/forms' import { FormGroup } from '@angular/forms'
import { convertValuesRecursive, FormService } from 'src/app/services/form.service' import {
convertValuesRecursive,
FormService,
} from 'src/app/services/form.service'
import { compare, Operation, getValueByPointer } from 'fast-json-patch' import { compare, Operation, getValueByPointer } from 'fast-json-patch'
@Component({ @Component({
@@ -31,7 +43,7 @@ export class AppConfigPage {
saving = false saving = false
loadingError: string | IonicSafeString loadingError: string | IonicSafeString
constructor ( constructor(
private readonly wizardBaker: WizardBaker, private readonly wizardBaker: WizardBaker,
private readonly embassyApi: ApiService, private readonly embassyApi: ApiService,
private readonly errToast: ErrorToastService, private readonly errToast: ErrorToastService,
@@ -40,9 +52,9 @@ export class AppConfigPage {
private readonly modalCtrl: ModalController, private readonly modalCtrl: ModalController,
private readonly formService: FormService, private readonly formService: FormService,
private readonly patch: PatchDbService, private readonly patch: PatchDbService,
) { } ) {}
async ngOnInit () { async ngOnInit() {
this.pkg = this.patch.getData()['package-data'][this.pkgId] this.pkg = this.patch.getData()['package-data'][this.pkgId]
this.hasConfig = !!this.pkg.manifest.config this.hasConfig = !!this.pkg.manifest.config
@@ -55,21 +67,33 @@ export class AppConfigPage {
let patch: Operation[] let patch: Operation[]
if (this.dependentInfo) { if (this.dependentInfo) {
this.loadingText = `Setting properties to accommodate ${this.dependentInfo.title}` this.loadingText = `Setting properties to accommodate ${this.dependentInfo.title}`
const { 'old-config': oc, 'new-config': nc, spec: s } = await this.embassyApi.dryConfigureDependency({ 'dependency-id': this.pkgId, 'dependent-id': this.dependentInfo.id }) const {
'old-config': oc,
'new-config': nc,
spec: s,
} = await this.embassyApi.dryConfigureDependency({
'dependency-id': this.pkgId,
'dependent-id': this.dependentInfo.id,
})
oldConfig = oc oldConfig = oc
newConfig = nc newConfig = nc
spec = s spec = s
patch = compare(oldConfig, newConfig) patch = compare(oldConfig, newConfig)
} else { } else {
this.loadingText = 'Loading Config' this.loadingText = 'Loading Config'
const { config: c, spec: s } = await this.embassyApi.getPackageConfig({ id: this.pkgId }) const { config: c, spec: s } = await this.embassyApi.getPackageConfig({
id: this.pkgId,
})
oldConfig = c oldConfig = c
spec = s spec = s
} }
this.original = oldConfig this.original = oldConfig
this.configSpec = spec this.configSpec = spec
this.configForm = this.formService.createForm(spec, newConfig || oldConfig) this.configForm = this.formService.createForm(
spec,
newConfig || oldConfig,
)
this.configForm.markAllAsTouched() this.configForm.markAllAsTouched()
if (patch) { if (patch) {
@@ -83,17 +107,17 @@ export class AppConfigPage {
} }
} }
ngAfterViewInit () { ngAfterViewInit() {
this.content.scrollToPoint(undefined, 1) this.content.scrollToPoint(undefined, 1)
} }
resetDefaults () { resetDefaults() {
this.configForm = this.formService.createForm(this.configSpec) this.configForm = this.formService.createForm(this.configSpec)
const patch = compare(this.original, this.configForm.value) const patch = compare(this.original, this.configForm.value)
this.markDirty(patch) this.markDirty(patch)
} }
async dismiss () { async dismiss() {
if (this.configForm?.dirty) { if (this.configForm?.dirty) {
await this.presentAlertUnsaved() await this.presentAlertUnsaved()
} else { } else {
@@ -101,17 +125,19 @@ export class AppConfigPage {
} }
} }
async save () { async save() {
convertValuesRecursive(this.configSpec, this.configForm) convertValuesRecursive(this.configSpec, this.configForm)
if (this.configForm.invalid) { if (this.configForm.invalid) {
document.getElementsByClassName('validation-error')[0].parentElement.parentElement.scrollIntoView({ behavior: 'smooth' }) document
.getElementsByClassName('validation-error')[0]
.parentElement.parentElement.scrollIntoView({ behavior: 'smooth' })
return return
} }
const loader = await this.loadingCtrl.create({ const loader = await this.loadingCtrl.create({
spinner: 'lines', spinner: 'lines',
message: `Saving config...`, message: `Saving config. This could take a while...`,
cssClass: 'loader', cssClass: 'loader',
}) })
await loader.present() await loader.present()
@@ -150,7 +176,7 @@ export class AppConfigPage {
} }
} }
private getDiff (patch: Operation[]): string[] { private getDiff(patch: Operation[]): string[] {
return patch.map(op => { return patch.map(op => {
let message: string let message: string
switch (op.op) { switch (op.op) {
@@ -161,7 +187,9 @@ export class AppConfigPage {
message = `Removed ${this.getOldValue(op.path)}` message = `Removed ${this.getOldValue(op.path)}`
break break
case 'replace': case 'replace':
message = `Changed from ${this.getOldValue(op.path)} to ${this.getNewValue(op.value)}` message = `Changed from ${this.getOldValue(
op.path,
)} to ${this.getNewValue(op.value)}`
break break
default: default:
message = `Unknown operation` message = `Unknown operation`
@@ -169,12 +197,13 @@ export class AppConfigPage {
let displayPath: string let displayPath: string
const arrPath = op.path.substring(1) const arrPath = op.path
.split('/') .substring(1)
.map(node => { .split('/')
const num = Number(node) .map(node => {
return isNaN(num) ? node : num const num = Number(node)
}) return isNaN(num) ? node : num
})
if (typeof arrPath[arrPath.length - 1] === 'number') { if (typeof arrPath[arrPath.length - 1] === 'number') {
arrPath.pop() arrPath.pop()
@@ -186,7 +215,7 @@ export class AppConfigPage {
}) })
} }
private getOldValue (path: any): string { private getOldValue(path: any): string {
const val = getValueByPointer(this.original, path) const val = getValueByPointer(this.original, path)
if (['string', 'number', 'boolean'].includes(typeof val)) { if (['string', 'number', 'boolean'].includes(typeof val)) {
return val return val
@@ -197,7 +226,7 @@ export class AppConfigPage {
} }
} }
private getNewValue (val: any): string { private getNewValue(val: any): string {
if (['string', 'number', 'boolean'].includes(typeof val)) { if (['string', 'number', 'boolean'].includes(typeof val)) {
return val return val
} else if (isObject(val)) { } else if (isObject(val)) {
@@ -207,14 +236,15 @@ export class AppConfigPage {
} }
} }
private markDirty (patch: Operation[]) { private markDirty(patch: Operation[]) {
patch.forEach(op => { patch.forEach(op => {
const arrPath = op.path.substring(1) const arrPath = op.path
.split('/') .substring(1)
.map(node => { .split('/')
const num = Number(node) .map(node => {
return isNaN(num) ? node : num const num = Number(node)
}) return isNaN(num) ? node : num
})
if (op.op !== 'remove') this.configForm.get(arrPath).markAsDirty() if (op.op !== 'remove') this.configForm.get(arrPath).markAsDirty()
@@ -225,7 +255,7 @@ export class AppConfigPage {
}) })
} }
private async presentAlertUnsaved () { private async presentAlertUnsaved() {
const alert = await this.alertCtrl.create({ const alert = await this.alertCtrl.create({
header: 'Unsaved Changes', header: 'Unsaved Changes',
message: 'You have unsaved changes. Are you sure you want to leave?', message: 'You have unsaved changes. Are you sure you want to leave?',
@@ -246,4 +276,3 @@ export class AppConfigPage {
await alert.present() await alert.present()
} }
} }