Browse Source

Allow users to edit the field after they create it in the field wizard. They can also go back and keep adding fields and editing them until they are done with that schema.

pull/328/head
Alexander Van Dyke 7 years ago
parent
commit
6ec2dadd40
  1. 155
      src/Squidex/app/features/schemas/pages/schema/field-wizard.component.html
  2. 173
      src/Squidex/app/features/schemas/pages/schema/field-wizard.component.ts
  3. 5
      src/Squidex/app/features/schemas/pages/schema/field.component.ts
  4. 26
      src/Squidex/app/features/schemas/pages/schema/forms/field-form-common.component.ts

155
src/Squidex/app/features/schemas/pages/schema/field-wizard.component.html

@ -1,68 +1,111 @@
<form [formGroup]="addFieldForm.form" (ngSubmit)="addField(false)"> <sqx-modal-dialog (closed)="complete()" large="true">
<sqx-modal-dialog (closed)="complete()" large="true"> <ng-container title>
<ng-container title> <ng-container *ngIf="parent; else noParent">
<ng-container *ngIf="parent; else noParent"> Add Nested Field
Add Nested Field
</ng-container>
<ng-template #noParent>
Add Field
</ng-template>
</ng-container> </ng-container>
<ng-container content> <ng-template #noParent>
<sqx-form-error [error]="addFieldForm.error | async"></sqx-form-error> {{step === 1 ? 'Add' : 'Edit'}} Field
</ng-template>
<div class="form-group"> </ng-container>
<div class="row">
<div class="col-4 type" *ngFor="let fieldType of fieldTypes"> <ng-container content>
<label> <ng-container *ngIf="step === 1">
<input type="radio" class="radio-input" formControlName="type" value="{{fieldType.type}}" /> <form [formGroup]="addFieldForm.form" (ngSubmit)="addField(false)">
<sqx-form-error [error]="addFieldForm.error | async"></sqx-form-error>
<div class="row no-gutters">
<div class="col col-auto"> <div class="form-group">
<div class="type-icon" [class.active]="addFieldForm.form.controls['type'].value === fieldType.type"> <div class="row">
<i class="icon-type-{{fieldType.type}}"></i> <div class="col-4 type" *ngFor="let fieldType of fieldTypes">
<label>
<input type="radio" class="radio-input" formControlName="type" value="{{fieldType.type}}" />
<div class="row no-gutters">
<div class="col col-auto">
<div class="type-icon" [class.active]="addFieldForm.form.controls['type'].value === fieldType.type">
<i class="icon-type-{{fieldType.type}}"></i>
</div>
</div>
<div class="col-lg">
<div class="type-title">{{fieldType.type}}</div>
<div class="type-text text-muted">{{fieldType.description}}</div>
</div> </div>
</div> </div>
<div class="col-lg">
<div class="type-title">{{fieldType.type}}</div>
<div class="type-text text-muted">{{fieldType.description}}</div>
</div>
</div>
</label> </label>
</div>
</div> </div>
</div> </div>
</div>
<div class="form-group">
<div class="form-group"> <sqx-control-errors for="name" submitOnly="true" [submitted]="addFieldForm.submitted | async"></sqx-control-errors>
<sqx-control-errors for="name" submitOnly="true" [submitted]="addFieldForm.submitted | async"></sqx-control-errors>
<input type="text" class="form-control" formControlName="name" maxlength="40" #nameInput
<input type="text" class="form-control" formControlName="name" maxlength="40" #nameInput placeholder="Enter field name" sqxFocusOnInit /> placeholder="Enter field name" sqxFocusOnInit />
</div>
<div class="form-group" *ngIf="!parent">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="isLocalizable" formControlName="isLocalizable" />
<label class="form-check-label" for="isLocalizable">
Localizable
</label>
</div> </div>
<small class="form-text text-muted"> <div class="form-group" *ngIf="!parent">
You can the field as localizable. It means that is dependent on the language, for example a city name. <div class="form-check">
</small> <input class="form-check-input" type="checkbox" id="isLocalizable" formControlName="isLocalizable" />
</div> <label class="form-check-label" for="isLocalizable">
Localizable
</label>
</div>
<small class="form-text text-muted">
You can the field as localizable. It means that is dependent on the language, for example a
city name.
</small>
</div>
</form>
</ng-container> </ng-container>
<ng-container footer> <div class="table-items-row-details" *ngIf="step === 2">
<button type="reset" class="float-left btn btn-secondary" (click)="complete()">Cancel</button> <form [formGroup]="editForm.form" (ngSubmit)="save()">
<div class="table-items-row-details-tabs clearfix">
<ul class="nav nav-tabs2">
<li class="nav-item">
<a class="nav-link" (click)="selectTab(0)" [class.active]="selectedTab === 0">Common</a>
</li>
<li class="nav-item">
<a class="nav-link" (click)="selectTab(1)" [class.active]="selectedTab === 1">Validation</a>
</li>
<li class="nav-item">
<a class="nav-link" (click)="selectTab(2)" [class.active]="selectedTab === 2">Editing</a>
</li>
</ul>
</div>
<div class="float-right"> <ng-container *ngIf="patternsState.patterns | async; let patterns">
<button class="btn btn-success mr-1" (click)="addField(false)">Create and close</button> <div class="table-items-row-details-tab" [class.hidden]="selectedTab !== 0">
<button class="btn btn-success" (click)="addField(true)">Create and new field</button> <sqx-field-form-common [editForm]="editForm.form" [editFormSubmitted]="editForm.submitted | async"
</div> [field]="field"></sqx-field-form-common>
</ng-container> </div>
</sqx-modal-dialog>
</form> <div class="table-items-row-details-tab" [class.hidden]="selectedTab !== 1">
<sqx-field-form-validation [patterns]="patterns" [editForm]="editForm.form" [field]="field"></sqx-field-form-validation>
</div>
<div class="table-items-row-details-tab" [class.hidden]="selectedTab !== 2">
<sqx-field-form-ui [editForm]="editForm.form" [field]="field"></sqx-field-form-ui>
</div>
</ng-container>
</form>
</div>
</ng-container>
<ng-container footer>
<button type="reset" class="float-left btn btn-secondary" (click)="complete()">Cancel</button>
<div class="float-right" *ngIf="step === 1">
<button class="btn btn-success mr-1" (click)="addField(false, false)">Create and close</button>
<button class="btn btn-success mr-1" (click)="addField(true, false)">Create and new field</button>
<button class="btn btn-success" (click)="addField(false, true)">Create and edit field</button>
</div>
<div class="float-right" *ngIf="step === 2">
<button class="btn btn-success mr-1" (click)="save(true)">Save and add field</button>
<button (click)="save()" class="btn btn-primary ml-1">Save and close</button>
</div>
</ng-container>
</sqx-modal-dialog>

173
src/Squidex/app/features/schemas/pages/schema/field-wizard.component.ts

@ -5,75 +5,142 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/ */
import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { import {
AddFieldForm, Component,
fieldTypes, ElementRef,
RootFieldDto, EventEmitter,
SchemaDetailsDto, Input,
SchemasState, OnInit,
Types Output,
} from '@app/shared'; ViewChild
} from "@angular/core";
import { FormBuilder } from "@angular/forms";
import {
AddFieldForm,
AppPatternDto,
createProperties,
EditFieldForm,
FieldDto,
fieldTypes,
ImmutableArray,
PatternsState,
RootFieldDto,
SchemaDetailsDto,
SchemasState,
Types,
UpdateFieldDto
} from "@app/shared";
import { onErrorResumeNext } from "rxjs/operators";
@Component({ @Component({
selector: 'sqx-field-wizard', selector: "sqx-field-wizard",
styleUrls: ['./field-wizard.component.scss'], styleUrls: ["./field-wizard.component.scss"],
templateUrl: './field-wizard.component.html' templateUrl: "./field-wizard.component.html"
}) })
export class FieldWizardComponent implements OnInit { export class FieldWizardComponent implements OnInit {
@ViewChild('nameInput') @ViewChild("nameInput")
public nameInput: ElementRef; public nameInput: ElementRef;
@Input()
public schema: SchemaDetailsDto;
@Input() @Input()
public schema: SchemaDetailsDto; public parent: RootFieldDto;
@Input() @Output()
public parent: RootFieldDto; public completed = new EventEmitter();
@Output() public fieldTypes = fieldTypes;
public completed = new EventEmitter();
public fieldTypes = fieldTypes; public addFieldForm = new AddFieldForm(this.formBuilder);
public editForm = new EditFieldForm(this.formBuilder);
public field: FieldDto;
public isEditing = false;
public selectedTab = 0;
public patterns: ImmutableArray<AppPatternDto>;
public addFieldForm = new AddFieldForm(this.formBuilder); public step = 1;
constructor( constructor(
private readonly formBuilder: FormBuilder, private readonly formBuilder: FormBuilder,
private readonly schemasState: SchemasState private readonly schemasState: SchemasState,
) { public readonly patternsState: PatternsState
) {}
public ngOnInit() {
if (this.parent) {
this.fieldTypes = this.fieldTypes.filter(x => x.type !== "Array");
} }
this.patternsState
.load()
.pipe(onErrorResumeNext())
.subscribe();
}
public complete() {
this.completed.emit();
}
public addField(next: boolean, edit: boolean) {
const value = this.addFieldForm.submit();
public ngOnInit() { if (value) {
if (this.parent) { this.schemasState.addField(this.schema, value, this.parent).subscribe(
this.fieldTypes = this.fieldTypes.filter(x => x.type !== 'Array'); dto => {
this.field = dto;
this.addFieldForm.submitCompleted({ type: fieldTypes[0].type });
if (next) {
if (Types.isFunction(this.nameInput.nativeElement.focus)) {
this.nameInput.nativeElement.focus();
}
} else if (edit) {
this.selectTab(0);
this.step++;
} else {
this.complete();
}
},
error => {
this.addFieldForm.submitFailed(error);
} }
);
} }
}
public complete() { public selectTab(tab: number) {
this.completed.emit(); this.selectedTab = tab;
} }
public addField(next: boolean) { public save(addNew: boolean) {
const value = this.addFieldForm.submit(); const value = this.editForm.submit();
if (value) { if (value) {
this.schemasState.addField(this.schema, value, this.parent) const properties = createProperties(
.subscribe(dto => { this.field.properties["fieldType"],
this.addFieldForm.submitCompleted({ type: fieldTypes[0].type }); value
);
if (next) {
if (Types.isFunction(this.nameInput.nativeElement.focus)) { this.schemasState
this.nameInput.nativeElement.focus(); .updateField(
} this.schema,
} else { this.field as RootFieldDto,
this.complete(); new UpdateFieldDto(properties)
} )
}, error => { .subscribe(
this.addFieldForm.submitFailed(error); () => {
}); this.isEditing = false;
} this.editForm.submitCompleted();
if (addNew) {
this.step--;
} else {
this.complete();
}
},
error => {
this.editForm.submitFailed(error);
}
);
} }
}
} }

5
src/Squidex/app/features/schemas/pages/schema/field.component.ts

@ -71,6 +71,11 @@ export class FieldComponent implements OnInit {
public toggleEditing() { public toggleEditing() {
this.isEditing = !this.isEditing; this.isEditing = !this.isEditing;
// Reload the defaults if they were set in the wizard
if (this.isEditing) {
this.editForm.load(this.field.properties);
}
} }
public selectTab(tab: number) { public selectTab(tab: number) {

26
src/Squidex/app/features/schemas/pages/schema/forms/field-form-common.component.ts

@ -5,8 +5,8 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/ */
import { Component, Input } from '@angular/core'; import { Component, Input, OnChanges } from '@angular/core';
import { FormGroup } from '@angular/forms'; import { FormControl, FormGroup } from '@angular/forms';
import { FieldDto } from '@app/shared'; import { FieldDto } from '@app/shared';
@ -15,7 +15,7 @@ import { FieldDto } from '@app/shared';
styleUrls: ['field-form-common.component.scss'], styleUrls: ['field-form-common.component.scss'],
templateUrl: 'field-form-common.component.html' templateUrl: 'field-form-common.component.html'
}) })
export class FieldFormCommonComponent { export class FieldFormCommonComponent implements OnChanges {
@Input() @Input()
public editForm: FormGroup; public editForm: FormGroup;
@ -27,4 +27,24 @@ export class FieldFormCommonComponent {
@Input() @Input()
public field: FieldDto; public field: FieldDto;
public ngOnChanges() {
this.editForm.setControl('isRequired',
new FormControl(this.field.properties.isRequired));
this.editForm.setControl('isListField',
new FormControl(this.field.properties.isListField));
this.editForm.setControl('editorUrl',
new FormControl(this.field.properties.editorUrl));
this.editForm.setControl('hints',
new FormControl(this.field.properties.hints));
this.editForm.setControl('placeholder',
new FormControl(this.field.properties.placeholder));
this.editForm.setControl('label',
new FormControl(this.field.properties.label));
}
} }
Loading…
Cancel
Save