refactor tenant, notification-template ui editors

This commit is contained in:
amentis 2024-03-01 09:38:11 +02:00
parent 46862e06cc
commit 5da3c4f9b9
14 changed files with 459 additions and 615 deletions

View File

@ -0,0 +1,92 @@
<div class="col-6" >
<mat-form-field class="chip-list">
<mat-label>{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.MANDATORY' | translate}}</mat-label>
<mat-chip-grid #chipGrid [formControl]="form.get('mandatory')">
<mat-chip-row *ngFor="let field of mandatoryFields"
(removed)="removeChipListValues(field)"
[editable]="true"
(edited)="editChipListValues($event, field)">
{{field}}
<button matChipRemove>
<mat-icon>cancel</mat-icon>
</button>
</mat-chip-row>
<input placeholder="{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.MANDATORY-PLACEHOLDER' | translate}}"
[matChipInputFor]="chipGrid"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="true"
(matChipInputTokenEnd)="addChipListValues($event)"/>
</mat-chip-grid>
<mat-error *ngIf="form.get('mandatory').hasError('backendError')">{{form.get('mandatory').getError('backendError').message}}</mat-error>
</mat-form-field>
</div>
<h4 class="col-md-12">{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.OPTIONAL-TITLE' | translate}}</h4>
<div class="col-12">
<div class="row" *ngFor="let options of form.get('optional')['controls']; let i = index">
<div class="col-4">
<mat-form-field class="col-auto">
<mat-label>{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.KEY' | translate}}</mat-label>
<input matInput [formControl]="options.get('key')">
<mat-error *ngIf="options.get('key').hasError('backendError')">{{options.get('key').getError('backendError').message}}</mat-error>
<mat-error *ngIf="options.get('key').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<div class="col-4">
<mat-form-field class="col-auto">
<mat-label>{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.DATA-TYPE' | translate}}</mat-label>
<mat-select name="channel" [formControl]="options.get('type')">
<mat-option *ngFor="let type of notificationDataTypeEnum" [value]="type">
{{enumUtils.toNotificationTemplateDataTypeString(type)}}
</mat-option>
</mat-select>
<mat-error *ngIf="options.get('type').hasError('backendError')">{{options.get('type').getError('backendError').message}}</mat-error>
<mat-error *ngIf="options.get('type').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<div class="col-4">
<mat-form-field class="col">
<mat-label>{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.VALUE' | translate}}</mat-label>
<input matInput [formControl]="options.get('value')">
<mat-error *ngIf="options.get('value').hasError('backendError')">{{options.get('value').getError('backendError').message}}</mat-error>
<mat-error *ngIf="options.get('value').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
<div class="col-auto">
<button mat-icon-button (click)="removeSubjectOptionalItem(i)" [disabled]="form.disabled">
<mat-icon>remove</mat-icon>
</button>
</div>
</div>
</div>
<div class="row">
<div class="col-auto">
<button mat-icon-button (click)="addOptionalItem()" [disabled]="form.disabled">
<mat-icon>add</mat-icon>
</button>
</div>
</div>
</div>
<h4 class="col-md-12">{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.FORMATTING' | translate}}</h4>
<div class="row" *ngFor="let item of form.get('mandatory').value; let i = index">
<mat-form-field class="col-md-4">
<mat-label>{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.KEY' | translate}}</mat-label>
<input matInput [value]="item" [disabled] = "true">
</mat-form-field>
<mat-form-field class="col-md-4">
<mat-label>{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.VALUE' | translate}}</mat-label>
<input matInput [value] ="formatting[item]" (change)="formattingValueChange($event, item)">
<mat-error *ngIf="form.get('formatting').hasError('backendError')">{{form.get('formatting').getError('backendError').message}}</mat-error>
</mat-form-field>
</div>
<div class="row" *ngFor="let item of form.get('optional')['controls']; let i = index">
<div *ngIf="item.valid">
<mat-form-field class="col-md-4">
<mat-label>{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.KEY' | translate}}</mat-label>
<input matInput [value]="item.value.key" [disabled] = "true">
</mat-form-field>
<mat-form-field class="col-md-4">
<mat-label>{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.VALUE' | translate}}</mat-label>
<input matInput [value]="formatting[item]" (change)="formattingValueChange($event, item)">
<mat-error *ngIf="form.get('formatting').hasError('backendError')">{{form.get('formatting').getError('backendError').message}}</mat-error>
</mat-form-field>
</div>
</div>

View File

@ -0,0 +1,127 @@
import { Component, Input, OnInit } from '@angular/core';
import { UntypedFormArray } from '@angular/forms';
import { NotificationDataType } from '@app/core/common/enum/notification-data-type';
import { EnumUtils } from '@app/core/services/utilities/enum-utils.service';
import { BaseComponent } from '@common/base/base.component';
import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model';
import { NotificationFieldInfoEditorModel, NotificationFieldOptionsEditorModel } from '../notification-template-editor.model';
import { MatChipEditedEvent, MatChipInputEvent } from '@angular/material/chips';
import { COMMA, ENTER } from '@angular/cdk/keycodes';
@Component({
selector: 'app-notification-template-field-options-component',
templateUrl: 'notification-template-field-options.component.html',
styleUrls: ['./notification-template-field-options.component.scss']
})
export class NotificationTemplateFieldOptionsComponent extends BaseComponent implements OnInit {
@Input() form;
@Input() validationErrorModel: ValidationErrorModel = null;
@Input() validationRootPath: string = null;
@Input() mandatoryFields: string[] = [];
@Input() formatting: { [key: string]: string } = {};
public notificationDataTypeEnum = this.enumUtils.getEnumValues(NotificationDataType);
readonly separatorKeysCodes: number[] = [ENTER, COMMA];
constructor(
public enumUtils: EnumUtils,
) { super(); }
ngOnInit() {
}
addChipListValues(event: MatChipInputEvent){
this.mandatoryFields = this.add(event, this.mandatoryFields);
}
editChipListValues(event: MatChipEditedEvent, field: string){
this.mandatoryFields = this.edit(field, this.mandatoryFields, event);
this.editFormmattingKey(field, event.value.trim());
}
removeChipListValues(field: string){
this.mandatoryFields = this.remove(field, this.mandatoryFields);
this.deleteFormattingItem(field);
}
add(event: MatChipInputEvent, values: string[]) {
const value = (event.value || '').trim();
if (value) values.push(value)
event.chipInput!.clear();
return values;
}
remove(field: string, values: string[]) {
const index = values.indexOf(field);
if (index >= 0) values.splice(index, 1);
return values;
}
edit(field: string, values: string[], event: MatChipEditedEvent) {
const value = event.value.trim();
if (!value) {
values = this.remove(field, values);
return values;
}
const index = values.indexOf(field);
if (index >= 0) values[index] = value
return values;
}
//options fields
addOptionalItem() {
const formArray = (this.form.get('optional') as UntypedFormArray);
const optional: NotificationFieldInfoEditorModel = new NotificationFieldInfoEditorModel(this.validationErrorModel);
formArray.push(optional.buildForm({ rootPath: this.validationRootPath + 'optional[' + formArray.length + '].' }));
}
removeSubjectOptionalItem(optionalIndex: number): void {
const key = (this.form.get('optional') as UntypedFormArray).at(optionalIndex).get("key").value;
this.deleteFormattingItem(key);
(this.form.get('optional') as UntypedFormArray).removeAt(optionalIndex);
//Reapply validators
NotificationFieldOptionsEditorModel.reapplyValidators(
{
formGroup: this.form,
validationErrorModel: this.validationErrorModel,
rootPath: this.validationRootPath
}
);
this.form.get('optional').markAsDirty();
}
// subject formatting
insertFormattingItem(key: string, value: string){
this.formatting[key] = value;
this.form.get('formatting').setValue(this.formatting);
}
formattingValueChange(event: Event, key: string){
this.formatting[key] = (event.target as HTMLInputElement).value;
this.form.get('formatting').setValue(this.formatting);
}
editFormmattingKey(oldKey: string, newKey: string){
this.insertFormattingItem(newKey, this.formatting[oldKey]);
this.deleteFormattingItem(oldKey);
}
deleteFormattingItem(key:string){
if (key in this.formatting) {
delete this.formatting[key];
this.form.get('formatting').setValue(this.formatting);
}
}
}

View File

@ -102,98 +102,13 @@
<mat-checkbox [checked]="subjectFieldOptionsEnabled" (change)="subjectFieldOptionsSelectionChanged($event)"></mat-checkbox> <mat-checkbox [checked]="subjectFieldOptionsEnabled" (change)="subjectFieldOptionsSelectionChanged($event)"></mat-checkbox>
</h4> </h4>
<div *ngIf="subjectFieldOptionsEnabled == true"> <div *ngIf="subjectFieldOptionsEnabled == true">
<div class="col-6" > <app-notification-template-field-options-component
<mat-form-field class="chip-list"> [form]="formGroup.get('value').get('subjectFieldOptions')"
<mat-label>{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.MANDATORY' | translate}}</mat-label> [validationErrorModel]="editorModel.validationErrorModel"
<mat-chip-grid #chipGrid [formControl]="formGroup.get('value').get('subjectFieldOptions').get('mandatory')"> [validationRootPath]="'value.subjectFieldOptions.'"
<mat-chip-row *ngFor="let field of subjectMandatoryFields" [mandatoryFields]="subjectMandatoryFields"
(removed)="removeChipListValues('subject', field)" [formatting]="subjectFormatting">
[editable]="true" </app-notification-template-field-options-component>
(edited)="editChipListValues('subject', $event, field)">
{{field}}
<button matChipRemove>
<mat-icon>cancel</mat-icon>
</button>
</mat-chip-row>
<input placeholder="{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.MANDATORY-PLACEHOLDER' | translate}}"
[matChipInputFor]="chipGrid"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="true"
(matChipInputTokenEnd)="addChipListValues('subject', $event)"/>
</mat-chip-grid>
<mat-error *ngIf="formGroup.get('value').get('subjectFieldOptions').get('mandatory').hasError('backendError')">{{formGroup.get('value').get('subjectFieldOptions').get('mandatory').getError('backendError').message}}</mat-error>
</mat-form-field>
</div>
<h4 class="col-md-12">{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.OPTIONAL-TITLE' | translate}}</h4>
<div class="col-12">
<div class="row" *ngFor="let subjectOptions of formGroup.get('value').get('subjectFieldOptions').get('optional')['controls']; let i = index">
<div class="col-4">
<mat-form-field class="col-auto">
<mat-label>{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.KEY' | translate}}</mat-label>
<input matInput [formControl]="subjectOptions.get('key')">
<mat-error *ngIf="subjectOptions.get('key').hasError('backendError')">{{subjectOptions.get('key').getError('backendError').message}}</mat-error>
<mat-error *ngIf="subjectOptions.get('key').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<div class="col-4">
<mat-form-field class="col-auto">
<mat-label>{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.DATA-TYPE' | translate}}</mat-label>
<mat-select name="channel" [formControl]="subjectOptions.get('type')">
<mat-option *ngFor="let type of notificationDataTypeEnum" [value]="type">
{{enumUtils.toNotificationTemplateDataTypeString(type)}}
</mat-option>
</mat-select>
<mat-error *ngIf="subjectOptions.get('type').hasError('backendError')">{{subjectOptions.get('type').getError('backendError').message}}</mat-error>
<mat-error *ngIf="subjectOptions.get('type').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<div class="col-4">
<mat-form-field class="col">
<mat-label>{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.VALUE' | translate}}</mat-label>
<input matInput [formControl]="subjectOptions.get('value')">
<mat-error *ngIf="subjectOptions.get('value').hasError('backendError')">{{subjectOptions.get('value').getError('backendError').message}}</mat-error>
<mat-error *ngIf="subjectOptions.get('value').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
<div class="col-auto">
<button mat-icon-button (click)="removeSubjectOptionalItem(i)" [disabled]="formGroup.disabled">
<mat-icon>remove</mat-icon>
</button>
</div>
</div>
</div>
<div class="row">
<div class="col-auto">
<button mat-icon-button (click)="addSubjectOptionalItem()" [disabled]="formGroup.disabled">
<mat-icon>add</mat-icon>
</button>
</div>
</div>
</div>
<h4 class="col-md-12">{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.FORMATTING' | translate}}</h4>
<div class="row" *ngFor="let item of formGroup.get('value').get('subjectFieldOptions').get('mandatory').value; let i = index">
<mat-form-field class="col-md-4">
<mat-label>{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.KEY' | translate}}</mat-label>
<input matInput [value]="item" [disabled] = "true">
</mat-form-field>
<mat-form-field class="col-md-4">
<mat-label>{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.VALUE' | translate}}</mat-label>
<input matInput [value] ="subjectFormatting[item]" (change)="subjectFormattingValueChange($event, item)">
<mat-error *ngIf="formGroup.get('value').get('subjectFieldOptions').get('formatting').hasError('backendError')">{{formGroup.get('value').get('subjectFieldOptions').get('formatting').getError('backendError').message}}</mat-error>
</mat-form-field>
</div>
<div class="row" *ngFor="let item of formGroup.get('value').get('subjectFieldOptions').get('optional')['controls']; let i = index">
<div *ngIf="item.valid">
<mat-form-field class="col-md-4">
<mat-label>{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.KEY' | translate}}</mat-label>
<input matInput [value]="item.value.key" [disabled] = "true">
</mat-form-field>
<mat-form-field class="col-md-4">
<mat-label>{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.VALUE' | translate}}</mat-label>
<input matInput [value]="subjectFormatting[item]" (change)="subjectFormattingValueChange($event, item)">
<mat-error *ngIf="formGroup.get('value').get('subjectFieldOptions').get('formatting').hasError('backendError')">{{formGroup.get('value').get('subjectFieldOptions').get('formatting').getError('backendError').message}}</mat-error>
</mat-form-field>
</div>
</div>
</div> </div>
<!-- Body --> <!-- Body -->
@ -236,98 +151,13 @@
<mat-checkbox [checked]="bodyFieldOptionsEnabled" (change)="bodyFieldOptionsSelectionChanged($event)"></mat-checkbox> <mat-checkbox [checked]="bodyFieldOptionsEnabled" (change)="bodyFieldOptionsSelectionChanged($event)"></mat-checkbox>
</h4> </h4>
<div *ngIf="bodyFieldOptionsEnabled == true"> <div *ngIf="bodyFieldOptionsEnabled == true">
<div class="col-6" > <app-notification-template-field-options-component
<mat-form-field class="chip-list"> [form]="formGroup.get('value').get('bodyFieldOptions')"
<mat-label>{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.MANDATORY' | translate}}</mat-label> [validationErrorModel]="editorModel.validationErrorModel"
<mat-chip-grid #chipGrid [formControl]="formGroup.get('value').get('bodyFieldOptions').get('mandatory')"> [validationRootPath]="'value.bodyFieldOptions.'"
<mat-chip-row *ngFor="let field of bodyMandatoryFields" [bodyMandatoryFields]="subjectMandatoryFields"
(removed)="removeChipListValues('body', field)" [formatting]="bodyFormatting">
[editable]="true" </app-notification-template-field-options-component>
(edited)="editChipListValues('body', $event, field)">
{{field}}
<button matChipRemove>
<mat-icon>cancel</mat-icon>
</button>
</mat-chip-row>
<input placeholder="{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.MANDATORY-PLACEHOLDER' | translate}}"
[matChipInputFor]="chipGrid"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="true"
(matChipInputTokenEnd)="addChipListValues('body',$event)"/>
</mat-chip-grid>
<mat-error *ngIf="formGroup.get('value').get('bodyFieldOptions').get('mandatory').hasError('backendError')">{{formGroup.get('value').get('bodyFieldOptions').get('mandatory').getError('backendError').message}}</mat-error>
</mat-form-field>
</div>
<h4 class="col-md-12">{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.OPTIONAL-TITLE' | translate}}</h4>
<div class="col-12">
<div class="row" *ngFor="let bodyOptions of formGroup.get('value').get('bodyFieldOptions').get('optional')['controls']; let i = index">
<div class="col-4">
<mat-form-field class="col-auto">
<mat-label>{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.KEY' | translate}}</mat-label>
<input matInput [formControl]="bodyOptions.get('key')">
<mat-error *ngIf="bodyOptions.get('key').hasError('backendError')">{{bodyOptions.get('key').getError('backendError').message}}</mat-error>
<mat-error *ngIf="bodyOptions.get('key').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<div class="col-4">
<mat-form-field class="col-auto">
<mat-label>{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.DATA-TYPE' | translate}}</mat-label>
<mat-select name="channel" [formControl]="bodyOptions.get('type')">
<mat-option *ngFor="let type of notificationDataTypeEnum" [value]="type">
{{enumUtils.toNotificationTemplateDataTypeString(type)}}
</mat-option>
</mat-select>
<mat-error *ngIf="bodyOptions.get('type').hasError('backendError')">{{bodyOptions.get('type').getError('backendError').message}}</mat-error>
<mat-error *ngIf="bodyOptions.get('type').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<div class="col-4">
<mat-form-field class="col">
<mat-label>{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.VALUE' | translate}}</mat-label>
<input matInput [formControl]="bodyOptions.get('value')">
<mat-error *ngIf="bodyOptions.get('value').hasError('backendError')">{{bodyOptions.get('value').getError('backendError').message}}</mat-error>
<mat-error *ngIf="bodyOptions.get('value').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
<div class="col-auto">
<button mat-icon-button (click)="removeBodyOptionalItem(i)" [disabled]="formGroup.disabled">
<mat-icon>remove</mat-icon>
</button>
</div>
</div>
</div>
<div class="row">
<div class="col-auto">
<button mat-icon-button (click)="addBodyOptionalItem()" [disabled]="formGroup.disabled">
<mat-icon>add</mat-icon>
</button>
</div>
</div>
<h4 class="col-md-12">{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.FORMATTING' | translate}}</h4>
<div class="row" *ngFor="let item of formGroup.get('value').get('bodyFieldOptions').get('mandatory').value; let i = index">
<mat-form-field class="col-md-4">
<mat-label>{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.KEY' | translate}}</mat-label>
<input matInput [value]="item" [disabled] = "true">
</mat-form-field>
<mat-form-field class="col-md-4">
<mat-label>{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.VALUE' | translate}}</mat-label>
<input matInput [value] ="bodyFormatting[item]" (change)="bodyFormattingValueChange($event, item)">
<mat-error *ngIf="formGroup.get('value').get('bodyFieldOptions').get('formatting').hasError('backendError')">{{formGroup.get('value').get('bodyFieldOptions').get('formatting').getError('backendError').message}}</mat-error>
</mat-form-field>
</div>
<div class="row" *ngFor="let item of formGroup.get('value').get('bodyFieldOptions').get('optional')['controls']; let i = index">
<div *ngIf="item.valid">
<mat-form-field class="col-md-4">
<mat-label>{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.KEY' | translate}}</mat-label>
<input matInput [value]="item.value.key" [disabled] = "true">
</mat-form-field>
<mat-form-field class="col-md-4">
<mat-label>{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.FIELDS.VALUE' | translate}}</mat-label>
<input matInput [value]="bodyFormatting[item]" (change)="bodyFormattingValueChange($event, item)">
<mat-error *ngIf="formGroup.get('value').get('bodyFieldOptions').get('formatting').hasError('backendError')">{{formGroup.get('value').get('bodyFieldOptions').get('formatting').getError('backendError').message}}</mat-error>
</mat-form-field>
</div>
</div>
</div>
</div> </div>
<!--Extra Options --> <!--Extra Options -->
<div class="row"> <div class="row">

View File

@ -252,10 +252,6 @@ export class NotificationTemplateEditorComponent extends BaseEditor<Notification
this.bccValues = this.add(event, this.bccValues); this.bccValues = this.add(event, this.bccValues);
}else if(type == "extraDataKeys"){ }else if(type == "extraDataKeys"){
this.extraDataKeys = this.add(event, this.extraDataKeys); this.extraDataKeys = this.add(event, this.extraDataKeys);
}else if(type == "subject"){
this.subjectMandatoryFields = this.add(event, this.subjectMandatoryFields);
}else if(type == "body"){
this.bodyMandatoryFields = this.add(event, this.bodyMandatoryFields);
} }
} }
@ -266,12 +262,6 @@ export class NotificationTemplateEditorComponent extends BaseEditor<Notification
this.bccValues = this.edit(field, this.bccValues, event); this.bccValues = this.edit(field, this.bccValues, event);
}else if(type == "extraDataKeys"){ }else if(type == "extraDataKeys"){
this.extraDataKeys = this.edit(field, this.extraDataKeys, event); this.extraDataKeys = this.edit(field, this.extraDataKeys, event);
}else if(type == "subject"){
this.subjectMandatoryFields = this.edit(field, this.subjectMandatoryFields, event);
this.editSubjectFormmattingKey(field, event.value.trim());
}else if(type == "body"){
this.bodyMandatoryFields = this.edit(field, this.bodyMandatoryFields, event);
this.editBodyFormmattingKey(field, event.value.trim());
} }
} }
@ -282,12 +272,6 @@ export class NotificationTemplateEditorComponent extends BaseEditor<Notification
this.bccValues = this.remove(field, this.bccValues); this.bccValues = this.remove(field, this.bccValues);
}else if(type == "extraDataKeys"){ }else if(type == "extraDataKeys"){
this.extraDataKeys = this.remove(field, this.extraDataKeys); this.extraDataKeys = this.remove(field, this.extraDataKeys);
}else if(type == "subject"){
this.subjectMandatoryFields = this.remove(field, this.subjectMandatoryFields);
this.deleteSubjectFormattingItem(field);
}else if(type == "body"){
this.bodyMandatoryFields = this.remove(field, this.bodyMandatoryFields);
this.deleteBodyFormattingItem(field);
} }
} }
@ -321,92 +305,4 @@ export class NotificationTemplateEditorComponent extends BaseEditor<Notification
return values; return values;
} }
//options fields
addSubjectOptionalItem() {
(this.formGroup.get('value').get('subjectFieldOptions').get('optional') as FormArray).push(this.editorModel.createSubjectOptionalField((this.formGroup.get('value').get('subjectFieldOptions').get('optional') as FormArray).length));
}
addBodyOptionalItem() {
(this.formGroup.get('value').get('bodyFieldOptions').get('optional') as FormArray).push(this.editorModel.createBodyOptionalField((this.formGroup.get('value').get('bodyFieldOptions').get('optional') as FormArray).length));
}
removeSubjectOptionalItem(optionalIndex: number): void {
const key = (this.formGroup.get('value').get('subjectFieldOptions').get('optional') as FormArray).at(optionalIndex).get("key").value;
this.deleteSubjectFormattingItem(key);
(this.formGroup.get('value').get('subjectFieldOptions').get('optional') as FormArray).removeAt(optionalIndex);
//Reapply validators
NotificationTemplateEditorModel.reApplyValueValidators(
{
formGroup: this.formGroup,
validationErrorModel: this.editorModel.validationErrorModel
}
);
this.formGroup.get('value').get('subjectFieldOptions').get('optional').markAsDirty();
}
removeBodyOptionalItem(optionalIndex: number): void {
const key = (this.formGroup.get('value').get('bodyFieldOptions').get('optional') as FormArray).at(optionalIndex).get("key").value;
this.deleteBodyFormattingItem(key);
(this.formGroup.get('value').get('bodyFieldOptions').get('optional') as FormArray).removeAt(optionalIndex);
//Reapply validators
NotificationTemplateEditorModel.reApplyValueValidators(
{
formGroup: this.formGroup,
validationErrorModel: this.editorModel.validationErrorModel
}
);
this.formGroup.get('value').get('bodyFieldOptions').get('optional').markAsDirty();
}
// subject formatting
insertSubjectFormattingItem(key: string, value: string){
this.subjectFormatting[key] = value;
this.formGroup.get('value').get('subjectFieldOptions').get('formatting').setValue(this.subjectFormatting);
}
subjectFormattingValueChange(event: Event, key: string){
this.bodyFormatting[key] = (event.target as HTMLInputElement).value;
this.formGroup.get('value').get('subjectFieldOptions').get('formatting').setValue(this.bodyFormatting);
}
editSubjectFormmattingKey(oldKey: string, newKey: string){
this.insertSubjectFormattingItem(newKey, this.subjectFormatting[oldKey]);
this.deleteSubjectFormattingItem(oldKey);
}
deleteSubjectFormattingItem(key:string){
if (key in this.subjectFormatting) {
delete this.subjectFormatting[key];
this.formGroup.get('value').get('subjectFieldOptions').get('formatting').setValue(this.subjectFormatting);
}
}
// body formatting
insertBodyFormattingItem(key: string, value: string){
this.bodyFormatting[key] = value;
this.formGroup.get('value').get('bodyFieldOptions').get('formatting').setValue(this.bodyFormatting);
}
bodyFormattingValueChange(event: Event, key: string){
this.bodyFormatting[key] = (event.target as HTMLInputElement).value;
this.formGroup.get('value').get('bodyFieldOptions').get('formatting').setValue(this.bodyFormatting);
}
editBodyFormmattingKey(oldKey: string, newKey: string){
this.insertBodyFormattingItem(newKey, this.bodyFormatting[oldKey]);
this.deleteBodyFormattingItem(oldKey);
}
deleteBodyFormattingItem(key:string){
if (key in this.bodyFormatting) {
delete this.bodyFormatting[key];
this.formGroup.get('value').get('bodyFieldOptions').get('formatting').setValue(this.bodyFormatting);
}
}
} }

View File

@ -68,16 +68,6 @@ export class NotificationTemplateEditorModel extends BaseEditorModel implements
return baseContext; return baseContext;
} }
createSubjectOptionalField(index: number): UntypedFormGroup {
const source: NotificationFieldInfoEditorModel = new NotificationFieldInfoEditorModel(this.validationErrorModel);
return source.buildForm({ rootPath: 'value.subjectFieldOptions.optional[' + index + '].' });
}
createBodyOptionalField(index: number): UntypedFormGroup {
const source: NotificationFieldInfoEditorModel = new NotificationFieldInfoEditorModel(this.validationErrorModel);
return source.buildForm({ rootPath: 'value.bodyFieldOptions.optional[' + index + '].' });
}
static reApplyValueValidators(params: { static reApplyValueValidators(params: {
formGroup: UntypedFormGroup, formGroup: UntypedFormGroup,
validationErrorModel: ValidationErrorModel, validationErrorModel: ValidationErrorModel,

View File

@ -16,6 +16,7 @@ import { NotificationTemplateEditorComponent } from './editor/notification-templ
import { NotificationTemplateListingFiltersComponent } from './listing/filters/notification-template-listing-filters.component'; import { NotificationTemplateListingFiltersComponent } from './listing/filters/notification-template-listing-filters.component';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
import { EditorModule } from '@tinymce/tinymce-angular'; import { EditorModule } from '@tinymce/tinymce-angular';
import { NotificationTemplateFieldOptionsComponent } from './editor/field-options/notification-template-field-options.component';
@NgModule({ @NgModule({
imports: [ imports: [
@ -37,7 +38,8 @@ import { EditorModule } from '@tinymce/tinymce-angular';
declarations: [ declarations: [
NotificationTemplateEditorComponent, NotificationTemplateEditorComponent,
NotificationTemplateListingComponent, NotificationTemplateListingComponent,
NotificationTemplateListingFiltersComponent NotificationTemplateListingFiltersComponent,
NotificationTemplateFieldOptionsComponent
] ]
}) })
export class NotificationTemplateModule { } export class NotificationTemplateModule { }

View File

@ -0,0 +1,83 @@
<h3>
{{label}}
<button mat-button class="action-btn" type="button" (click)="addSource()" [disabled]="form.disabled">{{'TENANT-EDITOR.ACTIONS.ADD-SOURCE' | translate}}</button>
</h3>
<div *ngFor="let source of form.get('sources').controls; let sourceIndex=index;" class="row mb-3">
<div class="col-12">
<div class="row mb-3 d-flex align-items-center">
<div class="col-auto d-flex">
<mat-card-title>{{'TENANT-EDITOR.FIELDS.SOURCE' | translate}} {{sourceIndex + 1}}</mat-card-title>
</div>
<div class="col-auto d-flex">
<button mat-icon-button class="action-list-icon" matTooltip="{{'TENANT-EDITOR.ACTIONS.REMOVE-SOURCE' | translate}}" (click)="removeSource(sourceIndex)" [disabled]="form.disabled">
<mat-icon>delete</mat-icon>
</button>
</div>
</div>
<div class="row" >
<div class="col-6">
<mat-form-field class="w-100">
<mat-label>{{'TENANT-EDITOR.FIELDS.URL' | translate}}</mat-label>
<input matInput type="text" name="url" [formControl]="source.get('url')" required>
<mat-error *ngIf="source.get('url').hasError('backendError')">{{source.get('url').getError('backendError').message}}</mat-error>
<mat-error *ngIf="source.get('url').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<div class="col-6">
<mat-form-field class="w-100">
<mat-label>{{'TENANT-EDITOR.FIELDS.ISSUER-URL' | translate}}</mat-label>
<input matInput type="text" name="issuerUrl" [formControl]="source.get('issuerUrl')" required>
<mat-error *ngIf="source.get('issuerUrl').hasError('backendError')">{{source.get('issuerUrl').getError('backendError').message}}</mat-error>
<mat-error *ngIf="source.get('issuerUrl').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<div class="col-6">
<mat-form-field class="w-100">
<mat-label>{{'TENANT-EDITOR.FIELDS.CLIENT-ID' | translate}}</mat-label>
<input matInput type="text" name="clientId" [formControl]="source.get('clientId')" required>
<mat-error *ngIf="source.get('clientId').hasError('backendError')">{{source.get('clientId').getError('backendError').message}}</mat-error>
<mat-error *ngIf="source.get('clientId').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<div class="col-6">
<mat-form-field class="w-100">
<mat-label>{{'TENANT-EDITOR.FIELDS.CLIENT-SECRET' | translate}}</mat-label>
<input matInput type="text" name="clientSecret" [formControl]="source.get('clientSecret')" required>
<mat-error *ngIf="source.get('clientSecret').hasError('backendError')">{{source.get('clientSecret').getError('backendError').message}}</mat-error>
<mat-error *ngIf="source.get('clientSecret').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<div class="col-6">
<mat-form-field class="w-100">
<mat-label>{{'TENANT-EDITOR.FIELDS.SCOPE' | translate}}</mat-label>
<input matInput type="text" name="scope" [formControl]="source.get('scope')" required>
<mat-error *ngIf="source.get('scope').hasError('backendError')">{{source.get('scope').getError('backendError').message}}</mat-error>
<mat-error *ngIf="source.get('scope').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<div class="col-6">
<mat-form-field class="chip-list">
<mat-label>{{'TENANT-EDITOR.FIELDS.CODES' | translate}}</mat-label>
<mat-chip-grid #chipGrid [formControl]="source.get('codes')">
<mat-chip-row *ngFor="let code of codes.get(sourceIndex)"
(removed)="removeCode(code, sourceIndex)"
[editable]="true"
(edited)="editCode(code, $event, sourceIndex)">
{{code}}
<button matChipRemove>
<mat-icon>cancel</mat-icon>
</button>
</mat-chip-row>
<input placeholder="{{'TENANT-EDITOR.FIELDS.CODES-PLACEHOLDER' | translate}}"
[matChipInputFor]="chipGrid"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="true"
(matChipInputTokenEnd)="addCode($event, sourceIndex)"/>
</mat-chip-grid>
<mat-error *ngIf="source.get('codes').hasError('backendError')">{{source.get('codes').getError('backendError').message}}</mat-error>
<mat-error *ngIf="source.get('codes').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,18 @@
.action-btn {
border-radius: 30px;
background-color: var(--secondary-color);
border: 1px solid transparent;
padding-left: 2em;
padding-right: 2em;
box-shadow: 0px 3px 6px #1E202029;
transition-property: background-color, color;
transition-duration: 200ms;
transition-delay: 50ms;
transition-timing-function: ease-in-out;
&:disabled{
background-color: #CBCBCB;
color: #FFF;
border: 0px;
}
}

View File

@ -0,0 +1,99 @@
import { Component, Input, OnInit } from '@angular/core';
import { UntypedFormArray } from '@angular/forms';
import { MatChipEditedEvent, MatChipInputEvent } from '@angular/material/chips';
import { EnumUtils } from '@app/core/services/utilities/enum-utils.service';
import { BaseComponent } from '@common/base/base.component';
import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model';
import { TenantDepositConfigEditorModel, TenantEditorModel, TenantSourceEditorModel } from '../tenant-editor.model';
@Component({
selector: 'app-tenant-source-component',
templateUrl: 'tenant-source.component.html',
styleUrls: ['./tenant-source.component.scss']
})
export class TenantSourceComponent extends BaseComponent implements OnInit {
@Input() form;
@Input() validationErrorModel: ValidationErrorModel = null;
@Input() validationRootPath: string = null;
@Input() codes: Map<number, string[]>;
@Input() label: string = null;
constructor(
public enumUtils: EnumUtils,
) { super(); }
ngOnInit() {
}
//
// source
//
addSource(): void {
const formArray = this.form.get('sources') as UntypedFormArray;
this.codes.set(formArray.length, []);
const source: TenantSourceEditorModel = new TenantSourceEditorModel(this.validationErrorModel);
formArray.push(source.buildForm({ rootPath: this.validationRootPath + 'sources[' + formArray.length + '].' }));
}
removeSource(sourceIndex: number): void {
this.codes.delete((this.form.get('sources') as UntypedFormArray).length);
(this.form.get('sources') as UntypedFormArray).removeAt(sourceIndex);
// Reapply validators
TenantDepositConfigEditorModel.reapplySourcesFieldsValidators(
{
formArray: this.form.get('sources') as UntypedFormArray,
validationErrorModel: this.validationErrorModel,
rootPath: this.validationRootPath
}
)
this.form.get('sources').markAsDirty();
}
// source codes
addCode(event: MatChipInputEvent, key: number): void {
const value = (event.value || '').trim();
if (value){
const values = this.codes.get(key);
values.push(value);
this.codes.set(key, values);
}
event.chipInput!.clear();
}
removeCode(code: string, key: number): void {
const values = this.codes.get(key);
if (values){
const index = values.indexOf(code);
if (index >= 0) {
values.splice(index, 1);
this.codes.set(key, values);
}
}
}
editCode(code: string, event: MatChipEditedEvent, key: number) {
const values = this.codes.get(key);
if (values){
const value = event.value.trim();
// Remove code if it no longer has a value
if (!value) {
this.removeCode(code, key);
return;
}
const index = values.indexOf(code);
if (index >= 0) {
values[index] = value;
this.codes.set(key, values);
}
}
}
}

View File

@ -57,174 +57,22 @@
</div> </div>
<!-- Deposit --> <!-- Deposit -->
<div class="col-12"> <div class="col-12">
<h3> <app-tenant-source-component
{{'TENANT-EDITOR.FIELDS.DEPOSIT' | translate}} [form]="formGroup.get('config').get('deposit')"
<button mat-button class="action-btn" type="button" (click)="addDepositSource()" [disabled]="formGroup.disabled">{{'TENANT-EDITOR.ACTIONS.ADD-SOURCE' | translate}}</button> [validationErrorModel]="editorModel.validationErrorModel"
</h3> [validationRootPath]="'config.deposit.'"
<div *ngFor="let source of formGroup.get('config').get('deposit').get('sources').controls; let sourceIndex=index;" class="row mb-3"> [codes]="depositCodes"
<div class="col-12"> [label]="'TENANT-EDITOR.FIELDS.DEPOSIT' | translate">
<div class="row mb-3 d-flex align-items-center"> </app-tenant-source-component>
<div class="col-auto d-flex">
<mat-card-title>{{'TENANT-EDITOR.FIELDS.SOURCE' | translate}} {{sourceIndex + 1}}</mat-card-title>
</div>
<div class="col-auto d-flex">
<button mat-icon-button class="action-list-icon" matTooltip="{{'TENANT-EDITOR.ACTIONS.REMOVE-SOURCE' | translate}}" (click)="removeDepositSource(sourceIndex)" [disabled]="formGroup.disabled">
<mat-icon>delete</mat-icon>
</button>
</div>
</div>
<div class="row" >
<div class="col-6">
<mat-form-field class="w-100">
<mat-label>{{'TENANT-EDITOR.FIELDS.URL' | translate}}</mat-label>
<input matInput type="text" name="url" [formControl]="source.get('url')" required>
<mat-error *ngIf="source.get('url').hasError('backendError')">{{source.get('url').getError('backendError').message}}</mat-error>
<mat-error *ngIf="source.get('url').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<div class="col-6">
<mat-form-field class="w-100">
<mat-label>{{'TENANT-EDITOR.FIELDS.ISSUER-URL' | translate}}</mat-label>
<input matInput type="text" name="issuerUrl" [formControl]="source.get('issuerUrl')" required>
<mat-error *ngIf="source.get('issuerUrl').hasError('backendError')">{{source.get('issuerUrl').getError('backendError').message}}</mat-error>
<mat-error *ngIf="source.get('issuerUrl').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<div class="col-6">
<mat-form-field class="w-100">
<mat-label>{{'TENANT-EDITOR.FIELDS.CLIENT-ID' | translate}}</mat-label>
<input matInput type="text" name="clientId" [formControl]="source.get('clientId')" required>
<mat-error *ngIf="source.get('clientId').hasError('backendError')">{{source.get('clientId').getError('backendError').message}}</mat-error>
<mat-error *ngIf="source.get('clientId').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<div class="col-6">
<mat-form-field class="w-100">
<mat-label>{{'TENANT-EDITOR.FIELDS.CLIENT-SECRET' | translate}}</mat-label>
<input matInput type="text" name="clientSecret" [formControl]="source.get('clientSecret')" required>
<mat-error *ngIf="source.get('clientSecret').hasError('backendError')">{{source.get('clientSecret').getError('backendError').message}}</mat-error>
<mat-error *ngIf="source.get('clientSecret').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<div class="col-6">
<mat-form-field class="w-100">
<mat-label>{{'TENANT-EDITOR.FIELDS.SCOPE' | translate}}</mat-label>
<input matInput type="text" name="scope" [formControl]="source.get('scope')" required>
<mat-error *ngIf="source.get('scope').hasError('backendError')">{{source.get('scope').getError('backendError').message}}</mat-error>
<mat-error *ngIf="source.get('scope').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<div class="col-6">
<mat-form-field class="chip-list">
<mat-label>{{'TENANT-EDITOR.FIELDS.CODES' | translate}}</mat-label>
<mat-chip-grid #chipGrid [formControl]="source.get('codes')">
<mat-chip-row *ngFor="let code of depositCodes.get(sourceIndex)"
(removed)="removeDepositCode(code, sourceIndex)"
[editable]="true"
(edited)="editDepositCode(code, $event, sourceIndex)">
{{code}}
<button matChipRemove>
<mat-icon>cancel</mat-icon>
</button>
</mat-chip-row>
<input placeholder="{{'TENANT-EDITOR.FIELDS.CODES-PLACEHOLDER' | translate}}"
[matChipInputFor]="chipGrid"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="true"
(matChipInputTokenEnd)="addDepositCode($event, sourceIndex)"/>
</mat-chip-grid>
<mat-error *ngIf="source.get('codes').hasError('backendError')">{{source.get('codes').getError('backendError').message}}</mat-error>
<mat-error *ngIf="source.get('codes').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
</div>
</div>
</div>
</div> </div>
<div class="col-12"> <div class="col-12">
<h3> <app-tenant-source-component
{{'TENANT-EDITOR.FIELDS.FILE-TRANSFORMERS' | translate}} [form]="formGroup.get('config').get('fileTransformers')"
<button mat-button class="action-btn" type="button" (click)="addFileSource()" [disabled]="formGroup.disabled">{{'TENANT-EDITOR.ACTIONS.ADD-SOURCE' | translate}}</button> [validationErrorModel]="editorModel.validationErrorModel"
</h3> [validationRootPath]="'config.fileTransformers.'"
<div *ngFor="let source of formGroup.get('config').get('fileTransformers').get('sources').controls; let sourceIndex=index;" class="row mb-3"> [codes]="fileTransformersCodes"
<div class="col-12"> [label]="'TENANT-EDITOR.FIELDS.FILE-TRANSFORMERS' | translate">
<div class="row mb-3 d-flex align-items-center"> </app-tenant-source-component>
<div class="col-auto d-flex">
<mat-card-title>{{'TENANT-EDITOR.FIELDS.SOURCE' | translate}} {{sourceIndex + 1}}</mat-card-title>
</div>
<div class="col-auto d-flex">
<button mat-icon-button class="action-list-icon" matTooltip="{{'TENANT-EDITOR.ACTIONS.REMOVE-SOURCE' | translate}}" (click)="removeFileSource(sourceIndex)" [disabled]="formGroup.disabled">
<mat-icon>delete</mat-icon>
</button>
</div>
</div>
<div class="row" >
<div class="col-6">
<mat-form-field class="w-100">
<mat-label>{{'TENANT-EDITOR.FIELDS.URL' | translate}}</mat-label>
<input matInput type="text" name="url" [formControl]="source.get('url')" required>
<mat-error *ngIf="source.get('url').hasError('backendError')">{{source.get('url').getError('backendError').message}}</mat-error>
<mat-error *ngIf="source.get('url').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<div class="col-6">
<mat-form-field class="w-100">
<mat-label>{{'TENANT-EDITOR.FIELDS.ISSUER-URL' | translate}}</mat-label>
<input matInput type="text" name="issuerUrl" [formControl]="source.get('issuerUrl')" required>
<mat-error *ngIf="source.get('issuerUrl').hasError('backendError')">{{source.get('issuerUrl').getError('backendError').message}}</mat-error>
<mat-error *ngIf="source.get('issuerUrl').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<div class="col-6">
<mat-form-field class="w-100">
<mat-label>{{'TENANT-EDITOR.FIELDS.CLIENT-ID' | translate}}</mat-label>
<input matInput type="text" name="clientId" [formControl]="source.get('clientId')" required>
<mat-error *ngIf="source.get('clientId').hasError('backendError')">{{source.get('clientId').getError('backendError').message}}</mat-error>
<mat-error *ngIf="source.get('clientId').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<div class="col-6">
<mat-form-field class="w-100">
<mat-label>{{'TENANT-EDITOR.FIELDS.CLIENT-SECRET' | translate}}</mat-label>
<input matInput type="text" name="clientSecret" [formControl]="source.get('clientSecret')" required>
<mat-error *ngIf="source.get('clientSecret').hasError('backendError')">{{source.get('clientSecret').getError('backendError').message}}</mat-error>
<mat-error *ngIf="source.get('clientSecret').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<div class="col-6">
<mat-form-field class="w-100">
<mat-label>{{'TENANT-EDITOR.FIELDS.SCOPE' | translate}}</mat-label>
<input matInput type="text" name="scope" [formControl]="source.get('scope')" required>
<mat-error *ngIf="source.get('scope').hasError('backendError')">{{source.get('scope').getError('backendError').message}}</mat-error>
<mat-error *ngIf="source.get('scope').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<div class="col-6">
<mat-form-field class="chip-list">
<mat-label>{{'TENANT-EDITOR.FIELDS.CODES' | translate}}</mat-label>
<mat-chip-grid #chipGrid [formControl]="source.get('codes')">
<mat-chip-row *ngFor="let code of fileTransformersCodes.get(sourceIndex)"
(removed)="removeFileCode(code, sourceIndex)"
[editable]="true"
(edited)="editFileCode(code, $event, sourceIndex)">
{{code}}
<button matChipRemove>
<mat-icon>cancel</mat-icon>
</button>
</mat-chip-row>
<input placeholder="{{'TENANT-EDITOR.FIELDS.CODES-PLACEHOLDER' | translate}}"
[matChipInputFor]="chipGrid"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="true"
(matChipInputTokenEnd)="addFileCode($event, sourceIndex)"/>
</mat-chip-grid>
<mat-error *ngIf="source.get('codes').hasError('backendError')">{{source.get('codes').getError('backendError').message}}</mat-error>
<mat-error *ngIf="source.get('codes').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
</div>
</div>
</div>
</div> </div>
</div> </div>
</mat-card-content> </mat-card-content>

View File

@ -27,8 +27,7 @@ import { TranslateService } from '@ngx-translate/core';
import { map, takeUntil } from 'rxjs/operators'; import { map, takeUntil } from 'rxjs/operators';
import { TenantEditorResolver } from './tenant-editor.resolver'; import { TenantEditorResolver } from './tenant-editor.resolver';
import { TenantEditorService } from './tenant-editor.service'; import { TenantEditorService } from './tenant-editor.service';
import { TenantEditorModel, TenantSourceEditorModel } from './tenant-editor.model'; import { TenantEditorModel } from './tenant-editor.model';
import { MatChipEditedEvent, MatChipInputEvent } from '@angular/material/chips';
@Component({ @Component({
@ -188,137 +187,5 @@ export class TenantEditorComponent extends BaseEditor<TenantEditorModel, Tenant>
this.formService.validateAllFormFields(this.formGroup); this.formService.validateAllFormFields(this.formGroup);
} }
//
// deposit source
//
addDepositSource(): void {
this.depositCodes.set((this.formGroup.get('config').get('deposit').get('sources') as FormArray).length, []);
(this.formGroup.get('config').get('deposit').get('sources') as FormArray).push(this.editorModel.createChildDeposit((this.formGroup.get('config').get('deposit').get('sources') as FormArray).length));
}
removeDepositSource(sourceIndex: number): void {
this.depositCodes.delete((this.formGroup.get('config').get('deposit').get('sources') as FormArray).length);
(this.formGroup.get('config').get('deposit').get('sources') as FormArray).removeAt(sourceIndex);
//Reapply validators
TenantEditorModel.reApplyDepositSourcesValidators(
{
formGroup: this.formGroup,
validationErrorModel: this.editorModel.validationErrorModel
}
)
this.formGroup.get('config').get('deposit').get('sources').markAsDirty();
}
// deposit source codes
addDepositCode(event: MatChipInputEvent, key: number): void {
const value = (event.value || '').trim();
if (value){
const values = this.depositCodes.get(key);
values.push(value);
this.depositCodes.set(key, values);
}
event.chipInput!.clear();
}
removeDepositCode(code: string, key: number): void {
const values = this.depositCodes.get(key);
if (values){
const index = values.indexOf(code);
if (index >= 0) {
values.splice(index, 1);
this.depositCodes.set(key, values);
}
}
}
editDepositCode(code: string, event: MatChipEditedEvent, key: number) {
const values = this.depositCodes.get(key);
if (values){
const value = event.value.trim();
// Remove code if it no longer has a value
if (!value) {
this.removeDepositCode(code, key);
return;
}
const index = values.indexOf(code);
if (index >= 0) {
values[index] = value;
this.depositCodes.set(key, values);
}
}
}
//
// fileTransformers source
//
addFileSource(): void {
this.fileTransformersCodes.set((this.formGroup.get('config').get('fileTransformers').get('sources') as FormArray).length, []);
(this.formGroup.get('config').get('fileTransformers').get('sources') as FormArray).push(this.editorModel.createChildFileTransformer((this.formGroup.get('config').get('fileTransformers').get('sources') as FormArray).length));
}
removeFileSource(sourceIndex: number): void {
this.fileTransformersCodes.delete((this.formGroup.get('config').get('fileTransformers').get('sources') as FormArray).length);
(this.formGroup.get('config').get('fileTransformers').get('sources') as FormArray).removeAt(sourceIndex);
//Reapply validators
TenantEditorModel.reApplyFileTransformerSourcesValidators(
{
formGroup: this.formGroup,
validationErrorModel: this.editorModel.validationErrorModel
}
)
this.formGroup.get('config').get('fileTransformers').get('sources').markAsDirty();
}
// fileTransformers source codes
addFileCode(event: MatChipInputEvent, key: number): void {
const value = (event.value || '').trim();
if (value){
const values = this.fileTransformersCodes.get(key);
values.push(value);
this.fileTransformersCodes.set(key, values);
}
event.chipInput!.clear();
}
removeFileCode(code: string, key: number): void {
const values = this.fileTransformersCodes.get(key);
if (values){
const index = values.indexOf(code);
if (index >= 0) {
values.splice(index, 1);
this.fileTransformersCodes.set(key, values);
}
}
}
editFileCode(code: string, event: MatChipEditedEvent, key:number) {
const values = this.fileTransformersCodes.get(key);
if (values){
const value = event.value.trim();
// Remove code if it no longer has a value
if (!value) {
this.removeFileCode(code, key);
return;
}
const index = values.indexOf(code);
if (index >= 0) {
values[index] = value;
this.fileTransformersCodes.set(key, values);
}
}
}
} }

View File

@ -56,11 +56,6 @@ export class TenantEditorModel extends BaseEditorModel implements TenantPersist
return baseContext; return baseContext;
} }
createChildDeposit(index: number): UntypedFormGroup {
const deposit: TenantSourceEditorModel = new TenantSourceEditorModel(this.validationErrorModel);
return deposit.buildForm({ rootPath: 'config.deposit.sources[' + index + '].' });
}
static reApplyDepositSourcesValidators(params: { static reApplyDepositSourcesValidators(params: {
formGroup: UntypedFormGroup, formGroup: UntypedFormGroup,
validationErrorModel: ValidationErrorModel, validationErrorModel: ValidationErrorModel,
@ -75,11 +70,6 @@ export class TenantEditorModel extends BaseEditorModel implements TenantPersist
}); });
} }
createChildFileTransformer(index: number): UntypedFormGroup {
const deposit: TenantSourceEditorModel = new TenantSourceEditorModel(this.validationErrorModel);
return deposit.buildForm({ rootPath: 'config.fileTransformers.sources[' + index + '].' });
}
static reApplyFileTransformerSourcesValidators(params: { static reApplyFileTransformerSourcesValidators(params: {
formGroup: UntypedFormGroup, formGroup: UntypedFormGroup,
validationErrorModel: ValidationErrorModel, validationErrorModel: ValidationErrorModel,
@ -186,8 +176,8 @@ export class TenantDepositConfigEditorModel implements TenantDepositConfigPersis
this.validationErrorModel this.validationErrorModel
).fromModel(item).buildForm({ ).fromModel(item).buildForm({
rootPath: `${rootPath}sources[${index}].` rootPath: `${rootPath}sources[${index}].`
}), context.getValidation('sources') })
) ), context.getValidation('sources')
), ),
}); });
} }
@ -258,8 +248,8 @@ export class TenantFileTransformersConfigEditorModel implements TenantFileTransf
this.validationErrorModel this.validationErrorModel
).fromModel(item).buildForm({ ).fromModel(item).buildForm({
rootPath: `${rootPath}sources[${index}].` rootPath: `${rootPath}sources[${index}].`
}), context.getValidation('sources') })
) ), context.getValidation('sources')
), ),
}); });
} }

View File

@ -14,6 +14,7 @@ import { TenantEditorComponent } from './editor/tenant-editor.component';
import { TenantListingComponent } from './listing/tenant-listing.component'; import { TenantListingComponent } from './listing/tenant-listing.component';
import { TenantListingFiltersComponent } from "./listing/filters/tenant-listing-filters.component"; import { TenantListingFiltersComponent } from "./listing/filters/tenant-listing-filters.component";
import { RichTextEditorModule } from '@app/library/rich-text-editor/rich-text-editor.module'; import { RichTextEditorModule } from '@app/library/rich-text-editor/rich-text-editor.module';
import { TenantSourceComponent } from './editor/source/tenant-source.component';
@NgModule({ @NgModule({
imports: [ imports: [
@ -33,7 +34,8 @@ import { RichTextEditorModule } from '@app/library/rich-text-editor/rich-text-ed
declarations: [ declarations: [
TenantEditorComponent, TenantEditorComponent,
TenantListingComponent, TenantListingComponent,
TenantListingFiltersComponent TenantListingFiltersComponent,
TenantSourceComponent
] ]
}) })
export class TenantModule { } export class TenantModule { }