Merge branch 'dmp-refactoring' of code-repo.d4science.org:MaDgiK-CITE/argos into dmp-refactoring
This commit is contained in:
commit
b1ebc6b35a
|
@ -18,6 +18,12 @@ export enum AppPermission {
|
||||||
BrowseDmp = "BrowseDmp",
|
BrowseDmp = "BrowseDmp",
|
||||||
EditDmp = "EditDmp",
|
EditDmp = "EditDmp",
|
||||||
DeleteDmp= "DeleteDmp",
|
DeleteDmp= "DeleteDmp",
|
||||||
|
CloneDmp = "CloneDmp",
|
||||||
|
CreateNewVersionDmp = "CreateNewVersionDmp",
|
||||||
|
ExportDmp = "ExportDmp",
|
||||||
|
FinalizeDmp = "FinalizeDmp",
|
||||||
|
AssignDmpUsers = "AssignDmpUsers",
|
||||||
|
InviteDmpUsers = "InviteDmpUsers",
|
||||||
|
|
||||||
//DescriptionTemplateType
|
//DescriptionTemplateType
|
||||||
BrowseDescriptionTemplate = "BrowseDescriptionTemplate",
|
BrowseDescriptionTemplate = "BrowseDescriptionTemplate",
|
||||||
|
|
|
@ -131,10 +131,10 @@ export class ReferenceTypeService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public getResearcherReferenceType(): Guid {
|
public getResearcherReferenceType(): Guid {
|
||||||
return null;
|
return Guid.parse('5a2112e7-ea99-4cfe-98a1-68665e26726e');;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getGrantReferenceType(): Guid {
|
public getGrantReferenceType(): Guid {
|
||||||
return null;
|
return Guid.parse('5b9c284f-f041-4995-96cc-fad7ad13289c');
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -163,7 +163,7 @@
|
||||||
<div class="col" *ngIf="field.get('category').value != null">
|
<div class="col" *ngIf="field.get('category').value != null">
|
||||||
<mat-form-field class="w-100">
|
<mat-form-field class="w-100">
|
||||||
<mat-label>{{'DMP-BLUEPRINT-EDITOR.FIELDS.SEMANTICS' | translate}}</mat-label>
|
<mat-label>{{'DMP-BLUEPRINT-EDITOR.FIELDS.SEMANTICS' | translate}}</mat-label>
|
||||||
<app-multiple-auto-complete placeholder="{{'DMP-BLUEPRINT-EDITOR.FIELDS.SEMANTICS' | translate}}" [hidePlaceholder]="true" required='false' [separatorKeysCodes]="separatorKeysCodes" [formControl]="field.get('semantics')" [configuration]="semanticsService.multipleAutocompleteConfiguration">
|
<app-multiple-auto-complete placeholder="{{'DMP-BLUEPRINT-EDITOR.FIELDS.SEMANTICS' | translate}}" [hidePlaceholder]="true" [required]="false" [separatorKeysCodes]="separatorKeysCodes" [formControl]="field.get('semantics')" [configuration]="semanticsService.multipleAutocompleteConfiguration">
|
||||||
</app-multiple-auto-complete>
|
</app-multiple-auto-complete>
|
||||||
<mat-error *ngIf="field.get('semantics').hasError('backendError')">{{field.get('semantics').getError('backendError').message}}</mat-error>
|
<mat-error *ngIf="field.get('semantics').hasError('backendError')">{{field.get('semantics').getError('backendError').message}}</mat-error>
|
||||||
<mat-error *ngIf="field.get('semantics').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
<mat-error *ngIf="field.get('semantics').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||||
|
|
|
@ -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>
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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">
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 { }
|
||||||
|
|
|
@ -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>
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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>
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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')
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 { }
|
||||||
|
|
|
@ -30,11 +30,11 @@
|
||||||
<div class="dmp-card-actions">
|
<div class="dmp-card-actions">
|
||||||
<a class="col-auto border-right pointer" [matMenuTriggerFor]="exportMenu"><span class="material-icons icon-align pr-2">open_in_new</span>{{'DMP-LISTING.ACTIONS.EXPORT' | translate}}</a>
|
<a class="col-auto border-right pointer" [matMenuTriggerFor]="exportMenu"><span class="material-icons icon-align pr-2">open_in_new</span>{{'DMP-LISTING.ACTIONS.EXPORT' | translate}}</a>
|
||||||
<a class="col-auto border-right pointer" *ngIf="isDraftDmp(dmp)" [routerLink]="['/plans/edit/' + dmp.id]" target="_blank"><span class="material-icons icon-align">add</span>{{'DMP-LISTING.ACTIONS.ADD-DESCRIPTION-SHORT' | translate}}</a>
|
<a class="col-auto border-right pointer" *ngIf="isDraftDmp(dmp)" [routerLink]="['/plans/edit/' + dmp.id]" target="_blank"><span class="material-icons icon-align">add</span>{{'DMP-LISTING.ACTIONS.ADD-DESCRIPTION-SHORT' | translate}}</a>
|
||||||
<a class="col-auto border-right pointer" *ngIf="isUserOwner(dmp)" (click)="inviteToDmp()"><span class="material-icons icon-align pr-2">group_add</span>{{'DMP-LISTING.ACTIONS.INVITE-SHORT' | translate}}</a>
|
<a class="col-auto border-right pointer" *ngIf="isDmpOwner(dmp)" (click)="inviteToDmp()"><span class="material-icons icon-align pr-2">group_add</span>{{'DMP-LISTING.ACTIONS.INVITE-SHORT' | translate}}</a>
|
||||||
<a class="col-auto border-right pointer" *ngIf="isAuthenticated()" (click)="cloneClicked()"><span class="material-icons icon-align pr-2">filter_none</span>{{'DMP-LISTING.ACTIONS.CLONE' | translate}}</a>
|
<a class="col-auto border-right pointer" *ngIf="isAuthenticated()" (click)="cloneClicked()"><span class="material-icons icon-align pr-2">filter_none</span>{{'DMP-LISTING.ACTIONS.CLONE' | translate}}</a>
|
||||||
<a class="col-auto border-right pointer" *ngIf="!isAuthenticated()" (click)="viewVersions(dmp)"><span class="material-icons icon-align pr-2">library_books</span>{{'DMP-LISTING.ACTIONS.VIEW-VERSION' | translate}}</a>
|
<a class="col-auto border-right pointer" *ngIf="!isAuthenticated()" (click)="viewVersions(dmp)"><span class="material-icons icon-align pr-2">library_books</span>{{'DMP-LISTING.ACTIONS.VIEW-VERSION' | translate}}</a>
|
||||||
|
|
||||||
<a class="col-auto border-right pointer" *ngIf="!isDraftDmp(dmp) && isUserOwner(dmp)" (click)="deleteClicked(dmp.id)"><span class="material-icons icon-align pr-2">delete</span>{{ 'DMP-LISTING.ACTIONS.DELETE' | translate }}</a>
|
<a class="col-auto border-right pointer" *ngIf="!isDraftDmp(dmp) && isDmpOwner(dmp)" (click)="deleteClicked(dmp.id)"><span class="material-icons icon-align pr-2">delete</span>{{ 'DMP-LISTING.ACTIONS.DELETE' | translate }}</a>
|
||||||
<a class="col-auto pointer" *ngIf="isAuthenticated()" [matMenuTriggerFor]="actionsMenu"><span class="material-icons icon-align pl-2">more_horiz</span></a>
|
<a class="col-auto pointer" *ngIf="isAuthenticated()" [matMenuTriggerFor]="actionsMenu"><span class="material-icons icon-align pl-2">more_horiz</span></a>
|
||||||
</div>
|
</div>
|
||||||
<mat-menu #exportMenu="matMenu" xPosition="before">
|
<mat-menu #exportMenu="matMenu" xPosition="before">
|
||||||
|
@ -44,13 +44,13 @@
|
||||||
</button>
|
</button>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
<mat-menu #actionsMenu="matMenu" xPosition="before">
|
<mat-menu #actionsMenu="matMenu" xPosition="before">
|
||||||
<button *ngIf="isUserOwner(dmp)" mat-menu-item (click)="newVersionClicked()">
|
<button *ngIf="canCreateNewVersion(dmp)" mat-menu-item (click)="newVersionClicked()">
|
||||||
<mat-icon>queue</mat-icon>{{'DMP-LISTING.ACTIONS.NEW-VERSION' | translate}}
|
<mat-icon>queue</mat-icon>{{'DMP-LISTING.ACTIONS.NEW-VERSION' | translate}}
|
||||||
</button>
|
</button>
|
||||||
<button mat-menu-item (click)="viewVersions(dmp)">
|
<button mat-menu-item (click)="viewVersions(dmp)">
|
||||||
<mat-icon>library_books</mat-icon>{{'DMP-LISTING.ACTIONS.VIEW-VERSION' | translate}}
|
<mat-icon>library_books</mat-icon>{{'DMP-LISTING.ACTIONS.VIEW-VERSION' | translate}}
|
||||||
</button>
|
</button>
|
||||||
<button mat-menu-item *ngIf="isDraftDmp(dmp) && isUserOwner(dmp)" (click)="deleteClicked(dmp.id)" class="menu-item">
|
<button mat-menu-item *ngIf="isDraftDmp(dmp) && isDmpOwner(dmp)" (click)="deleteClicked(dmp.id)" class="menu-item">
|
||||||
<mat-icon>delete</mat-icon>{{ 'DMP-LISTING.ACTIONS.DELETE' | translate }}
|
<mat-icon>delete</mat-icon>{{ 'DMP-LISTING.ACTIONS.DELETE' | translate }}
|
||||||
</button>
|
</button>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
|
|
|
@ -26,6 +26,7 @@ import { AuthService } from '../../../../core/services/auth/auth.service';
|
||||||
import { CloneDmpDialogComponent } from '../../clone-dialog/dmp-clone-dialog.component';
|
import { CloneDmpDialogComponent } from '../../clone-dialog/dmp-clone-dialog.component';
|
||||||
import { DmpInvitationDialogComponent } from '../../invitation/dialog/dmp-invitation-dialog.component';
|
import { DmpInvitationDialogComponent } from '../../invitation/dialog/dmp-invitation-dialog.component';
|
||||||
import { NewVersionDmpDialogComponent } from '../../new-version-dialog/dmp-new-version-dialog.component';
|
import { NewVersionDmpDialogComponent } from '../../new-version-dialog/dmp-new-version-dialog.component';
|
||||||
|
import { AppPermission } from '@app/core/common/enum/permission.enum';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-dmp-listing-item-component',
|
selector: 'app-dmp-listing-item-component',
|
||||||
|
@ -104,7 +105,7 @@ export class DmpListingItemComponent extends BaseComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
viewVersions(dmp: Dmp) {
|
viewVersions(dmp: Dmp) {
|
||||||
if (dmp.accessType == DmpAccessType.Public && dmp.status == DmpStatus.Finalized && !this.isUserOwner(dmp)) {
|
if (dmp.accessType == DmpAccessType.Public && dmp.status == DmpStatus.Finalized && !this.isDmpOwner(dmp)) {
|
||||||
let url = this.router.createUrlTree(['/explore-plans/versions/', dmp.groupId]);
|
let url = this.router.createUrlTree(['/explore-plans/versions/', dmp.groupId]);
|
||||||
window.open(url.toString(), '_blank');
|
window.open(url.toString(), '_blank');
|
||||||
} else {
|
} else {
|
||||||
|
@ -214,8 +215,12 @@ export class DmpListingItemComponent extends BaseComponent implements OnInit {
|
||||||
this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DELETE'), SnackBarNotificationLevel.Error);
|
this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DELETE'), SnackBarNotificationLevel.Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
isUserOwner(dmp: Dmp): boolean {
|
isDmpOwner(dmp: Dmp): boolean {
|
||||||
const principalId: Guid = this.authentication.userId();
|
const principalId: Guid = this.authentication.userId();
|
||||||
if (principalId) return !!dmp.dmpUsers?.find(x => (x.role === DmpUserRole.Owner) && (principalId === x.id));
|
if (principalId) return !!dmp.dmpUsers?.find(x => (x.role === DmpUserRole.Owner) && (principalId === x.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
canCreateNewVersion(dmp: Dmp): boolean {
|
||||||
|
return this.isDmpOwner(dmp) || this.authentication.hasPermission(AppPermission.CreateNewVersionDmp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue