mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 12:11:56 +00:00
chore: break form-object file structure
This commit is contained in:
committed by
Aiden McClelland
parent
3933819d53
commit
e76ccba2f7
@@ -2,7 +2,7 @@
|
|||||||
*ngIf="data.description"
|
*ngIf="data.description"
|
||||||
class="slot-start"
|
class="slot-start"
|
||||||
fill="clear"
|
fill="clear"
|
||||||
(click)="presentAlertDescription($event)"
|
(click.stop)="presentAlertDescription()"
|
||||||
>
|
>
|
||||||
<ion-icon name="help-circle-outline" slot="icon-only" size="small"></ion-icon>
|
<ion-icon name="help-circle-outline" slot="icon-only" size="small"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
@@ -13,4 +13,4 @@
|
|||||||
<ion-text color="success" *ngIf="data.newOptions"> (New Options)</ion-text>
|
<ion-text color="success" *ngIf="data.newOptions"> (New Options)</ion-text>
|
||||||
<ion-text color="warning" *ngIf="data.edited"> (Edited)</ion-text>
|
<ion-text color="warning" *ngIf="data.edited"> (Edited)</ion-text>
|
||||||
|
|
||||||
<span *ngIf="data.required"> * </span>
|
<span *ngIf="data.required"> *</span>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
:host {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slot-start {
|
||||||
|
--padding-start: 0;
|
||||||
|
--padding-end: 7px;
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
|
||||||
|
import { AlertController } from '@ionic/angular'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'form-label',
|
||||||
|
templateUrl: './form-label.component.html',
|
||||||
|
styleUrls: ['./form-label.component.scss'],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class FormLabelComponent {
|
||||||
|
@Input() data!: {
|
||||||
|
name: string
|
||||||
|
new: boolean
|
||||||
|
edited: boolean
|
||||||
|
description?: string
|
||||||
|
required?: boolean
|
||||||
|
newOptions?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(private readonly alertCtrl: AlertController) {}
|
||||||
|
|
||||||
|
async presentAlertDescription() {
|
||||||
|
const alert = await this.alertCtrl.create({
|
||||||
|
header: this.data.name,
|
||||||
|
message: this.data.description,
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
text: 'OK',
|
||||||
|
cssClass: 'enter-click',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
await alert.present()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
.slot-start {
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: middle;
|
|
||||||
--padding-start: 0;
|
|
||||||
--padding-end: 7px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.error-border {
|
|
||||||
border-color: var(--ion-color-danger-shade);
|
|
||||||
--border-color: var(--ion-color-danger-shade);
|
|
||||||
}
|
|
||||||
|
|
||||||
.redacted {
|
|
||||||
font-family: 'Redacted'
|
|
||||||
}
|
|
||||||
|
|
||||||
ion-input {
|
|
||||||
font-family: 'Courier New';
|
|
||||||
font-weight: bold;
|
|
||||||
--placeholder-font-weight: 400;
|
|
||||||
}
|
|
||||||
|
|
||||||
ion-item-divider {
|
|
||||||
text-transform: unset;
|
|
||||||
--padding-top: 18px;
|
|
||||||
--padding-start: 0;
|
|
||||||
border-bottom: 1px solid var(--ion-item-border-color, var(--ion-border-color, var(--ion-color-step-150, rgba(0, 0, 0, 0.13))))
|
|
||||||
}
|
|
||||||
|
|
||||||
.nested-wrapper {
|
|
||||||
padding: 0 0 16px 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.error-message {
|
|
||||||
margin-top: 2px;
|
|
||||||
font-size: small;
|
|
||||||
color: var(--ion-color-danger);
|
|
||||||
}
|
|
||||||
|
|
||||||
.indent {
|
|
||||||
margin-left: 24px;
|
|
||||||
}
|
|
||||||
@@ -1,10 +1,15 @@
|
|||||||
import { NgModule } from '@angular/core'
|
|
||||||
import { CommonModule } from '@angular/common'
|
import { CommonModule } from '@angular/common'
|
||||||
import {
|
import { NgModule } from '@angular/core'
|
||||||
FormObjectComponent,
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
|
||||||
FormUnionComponent,
|
import { IonicModule } from '@ionic/angular'
|
||||||
FormLabelComponent,
|
import { SharedPipesModule } from '@start9labs/shared'
|
||||||
} from './form-object.component'
|
import { TuiElasticContainerModule } from '@taiga-ui/kit'
|
||||||
|
import { TuiExpandModule } from '@taiga-ui/core'
|
||||||
|
import { EnumListPageModule } from 'src/app/modals/enum-list/enum-list.module'
|
||||||
|
|
||||||
|
import { FormLabelComponent } from './form-label/form-label.component'
|
||||||
|
import { FormObjectComponent } from './form-object/form-object.component'
|
||||||
|
import { FormUnionComponent } from './form-union/form-union.component'
|
||||||
import {
|
import {
|
||||||
GetErrorPipe,
|
GetErrorPipe,
|
||||||
ToWarningTextPipe,
|
ToWarningTextPipe,
|
||||||
@@ -13,12 +18,6 @@ import {
|
|||||||
ToEnumListDisplayPipe,
|
ToEnumListDisplayPipe,
|
||||||
ToRangePipe,
|
ToRangePipe,
|
||||||
} from './form-object.pipes'
|
} from './form-object.pipes'
|
||||||
import { IonicModule } from '@ionic/angular'
|
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
|
|
||||||
import { SharedPipesModule } from '@start9labs/shared'
|
|
||||||
import { TuiElasticContainerModule } from '@taiga-ui/kit'
|
|
||||||
import { EnumListPageModule } from 'src/app/modals/enum-list/enum-list.module'
|
|
||||||
import { TuiExpandModule } from '@taiga-ui/core'
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@@ -44,4 +43,4 @@ import { TuiExpandModule } from '@taiga-ui/core'
|
|||||||
],
|
],
|
||||||
exports: [FormObjectComponent, FormLabelComponent],
|
exports: [FormObjectComponent, FormLabelComponent],
|
||||||
})
|
})
|
||||||
export class FormObjectComponentModule {}
|
export class FormObjectModule {}
|
||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
import { IonicSafeString } from '@ionic/angular'
|
import { IonicSafeString } from '@ionic/angular'
|
||||||
import { ListValueSpecOf } from 'start-sdk/types/config-types'
|
import { ListValueSpecOf } from 'start-sdk/types/config-types'
|
||||||
import { Range } from 'src/app/util/config-utilities'
|
import { Range } from 'src/app/util/config-utilities'
|
||||||
import { getElementId } from './form-object.component'
|
import { getElementId } from './form-object/form-object.component'
|
||||||
|
|
||||||
@Pipe({
|
@Pipe({
|
||||||
name: 'getError',
|
name: 'getError',
|
||||||
|
|||||||
@@ -26,13 +26,14 @@
|
|||||||
<ng-template #notTextArea>
|
<ng-template #notTextArea>
|
||||||
<ion-input
|
<ion-input
|
||||||
type="text"
|
type="text"
|
||||||
[inputmode]="spec.type === 'number' ? 'tel' : 'text'"
|
class="input"
|
||||||
[class.redacted]="
|
[class.input_redacted]="
|
||||||
spec.type === 'string' &&
|
spec.type === 'string' &&
|
||||||
entry.value.value &&
|
entry.value.value &&
|
||||||
spec.masked &&
|
spec.masked &&
|
||||||
!unmasked[entry.key]
|
!unmasked[entry.key]
|
||||||
"
|
"
|
||||||
|
[inputmode]="spec.type === 'number' ? 'tel' : 'text'"
|
||||||
[placeholder]="spec.placeholder || 'Enter ' + spec.name"
|
[placeholder]="spec.placeholder || 'Enter ' + spec.name"
|
||||||
[formControlName]="entry.key"
|
[formControlName]="entry.key"
|
||||||
(ionFocus)="presentAlertChangeWarning(entry.key, spec)"
|
(ionFocus)="presentAlertChangeWarning(entry.key, spec)"
|
||||||
@@ -130,9 +131,9 @@
|
|||||||
<ng-container *ngIf="spec.type === 'object'">
|
<ng-container *ngIf="spec.type === 'object'">
|
||||||
<!-- label -->
|
<!-- label -->
|
||||||
<ion-item-divider
|
<ion-item-divider
|
||||||
(click)="toggleExpandObject(entry.key)"
|
|
||||||
style="cursor: pointer"
|
style="cursor: pointer"
|
||||||
[class.error-border]="entry.value.invalid"
|
[class.error-border]="entry.value.invalid"
|
||||||
|
(click)="toggleExpandObject(entry.key)"
|
||||||
>
|
>
|
||||||
<form-label
|
<form-label
|
||||||
[data]="{
|
[data]="{
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
font-family: 'Courier New';
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
--placeholder-font-weight: 400;
|
||||||
|
|
||||||
|
&_redacted {
|
||||||
|
font-family: 'Redacted';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ion-item-divider {
|
||||||
|
text-transform: unset;
|
||||||
|
border-bottom: 1px solid
|
||||||
|
var(
|
||||||
|
--ion-item-border-color,
|
||||||
|
var(--ion-border-color, var(--ion-color-step-150, rgba(0, 0, 0, 0.13)))
|
||||||
|
);
|
||||||
|
|
||||||
|
--padding-top: 18px;
|
||||||
|
--padding-start: 0;
|
||||||
|
|
||||||
|
&.error-border {
|
||||||
|
border-color: var(--ion-color-danger-shade);
|
||||||
|
--border-color: var(--ion-color-danger-shade);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nested-wrapper {
|
||||||
|
padding: 0 0 16px 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-message {
|
||||||
|
margin-top: 2px;
|
||||||
|
font-size: small;
|
||||||
|
color: var(--ion-color-danger);
|
||||||
|
}
|
||||||
@@ -3,7 +3,6 @@ import {
|
|||||||
Input,
|
Input,
|
||||||
Output,
|
Output,
|
||||||
EventEmitter,
|
EventEmitter,
|
||||||
ChangeDetectionStrategy,
|
|
||||||
Inject,
|
Inject,
|
||||||
inject,
|
inject,
|
||||||
SimpleChanges,
|
SimpleChanges,
|
||||||
@@ -28,9 +27,6 @@ import { DOCUMENT } from '@angular/common'
|
|||||||
|
|
||||||
const Mustache = require('mustache')
|
const Mustache = require('mustache')
|
||||||
|
|
||||||
interface Config {
|
|
||||||
[key: string]: any
|
|
||||||
}
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'form-object',
|
selector: 'form-object',
|
||||||
templateUrl: './form-object.component.html',
|
templateUrl: './form-object.component.html',
|
||||||
@@ -39,8 +35,8 @@ interface Config {
|
|||||||
export class FormObjectComponent {
|
export class FormObjectComponent {
|
||||||
@Input() objectSpec!: InputSpec
|
@Input() objectSpec!: InputSpec
|
||||||
@Input() formGroup!: UntypedFormGroup
|
@Input() formGroup!: UntypedFormGroup
|
||||||
@Input() current?: Config
|
@Input() current?: Record<string, any>
|
||||||
@Input() original?: Config
|
@Input() original?: Record<string, any>
|
||||||
@Output() onInputChange = new EventEmitter<void>()
|
@Output() onInputChange = new EventEmitter<void>()
|
||||||
@Output() hasNewOptions = new EventEmitter<void>()
|
@Output() hasNewOptions = new EventEmitter<void>()
|
||||||
warningAck: { [key: string]: boolean } = {}
|
warningAck: { [key: string]: boolean } = {}
|
||||||
@@ -330,96 +326,6 @@ export class FormObjectComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'form-union',
|
|
||||||
templateUrl: './form-union.component.html',
|
|
||||||
styleUrls: ['./form-object.component.scss'],
|
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
||||||
})
|
|
||||||
export class FormUnionComponent {
|
|
||||||
@Input() formGroup!: UntypedFormGroup
|
|
||||||
@Input() spec!: ValueSpecUnion
|
|
||||||
@Input() current?: Config
|
|
||||||
@Input() original?: Config
|
|
||||||
|
|
||||||
get unionValue() {
|
|
||||||
return this.formGroup.get(this.spec.tag.id)?.value
|
|
||||||
}
|
|
||||||
|
|
||||||
get isNew() {
|
|
||||||
return !this.original
|
|
||||||
}
|
|
||||||
|
|
||||||
get hasNewOptions() {
|
|
||||||
const tagId = this.spec.tag.id
|
|
||||||
return (
|
|
||||||
this.original?.[tagId] === this.current?.[tagId] &&
|
|
||||||
!!Object.keys(this.current || {}).find(
|
|
||||||
key => this.original![key] === undefined,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
objectId = v4()
|
|
||||||
|
|
||||||
constructor(private readonly formService: FormService) {}
|
|
||||||
|
|
||||||
updateUnion(e: any): void {
|
|
||||||
const tagId = this.spec.tag.id
|
|
||||||
|
|
||||||
Object.keys(this.formGroup.controls).forEach(control => {
|
|
||||||
if (control === tagId) return
|
|
||||||
this.formGroup.removeControl(control)
|
|
||||||
})
|
|
||||||
|
|
||||||
const unionGroup = this.formService.getUnionObject(
|
|
||||||
this.spec as ValueSpecUnion,
|
|
||||||
e.detail.value,
|
|
||||||
)
|
|
||||||
|
|
||||||
Object.keys(unionGroup.controls).forEach(control => {
|
|
||||||
if (control === tagId) return
|
|
||||||
this.formGroup.addControl(control, unionGroup.controls[control])
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'form-label',
|
|
||||||
templateUrl: './form-label.component.html',
|
|
||||||
styleUrls: ['./form-object.component.scss'],
|
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
||||||
})
|
|
||||||
export class FormLabelComponent {
|
|
||||||
@Input() data!: {
|
|
||||||
name: string
|
|
||||||
new: boolean
|
|
||||||
edited: boolean
|
|
||||||
description: string | null
|
|
||||||
required?: boolean
|
|
||||||
newOptions?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(private readonly alertCtrl: AlertController) {}
|
|
||||||
|
|
||||||
async presentAlertDescription(event: Event) {
|
|
||||||
event.stopPropagation()
|
|
||||||
const { name, description } = this.data
|
|
||||||
|
|
||||||
const alert = await this.alertCtrl.create({
|
|
||||||
header: name,
|
|
||||||
message: description || '',
|
|
||||||
buttons: [
|
|
||||||
{
|
|
||||||
text: 'OK',
|
|
||||||
cssClass: 'enter-click',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
await alert.present()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getElementId(objectId: string, key: string, index = 0): string {
|
export function getElementId(objectId: string, key: string, index = 0): string {
|
||||||
return `${key}-${index}-${objectId}`
|
return `${key}-${index}-${objectId}`
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
ion-item-divider {
|
||||||
|
text-transform: unset;
|
||||||
|
border-bottom: 1px solid
|
||||||
|
var(
|
||||||
|
--ion-item-border-color,
|
||||||
|
var(--ion-border-color, var(--ion-color-step-150, rgba(0, 0, 0, 0.13)))
|
||||||
|
);
|
||||||
|
|
||||||
|
--padding-top: 18px;
|
||||||
|
--padding-start: 0;
|
||||||
|
|
||||||
|
&.error-border {
|
||||||
|
border-color: var(--ion-color-danger-shade);
|
||||||
|
--border-color: var(--ion-color-danger-shade);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.indent {
|
||||||
|
margin-left: 24px;
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
|
||||||
|
import { UntypedFormGroup } from '@angular/forms'
|
||||||
|
import { v4 } from 'uuid'
|
||||||
|
import { FormService } from 'src/app/services/form.service'
|
||||||
|
import { ValueSpecUnion } from 'src/app/pkg-config/config-types'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'form-union',
|
||||||
|
templateUrl: './form-union.component.html',
|
||||||
|
styleUrls: ['./form-union.component.scss'],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class FormUnionComponent {
|
||||||
|
@Input() formGroup!: UntypedFormGroup
|
||||||
|
@Input() spec!: ValueSpecUnion
|
||||||
|
@Input() current?: Record<string, any>
|
||||||
|
@Input() original?: Record<string, any>
|
||||||
|
|
||||||
|
get unionValue() {
|
||||||
|
return this.formGroup.get(this.spec.tag.id)?.value
|
||||||
|
}
|
||||||
|
|
||||||
|
get isNew() {
|
||||||
|
return !this.original
|
||||||
|
}
|
||||||
|
|
||||||
|
get hasNewOptions() {
|
||||||
|
const tagId = this.spec.tag.id
|
||||||
|
return (
|
||||||
|
this.original?.[tagId] === this.current?.[tagId] &&
|
||||||
|
!!Object.keys(this.current || {}).find(
|
||||||
|
key => this.original![key] === undefined,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
objectId = v4()
|
||||||
|
|
||||||
|
constructor(private readonly formService: FormService) {}
|
||||||
|
|
||||||
|
updateUnion(e: any): void {
|
||||||
|
const tagId = this.spec.tag.id
|
||||||
|
|
||||||
|
Object.keys(this.formGroup.controls).forEach(control => {
|
||||||
|
if (control === tagId) return
|
||||||
|
this.formGroup.removeControl(control)
|
||||||
|
})
|
||||||
|
|
||||||
|
const unionGroup = this.formService.getUnionObject(
|
||||||
|
this.spec as ValueSpecUnion,
|
||||||
|
e.detail.value,
|
||||||
|
)
|
||||||
|
|
||||||
|
Object.keys(unionGroup.controls).forEach(control => {
|
||||||
|
if (control === tagId) return
|
||||||
|
this.formGroup.addControl(control, unionGroup.controls[control])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms'
|
|||||||
import { IonicModule } from '@ionic/angular'
|
import { IonicModule } from '@ionic/angular'
|
||||||
import { AppConfigPage } from './app-config.page'
|
import { AppConfigPage } from './app-config.page'
|
||||||
import { TextSpinnerComponentModule } from '@start9labs/shared'
|
import { TextSpinnerComponentModule } from '@start9labs/shared'
|
||||||
import { FormObjectComponentModule } from 'src/app/components/form-object/form-object.component.module'
|
import { FormObjectModule } from 'src/app/components/form-object/form-object.module'
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [AppConfigPage],
|
declarations: [AppConfigPage],
|
||||||
@@ -13,7 +13,7 @@ import { FormObjectComponentModule } from 'src/app/components/form-object/form-o
|
|||||||
FormsModule,
|
FormsModule,
|
||||||
IonicModule,
|
IonicModule,
|
||||||
TextSpinnerComponentModule,
|
TextSpinnerComponentModule,
|
||||||
FormObjectComponentModule,
|
FormObjectModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
],
|
],
|
||||||
exports: [AppConfigPage],
|
exports: [AppConfigPage],
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { CommonModule } from '@angular/common'
|
|||||||
import { IonicModule } from '@ionic/angular'
|
import { IonicModule } from '@ionic/angular'
|
||||||
import { GenericFormPage } from './generic-form.page'
|
import { GenericFormPage } from './generic-form.page'
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
|
||||||
import { FormObjectComponentModule } from 'src/app/components/form-object/form-object.component.module'
|
import { FormObjectModule } from 'src/app/components/form-object/form-object.module'
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [GenericFormPage],
|
declarations: [GenericFormPage],
|
||||||
@@ -12,8 +12,8 @@ import { FormObjectComponentModule } from 'src/app/components/form-object/form-o
|
|||||||
IonicModule,
|
IonicModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
FormObjectComponentModule,
|
FormObjectModule,
|
||||||
],
|
],
|
||||||
exports: [GenericFormPage],
|
exports: [GenericFormPage],
|
||||||
})
|
})
|
||||||
export class GenericFormPageModule { }
|
export class GenericFormPageModule {}
|
||||||
|
|||||||
Reference in New Issue
Block a user