mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-27 02:41:53 +00:00
generic form options
This commit is contained in:
committed by
Aiden McClelland
parent
13cda80ee6
commit
234258a077
@@ -24,7 +24,7 @@
|
||||
<ion-toolbar class="footer">
|
||||
<ion-buttons slot="end">
|
||||
<ion-button
|
||||
class="ion-padding-end"
|
||||
class="ion-padding-end enter-click"
|
||||
*ngFor="let button of buttons"
|
||||
(click)="handleClick(button.handler)"
|
||||
>
|
||||
|
||||
@@ -22,7 +22,7 @@ export class GenericFormPage {
|
||||
@Input() title!: string
|
||||
@Input() spec!: InputSpec
|
||||
@Input() buttons!: ActionButton[]
|
||||
@Input() initialValue: object = {}
|
||||
@Input() initialValue: Record<string, any> = {}
|
||||
|
||||
submitBtn!: ActionButton
|
||||
formGroup!: UntypedFormGroup
|
||||
@@ -34,10 +34,7 @@ export class GenericFormPage {
|
||||
|
||||
ngOnInit() {
|
||||
this.formGroup = this.formService.createForm(this.spec, this.initialValue)
|
||||
this.submitBtn = this.buttons.find(btn => btn.isSubmit) || {
|
||||
text: '',
|
||||
handler: () => Promise.resolve(true),
|
||||
}
|
||||
this.submitBtn = this.buttons.find(btn => btn.isSubmit)! // @TODO this really needs to be redesigned. No way to enforce this with types.
|
||||
}
|
||||
|
||||
async dismiss(): Promise<void> {
|
||||
@@ -56,6 +53,15 @@ export class GenericFormPage {
|
||||
|
||||
// @TODO make this more like generic input component dismissal
|
||||
const success = await handler(this.formGroup.value)
|
||||
if (success !== false) this.modalCtrl.dismiss()
|
||||
if (success === true) this.modalCtrl.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
export interface GenericFormOptions {
|
||||
// required
|
||||
title: string
|
||||
spec: InputSpec
|
||||
buttons: ActionButton[]
|
||||
// optional
|
||||
initialValue?: Record<string, any>
|
||||
}
|
||||
|
||||
@@ -92,5 +92,5 @@ export interface GenericInputOptions {
|
||||
placeholder?: string
|
||||
nullable?: boolean
|
||||
useMask?: boolean
|
||||
initialValue?: string
|
||||
initialValue?: string | null
|
||||
}
|
||||
|
||||
@@ -15,7 +15,10 @@ import { ErrorToastService, sameUrl, toUrl } from '@start9labs/shared'
|
||||
import { AbstractMarketplaceService } from '@start9labs/marketplace'
|
||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||
import { ValueSpecObject } from 'start-sdk/types/config-types'
|
||||
import { GenericFormPage } from 'src/app/modals/generic-form/generic-form.page'
|
||||
import {
|
||||
GenericFormPage,
|
||||
GenericFormOptions,
|
||||
} from 'src/app/modals/generic-form/generic-form.page'
|
||||
import { PatchDB } from 'patch-db-client'
|
||||
import { DataModel, UIStore } from 'src/app/services/patch-db/data-model'
|
||||
import { MarketplaceService } from 'src/app/services/marketplace.service'
|
||||
@@ -65,27 +68,27 @@ export class MarketplaceSettingsPage {
|
||||
|
||||
async presentModalAdd() {
|
||||
const { name, spec } = getMarketplaceValueSpec()
|
||||
|
||||
const options: GenericFormOptions = {
|
||||
title: name,
|
||||
spec,
|
||||
buttons: [
|
||||
{
|
||||
text: 'Save for Later',
|
||||
handler: async (value: { url: string }) => this.saveOnly(value.url),
|
||||
},
|
||||
{
|
||||
text: 'Save and Connect',
|
||||
handler: async (value: { url: string }) =>
|
||||
this.saveAndConnect(value.url),
|
||||
isSubmit: true,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const modal = await this.modalCtrl.create({
|
||||
component: GenericFormPage,
|
||||
componentProps: {
|
||||
title: name,
|
||||
spec,
|
||||
buttons: [
|
||||
{
|
||||
text: 'Save for Later',
|
||||
handler: (value: { url: string }) => {
|
||||
this.saveOnly(value.url)
|
||||
},
|
||||
},
|
||||
{
|
||||
text: 'Save and Connect',
|
||||
handler: (value: { url: string }) => {
|
||||
this.saveAndConnect(value.url)
|
||||
},
|
||||
isSubmit: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
componentProps: options,
|
||||
cssClass: 'alertlike-modal',
|
||||
})
|
||||
|
||||
@@ -166,28 +169,32 @@ export class MarketplaceSettingsPage {
|
||||
}
|
||||
}
|
||||
|
||||
private async saveOnly(rawUrl: string): Promise<void> {
|
||||
private async saveOnly(rawUrl: string): Promise<boolean> {
|
||||
const loader = await this.loadingCtrl.create()
|
||||
|
||||
try {
|
||||
const url = new URL(rawUrl).toString()
|
||||
await this.validateAndSave(url, loader)
|
||||
return true
|
||||
} catch (e: any) {
|
||||
this.errToast.present(e)
|
||||
return false
|
||||
} finally {
|
||||
loader.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
private async saveAndConnect(rawUrl: string): Promise<void> {
|
||||
private async saveAndConnect(rawUrl: string): Promise<boolean> {
|
||||
const loader = await this.loadingCtrl.create()
|
||||
|
||||
try {
|
||||
const url = new URL(rawUrl).toString()
|
||||
await this.validateAndSave(url, loader)
|
||||
await this.connect(url, loader)
|
||||
return true
|
||||
} catch (e: any) {
|
||||
this.errToast.present(e)
|
||||
return false
|
||||
} finally {
|
||||
loader.dismiss()
|
||||
this.dismiss()
|
||||
|
||||
@@ -20,7 +20,10 @@ import {
|
||||
PackageDataEntry,
|
||||
PackageState,
|
||||
} from 'src/app/services/patch-db/data-model'
|
||||
import { GenericFormPage } from 'src/app/modals/generic-form/generic-form.page'
|
||||
import {
|
||||
GenericFormPage,
|
||||
GenericFormOptions,
|
||||
} from 'src/app/modals/generic-form/generic-form.page'
|
||||
import {
|
||||
isEmptyObject,
|
||||
ErrorToastService,
|
||||
@@ -64,22 +67,21 @@ export class AppActionsPage {
|
||||
})
|
||||
await alert.present()
|
||||
} else {
|
||||
if (!isEmptyObject(action['input-spec'] || {})) {
|
||||
if (action['input-spec'] && !isEmptyObject(action['input-spec'])) {
|
||||
const options: GenericFormOptions = {
|
||||
title: action.name,
|
||||
spec: action['input-spec'],
|
||||
buttons: [
|
||||
{
|
||||
text: 'Execute',
|
||||
handler: (value: any) => this.executeAction(action.id, value),
|
||||
isSubmit: true,
|
||||
},
|
||||
],
|
||||
}
|
||||
const modal = await this.modalCtrl.create({
|
||||
component: GenericFormPage,
|
||||
componentProps: {
|
||||
title: action.name,
|
||||
spec: action['input-spec'],
|
||||
buttons: [
|
||||
{
|
||||
text: 'Execute',
|
||||
handler: (value: any) => {
|
||||
return this.executeAction(action.id, value)
|
||||
},
|
||||
isSubmit: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
componentProps: options,
|
||||
})
|
||||
await modal.present()
|
||||
} else {
|
||||
|
||||
@@ -7,7 +7,10 @@ import { filter, take } from 'rxjs/operators'
|
||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||
import { PatchDB } from 'patch-db-client'
|
||||
import { getProjectId } from 'src/app/util/get-project-id'
|
||||
import { GenericFormPage } from '../../../modals/generic-form/generic-form.page'
|
||||
import {
|
||||
GenericFormPage,
|
||||
GenericFormOptions,
|
||||
} from '../../../modals/generic-form/generic-form.page'
|
||||
import { DataModel } from 'src/app/services/patch-db/data-model'
|
||||
|
||||
@Component({
|
||||
@@ -46,21 +49,21 @@ export class DevConfigPage {
|
||||
this.errToast.present(e)
|
||||
}
|
||||
|
||||
const options: GenericFormOptions = {
|
||||
title: 'Config Sample',
|
||||
spec: JSON.parse(JSON.stringify(doc, null, 2)),
|
||||
buttons: [
|
||||
{
|
||||
text: 'OK',
|
||||
handler: async () => true,
|
||||
isSubmit: true,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const modal = await this.modalCtrl.create({
|
||||
component: GenericFormPage,
|
||||
componentProps: {
|
||||
title: 'Config Sample',
|
||||
spec: JSON.parse(JSON.stringify(doc, null, 2)),
|
||||
buttons: [
|
||||
{
|
||||
text: 'OK',
|
||||
handler: () => {
|
||||
return
|
||||
},
|
||||
isSubmit: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
componentProps: options,
|
||||
})
|
||||
await modal.present()
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core'
|
||||
import { ActivatedRoute } from '@angular/router'
|
||||
import { LoadingController, ModalController } from '@ionic/angular'
|
||||
import { GenericFormPage } from 'src/app/modals/generic-form/generic-form.page'
|
||||
import {
|
||||
GenericFormPage,
|
||||
GenericFormOptions,
|
||||
} from 'src/app/modals/generic-form/generic-form.page'
|
||||
import { BasicInfo, getBasicInfoSpec } from './form-info'
|
||||
import { PatchDB } from 'patch-db-client'
|
||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||
@@ -29,26 +32,27 @@ export class DeveloperMenuPage {
|
||||
) {}
|
||||
|
||||
async openBasicInfoModal(data: DevProjectData) {
|
||||
const options: GenericFormOptions = {
|
||||
title: 'Basic Info',
|
||||
spec: getBasicInfoSpec(data),
|
||||
buttons: [
|
||||
{
|
||||
text: 'Save',
|
||||
handler: async (basicInfo: BasicInfo) =>
|
||||
this.saveBasicInfo(basicInfo),
|
||||
isSubmit: true,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const modal = await this.modalCtrl.create({
|
||||
component: GenericFormPage,
|
||||
componentProps: {
|
||||
title: 'Basic Info',
|
||||
spec: getBasicInfoSpec(data),
|
||||
buttons: [
|
||||
{
|
||||
text: 'Save',
|
||||
handler: (basicInfo: BasicInfo) => {
|
||||
this.saveBasicInfo(basicInfo)
|
||||
},
|
||||
isSubmit: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
componentProps: options,
|
||||
})
|
||||
await modal.present()
|
||||
}
|
||||
|
||||
async saveBasicInfo(basicInfo: BasicInfo) {
|
||||
async saveBasicInfo(basicInfo: BasicInfo): Promise<boolean> {
|
||||
const loader = await this.loadingCtrl.create({
|
||||
message: 'Saving...',
|
||||
})
|
||||
@@ -59,8 +63,10 @@ export class DeveloperMenuPage {
|
||||
['dev', this.projectId, 'basic-info'],
|
||||
basicInfo,
|
||||
)
|
||||
return true
|
||||
} catch (e: any) {
|
||||
this.errToast.present(e)
|
||||
return false
|
||||
} finally {
|
||||
loader.dismiss()
|
||||
}
|
||||
|
||||
@@ -57,7 +57,25 @@ export class ServerShowPage {
|
||||
@Inject(DOCUMENT) private readonly document: Document,
|
||||
) {}
|
||||
|
||||
async setBrowserTab(): Promise<void> {
|
||||
async launchHttps() {
|
||||
const { 'lan-address': lanAddress } = await getServerInfo(this.patch)
|
||||
window.open(lanAddress)
|
||||
}
|
||||
|
||||
addClick(title: string) {
|
||||
switch (title) {
|
||||
case 'Manage':
|
||||
this.addManageClick()
|
||||
break
|
||||
case 'Power':
|
||||
this.addPowerClick()
|
||||
break
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
private async setBrowserTab(): Promise<void> {
|
||||
const chosenName = await firstValueFrom(this.patch.watch$('ui', 'name'))
|
||||
|
||||
const options: GenericInputOptions = {
|
||||
@@ -82,14 +100,14 @@ export class ServerShowPage {
|
||||
await modal.present()
|
||||
}
|
||||
|
||||
async updateEos(): Promise<void> {
|
||||
private async updateEos(): Promise<void> {
|
||||
const modal = await this.modalCtrl.create({
|
||||
component: OSUpdatePage,
|
||||
})
|
||||
modal.present()
|
||||
}
|
||||
|
||||
async presentAlertLogout() {
|
||||
private async presentAlertLogout() {
|
||||
const alert = await this.alertCtrl.create({
|
||||
header: 'Confirm',
|
||||
message: 'Are you sure you want to log out?',
|
||||
@@ -109,7 +127,7 @@ export class ServerShowPage {
|
||||
await alert.present()
|
||||
}
|
||||
|
||||
async presentAlertRestart() {
|
||||
private async presentAlertRestart() {
|
||||
const alert = await this.alertCtrl.create({
|
||||
header: 'Restart',
|
||||
message:
|
||||
@@ -131,7 +149,7 @@ export class ServerShowPage {
|
||||
await alert.present()
|
||||
}
|
||||
|
||||
async presentAlertShutdown() {
|
||||
private async presentAlertShutdown() {
|
||||
const alert = await this.alertCtrl.create({
|
||||
header: 'Warning',
|
||||
message:
|
||||
@@ -154,7 +172,7 @@ export class ServerShowPage {
|
||||
await alert.present()
|
||||
}
|
||||
|
||||
async presentAlertSystemRebuild() {
|
||||
private async presentAlertSystemRebuild() {
|
||||
const localPkgs = await getAllPackages(this.patch)
|
||||
const minutes = Object.keys(localPkgs).length * 2
|
||||
const alert = await this.alertCtrl.create({
|
||||
@@ -178,7 +196,7 @@ export class ServerShowPage {
|
||||
await alert.present()
|
||||
}
|
||||
|
||||
async presentAlertRepairDisk() {
|
||||
private async presentAlertRepairDisk() {
|
||||
const alert = await this.alertCtrl.create({
|
||||
header: 'Warning',
|
||||
message: `<p>This action should only be executed if directed by a Start9 support specialist. We recommend backing up your device before preforming this action.</p><p>If anything happens to the device during the reboot, such as losing power or unplugging the drive, the filesystem <i>will</i> be in an unrecoverable state. Please proceed with caution.</p>`,
|
||||
@@ -206,24 +224,6 @@ export class ServerShowPage {
|
||||
await alert.present()
|
||||
}
|
||||
|
||||
async launchHttps() {
|
||||
const { 'lan-address': lanAddress } = await getServerInfo(this.patch)
|
||||
window.open(lanAddress)
|
||||
}
|
||||
|
||||
addClick(title: string) {
|
||||
switch (title) {
|
||||
case 'Manage':
|
||||
this.addManageClick()
|
||||
break
|
||||
case 'Power':
|
||||
this.addPowerClick()
|
||||
break
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
private async setName(value: string | null): Promise<void> {
|
||||
const loader = await this.loadingCtrl.create({
|
||||
message: 'Saving...',
|
||||
|
||||
@@ -12,7 +12,10 @@ import { ActionSheetButton } from '@ionic/core'
|
||||
import { ValueSpecObject } from 'start-sdk/types/config-types'
|
||||
import { RR } from 'src/app/services/api/api.types'
|
||||
import { pauseFor, ErrorToastService } from '@start9labs/shared'
|
||||
import { GenericFormPage } from 'src/app/modals/generic-form/generic-form.page'
|
||||
import {
|
||||
GenericFormPage,
|
||||
GenericFormOptions,
|
||||
} from 'src/app/modals/generic-form/generic-form.page'
|
||||
import { ConfigService } from 'src/app/services/config.service'
|
||||
|
||||
@Component({
|
||||
@@ -98,9 +101,7 @@ export class WifiPage {
|
||||
},
|
||||
{
|
||||
text: 'Save',
|
||||
handler: async (country: string) => {
|
||||
this.setCountry(country)
|
||||
},
|
||||
handler: (country: string) => this.setCountry(country),
|
||||
},
|
||||
],
|
||||
cssClass: 'enter-click select-warning',
|
||||
@@ -110,27 +111,28 @@ export class WifiPage {
|
||||
|
||||
async presentModalAdd(ssid?: string, needsPW: boolean = true) {
|
||||
const wifiSpec = getWifiValueSpec(ssid, needsPW)
|
||||
|
||||
const options: GenericFormOptions = {
|
||||
title: wifiSpec.name,
|
||||
spec: wifiSpec.spec,
|
||||
buttons: [
|
||||
{
|
||||
text: 'Save for Later',
|
||||
handler: async (value: { ssid: string; password: string }) =>
|
||||
this.save(value.ssid, value.password),
|
||||
},
|
||||
{
|
||||
text: 'Save and Connect',
|
||||
handler: async (value: { ssid: string; password: string }) =>
|
||||
this.saveAndConnect(value.ssid, value.password),
|
||||
isSubmit: true,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const modal = await this.modalCtrl.create({
|
||||
component: GenericFormPage,
|
||||
componentProps: {
|
||||
title: wifiSpec.name,
|
||||
spec: wifiSpec.spec,
|
||||
buttons: [
|
||||
{
|
||||
text: 'Save for Later',
|
||||
handler: async (value: { ssid: string; password: string }) => {
|
||||
await this.save(value.ssid, value.password)
|
||||
},
|
||||
},
|
||||
{
|
||||
text: 'Save and Connect',
|
||||
handler: async (value: { ssid: string; password: string }) => {
|
||||
await this.saveAndConnect(value.ssid, value.password)
|
||||
},
|
||||
isSubmit: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
componentProps: options,
|
||||
})
|
||||
|
||||
await modal.present()
|
||||
@@ -292,7 +294,7 @@ export class WifiPage {
|
||||
}
|
||||
}
|
||||
|
||||
private async save(ssid: string, password: string): Promise<void> {
|
||||
private async save(ssid: string, password: string): Promise<boolean> {
|
||||
const loader = await this.loadingCtrl.create({
|
||||
message: 'Saving...',
|
||||
})
|
||||
@@ -306,14 +308,19 @@ export class WifiPage {
|
||||
connect: false,
|
||||
})
|
||||
await this.getWifi()
|
||||
return true
|
||||
} catch (e: any) {
|
||||
this.errToast.present(e)
|
||||
return false
|
||||
} finally {
|
||||
loader.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
private async saveAndConnect(ssid: string, password: string): Promise<void> {
|
||||
private async saveAndConnect(
|
||||
ssid: string,
|
||||
password: string,
|
||||
): Promise<boolean> {
|
||||
const loader = await this.loadingCtrl.create({
|
||||
message: 'Connecting. This could take a while...',
|
||||
})
|
||||
@@ -326,10 +333,11 @@ export class WifiPage {
|
||||
priority: 0,
|
||||
connect: true,
|
||||
})
|
||||
|
||||
await this.confirmWifi(ssid, true)
|
||||
return true
|
||||
} catch (e: any) {
|
||||
this.errToast.present(e)
|
||||
return false
|
||||
} finally {
|
||||
loader.dismiss()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user