From 90ad316db44d10bc57144d88cf74f2ccd9396c20 Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Thu, 14 Dec 2023 16:25:02 +0100 Subject: [PATCH 1/5] fix issue with edit and creation, unify files, refactor --- .../admin-ldn-services-routing.module.ts | 7 +- .../admin-ldn-services.module.ts | 4 - .../ldn-service-form-edit.component.html | 415 ------------ .../ldn-service-form-edit.component.scss | 141 ---- .../ldn-service-form-edit.component.spec.ts | 80 --- .../ldn-service-form-edit.component.ts | 597 ----------------- .../ldn-service-form.component.html | 184 ++++-- .../ldn-service-form.component.scss | 31 +- .../ldn-service-form.component.spec.ts | 86 ++- .../ldn-service-form.component.ts | 614 ++++++++++++++---- .../ldn-service-new.component.html | 1 - .../ldn-service-new.component.scss | 0 .../ldn-service-new.component.spec.ts | 25 - .../ldn-service-new.component.ts | 9 - 14 files changed, 651 insertions(+), 1543 deletions(-) delete mode 100644 src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html delete mode 100644 src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss delete mode 100644 src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.spec.ts delete mode 100644 src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts delete mode 100644 src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.html delete mode 100644 src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.scss delete mode 100644 src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.spec.ts delete mode 100644 src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.ts diff --git a/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts b/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts index 282ca430a23..300daa7045b 100644 --- a/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts +++ b/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts @@ -2,8 +2,7 @@ import {NgModule} from '@angular/core'; import {RouterModule} from '@angular/router'; import {I18nBreadcrumbResolver} from 'src/app/core/breadcrumbs/i18n-breadcrumb.resolver'; import {LdnServicesOverviewComponent} from './ldn-services-directory/ldn-services-directory.component'; -import {LdnServiceNewComponent} from './ldn-service-new/ldn-service-new.component'; -import {LdnServiceFormEditComponent} from './ldn-service-form-edit/ldn-service-form-edit.component'; +import {LdnServiceFormComponent} from './ldn-service-form/ldn-service-form.component'; @NgModule({ imports: [ @@ -18,13 +17,13 @@ import {LdnServiceFormEditComponent} from './ldn-service-form-edit/ldn-service-f { path: 'new', resolve: {breadcrumb: I18nBreadcrumbResolver}, - component: LdnServiceNewComponent, + component: LdnServiceFormComponent, data: {title: 'ldn-register-new-service.title', breadcrumbKey: 'ldn-register-new-service'} }, { path: 'edit/:serviceId', resolve: {breadcrumb: I18nBreadcrumbResolver}, - component: LdnServiceFormEditComponent, + component: LdnServiceFormComponent, data: {title: 'ldn-edit-service.title', breadcrumbKey: 'ldn-edit-service'} }, ]), diff --git a/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts b/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts index 48ad89fdccc..1eecf1d751a 100644 --- a/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts +++ b/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts @@ -3,9 +3,7 @@ import {CommonModule} from '@angular/common'; import {AdminLdnServicesRoutingModule} from './admin-ldn-services-routing.module'; import {LdnServicesOverviewComponent} from './ldn-services-directory/ldn-services-directory.component'; import {SharedModule} from '../../shared/shared.module'; -import {LdnServiceNewComponent} from './ldn-service-new/ldn-service-new.component'; import {LdnServiceFormComponent} from './ldn-service-form/ldn-service-form.component'; -import {LdnServiceFormEditComponent} from './ldn-service-form-edit/ldn-service-form-edit.component'; import {FormsModule} from '@angular/forms'; import {LdnItemfiltersService} from './ldn-services-data/ldn-itemfilters-data.service'; @@ -19,9 +17,7 @@ import {LdnItemfiltersService} from './ldn-services-data/ldn-itemfilters-data.se ], declarations: [ LdnServicesOverviewComponent, - LdnServiceNewComponent, LdnServiceFormComponent, - LdnServiceFormEditComponent, ], providers: [LdnItemfiltersService] }) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html deleted file mode 100644 index 9a34f697e54..00000000000 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html +++ /dev/null @@ -1,415 +0,0 @@ -
-
-
-

{{ 'ldn-edit-registered-service.title' | translate }}

-
- -
- -
- -
-
-
-
-
- -
- - -
- {{ 'ldn-new-service.form.error.name' | translate }} -
-
- - -
- - -
- - -
- - -
- {{ 'ldn-new-service.form.error.url' | translate }} -
-
- - -
- - -
- {{ 'ldn-new-service.form.error.ldnurl' | translate }} -
-
- - -
- - -
- {{ 'ldn-new-service.form.error.score' | translate }} -
-
- - -
-
- -
- -
- -
-
- -
-
-
-
-
- - -
- - - - -
-
-
-
- - - -
-
-
- -
- -
-
- - - -
-
-
-
- -
- -
-
-
-
- - -
-
- - - - -
-
-
-
-
- - - {{ 'ldn-new-service.form.label.addPattern' | translate }} - - -
-
- -
- -
- -
-
-
- -
-
-
-
- - -
- - - -
-
-
-
- - - -
-
-
-
- -
-
- - - -
-
-
-
- -
- -
-
-
-
- -
-
- - -
-
-
-
-
- - - - - -
-
- - - - - - - - - - - - - - diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss deleted file mode 100644 index 91666cde50c..00000000000 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss +++ /dev/null @@ -1,141 +0,0 @@ -@import '../../../shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.scss'; -@import '../../../shared/form/form.component.scss'; - -form { - font-size: 14px; - position: relative; -} - -input[type="text"], -select { - max-width: 100%; - width: 100%; - padding: 8px; - font-size: 14px; -} - -option:not(:first-child) { - font-weight: bold; -} - -.trash-button { - width: 40px; - height: 40px; -} - -textarea { - height: 200px; - resize: none; -} - -.add-pattern-link { - color: #0048ff; - cursor: pointer; -} - -.remove-pattern-link { - color: #e34949; - cursor: pointer; - margin-left: 10px; -} - -.status-checkbox { - margin-top: 5px; -} - - -.invalid-field { - border: 1px solid red; - color: #000000; -} - -.error-text { - color: red; - font-size: 0.8em; - margin-top: 5px; -} - -.toggle-switch { - display: flex; - align-items: center; - opacity: 0.8; - position: relative; - width: 60px; - height: 30px; - background-color: #ccc; - border-radius: 15px; - cursor: pointer; - transition: background-color 0.3s; -} - -.toggle-switch.checked { - background-color: #24cc9a; -} - -.slider { - position: absolute; - width: 30px; - height: 30px; - border-radius: 50%; - background-color: #fff; - transition: transform 0.3s; -} - - -.toggle-switch .slider { - width: 22px; - height: 22px; - border-radius: 50%; - margin: 0 auto; -} - -.toggle-switch.checked .slider { - transform: translateX(30px); -} - -.toggle-switch-container { - display: flex; - flex-direction: column; - justify-content: flex-start; - align-items: flex-end; - margin-top: 10px; -} - -.small-text { - font-size: 0.7em; - color: #888; -} - -.toggle-switch { - cursor: pointer; - margin-top: 3px; - margin-right: 3px -} - -.label-box { - margin-left: 11px; -} - -.label-box-2 { - margin-left: 14px; -} - -.label-box-3 { - margin-left: 5px; -} - -.submission-form-footer { - border-radius: var(--bs-card-border-radius); - bottom: 0; - background-color: var(--bs-gray-400); - padding: calc(var(--bs-spacer) / 2); - z-index: var(--ds-submission-footer-z-index); -} - -.marked-for-deletion { - background-color: lighten($red, 30%); -} - - - - diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.spec.ts b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.spec.ts deleted file mode 100644 index 2fa27ac743c..00000000000 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.spec.ts +++ /dev/null @@ -1,80 +0,0 @@ -import {ComponentFixture, TestBed} from '@angular/core/testing'; - -import {NgbDropdownModule, NgbModal} from '@ng-bootstrap/ng-bootstrap'; -import {LdnServiceFormEditComponent} from './ldn-service-form-edit.component'; -import {ChangeDetectorRef, EventEmitter} from '@angular/core'; -import {FormBuilder, ReactiveFormsModule} from '@angular/forms'; -import {ActivatedRoute, Router} from '@angular/router'; -import {TranslateModule, TranslateService} from '@ngx-translate/core'; -import {PaginationService} from 'ngx-pagination'; -import {NotificationsService} from '../../../shared/notifications/notifications.service'; -import {LdnItemfiltersService} from '../ldn-services-data/ldn-itemfilters-data.service'; -import {LdnServicesService} from '../ldn-services-data/ldn-services-data.service'; -import {RouterStub} from '../../../shared/testing/router.stub'; -import {MockActivatedRoute} from '../../../shared/mocks/active-router.mock'; -import {NotificationsServiceStub} from '../../../shared/testing/notifications-service.stub'; -import {of} from 'rxjs'; -import {RouteService} from '../../../core/services/route.service'; -import {provideMockStore} from '@ngrx/store/testing'; - -describe('LdnServiceFormEditComponent', () => { - let component: LdnServiceFormEditComponent; - let fixture: ComponentFixture; - - let ldnServicesService: any; - let ldnItemfiltersService: any; - let cdRefStub: any; - let modalService: any; - - const translateServiceStub = { - get: () => of('translated-text'), - instant: () => 'translated-text', - onLangChange: new EventEmitter(), - onTranslationChange: new EventEmitter(), - onDefaultLangChange: new EventEmitter() - }; - - beforeEach(async () => { - ldnServicesService = { - update: () => ({}), - }; - ldnItemfiltersService = { - findAll: () => of(['item1', 'item2']), - }; - cdRefStub = Object.assign({ - detectChanges: () => fixture.detectChanges() - }); - modalService = { - open: () => {/*comment*/ - } - }; - - await TestBed.configureTestingModule({ - imports: [ReactiveFormsModule, TranslateModule.forRoot(), NgbDropdownModule], - declarations: [LdnServiceFormEditComponent], - providers: [ - {provide: LdnServicesService, useValue: ldnServicesService}, - {provide: LdnItemfiltersService, useValue: ldnItemfiltersService}, - {provide: Router, useValue: new RouterStub()}, - {provide: ActivatedRoute, useValue: new MockActivatedRoute()}, - {provide: ChangeDetectorRef, useValue: cdRefStub}, - {provide: NgbModal, useValue: modalService}, - {provide: NotificationsService, useValue: NotificationsServiceStub}, - {provide: TranslateService, useValue: translateServiceStub}, - {provide: PaginationService, useValue: {}}, - FormBuilder, - RouteService, - provideMockStore({}), - ] - }) - .compileComponents(); - - fixture = TestBed.createComponent(LdnServiceFormEditComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts deleted file mode 100644 index 787209c621e..00000000000 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts +++ /dev/null @@ -1,597 +0,0 @@ -import {ChangeDetectorRef, Component, Input, OnInit, TemplateRef, ViewChild} from '@angular/core'; -import {FormArray, FormBuilder, FormGroup, Validators} from '@angular/forms'; -import {LDN_SERVICE} from '../ldn-services-model/ldn-service.resource-type'; -import {ActivatedRoute, Router} from '@angular/router'; -import {LdnServicesService} from '../ldn-services-data/ldn-services-data.service'; -import {notifyPatterns} from '../ldn-services-patterns/ldn-service-coar-patterns'; -import {animate, state, style, transition, trigger} from '@angular/animations'; -import {NgbModal} from '@ng-bootstrap/ng-bootstrap'; -import {NotificationsService} from '../../../shared/notifications/notifications.service'; -import {TranslateService} from '@ngx-translate/core'; -import {LdnService} from '../ldn-services-model/ldn-services.model'; -import {RemoteData} from 'src/app/core/data/remote-data'; -import {Operation} from 'fast-json-patch'; -import {getFirstCompletedRemoteData} from '../../../core/shared/operators'; -import {LdnItemfiltersService} from '../ldn-services-data/ldn-itemfilters-data.service'; -import {Itemfilter} from '../ldn-services-model/ldn-service-itemfilters'; -import {PaginatedList} from '../../../core/data/paginated-list.model'; -import {Observable} from 'rxjs'; -import {PaginationService} from '../../../core/pagination/pagination.service'; -import {FindListOptions} from '../../../core/data/find-list-options.model'; -import {PaginationComponentOptions} from '../../../shared/pagination/pagination-component-options.model'; -import {NotifyServicePattern} from '../ldn-services-model/ldn-service-patterns.model'; - - -/** - * Component for editing LDN service through a form that allows to edit the properties of the selected service - */ -@Component({ - selector: 'ds-ldn-service-form-edit', - templateUrl: './ldn-service-form-edit.component.html', - styleUrls: ['./ldn-service-form-edit.component.scss'], - animations: [ - trigger('toggleAnimation', [ - state('true', style({})), - state('false', style({})), - transition('true <=> false', animate('300ms ease-in')), - ]), - ], -}) -export class LdnServiceFormEditComponent implements OnInit { - formModel: FormGroup; - @ViewChild('confirmModal', {static: true}) confirmModal: TemplateRef; - @ViewChild('resetFormModal', {static: true}) resetFormModal: TemplateRef; - - public inboundPatterns: string[] = notifyPatterns; - public outboundPatterns: string[] = notifyPatterns; - itemfiltersRD$: Observable>>; - config: FindListOptions = Object.assign(new FindListOptions(), { - elementsPerPage: 20 - }); - pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { - id: 'po', - pageSize: 20 - }); - @Input() public name: string; - @Input() public description: string; - @Input() public url: string; - @Input() public ldnUrl: string; - @Input() public score: number; - @Input() public inboundPattern: string; - @Input() public outboundPattern: string; - @Input() public constraint: string; - @Input() public automatic: boolean; - @Input() public headerKey: string; - markedForDeletionInboundPattern: number[] = []; - markedForDeletionOutboundPattern: number[] = []; - selectedOutboundPatterns: string[]; - selectedInboundItemfilters: string[]; - selectedOutboundItemfilters: string[]; - selectedInboundPatterns: string[]; - protected serviceId: string; - private deletedInboundPatterns: number[] = []; - private deletedOutboundPatterns: number[] = []; - private modalRef: any; - private service: LdnService; - private selectPatternDefaultLabeli18Key = 'ldn-service.form.label.placeholder.default-select'; - - constructor( - protected ldnServicesService: LdnServicesService, - private ldnItemfiltersService: LdnItemfiltersService, - private formBuilder: FormBuilder, - private router: Router, - private route: ActivatedRoute, - private cdRef: ChangeDetectorRef, - protected modalService: NgbModal, - private notificationService: NotificationsService, - private translateService: TranslateService, - protected paginationService: PaginationService - ) { - - this.formModel = this.formBuilder.group({ - id: [''], - name: ['', Validators.required], - description: ['', Validators.required], - url: ['', Validators.required], - ldnUrl: ['', Validators.required], - score: ['', [Validators.required, Validators.pattern('^0*(\.[0-9]+)?$|^1(\.0+)?$')]], inboundPattern: [''], - outboundPattern: [''], - constraintPattern: [''], - enabled: [''], - notifyServiceInboundPatterns: this.formBuilder.array([this.createInboundPatternFormGroup()]), - notifyServiceOutboundPatterns: this.formBuilder.array([this.createOutboundPatternFormGroup()]), - type: LDN_SERVICE.value, - }); - } - - ngOnInit(): void { - this.route.params.subscribe((params) => { - this.serviceId = params.serviceId; - if (this.serviceId) { - this.fetchServiceData(this.serviceId); - } - }); - this.setItemfilters(); - } - - /** - * Sets item filters using LDN item filters service - */ - setItemfilters() { - this.itemfiltersRD$ = this.ldnItemfiltersService.findAll().pipe( - getFirstCompletedRemoteData()); - } - - /** - * Fetches LDN service data by ID and updates the form - * @param serviceId - The ID of the LDN service - */ - fetchServiceData(serviceId: string): void { - this.ldnServicesService.findById(serviceId).pipe( - getFirstCompletedRemoteData() - ).subscribe( - (data: RemoteData) => { - if (data.hasSucceeded) { - this.service = data.payload; - - this.formModel.patchValue({ - id: this.service.id, - name: this.service.name, - description: this.service.description, - url: this.service.url, - score: this.service.score, ldnUrl: this.service.ldnUrl, - type: this.service.type, - enabled: this.service.enabled - }); - this.filterPatternObjectsAndPickLabel('notifyServiceInboundPatterns', false); - this.filterPatternObjectsAndPickLabel('notifyServiceOutboundPatterns', true); - } - }, - ); - } - - /** - * Filters pattern objects, initializes form groups, assigns labels, and adds them to the specified form array so the correct string is shown in the dropdown.. - * @param formArrayName - The name of the form array to be populated - * @param isOutbound - A boolean indicating whether the patterns are outbound (true) or inbound (false) - */ - filterPatternObjectsAndPickLabel(formArrayName: string, isOutbound: boolean) { - const PatternsArray = this.formModel.get(formArrayName) as FormArray; - PatternsArray.clear(); - let servicesToUse; - if (isOutbound) { - servicesToUse = this.service.notifyServiceOutboundPatterns; - } else { - servicesToUse = this.service.notifyServiceInboundPatterns; - } - - servicesToUse.forEach((patternObj: NotifyServicePattern) => { - let patternFormGroup; - if (isOutbound) { - patternFormGroup = this.initializeOutboundPatternFormGroup(); - } else { - patternFormGroup = this.initializeInboundPatternFormGroup(); - } - const newPatternObjWithLabel = Object.assign(new NotifyServicePattern(), { - ...patternObj, - patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternObj?.pattern + '.label') - }); - patternFormGroup.patchValue(newPatternObjWithLabel); - - PatternsArray.push(patternFormGroup); - this.cdRef.detectChanges(); - }); - - - } - - /** - * Generates an array of patch operations based on form changes - * @returns Array of patch operations - */ - generatePatchOperations(): any[] { - const patchOperations: any[] = []; - - this.createReplaceOperation(patchOperations, 'name', '/name'); - this.createReplaceOperation(patchOperations, 'description', '/description'); - this.createReplaceOperation(patchOperations, 'ldnUrl', '/ldnurl'); - this.createReplaceOperation(patchOperations, 'url', '/url'); - this.createReplaceOperation(patchOperations, 'score', '/score'); - - this.handlePatterns(patchOperations, 'notifyServiceInboundPatterns'); - this.handlePatterns(patchOperations, 'notifyServiceOutboundPatterns'); - - - this.deletedInboundPatterns.forEach(index => { - const removeOperation: Operation = { - op: 'remove', - path: `notifyServiceInboundPatterns[${index}]` - }; - patchOperations.push(removeOperation); - }); - - this.deletedOutboundPatterns.forEach(index => { - const removeOperation: Operation = { - op: 'remove', - path: `notifyServiceOutboundPatterns[${index}]` - }; - patchOperations.push(removeOperation); - }); - - return patchOperations; - } - - /** - * Submits the form by opening the confirmation modal - */ - onSubmit() { - this.openConfirmModal(this.confirmModal); - } - - /** - * Adds a new inbound pattern form group to the array of inbound patterns in the form - */ - addInboundPattern() { - const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; - notifyServiceInboundPatternsArray.push(this.createInboundPatternFormGroup()); - } - - /** - * Adds a new outbound pattern form group to the array of outbound patterns in the form - */ - addOutboundPattern() { - const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; - notifyServiceOutboundPatternsArray.push(this.createOutboundPatternFormGroup()); - } - - /** - * Selects an outbound pattern by updating its values based on the provided pattern value and index - * @param patternValue - The selected pattern value - * @param index - The index of the outbound pattern in the array - */ - selectOutboundPattern(patternValue: string, index: number): void { - const patternArray = (this.formModel.get('notifyServiceOutboundPatterns') as FormArray); - patternArray.controls[index].patchValue({pattern: patternValue}); - patternArray.controls[index].patchValue({patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternValue + '.label')}); - - } - - /** - * Selects an outbound item filter by updating its value based on the provided filter value and index - * @param filterValue - The selected filter value - * @param index - The index of the inbound pattern in the array - */ - selectOutboundItemFilter(filterValue: string, index: number) { - const filterArray = (this.formModel.get('notifyServiceOutboundPatterns') as FormArray); - filterArray.controls[index].patchValue({constraint: filterValue}); - } - - /** - * Selects an inbound pattern by updating its values based on the provided pattern value and index - * @param patternValue - The selected pattern value - * @param index - The index of the inbound pattern in the array - */ - selectInboundPattern(patternValue: string, index: number): void { - const patternArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray); - patternArray.controls[index].patchValue({pattern: patternValue}); - patternArray.controls[index].patchValue({patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternValue + '.label')}); - } - - /** - * Selects an inbound item filter by updating its value based on the provided filter value and index - * @param filterValue - The selected filter value - * @param index - The index of the inbound pattern in the array - */ - selectInboundItemFilter(filterValue: string, index: number): void { - const filterArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray); - filterArray.controls[index].patchValue({constraint: filterValue}); - } - - /** - * Toggles the automatic property of an inbound pattern at the specified index - * @param i - The index of the inbound pattern in the array - */ - toggleAutomatic(i: number) { - const automaticControl = this.formModel.get(`notifyServiceInboundPatterns.${i}.automatic`); - if (automaticControl) { - automaticControl.markAsTouched(); - automaticControl.setValue(!automaticControl.value); - } - } - - /** - * Toggles the enabled status of the LDN service by sending a patch request - */ - toggleEnabled() { - const newStatus = !this.formModel.get('enabled').value; - - const patchOperation: Operation = { - op: 'replace', - path: '/enabled', - value: newStatus, - }; - - this.ldnServicesService.patch(this.service, [patchOperation]).pipe( - getFirstCompletedRemoteData() - ).subscribe( - () => { - - this.formModel.get('enabled').setValue(newStatus); - this.cdRef.detectChanges(); - } - ); - } - - /** - * Closes the modal - */ - closeModal() { - this.modalRef.close(); - this.cdRef.detectChanges(); - } - - /** - * Opens a confirmation modal with the specified content - * @param content - The content to be displayed in the modal - */ - openConfirmModal(content) { - this.modalRef = this.modalService.open(content); - } - - /** - * Opens a reset form modal with the specified content - * @param content - The content to be displayed in the modal - */ - openResetFormModal(content) { - this.modalRef = this.modalService.open(content); - } - - /** - * Patches the LDN service by retrieving and sending patch operations geenrated in generatePatchOperations() - */ - patchService() { - this.deleteMarkedInboundPatterns(); - this.deleteMarkedOutboundPatterns(); - - const patchOperations = this.generatePatchOperations(); - this.formModel.markAllAsTouched(); - - // If the form is invalid, close the modal and return - if (this.formModel.invalid) { - this.closeModal(); - return; - } - - const notifyServiceOutboundPatterns = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; - const notifyServiceInboundPatterns = this.formModel.get('notifyServiceInboundPatterns') as FormArray; - // If no inbound or outbound patterns are specified, close the modal and return - // noify the user that no patterns are specified - if ( - (notifyServiceOutboundPatterns.length === 0 && !notifyServiceOutboundPatterns[0]?.value) || - (notifyServiceInboundPatterns.length === 0 && !notifyServiceInboundPatterns[0]?.value)) { - this.notificationService.warning(this.translateService.get('ldn-service-notification.created.warning.title')); - this.closeModal(); - return; - } - - this.ldnServicesService.patch(this.service, patchOperations).pipe( - getFirstCompletedRemoteData() - ).subscribe( - (rd: RemoteData) => { - if (rd.hasSucceeded) { - this.closeModal(); - this.sendBack(); - this.notificationService.success(this.translateService.get('admin.registries.services-formats.modify.success.head'), - this.translateService.get('admin.registries.services-formats.modify.success.content')); - } else { - this.notificationService.error(this.translateService.get('admin.registries.services-formats.modify.failure.head'), - this.translateService.get('admin.registries.services-formats.modify.failure.content')); - this.closeModal(); - } - }); - } - - /** - * Resets the form and navigates back to the LDN services page - */ - resetFormAndLeave() { - this.sendBack(); - this.closeModal(); - } - - /** - * Marks the specified inbound pattern for deletion - * @param index - The index of the inbound pattern in the array - */ - markForInboundPatternDeletion(index: number) { - if (!this.markedForDeletionInboundPattern.includes(index)) { - this.markedForDeletionInboundPattern.push(index); - } - } - - /** - * Unmarks the specified inbound pattern for deletion - * @param index - The index of the inbound pattern in the array - */ - unmarkForInboundPatternDeletion(index: number) { - const i = this.markedForDeletionInboundPattern.indexOf(index); - if (i !== -1) { - this.markedForDeletionInboundPattern.splice(i, 1); - } - } - - /** - * Marks the specified outbound pattern for deletion - * @param index - The index of the outbound pattern in the array - */ - markForOutboundPatternDeletion(index: number) { - if (!this.markedForDeletionOutboundPattern.includes(index)) { - this.markedForDeletionOutboundPattern.push(index); - } - } - - /** - * Unmarks the specified outbound pattern for deletion - * @param index - The index of the outbound pattern in the array - */ - unmarkForOutboundPatternDeletion(index: number) { - const i = this.markedForDeletionOutboundPattern.indexOf(index); - if (i !== -1) { - this.markedForDeletionOutboundPattern.splice(i, 1); - } - } - - /** - * Deletes marked inbound patterns from the form model - */ - deleteMarkedInboundPatterns() { - this.markedForDeletionInboundPattern.sort((a, b) => b - a); - const patternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; - - for (const index of this.markedForDeletionInboundPattern) { - if (index >= 0 && index < patternsArray.length) { - const patternGroup = patternsArray.at(index) as FormGroup; - const patternValue = patternGroup.value; - if (patternValue.isNew) { - patternsArray.removeAt(index); - } else { - this.deletedInboundPatterns.push(index); - } - } - } - - this.markedForDeletionInboundPattern = []; - } - - /** - * Deletes marked outbound patterns from the form model - */ - deleteMarkedOutboundPatterns() { - this.markedForDeletionOutboundPattern.sort((a, b) => b - a); - const patternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; - - for (const index of this.markedForDeletionOutboundPattern) { - if (index >= 0 && index < patternsArray.length) { - const patternGroup = patternsArray.at(index) as FormGroup; - const patternValue = patternGroup.value; - if (patternValue.isNew) { - patternsArray.removeAt(index); - } else { - - this.deletedOutboundPatterns.push(index); - } - } - } - - this.markedForDeletionOutboundPattern = []; - } - - /** - * Creates a replace operation and adds it to the patch operations if the form control is dirty - * @param patchOperations - The array to store patch operations - * @param formControlName - The name of the form control - * @param path - The JSON Patch path for the operation - */ - private createReplaceOperation(patchOperations: any[], formControlName: string, path: string): void { - if (this.formModel.get(formControlName).dirty) { - patchOperations.push({ - op: 'replace', - path, - value: this.formModel.get(formControlName).value.toString(), - }); - } - } - - /** - * Handles patterns in the form array, checking if an add or replace operations is required - * @param patchOperations - The array to store patch operations - * @param formArrayName - The name of the form array - */ - private handlePatterns(patchOperations: any[], formArrayName: string): void { - const patternsArray = this.formModel.get(formArrayName) as FormArray; - - for (let i = 0; i < patternsArray.length; i++) { - const patternGroup = patternsArray.at(i) as FormGroup; - - const patternValue = patternGroup.value; - if (patternGroup.touched && patternGroup.valid) { - delete patternValue?.patternLabel; - if (patternValue.isNew) { - delete patternValue.isNew; - const addOperation = { - op: 'add', - path: `${formArrayName}/-`, - value: patternValue, - }; - patchOperations.push(addOperation); - } else { - const replaceOperation = { - op: 'replace', - path: `${formArrayName}[${i}]`, - value: patternValue, - }; - patchOperations.push(replaceOperation); - } - } - } - } - - /** - * Navigates back to the LDN services page - */ - private sendBack() { - this.router.navigateByUrl('admin/ldn/services'); - } - - /** - * Creates a form group for outbound patterns - * @returns The form group for outbound patterns - */ - private createOutboundPatternFormGroup(): FormGroup { - return this.formBuilder.group({ - pattern: '', - patternLabel: this.translateService.instant(this.selectPatternDefaultLabeli18Key), - constraint: '', - isNew: true, - }); - } - - /** - * Creates a form group for inbound patterns - * @returns The form group for inbound patterns - */ - private createInboundPatternFormGroup(): FormGroup { - return this.formBuilder.group({ - pattern: '', - patternLabel: this.translateService.instant(this.selectPatternDefaultLabeli18Key), - constraint: '', - automatic: false, - isNew: true - }); - } - - /** - * Initializes an existing form group for outbound patterns - * @returns The initialized form group for outbound patterns - */ - private initializeOutboundPatternFormGroup(): FormGroup { - return this.formBuilder.group({ - pattern: '', - patternLabel: '', - constraint: '', - }); - } - - /** - * Initializes an existing form group for inbound patterns - * @returns The initialized form group for inbound patterns - */ - private initializeInboundPatternFormGroup(): FormGroup { - return this.formBuilder.group({ - pattern: '', - patternLabel: '', - constraint: '', - automatic: '', - }); - } -} diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html index 74ddc478725..10327985de9 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html @@ -1,11 +1,21 @@
-
-

{{ 'ldn-create-service.title' | translate }}

+
+

{{ isNewForm ? ('ldn-create-service.title' | translate) : ('ldn-edit-registered-service.title' | translate) }}

- + +
+ +
+ +
+
+
+
+
+
- + {{ 'ldn-create-service.title' | translate }}
- +
-
- + {{ 'ldn-create-service.title' | translate }}
-
- + {{ 'ldn-create-service.title' | translate }} {{ 'ldn-new-service.form.error.ldnurl' | translate }}
+
- + {{ 'ldn-create-service.title' | translate }}
-
+
- +
- +
- +
-
+
@@ -96,18 +106,17 @@

{{ 'ldn-create-service.title' | translate }}

-
+
+ ngbDropdownToggle> {{ 'ldn-create-service.title' | translate }} ngbDropdownMenu>
-
@@ -160,7 +168,7 @@

{{ 'ldn-create-service.title' | translate }}

class="dropdown-item collection-item text-truncate w-100" ngbDropdownItem type="button"> {{'ldn-service.control-constaint-select-none' | translate}} -
@@ -186,36 +194,53 @@

{{ 'ldn-create-service.title' | translate }}

-
- -
+
+
+ + + + +
+
- {{ 'ldn-new-service.form.label.addPattern' | translate }} + {{ 'ldn-new-service.form.label.addPattern' | translate }}
- +
- +
-
+
+ +
+
@@ -243,7 +268,7 @@

{{ 'ldn-create-service.title' | translate }}

ngbDropdownMenu>
-
@@ -300,42 +324,51 @@

{{ 'ldn-create-service.title' | translate }}

- +
-
- +
+
+ + +
-
- - + - + - - diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss index 78a73a3e767..91666cde50c 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss @@ -6,10 +6,6 @@ form { position: relative; } -label { - font-weight: bold; -} - input[type="text"], select { max-width: 100%; @@ -43,11 +39,6 @@ textarea { margin-left: 10px; } -.small-text { - font-size: 0.7em; - color: #888; -} - .status-checkbox { margin-top: 5px; } @@ -110,8 +101,27 @@ textarea { margin-top: 10px; } +.small-text { + font-size: 0.7em; + color: #888; +} + .toggle-switch { cursor: pointer; + margin-top: 3px; + margin-right: 3px +} + +.label-box { + margin-left: 11px; +} + +.label-box-2 { + margin-left: 14px; +} + +.label-box-3 { + margin-left: 5px; } .submission-form-footer { @@ -122,6 +132,9 @@ textarea { z-index: var(--ds-submission-footer-z-index); } +.marked-for-deletion { + background-color: lighten($red, 30%); +} diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.spec.ts b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.spec.ts index 5db8e66c332..73b45c14551 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.spec.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.spec.ts @@ -1,30 +1,30 @@ import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {NgbDropdownModule, NgbModal} from '@ng-bootstrap/ng-bootstrap'; import {LdnServiceFormComponent} from './ldn-service-form.component'; +import {ChangeDetectorRef, EventEmitter} from '@angular/core'; import {FormBuilder, ReactiveFormsModule} from '@angular/forms'; -import {RouterTestingModule} from '@angular/router/testing'; -import {NgbDropdownModule, NgbModal, NgbModalModule} from '@ng-bootstrap/ng-bootstrap'; +import {ActivatedRoute, Router} from '@angular/router'; import {TranslateModule, TranslateService} from '@ngx-translate/core'; +import {PaginationService} from 'ngx-pagination'; +import {NotificationsService} from '../../../shared/notifications/notifications.service'; import {LdnItemfiltersService} from '../ldn-services-data/ldn-itemfilters-data.service'; import {LdnServicesService} from '../ldn-services-data/ldn-services-data.service'; -import {NotificationsService} from 'src/app/shared/notifications/notifications.service'; -import {Router} from '@angular/router'; -import {RouterStub} from 'src/app/shared/testing/router.stub'; -import {createPaginatedList} from 'src/app/shared/testing/utils.test'; -import {Itemfilter} from '../ldn-services-model/ldn-service-itemfilters'; -import {createSuccessfulRemoteDataObject$} from 'src/app/shared/remote-data.utils'; +import {RouterStub} from '../../../shared/testing/router.stub'; +import {MockActivatedRoute} from '../../../shared/mocks/active-router.mock'; +import {NotificationsServiceStub} from '../../../shared/testing/notifications-service.stub'; import {of} from 'rxjs'; -import {EventEmitter} from '@angular/core'; +import {RouteService} from '../../../core/services/route.service'; +import {provideMockStore} from '@ngrx/store/testing'; -describe('LdnServiceFormComponent', () => { +describe('LdnServiceFormEditComponent', () => { let component: LdnServiceFormComponent; let fixture: ComponentFixture; let ldnServicesService: any; let ldnItemfiltersService: any; - let notificationsService: any; - - const itemFiltersRdPL$ = createSuccessfulRemoteDataObject$(createPaginatedList([new Itemfilter()])); + let cdRefStub: any; + let modalService: any; const translateServiceStub = { get: () => of('translated-text'), @@ -32,53 +32,45 @@ describe('LdnServiceFormComponent', () => { onLangChange: new EventEmitter(), onTranslationChange: new EventEmitter(), onDefaultLangChange: new EventEmitter() -}; + }; beforeEach(async () => { - ldnItemfiltersService = jasmine.createSpyObj('ldnItemfiltersService', { - findAll: jasmine.createSpy('findAll'), - }); - - ldnServicesService = jasmine.createSpyObj('ldnServicesService', { - create: jasmine.createSpy('create'), - }); - - notificationsService = jasmine.createSpyObj('notificationsService', { - success: jasmine.createSpy('success'), - error: jasmine.createSpy('error'), + ldnServicesService = { + update: () => ({}), + }; + ldnItemfiltersService = { + findAll: () => of(['item1', 'item2']), + }; + cdRefStub = Object.assign({ + detectChanges: () => fixture.detectChanges() }); + modalService = { + open: () => {/*comment*/ + } + }; await TestBed.configureTestingModule({ - imports: [ - ReactiveFormsModule, - RouterTestingModule, - NgbModalModule, - TranslateModule.forRoot(), - NgbDropdownModule - ], + imports: [ReactiveFormsModule, TranslateModule.forRoot(), NgbDropdownModule], + declarations: [LdnServiceFormComponent], providers: [ - {provide: LdnItemfiltersService, useValue: ldnItemfiltersService}, {provide: LdnServicesService, useValue: ldnServicesService}, - {provide: NotificationsService, useValue: notificationsService}, - {provide: TranslateService, useValue: translateServiceStub}, + {provide: LdnItemfiltersService, useValue: ldnItemfiltersService}, {provide: Router, useValue: new RouterStub()}, - { - provide: NgbModal, useValue: { - open: () => {/*comment*/ - } - } - }, - FormBuilder - ], - declarations: [LdnServiceFormComponent] + {provide: ActivatedRoute, useValue: new MockActivatedRoute()}, + {provide: ChangeDetectorRef, useValue: cdRefStub}, + {provide: NgbModal, useValue: modalService}, + {provide: NotificationsService, useValue: NotificationsServiceStub}, + {provide: TranslateService, useValue: translateServiceStub}, + {provide: PaginationService, useValue: {}}, + FormBuilder, + RouteService, + provideMockStore({}), + ] }) .compileComponents(); - }); - beforeEach(() => { fixture = TestBed.createComponent(LdnServiceFormComponent); component = fixture.componentInstance; - ldnItemfiltersService.findAll.and.returnValue(itemFiltersRdPL$); fixture.detectChanges(); }); diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts index 999e432e7a2..da877558e7e 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts @@ -1,27 +1,38 @@ -import {ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, TemplateRef, ViewChild} from '@angular/core'; +import { + ChangeDetectorRef, + Component, + EventEmitter, + Input, + OnDestroy, + OnInit, + Output, + TemplateRef, + ViewChild +} from '@angular/core'; import {FormArray, FormBuilder, FormGroup, Validators} from '@angular/forms'; -import {Router} from '@angular/router'; - +import {LDN_SERVICE} from '../ldn-services-model/ldn-service.resource-type'; +import {ActivatedRoute, Router} from '@angular/router'; import {LdnServicesService} from '../ldn-services-data/ldn-services-data.service'; import {notifyPatterns} from '../ldn-services-patterns/ldn-service-coar-patterns'; -import {LDN_SERVICE} from '../ldn-services-model/ldn-service.resource-type'; import {animate, state, style, transition, trigger} from '@angular/animations'; -import {getFirstCompletedRemoteData} from '../../../core/shared/operators'; -import {RemoteData} from '../../../core/data/remote-data'; -import {LdnService} from '../ldn-services-model/ldn-services.model'; +import {NgbModal} from '@ng-bootstrap/ng-bootstrap'; import {NotificationsService} from '../../../shared/notifications/notifications.service'; import {TranslateService} from '@ngx-translate/core'; -import {PaginatedList} from '../../../core/data/paginated-list.model'; +import {LdnService} from '../ldn-services-model/ldn-services.model'; +import {RemoteData} from 'src/app/core/data/remote-data'; +import {Operation} from 'fast-json-patch'; +import {getFirstCompletedRemoteData} from '../../../core/shared/operators'; +import {LdnItemfiltersService} from '../ldn-services-data/ldn-itemfilters-data.service'; import {Itemfilter} from '../ldn-services-model/ldn-service-itemfilters'; -import {Observable} from 'rxjs'; +import {PaginatedList} from '../../../core/data/paginated-list.model'; +import {combineLatestWith, Observable, Subscription} from 'rxjs'; +import {PaginationService} from '../../../core/pagination/pagination.service'; import {FindListOptions} from '../../../core/data/find-list-options.model'; -import {PaginationComponentOptions} from '../../../shared/pagination/pagination-component-options.model'; -import {LdnItemfiltersService} from '../ldn-services-data/ldn-itemfilters-data.service'; -import {NgbModal} from '@ng-bootstrap/ng-bootstrap'; +import {NotifyServicePattern} from '../ldn-services-model/ldn-service-patterns.model'; + /** - * Angular component representing the form for creating or editing LDN services. - * This component handles the creation, validation, and submission of LDN service data. + * Component for editing LDN service through a form that allows to create or edit the properties of a service */ @Component({ selector: 'ds-ldn-service-form', @@ -35,25 +46,24 @@ import {NgbModal} from '@ng-bootstrap/ng-bootstrap'; ]), ], }) -export class LdnServiceFormComponent implements OnInit { +export class LdnServiceFormComponent implements OnInit, OnDestroy { formModel: FormGroup; @ViewChild('confirmModal', {static: true}) confirmModal: TemplateRef; @ViewChild('resetFormModal', {static: true}) resetFormModal: TemplateRef; + public inboundPatterns: string[] = notifyPatterns; public outboundPatterns: string[] = notifyPatterns; + public isNewForm: boolean; itemfiltersRD$: Observable>>; config: FindListOptions = Object.assign(new FindListOptions(), { elementsPerPage: 20 }); - pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { - id: 'po', - pageSize: 20 - }); + @Input() public name: string; @Input() public description: string; @Input() public url: string; - @Input() public score: string; @Input() public ldnUrl: string; + @Input() public score: number; @Input() public inboundPattern: string; @Input() public outboundPattern: string; @Input() public constraint: string; @@ -61,82 +71,75 @@ export class LdnServiceFormComponent implements OnInit { @Input() public headerKey: string; @Output() submitForm: EventEmitter = new EventEmitter(); @Output() cancelForm: EventEmitter = new EventEmitter(); + markedForDeletionInboundPattern: number[] = []; + markedForDeletionOutboundPattern: number[] = []; selectedOutboundPatterns: string[]; selectedInboundPatterns: string[]; selectedInboundItemfilters: string[]; selectedOutboundItemfilters: string[]; - hasInboundPattern: boolean; - hasOutboundPattern: boolean; - isScoreValid: boolean; + protected serviceId: string; + private deletedInboundPatterns: number[] = []; + private deletedOutboundPatterns: number[] = []; private modalRef: any; + private service: LdnService; private selectPatternDefaultLabeli18Key = 'ldn-service.form.label.placeholder.default-select'; + private routeSubscription: Subscription; constructor( - private ldnServicesService: LdnServicesService, + protected ldnServicesService: LdnServicesService, private ldnItemfiltersService: LdnItemfiltersService, private formBuilder: FormBuilder, private router: Router, - private notificationsService: NotificationsService, - private translateService: TranslateService, + private route: ActivatedRoute, private cdRef: ChangeDetectorRef, protected modalService: NgbModal, + private notificationService: NotificationsService, + private translateService: TranslateService, + protected paginationService: PaginationService ) { this.formModel = this.formBuilder.group({ - enabled: true, id: [''], name: ['', Validators.required], description: [''], url: ['', Validators.required], - score: ['', [Validators.required, Validators.pattern('^0*(\.[0-9]+)?$|^1(\.0+)?$')]], ldnUrl: ['', Validators.required], - inboundPattern: [''], + score: ['', [Validators.required, Validators.pattern('^0*(\.[0-9]+)?$|^1(\.0+)?$')]], inboundPattern: [''], outboundPattern: [''], constraintPattern: [''], - notifyServiceInboundPatterns: this.formBuilder.array([this.createInboundPatternFormGroup()]), - notifyServiceOutboundPatterns: this.formBuilder.array([this.createOutboundPatternFormGroup()]), + enabled: [''], type: LDN_SERVICE.value, }); } ngOnInit(): void { + this.routeSubscription = this.route.params.pipe( + combineLatestWith(this.route.url) + ).subscribe(([params, segment]) => { + this.serviceId = params.serviceId; + this.isNewForm = segment[0].path === 'new'; + this.formModel.addControl('notifyServiceInboundPatterns', this.formBuilder.array([this.createInboundPatternFormGroup()])); + this.formModel.addControl('notifyServiceOutboundPatterns', this.formBuilder.array([this.createOutboundPatternFormGroup()])); + + if (this.serviceId && !this.isNewForm) { + this.fetchServiceData(this.serviceId); + } + }) this.setItemfilters(); + } + ngOnDestroy(): void { + this.routeSubscription.unsubscribe(); } /** - * Sets up the item filters by fetching and observing the paginated list of item filters. + * Sets item filters using LDN item filters service */ setItemfilters() { this.itemfiltersRD$ = this.ldnItemfiltersService.findAll().pipe( getFirstCompletedRemoteData()); } - /** - * Handles the form submission by opening the confirmation modal. - */ - onSubmit() { - this.openConfirmModal(this.confirmModal); - } - - /** - * Opens the confirmation modal. - * - * @param {any} content - The content of the modal. - */ - openConfirmModal(content) { - this.modalRef = this.modalService.open(content); - } - - /** - * Opens the reset form modal. - * - * @param {any} content - The content of the modal. - */ - openResetFormModal(content) { - this.modalRef = this.modalService.open(content); - } - /** * Handles the creation of an LDN service by retrieving and validating form fields, * and submitting the form data to the LDN services endpoint. @@ -152,15 +155,15 @@ export class LdnServiceFormComponent implements OnInit { const hasInboundPattern = this.checkPatterns(this.formModel.get('notifyServiceInboundPatterns') as FormArray); const hasOutboundPattern = this.checkPatterns(this.formModel.get('notifyServiceOutboundPatterns') as FormArray); - if (!name || !url || !ldnUrl || !score || this.formModel.get('score').invalid) { + if (!name || !url || !ldnUrl || (!score && score !== 0) || this.formModel.get('score').invalid) { this.closeModal(); return; } if (!hasInboundPattern || !hasOutboundPattern) { - this.notificationsService.warning(this.translateService.get('ldn-service-notification.created.warning.title')); - this.closeModal(); - return; + this.notificationService.warning(this.translateService.get('ldn-service-notification.created.warning.title')); + this.closeModal(); + return; } @@ -180,7 +183,7 @@ export class LdnServiceFormComponent implements OnInit { return rest; }); - const values = this.formModel.value; + const values = {...this.formModel.value, enabled: true}; const ldnServiceData = this.ldnServicesService.create(values); @@ -188,13 +191,13 @@ export class LdnServiceFormComponent implements OnInit { getFirstCompletedRemoteData() ).subscribe((rd: RemoteData) => { if (rd.hasSucceeded) { - this.notificationsService.success(this.translateService.get('ldn-service-notification.created.success.title'), + this.notificationService.success(this.translateService.get('ldn-service-notification.created.success.title'), this.translateService.get('ldn-service-notification.created.success.body')); this.sendBack(); this.closeModal(); } else { - this.notificationsService.error(this.translateService.get('ldn-service-notification.created.failure.title'), + this.notificationService.error(this.translateService.get('ldn-service-notification.created.failure.title'), this.translateService.get('ldn-service-notification.created.failure.body')); this.closeModal(); } @@ -218,42 +221,121 @@ export class LdnServiceFormComponent implements OnInit { } /** - * Closes the currently open modal and returns to the services directory.. + * Fetches LDN service data by ID and updates the form + * @param serviceId - The ID of the LDN service */ - resetFormAndLeave() { - this.sendBack(); - this.closeModal(); + fetchServiceData(serviceId: string): void { + this.ldnServicesService.findById(serviceId).pipe( + getFirstCompletedRemoteData() + ).subscribe( + (data: RemoteData) => { + if (data.hasSucceeded) { + this.service = data.payload; + + this.formModel.patchValue({ + id: this.service.id, + name: this.service.name, + description: this.service.description, + url: this.service.url, + score: this.service.score, ldnUrl: this.service.ldnUrl, + type: this.service.type, + enabled: this.service.enabled + }); + this.filterPatternObjectsAndPickLabel('notifyServiceInboundPatterns', false); + this.filterPatternObjectsAndPickLabel('notifyServiceOutboundPatterns', true); + } + }, + ); } /** - * Closes the currently open modal and triggers change detection. + * Filters pattern objects, initializes form groups, assigns labels, and adds them to the specified form array so the correct string is shown in the dropdown.. + * @param formArrayName - The name of the form array to be populated + * @param isOutbound - A boolean indicating whether the patterns are outbound (true) or inbound (false) */ - closeModal() { - this.modalRef.close(); - this.cdRef.detectChanges(); + filterPatternObjectsAndPickLabel(formArrayName: string, isOutbound: boolean) { + const PatternsArray = this.formModel.get(formArrayName) as FormArray; + PatternsArray.clear(); + let servicesToUse; + if (isOutbound) { + servicesToUse = this.service.notifyServiceOutboundPatterns; + } else { + servicesToUse = this.service.notifyServiceInboundPatterns; + } + + servicesToUse.forEach((patternObj: NotifyServicePattern) => { + let patternFormGroup; + if (isOutbound) { + patternFormGroup = this.initializeOutboundPatternFormGroup(); + } else { + patternFormGroup = this.initializeInboundPatternFormGroup(); + } + const newPatternObjWithLabel = Object.assign(new NotifyServicePattern(), { + ...patternObj, + patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternObj?.pattern + '.label') + }); + patternFormGroup.patchValue(newPatternObjWithLabel); + + PatternsArray.push(patternFormGroup); + this.cdRef.detectChanges(); + }); + + } /** - * Adds a new inbound pattern form group to the notifyServiceInboundPatterns form array. + * Generates an array of patch operations based on form changes + * @returns Array of patch operations */ - addInboundPattern() { - const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; - notifyServiceInboundPatternsArray.push(this.createInboundPatternFormGroup()); + generatePatchOperations(): any[] { + const patchOperations: any[] = []; + + this.createReplaceOperation(patchOperations, 'name', '/name'); + this.createReplaceOperation(patchOperations, 'description', '/description'); + this.createReplaceOperation(patchOperations, 'ldnUrl', '/ldnurl'); + this.createReplaceOperation(patchOperations, 'url', '/url'); + this.createReplaceOperation(patchOperations, 'score', '/score'); + + this.handlePatterns(patchOperations, 'notifyServiceInboundPatterns'); + this.handlePatterns(patchOperations, 'notifyServiceOutboundPatterns'); + + + this.deletedInboundPatterns.forEach(index => { + const removeOperation: Operation = { + op: 'remove', + path: `notifyServiceInboundPatterns[${index}]` + }; + patchOperations.push(removeOperation); + }); + + this.deletedOutboundPatterns.forEach(index => { + const removeOperation: Operation = { + op: 'remove', + path: `notifyServiceOutboundPatterns[${index}]` + }; + patchOperations.push(removeOperation); + }); + + return patchOperations; } /** - * Removes the inbound pattern form group at the specified index from the notifyServiceInboundPatterns form array. - * - * @param {number} index - The index of the inbound pattern form group to remove. - * @memberof LdnServiceFormComponent + * Submits the form by opening the confirmation modal */ - removeInboundPattern(index: number) { + onSubmit() { + this.openConfirmModal(this.confirmModal); + } + + /** + * Adds a new inbound pattern form group to the array of inbound patterns in the form + */ + addInboundPattern() { const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; - notifyServiceInboundPatternsArray.removeAt(index); + notifyServiceInboundPatternsArray.push(this.createInboundPatternFormGroup()); } /** - * Adds a new outbound pattern form group to the notifyServiceOutboundPatterns form array. + * Adds a new outbound pattern form group to the array of outbound patterns in the form */ addOutboundPattern() { const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; @@ -261,20 +343,51 @@ export class LdnServiceFormComponent implements OnInit { } /** - * Removes the outbound pattern form group at the specified index from the notifyServiceOutboundPatterns form array. - * - * @param {number} index - The index of the outbound pattern form group to remove. + * Selects an outbound pattern by updating its values based on the provided pattern value and index + * @param patternValue - The selected pattern value + * @param index - The index of the outbound pattern in the array */ - removeOutboundPattern(index: number) { - const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; - notifyServiceOutboundPatternsArray.removeAt(index); + selectOutboundPattern(patternValue: string, index: number): void { + const patternArray = (this.formModel.get('notifyServiceOutboundPatterns') as FormArray); + patternArray.controls[index].patchValue({pattern: patternValue}); + patternArray.controls[index].patchValue({patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternValue + '.label')}); + } /** - * Toggles the value of the 'automatic' control at the specified index in the notifyServiceInboundPatterns form array. - * - * @param {number} i - The index of the 'automatic' control to toggle. - * @memberof LdnServiceFormComponent + * Selects an outbound item filter by updating its value based on the provided filter value and index + * @param filterValue - The selected filter value + * @param index - The index of the inbound pattern in the array + */ + selectOutboundItemFilter(filterValue: string, index: number) { + const filterArray = (this.formModel.get('notifyServiceOutboundPatterns') as FormArray); + filterArray.controls[index].patchValue({constraint: filterValue}); + } + + /** + * Selects an inbound pattern by updating its values based on the provided pattern value and index + * @param patternValue - The selected pattern value + * @param index - The index of the inbound pattern in the array + */ + selectInboundPattern(patternValue: string, index: number): void { + const patternArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray); + patternArray.controls[index].patchValue({pattern: patternValue}); + patternArray.controls[index].patchValue({patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternValue + '.label')}); + } + + /** + * Selects an inbound item filter by updating its value based on the provided filter value and index + * @param filterValue - The selected filter value + * @param index - The index of the inbound pattern in the array + */ + selectInboundItemFilter(filterValue: string, index: number): void { + const filterArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray); + filterArray.controls[index].patchValue({constraint: filterValue}); + } + + /** + * Toggles the automatic property of an inbound pattern at the specified index + * @param i - The index of the inbound pattern in the array */ toggleAutomatic(i: number) { const automaticControl = this.formModel.get(`notifyServiceInboundPatterns.${i}.automatic`); @@ -285,88 +398,307 @@ export class LdnServiceFormComponent implements OnInit { } /** - * Selects an outbound pattern for a specific index in the notifyServiceOutboundPatterns form array. - * - * @param {string} patternValue - The selected pattern value. - * @param {number} index - The index of the outbound pattern in the form array. + * Toggles the enabled status of the LDN service by sending a patch request */ - selectOutboundPattern(patternValue: string, index: number): void { - const patternArray = (this.formModel.get('notifyServiceOutboundPatterns') as FormArray); - patternArray.controls[index].patchValue({pattern: patternValue}); - patternArray.controls[index].patchValue({patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternValue + '.label')}); + toggleEnabled() { + const newStatus = !this.formModel.get('enabled').value; + + const patchOperation: Operation = { + op: 'replace', + path: '/enabled', + value: newStatus, + }; + this.ldnServicesService.patch(this.service, [patchOperation]).pipe( + getFirstCompletedRemoteData() + ).subscribe( + () => { + + this.formModel.get('enabled').setValue(newStatus); + this.cdRef.detectChanges(); + } + ); } /** - * Selects an inbound pattern for a specific index in the form array. - * - * @param {string} patternValue - The selected pattern value. - * @param {number} index - The index of the inbound pattern in the form array. + * Closes the modal */ - selectInboundPattern(patternValue: string, index: number): void { - const patternArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray); - patternArray.controls[index].patchValue({pattern: patternValue}); - patternArray.controls[index].patchValue({patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternValue + '.label')}); + closeModal() { + this.modalRef.close(); + this.cdRef.detectChanges(); + } + /** + * Opens a confirmation modal with the specified content + * @param content - The content to be displayed in the modal + */ + openConfirmModal(content) { + this.modalRef = this.modalService.open(content); } /** - * Selects an inbound item filter for a specific index in the form array. - * - * @param {string} filterValue - The selected item filter value. - * @param {number} index - The index of the inbound item filter in the form array. + * Opens a reset form modal with the specified content + * @param content - The content to be displayed in the modal */ - selectInboundItemFilter(filterValue: string, index: number): void { - const filterArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray); - filterArray.controls[index].patchValue({constraint: filterValue}); + openResetFormModal(content) { + this.modalRef = this.modalService.open(content); } /** - * Selects an outbound item filter for a specific index in the form array. - * - * @param {string} filterValue - The selected item filter value. - * @param {number} index - The index of the outbound item filter in the form array. + * Patches the LDN service by retrieving and sending patch operations geenrated in generatePatchOperations() */ - selectOutboundItemFilter(filterValue: string, index: number) { - const filterArray = (this.formModel.get('notifyServiceOutboundPatterns') as FormArray); - filterArray.controls[index].patchValue({constraint: filterValue}); + patchService() { + this.deleteMarkedInboundPatterns(); + this.deleteMarkedOutboundPatterns(); + + const patchOperations = this.generatePatchOperations(); + this.formModel.markAllAsTouched(); + // If the form is invalid, close the modal and return + if (this.formModel.invalid) { + this.closeModal(); + return; + } + + const notifyServiceOutboundPatterns = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; + const notifyServiceInboundPatterns = this.formModel.get('notifyServiceInboundPatterns') as FormArray; + // If no inbound or outbound patterns are specified, close the modal and return + // noify the user that no patterns are specified + if ( + (notifyServiceOutboundPatterns.length === 0 && !notifyServiceOutboundPatterns[0]?.value) || + (notifyServiceInboundPatterns.length === 0 && !notifyServiceInboundPatterns[0]?.value)) { + this.notificationService.warning(this.translateService.get('ldn-service-notification.created.warning.title')); + this.closeModal(); + return; + } + + this.ldnServicesService.patch(this.service, patchOperations).pipe( + getFirstCompletedRemoteData() + ).subscribe( + (rd: RemoteData) => { + if (rd.hasSucceeded) { + this.closeModal(); + this.sendBack(); + this.notificationService.success(this.translateService.get('admin.registries.services-formats.modify.success.head'), + this.translateService.get('admin.registries.services-formats.modify.success.content')); + } else { + this.notificationService.error(this.translateService.get('admin.registries.services-formats.modify.failure.head'), + this.translateService.get('admin.registries.services-formats.modify.failure.content')); + this.closeModal(); + } + }); + } + + /** + * Resets the form and navigates back to the LDN services page + */ + resetFormAndLeave() { + this.sendBack(); + this.closeModal(); + } + + /** + * Marks the specified inbound pattern for deletion + * @param index - The index of the inbound pattern in the array + */ + markForInboundPatternDeletion(index: number) { + if (!this.markedForDeletionInboundPattern.includes(index)) { + this.markedForDeletionInboundPattern.push(index); + } + } + + /** + * Unmarks the specified inbound pattern for deletion + * @param index - The index of the inbound pattern in the array + */ + unmarkForInboundPatternDeletion(index: number) { + const i = this.markedForDeletionInboundPattern.indexOf(index); + if (i !== -1) { + this.markedForDeletionInboundPattern.splice(i, 1); + } + } + + /** + * Marks the specified outbound pattern for deletion + * @param index - The index of the outbound pattern in the array + */ + markForOutboundPatternDeletion(index: number) { + if (!this.markedForDeletionOutboundPattern.includes(index)) { + this.markedForDeletionOutboundPattern.push(index); + } + } + + /** + * Unmarks the specified outbound pattern for deletion + * @param index - The index of the outbound pattern in the array + */ + unmarkForOutboundPatternDeletion(index: number) { + const i = this.markedForDeletionOutboundPattern.indexOf(index); + if (i !== -1) { + this.markedForDeletionOutboundPattern.splice(i, 1); + } } /** - * Sends the user back to the LDN services list. + * Deletes marked inbound patterns from the form model + */ + deleteMarkedInboundPatterns() { + this.markedForDeletionInboundPattern.sort((a, b) => b - a); + const patternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; + + for (const index of this.markedForDeletionInboundPattern) { + if (index >= 0 && index < patternsArray.length) { + const patternGroup = patternsArray.at(index) as FormGroup; + const patternValue = patternGroup.value; + if (patternValue.isNew) { + patternsArray.removeAt(index); + } else { + this.deletedInboundPatterns.push(index); + } + } + } + + this.markedForDeletionInboundPattern = []; + } + + /** + * Deletes marked outbound patterns from the form model + */ + deleteMarkedOutboundPatterns() { + this.markedForDeletionOutboundPattern.sort((a, b) => b - a); + const patternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; + + for (const index of this.markedForDeletionOutboundPattern) { + if (index >= 0 && index < patternsArray.length) { + const patternGroup = patternsArray.at(index) as FormGroup; + const patternValue = patternGroup.value; + if (patternValue.isNew) { + patternsArray.removeAt(index); + } else { + + this.deletedOutboundPatterns.push(index); + } + } + } + + this.markedForDeletionOutboundPattern = []; + } + + /** + * Creates a replace operation and adds it to the patch operations if the form control is dirty + * @param patchOperations - The array to store patch operations + * @param formControlName - The name of the form control + * @param path - The JSON Patch path for the operation + */ + private createReplaceOperation(patchOperations: any[], formControlName: string, path: string): void { + if (this.formModel.get(formControlName).dirty) { + patchOperations.push({ + op: 'replace', + path, + value: this.formModel.get(formControlName).value.toString(), + }); + } + } + + /** + * Handles patterns in the form array, checking if an add or replace operations is required + * @param patchOperations - The array to store patch operations + * @param formArrayName - The name of the form array + */ + private handlePatterns(patchOperations: any[], formArrayName: string): void { + const patternsArray = this.formModel.get(formArrayName) as FormArray; + + for (let i = 0; i < patternsArray.length; i++) { + const patternGroup = patternsArray.at(i) as FormGroup; + + const patternValue = patternGroup.value; + if (patternGroup.touched && patternGroup.valid) { + delete patternValue?.patternLabel; + if (patternValue.isNew) { + delete patternValue.isNew; + const addOperation = { + op: 'add', + path: `${formArrayName}/-`, + value: patternValue, + }; + patchOperations.push(addOperation); + } else { + const replaceOperation = { + op: 'replace', + path: `${formArrayName}[${i}]`, + value: patternValue, + }; + patchOperations.push(replaceOperation); + } + } + } + } + + /** + * Navigates back to the LDN services page */ private sendBack() { this.router.navigateByUrl('admin/ldn/services'); } /** - * Creates a form group for an outbound pattern in the notifyServiceOutboundPatterns form array. - * - * @private - * @returns {FormGroup} - The created form group. + * Creates a form group for outbound patterns + * @returns The form group for outbound patterns */ private createOutboundPatternFormGroup(): FormGroup { - return this.formBuilder.group({ - pattern: [''], - constraint: [''], + const outBoundFormGroup = { + pattern: '', patternLabel: this.translateService.instant(this.selectPatternDefaultLabeli18Key), - }); + constraint: '', + } + + if(!this.isNewForm) { + outBoundFormGroup['isNew'] = true; + } + + return this.formBuilder.group(outBoundFormGroup); } /** - * Creates a form group for an inbound pattern in the notifyServiceInboundPatterns form array. - * - * @private - * @returns {FormGroup} - The created form group. + * Creates a form group for inbound patterns + * @returns The form group for inbound patterns */ private createInboundPatternFormGroup(): FormGroup { - return this.formBuilder.group({ - pattern: [''], - constraint: [''], - automatic: false, + const inBoundFormGroup = { + pattern: '', patternLabel: this.translateService.instant(this.selectPatternDefaultLabeli18Key), - }); + constraint: '', + automatic: false, + } + + if(!this.isNewForm) { + inBoundFormGroup['isNew'] = true; + } + + return this.formBuilder.group(inBoundFormGroup); } + /** + * Initializes an existing form group for outbound patterns + * @returns The initialized form group for outbound patterns + */ + private initializeOutboundPatternFormGroup(): FormGroup { + return this.formBuilder.group({ + pattern: '', + patternLabel: '', + constraint: '', + }); + } + /** + * Initializes an existing form group for inbound patterns + * @returns The initialized form group for inbound patterns + */ + private initializeInboundPatternFormGroup(): FormGroup { + return this.formBuilder.group({ + pattern: '', + patternLabel: '', + constraint: '', + automatic: '', + }); + } } diff --git a/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.html b/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.html deleted file mode 100644 index 9567cb1abef..00000000000 --- a/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.scss b/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.scss deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.spec.ts b/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.spec.ts deleted file mode 100644 index ced13716232..00000000000 --- a/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import {ComponentFixture, TestBed} from '@angular/core/testing'; - -import {LdnServiceNewComponent} from './ldn-service-new.component'; - -describe('LdnServiceNewComponent', () => { - let component: LdnServiceNewComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [LdnServiceNewComponent] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(LdnServiceNewComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.ts b/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.ts deleted file mode 100644 index 773f042d114..00000000000 --- a/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.ts +++ /dev/null @@ -1,9 +0,0 @@ -import {Component} from '@angular/core'; - -@Component({ - selector: 'ds-ldn-service-new', - templateUrl: './ldn-service-new.component.html', - styleUrls: ['./ldn-service-new.component.scss'] -}) -export class LdnServiceNewComponent { -} From 8e4408f118cda9105d2d18dadb2cc794f1c516a8 Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Thu, 14 Dec 2023 16:30:29 +0100 Subject: [PATCH 2/5] fix lint --- .../ldn-service-form.component.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts index da877558e7e..40e1024e5f6 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts @@ -124,7 +124,7 @@ export class LdnServiceFormComponent implements OnInit, OnDestroy { if (this.serviceId && !this.isNewForm) { this.fetchServiceData(this.serviceId); } - }) + }); this.setItemfilters(); } @@ -649,10 +649,11 @@ export class LdnServiceFormComponent implements OnInit, OnDestroy { pattern: '', patternLabel: this.translateService.instant(this.selectPatternDefaultLabeli18Key), constraint: '', - } + isNew: true + }; - if(!this.isNewForm) { - outBoundFormGroup['isNew'] = true; + if (this.isNewForm) { + delete outBoundFormGroup.isNew; } return this.formBuilder.group(outBoundFormGroup); @@ -668,10 +669,11 @@ export class LdnServiceFormComponent implements OnInit, OnDestroy { patternLabel: this.translateService.instant(this.selectPatternDefaultLabeli18Key), constraint: '', automatic: false, - } + isNew: true + }; - if(!this.isNewForm) { - inBoundFormGroup['isNew'] = true; + if (this.isNewForm) { + delete inBoundFormGroup.isNew; } return this.formBuilder.group(inBoundFormGroup); From 6a202bd685ff7a1454a1feb2d996b616fd87d89d Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Thu, 14 Dec 2023 16:46:02 +0100 Subject: [PATCH 3/5] fix rest, add initialization param --- .../ldn-service-form.component.html | 340 +++++++++--------- .../ldn-service-form.component.ts | 3 +- 2 files changed, 174 insertions(+), 169 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html index 10327985de9..69285efed7d 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html @@ -80,7 +80,7 @@

{{ isNewForm ? ('ldn-create-service.title' | translate)

-
+
@@ -97,130 +97,131 @@

{{ isNewForm ? ('ldn-create-service.title' | translate)

-
+
+
- + -
-
-
-
- - - -
-
-
- -
- -
+
+
+
-
- -
+
-
- -
-
+
+ +
+
+ + + +
+
+
+
+ +
+ +
+
+
-
-
-
- +
+
+ - + +
-
- + +
- {{ 'ldn-new-service.form.label.addPattern' | translate }} -
+
@@ -239,116 +240,119 @@

{{ isNewForm ? ('ldn-create-service.title' | translate)

-
+
+
- + -
-
-
-
- - - -
-
-
-
- -
+
+
-
- -
+
+
+ +
+
+ + + +
+
+
+
-
- -
-
+
+ +
+
+
-
-
-
- - +
+
+ + +
-
- + +
+