Commit b1184e9d authored by Boris Vasilenko's avatar Boris Vasilenko
Browse files

NAS-115593: Improvements after review, part 4

No related merge requests found
Showing with 230 additions and 179 deletions
+230 -179
export enum DynamicSchemaType {
Int = 'int',
String = 'string',
Boolean = 'boolean',
Hostpath = 'hostpath',
Path = 'path',
List = 'list',
Dict = 'dict',
}
......@@ -7,18 +7,19 @@ import { FormBuilder } from '@ngneat/reactive-forms';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { of } from 'rxjs';
import { ixChartApp } from 'app/constants/catalog.constants';
import { DynamicSchemaType } from 'app/enums/dynamic-schema-type.enum';
import helptext from 'app/helptext/apps/apps';
import { CatalogApp } from 'app/interfaces/catalog.interface';
import { ChartRelease, ChartReleaseCreate, ChartSchemaNode } from 'app/interfaces/chart-release.interface';
import {
AddListItemEmitter, DeleteListItemEmitter, DynamicFormSchema, DynamicFormSchemaNode,
AddListItemEmitter, DeleteListItemEmitter, DynamicFormSchema,
} from 'app/interfaces/dynamic-form-schema.interface';
import { Relation } from 'app/modules/entity/entity-form/models/field-relation.interface';
import { EntityJobComponent } from 'app/modules/entity/entity-job/entity-job.component';
import { EntityUtils } from 'app/modules/entity/utils';
import { DialogService } from 'app/services';
import { FilesystemService } from 'app/services/filesystem.service';
import { IxSlideInService } from 'app/services/ix-slide-in.service';
import { TransformAppSchemaService } from 'app/services/transform-app-schema.service';
@UntilDestroy()
@Component({
......@@ -45,7 +46,7 @@ export class ChartFormComponent {
private formBuilder: FormBuilder,
private slideInService: IxSlideInService,
private dialogService: DialogService,
private filesystemService: FilesystemService,
private transformAppSchemaService: TransformAppSchemaService,
private mdDialog: MatDialog,
) {}
......@@ -151,7 +152,13 @@ export class ChartFormComponent {
addFormControls(chartSchemaNode: ChartSchemaNode, formGroup: FormGroup): void {
const schema = chartSchemaNode.schema;
if (['string', 'int', 'boolean', 'hostpath', 'path'].includes(schema.type)) {
if ([
DynamicSchemaType.Int,
DynamicSchemaType.String,
DynamicSchemaType.Boolean,
DynamicSchemaType.Path,
DynamicSchemaType.Hostpath,
].includes(schema.type as DynamicSchemaType)) {
const newFormControl = new FormControl(schema.default, [
schema.required ? Validators.required : Validators.nullValidator,
schema.max ? Validators.max(schema.max) : Validators.nullValidator,
......@@ -211,12 +218,12 @@ export class ChartFormComponent {
}
});
}
} else if (schema.type === 'dict') {
} else if (schema.type === DynamicSchemaType.Dict) {
formGroup.addControl(chartSchemaNode.variable, new FormGroup({}));
for (const attr of schema.attrs) {
this.addFormControls(attr, formGroup.controls[chartSchemaNode.variable] as FormGroup);
}
} else if (schema.type === 'list') {
} else if (schema.type === DynamicSchemaType.List) {
formGroup.addControl(chartSchemaNode.variable, new FormArray([]));
if (!this.isNew) {
......@@ -253,140 +260,13 @@ export class ChartFormComponent {
addFormSchema(chartSchemaNode: ChartSchemaNode, group: string): void {
this.dynamicSection.forEach((section) => {
if (section.name === group) {
section.schema = section.schema.concat(this.transformSchemaNode(chartSchemaNode));
section.schema = section.schema.concat(
this.transformAppSchemaService.transformNode(chartSchemaNode),
);
}
});
}
transformSchemaNode(chartSchemaNode: ChartSchemaNode): DynamicFormSchemaNode[] {
const beforSchema = chartSchemaNode.schema;
let afterSchemas: DynamicFormSchemaNode[] = [];
if (['string', 'int', 'boolean', 'hostpath', 'path'].includes(beforSchema.type)) {
switch (beforSchema.type) {
case 'int':
afterSchemas.push({
controlName: chartSchemaNode.variable,
type: 'input',
title: chartSchemaNode.label,
required: beforSchema.required,
hidden: beforSchema.hidden,
tooltip: chartSchemaNode.description,
editable: beforSchema.editable,
private: beforSchema.private,
});
break;
case 'string':
if (beforSchema.enum) {
afterSchemas.push({
controlName: chartSchemaNode.variable,
type: 'select',
title: chartSchemaNode.label,
options: of(beforSchema.enum.map((option) => ({
value: option.value,
label: option.description,
}))),
required: true,
hidden: beforSchema.hidden,
editable: beforSchema.editable,
tooltip: chartSchemaNode.description,
});
} else {
afterSchemas.push({
controlName: chartSchemaNode.variable,
type: 'input',
title: chartSchemaNode.label,
required: beforSchema.required,
hidden: beforSchema.hidden,
editable: beforSchema.editable,
tooltip: chartSchemaNode.description,
private: beforSchema.private,
});
}
break;
case 'path':
afterSchemas.push({
controlName: chartSchemaNode.variable,
type: 'input',
title: chartSchemaNode.label,
required: beforSchema.required,
hidden: beforSchema.hidden,
editable: beforSchema.editable,
tooltip: chartSchemaNode.description,
});
break;
case 'hostpath':
afterSchemas.push({
controlName: chartSchemaNode.variable,
type: 'explorer',
title: chartSchemaNode.label,
nodeProvider: this.filesystemService.getFilesystemNodeProvider(),
required: beforSchema.required,
hidden: beforSchema.hidden,
editable: beforSchema.editable,
tooltip: chartSchemaNode.description,
});
break;
case 'boolean':
afterSchemas.push({
controlName: chartSchemaNode.variable,
type: 'checkbox',
title: chartSchemaNode.label,
required: beforSchema.required,
hidden: beforSchema.hidden,
editable: beforSchema.editable,
tooltip: chartSchemaNode.description,
});
break;
}
if (beforSchema.subquestions) {
beforSchema.subquestions.forEach((subquestion) => {
const objs = this.transformSchemaNode(subquestion);
objs.forEach((obj) => obj.indent = true);
afterSchemas = afterSchemas.concat(objs);
});
}
} else if (beforSchema.type === 'dict') {
let attrs: DynamicFormSchemaNode[] = [];
beforSchema.attrs.forEach((attr) => {
attrs = attrs.concat(this.transformSchemaNode(attr));
});
afterSchemas.push({
controlName: chartSchemaNode.variable,
type: 'dict',
title: chartSchemaNode.label,
attrs,
hidden: beforSchema.hidden,
editable: beforSchema.editable,
});
} else if (beforSchema.type === 'list') {
let items: DynamicFormSchemaNode[] = [];
let itemsSchema: ChartSchemaNode[] = [];
beforSchema.items.forEach((item) => {
if (item.schema.attrs) {
item.schema.attrs.forEach((attr) => {
items = items.concat(this.transformSchemaNode(attr));
itemsSchema = itemsSchema.concat(attr);
});
} else {
items = items.concat(this.transformSchemaNode(item));
itemsSchema = itemsSchema.concat(item);
}
});
afterSchemas.push({
controlName: chartSchemaNode.variable,
type: 'list',
title: chartSchemaNode.label,
items,
items_schema: itemsSchema,
hidden: beforSchema.hidden,
editable: beforSchema.editable,
});
} else {
console.error('Unsupported type = ', beforSchema.type);
}
return afterSchemas;
}
addFormListItem(event: AddListItemEmitter): void {
const itemFormGroup = new FormGroup({});
event.schema.forEach((item) => {
......
......@@ -4,19 +4,19 @@
<form [formGroup]="form" class="ix-form-container" (submit)="onSubmit()">
<ix-fieldset>
<ix-input
[formControlName]="'name'"
formControlName="name"
[label]="helptext.authenticator_name_placeholder | translate"
[tooltip]="helptext.authenticator_name_tooltip | translate"
[placeholder]="helptext.authenticator_name_placeholder | translate"
[required]="true"
></ix-input>
<ix-select
[formControlName]="'authenticator'"
formControlName="authenticator"
[label]="helptext.authenticator_provider_placeholder | translate"
[options]="authenticator_options$"
[tooltip]="helptext.authenticator_provider_tooltip | translate"
[required]="true"
(ngModelChange)="onChange($event)"
(ngModelChange)="onAuthenticatorTypeChanged($event)"
></ix-select>
</ix-fieldset>
<ix-dynamic-form
......
......@@ -8,7 +8,8 @@ import { map } from 'rxjs/operators';
import { DnsAuthenticatorType } from 'app/enums/dns-authenticator-type.enum';
import { helptextSystemAcme as helptext } from 'app/helptext/system/acme';
import { AuthenticatorSchema, DnsAuthenticator } from 'app/interfaces/dns-authenticator.interface';
import { DynamicFormSchema } from 'app/interfaces/dynamic-form-schema.interface';
import { DynamicFormSchema, DynamicFormSchemaNode } from 'app/interfaces/dynamic-form-schema.interface';
import { Option } from 'app/interfaces/option.interface';
import { FormErrorHandlerService } from 'app/modules/ix-forms/services/form-error-handler.service';
import { WebSocketService } from 'app/services';
import { IxSlideInService } from 'app/services/ix-slide-in.service';
......@@ -57,42 +58,7 @@ export class AcmednsFormComponent {
return this.ws.call('acme.dns.authenticator.authenticator_schemas');
}
authenticator_options$ = this.getAuthenticatorSchemas().pipe(
map((schemas) => {
this.isLoading = true;
const dynamicSchema: DynamicFormSchema = { name: '', description: '', schema: [] };
const opts = [];
this.dnsAuthenticatorList = [];
this.dynamicSection = [];
for (const schema of schemas) {
const variables: string[] = [];
for (const input of schema.schema) {
const newFormControl = new FormControl('', input._required_ ? [Validators.required] : []);
this.form.controls.attributes.addControl(input._name_, newFormControl);
dynamicSchema.schema.push({
controlName: input._name_,
type: 'input',
title: input.title,
required: input._required_,
});
variables.push(input._name_);
}
this.dnsAuthenticatorList.push({ key: schema.key, variables });
opts.push({ label: schema.key, value: schema.key });
}
this.dynamicSection.push(dynamicSchema);
this.onChange(DnsAuthenticatorType.Cloudflare);
if (!this.isNew) {
this.form.patchValue(this.editingAcmedns);
}
this.isLoading = false;
this.isLoadingSchemas = false;
return opts;
}),
);
authenticator_options$ = this.getAuthenticatorSchemas().pipe(map((schemas) => this.loadSchemas(schemas)));
private editingAcmedns: DnsAuthenticator;
......@@ -105,16 +71,60 @@ export class AcmednsFormComponent {
private ws: WebSocketService,
) {}
loadSchemas(schemas: AuthenticatorSchema[]): Option[] {
this.isLoading = true;
schemas.forEach((schema) => {
schema.schema.forEach((input) => {
this.form.controls.attributes.addControl(input._name_, new FormControl('', input._required_ ? [Validators.required] : []));
});
});
this.dynamicSection = [{
name: '',
description: '',
schema: schemas.map((schema) => this.parseSchemaForDynamicSchema(schema))
.reduce((all, val) => all.concat(val), []),
}];
this.dnsAuthenticatorList = schemas.map((schema) => this.parseSchemaForDnsAuthList(schema));
this.onAuthenticatorTypeChanged(DnsAuthenticatorType.Cloudflare);
if (!this.isNew) {
this.form.patchValue(this.editingAcmedns);
}
this.isLoading = false;
this.isLoadingSchemas = false;
return schemas.map((schema) => ({ label: schema.key, value: schema.key }));
}
parseSchemaForDynamicSchema(schema: AuthenticatorSchema): DynamicFormSchemaNode[] {
return schema.schema.map((input) => ({
controlName: input._name_,
type: 'input',
title: input.title,
required: input._required_,
}));
}
parseSchemaForDnsAuthList(schema: AuthenticatorSchema): DnsAuthenticatorList {
const variables = schema.schema.map((input) => input._name_);
return { key: schema.key, variables };
}
setAcmednsForEdit(acmedns: DnsAuthenticator): void {
this.editingAcmedns = acmedns;
}
onChange(event: DnsAuthenticatorType): void {
onAuthenticatorTypeChanged(event: DnsAuthenticatorType): void {
this.dnsAuthenticatorList.forEach((auth) => {
if (auth.key === event) {
auth.variables.forEach((varible) => this.form.controls.attributes.controls[varible].enable());
auth.variables.forEach((variable) => this.form.controls.attributes.controls[variable].enable());
} else {
auth.variables.forEach((varible) => this.form.controls.attributes.controls[varible].disable());
auth.variables.forEach((variable) => this.form.controls.attributes.controls[variable].disable());
}
});
}
......
import { Injectable } from '@angular/core';
import { UntilDestroy } from '@ngneat/until-destroy';
import { of } from 'rxjs';
import { DynamicSchemaType } from 'app/enums/dynamic-schema-type.enum';
import { ChartSchemaNode } from 'app/interfaces/chart-release.interface';
import { DynamicFormSchemaNode } from 'app/interfaces/dynamic-form-schema.interface';
import { FilesystemService } from 'app/services/filesystem.service';
@UntilDestroy()
@Injectable({
providedIn: 'root',
})
export class TransformAppSchemaService {
constructor(
protected filesystemService: FilesystemService,
) {}
transformNode(chartSchemaNode: ChartSchemaNode): DynamicFormSchemaNode[] {
const schema = chartSchemaNode.schema;
let newSchema: DynamicFormSchemaNode[] = [];
if ([
DynamicSchemaType.Int,
DynamicSchemaType.String,
DynamicSchemaType.Boolean,
DynamicSchemaType.Path,
DynamicSchemaType.Hostpath,
].includes(schema.type as DynamicSchemaType)) {
switch (schema.type) {
case DynamicSchemaType.Int:
newSchema.push({
controlName: chartSchemaNode.variable,
type: 'input',
title: chartSchemaNode.label,
required: schema.required,
hidden: schema.hidden,
tooltip: chartSchemaNode.description,
editable: schema.editable,
private: schema.private,
});
break;
case DynamicSchemaType.String:
if (schema.enum) {
newSchema.push({
controlName: chartSchemaNode.variable,
type: 'select',
title: chartSchemaNode.label,
options: of(schema.enum.map((option) => ({
value: option.value,
label: option.description,
}))),
required: true,
hidden: schema.hidden,
editable: schema.editable,
tooltip: chartSchemaNode.description,
});
} else {
newSchema.push({
controlName: chartSchemaNode.variable,
type: 'input',
title: chartSchemaNode.label,
required: schema.required,
hidden: schema.hidden,
editable: schema.editable,
tooltip: chartSchemaNode.description,
private: schema.private,
});
}
break;
case DynamicSchemaType.Path:
newSchema.push({
controlName: chartSchemaNode.variable,
type: 'input',
title: chartSchemaNode.label,
required: schema.required,
hidden: schema.hidden,
editable: schema.editable,
tooltip: chartSchemaNode.description,
});
break;
case DynamicSchemaType.Hostpath:
newSchema.push({
controlName: chartSchemaNode.variable,
type: 'explorer',
title: chartSchemaNode.label,
nodeProvider: this.filesystemService.getFilesystemNodeProvider(),
required: schema.required,
hidden: schema.hidden,
editable: schema.editable,
tooltip: chartSchemaNode.description,
});
break;
case DynamicSchemaType.Boolean:
newSchema.push({
controlName: chartSchemaNode.variable,
type: 'checkbox',
title: chartSchemaNode.label,
required: schema.required,
hidden: schema.hidden,
editable: schema.editable,
tooltip: chartSchemaNode.description,
});
break;
}
if (schema.subquestions) {
schema.subquestions.forEach((subquestion) => {
const objs = this.transformNode(subquestion);
objs.forEach((obj) => obj.indent = true);
newSchema = newSchema.concat(objs);
});
}
} else if (schema.type === DynamicSchemaType.Dict) {
let attrs: DynamicFormSchemaNode[] = [];
schema.attrs.forEach((attr) => {
attrs = attrs.concat(this.transformNode(attr));
});
newSchema.push({
controlName: chartSchemaNode.variable,
type: 'dict',
title: chartSchemaNode.label,
attrs,
hidden: schema.hidden,
editable: schema.editable,
});
} else if (schema.type === DynamicSchemaType.List) {
let items: DynamicFormSchemaNode[] = [];
let itemsSchema: ChartSchemaNode[] = [];
schema.items.forEach((item) => {
if (item.schema.attrs) {
item.schema.attrs.forEach((attr) => {
items = items.concat(this.transformNode(attr));
itemsSchema = itemsSchema.concat(attr);
});
} else {
items = items.concat(this.transformNode(item));
itemsSchema = itemsSchema.concat(item);
}
});
newSchema.push({
controlName: chartSchemaNode.variable,
type: 'list',
title: chartSchemaNode.label,
items,
items_schema: itemsSchema,
hidden: schema.hidden,
editable: schema.editable,
});
} else {
console.error('Unsupported type = ', schema.type);
}
return newSchema;
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment