fix issue with edit and creation, unify files, refactor

This commit is contained in:
FrancescoMolinaro
2023-12-14 16:25:02 +01:00
parent 62ae9226f5
commit 90ad316db4
14 changed files with 657 additions and 1549 deletions

View File

@@ -2,8 +2,7 @@ import {NgModule} from '@angular/core';
import {RouterModule} from '@angular/router'; import {RouterModule} from '@angular/router';
import {I18nBreadcrumbResolver} from 'src/app/core/breadcrumbs/i18n-breadcrumb.resolver'; import {I18nBreadcrumbResolver} from 'src/app/core/breadcrumbs/i18n-breadcrumb.resolver';
import {LdnServicesOverviewComponent} from './ldn-services-directory/ldn-services-directory.component'; import {LdnServicesOverviewComponent} from './ldn-services-directory/ldn-services-directory.component';
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';
@NgModule({ @NgModule({
imports: [ imports: [
@@ -18,13 +17,13 @@ import {LdnServiceFormEditComponent} from './ldn-service-form-edit/ldn-service-f
{ {
path: 'new', path: 'new',
resolve: {breadcrumb: I18nBreadcrumbResolver}, resolve: {breadcrumb: I18nBreadcrumbResolver},
component: LdnServiceNewComponent, component: LdnServiceFormComponent,
data: {title: 'ldn-register-new-service.title', breadcrumbKey: 'ldn-register-new-service'} data: {title: 'ldn-register-new-service.title', breadcrumbKey: 'ldn-register-new-service'}
}, },
{ {
path: 'edit/:serviceId', path: 'edit/:serviceId',
resolve: {breadcrumb: I18nBreadcrumbResolver}, resolve: {breadcrumb: I18nBreadcrumbResolver},
component: LdnServiceFormEditComponent, component: LdnServiceFormComponent,
data: {title: 'ldn-edit-service.title', breadcrumbKey: 'ldn-edit-service'} data: {title: 'ldn-edit-service.title', breadcrumbKey: 'ldn-edit-service'}
}, },
]), ]),

View File

@@ -3,9 +3,7 @@ import {CommonModule} from '@angular/common';
import {AdminLdnServicesRoutingModule} from './admin-ldn-services-routing.module'; import {AdminLdnServicesRoutingModule} from './admin-ldn-services-routing.module';
import {LdnServicesOverviewComponent} from './ldn-services-directory/ldn-services-directory.component'; import {LdnServicesOverviewComponent} from './ldn-services-directory/ldn-services-directory.component';
import {SharedModule} from '../../shared/shared.module'; 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 {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 {FormsModule} from '@angular/forms';
import {LdnItemfiltersService} from './ldn-services-data/ldn-itemfilters-data.service'; 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: [ declarations: [
LdnServicesOverviewComponent, LdnServicesOverviewComponent,
LdnServiceNewComponent,
LdnServiceFormComponent, LdnServiceFormComponent,
LdnServiceFormEditComponent,
], ],
providers: [LdnItemfiltersService] providers: [LdnItemfiltersService]
}) })

View File

@@ -1,415 +0,0 @@
<div class="container">
<form (ngSubmit)="onSubmit()" [formGroup]="formModel">
<div class="d-flex">
<h2 class="flex-grow-1">{{ 'ldn-edit-registered-service.title' | translate }}</h2>
</div>
<!-- In the toggle section -->
<div class="toggle-switch-container">
<label class="status-label font-weight-bold" for="enabled">{{ 'ldn-service-status' | translate }}</label>
<div>
<input formControlName="enabled" hidden id="enabled" name="enabled" type="checkbox">
<div (click)="toggleEnabled()" [class.checked]="formModel.get('enabled').value" class="toggle-switch">
<div class="slider"></div>
</div>
</div>
</div>
<!-- In the Name section -->
<div class="mb-5">
<label for="name" class="font-weight-bold">{{ 'ldn-new-service.form.label.name' | translate }}</label>
<input [class.invalid-field]="formModel.get('name').invalid && formModel.get('name').touched"
[placeholder]="'ldn-new-service.form.placeholder.name' | translate" class="form-control"
formControlName="name"
id="name"
name="name"
type="text">
<div *ngIf="formModel.get('name').invalid && formModel.get('name').touched" class="error-text">
{{ 'ldn-new-service.form.error.name' | translate }}
</div>
</div>
<!-- In the description section -->
<div class="mb-5 mt-5 d-flex flex-column">
<label for="description" class="font-weight-bold">{{ 'ldn-new-service.form.label.description' | translate }}</label>
<textarea [placeholder]="'ldn-new-service.form.placeholder.description' | translate"
class="form-control" formControlName="description" id="description" name="description"></textarea>
</div>
<!-- In the url section -->
<div class="mb-5 mt-5">
<label for="url" class="font-weight-bold">{{ 'ldn-new-service.form.label.url' | translate }}</label>
<input [class.invalid-field]="formModel.get('url').invalid && formModel.get('url').touched"
[placeholder]="'ldn-new-service.form.placeholder.url' | translate" class="form-control"
formControlName="url"
id="url"
name="url"
type="text">
<div *ngIf="formModel.get('url').invalid && formModel.get('url').touched" class="error-text">
{{ 'ldn-new-service.form.error.url' | translate }}
</div>
</div>
<!-- In the ldnUrl section -->
<div class="mb-5 mt-5">
<label for="ldnUrl" class="font-weight-bold">{{ 'ldn-new-service.form.label.ldnUrl' | translate }}</label>
<input [class.invalid-field]="formModel.get('ldnUrl').invalid && formModel.get('ldnUrl').touched"
[placeholder]="'ldn-new-service.form.placeholder.ldnUrl' | translate" class="form-control"
formControlName="ldnUrl"
id="ldnUrl"
name="ldnUrl"
type="text">
<div *ngIf="formModel.get('ldnUrl').invalid && formModel.get('ldnUrl').touched" class="error-text">
{{ 'ldn-new-service.form.error.ldnurl' | translate }}
</div>
</div>
<!-- In the score section -->
<div class="mb-2">
<label for="score" class="font-weight-bold">{{ 'ldn-new-service.form.label.score' | translate }}</label>
<input [class.invalid-field]="formModel.get('score').invalid && formModel.get('score').touched"
[placeholder]="'ldn-new-service.form.placeholder.score' | translate" formControlName="score"
id="score"
name="score"
min="0"
max="1"
step=".01"
class="form-control"
type="number">
<div *ngIf="formModel.get('score').invalid && formModel.get('score').touched" class="error-text">
{{ 'ldn-new-service.form.error.score' | translate }}
</div>
</div>
<!-- In the Inbound Patterns Labels section -->
<div class="row mb-1 mt-5">
<div class="col">
<label class="font-weight-bold">{{ 'ldn-new-service.form.label.inboundPattern' | translate }} </label>
</div>
<ng-container *ngIf="!!(formModel.get('notifyServiceInboundPatterns')['controls'][0]?.value?.pattern)">
<div class="col">
<label class="font-weight-bold">{{ 'ldn-new-service.form.label.ItemFilter' | translate }}</label>
</div>
<div class="col-sm-1">
<label class="font-weight-bold">{{ 'ldn-new-service.form.label.automatic' | translate }}</label>
</div>
</ng-container>
<div class="col-sm-2">
</div>
</div>
<!-- In the Inbound Patterns section -->
<div *ngFor="let patternGroup of formModel.get('notifyServiceInboundPatterns')['controls']; let i = index"
[class.marked-for-deletion]="markedForDeletionInboundPattern.includes(i)"
formGroupName="notifyServiceInboundPatterns">
<ng-container [formGroupName]="i">
<div class="row mb-1">
<div class="col">
<div #inboundPatternDropdown="ngbDropdown" class="w-80" display="dynamic"
id="additionalInboundPattern{{i}}"
ngbDropdown placement="bottom-start">
<div class="position-relative right-addon" role="combobox">
<i aria-hidden="true" class="position-absolute scrollable-dropdown-toggle"
ngbDropdownToggle></i>
<input
(click)="inboundPatternDropdown.open();"
[readonly]="true"
class="form-control w-80 scrollable-dropdown-input"
formControlName="patternLabel"
id="inboundPatternDropdownButton"
ngbDropdownAnchor
type="text"
/>
<div aria-labelledby="inboundPatternDropdownButton"
class="dropdown-menu scrollable-dropdown-menu w-100 "
ngbDropdownMenu>
<div class="scrollable-menu" role="listbox">
<button (click)="selectInboundPattern(pattern, i); $event.stopPropagation()"
*ngFor="let pattern of inboundPatterns; let internalIndex = index"
[title]="'ldn-service.form.pattern.' + pattern + '.description' | translate"
class="dropdown-item collection-item text-truncate w-100"
ngbDropdownItem
type="button">
<div>{{ 'ldn-service.form.pattern.' + pattern + '.label' | translate }}</div>
<div
class="small-text">{{ 'ldn-service.form.pattern.' + pattern + '.description' | translate }}</div>
</button>
</div>
</div>
</div>
</div>
</div>
<div class="col">
<ng-container
*ngIf="!!(formModel.get('notifyServiceInboundPatterns')['controls'][i].value.pattern)">
<div #inboundItemfilterDropdown="ngbDropdown" class="w-100" id="constraint{{i}}" ngbDropdown
placement="bottom-start">
<div class="position-relative right-addon" role="combobox">
<i aria-hidden="true" class="position-absolute scrollable-dropdown-toggle"
ngbDropdownToggle></i>
<input
(click)="inboundItemfilterDropdown.open();"
[readonly]="true"
[value]="selectedInboundItemfilters"
class="form-control w-100 scrollable-dropdown-input"
formControlName="constraint"
id="inboundItemfilterDropdown"
ngbDropdownAnchor
type="text"
/>
<div aria-labelledby="inboundItemfilterDropdownButton"
class="dropdown-menu scrollable-dropdown-menu w-100 "
ngbDropdownMenu>
<div class="scrollable-menu" role="listbox">
<button (click)="selectInboundItemFilter('', i); $event.stopPropagation()"
class="dropdown-item collection-item text-truncate w-100" ngbDropdownItem type="button">
<span> {{'ldn-service.control-constaint-select-none' | translate}} </span>
</button>
<button (click)="selectInboundItemFilter(constraint.id, i); $event.stopPropagation()"
*ngFor="let constraint of (itemfiltersRD$ | async)?.payload?.page; let internalIndex = index"
class="dropdown-item collection-item text-truncate w-100"
ngbDropdownItem
type="button">
<div>{{ constraint.id }}</div>
</button>
</div>
</div>
</div>
</div>
</ng-container>
</div>
<div
[style.visibility]="formModel.get('notifyServiceInboundPatterns')['controls'][i].value.pattern ? 'visible' : 'hidden'"
class="col-sm-1">
<input formControlName="automatic" hidden id="automatic{{i}}" name="automatic{{i}}"
type="checkbox">
<div (click)="toggleAutomatic(i)"
[class.checked]="formModel.get('notifyServiceInboundPatterns.' + i + '.automatic').value"
class="toggle-switch">
<div class="slider"></div>
</div>
</div>
<div class="col-sm-2">
<div class="btn-group">
<button (click)="markForInboundPatternDeletion(i)" class="btn btn-outline-dark trash-button"
type="button">
<i class="fas fa-trash"></i>
</button>
<button (click)="unmarkForInboundPatternDeletion(i)"
*ngIf="markedForDeletionInboundPattern.includes(i)"
class="btn btn-warning "
type="button">
<i class="fas fa-undo"></i>
</button>
</div>
</div>
</div>
</ng-container>
</div>
<span (click)="addInboundPattern()"
class="add-pattern-link mb-2">{{ 'ldn-new-service.form.label.addPattern' | translate }}</span>
<!-- In the Outbound Patterns Labels section -->
<div class="row mb-1 mt-5">
<div class="col">
<label class="font-weight-bold">{{ 'ldn-new-service.form.label.outboundPattern' | translate }} </label>
</div>
<ng-container *ngIf="!!(formModel.get('notifyServiceOutboundPatterns')['controls'][0]?.value?.pattern)">
<div class="col">
<label class="font-weight-bold">{{ 'ldn-new-service.form.label.ItemFilter' | translate }}</label>
</div>
</ng-container>
<div class="col-sm-1 ">
<label class="label-box-2" style="visibility: hidden;">
{{ 'ldn-new-service.form.label.automatic' | translate }}
</label>
</div>
<div class="col-sm-2 ">
</div>
</div>
<!-- In the Outbound Patterns section -->
<div *ngFor="let patternGroup of formModel.get('notifyServiceOutboundPatterns')['controls']; let i = index"
[class.marked-for-deletion]="markedForDeletionOutboundPattern.includes(i)"
formGroupName="notifyServiceOutboundPatterns">
<ng-container [formGroupName]="i">
<div class="row mb-1">
<div class="col">
<div #outboundPatternDropdown="ngbDropdown" class="w-100" id="additionalOutboundPattern{{i}}"
ngbDropdown
placement="bottom-start">
<div class="position-relative right-addon" role="combobox">
<i aria-hidden="true" class="position-absolute scrollable-dropdown-toggle"
ngbDropdownToggle></i>
<input
(click)="outboundPatternDropdown.open();"
[readonly]="true"
[value]="selectedOutboundPatterns"
class="form-control w-100 scrollable-dropdown-input"
formControlName="patternLabel"
id="outboundPatternDropdownButton"
ngbDropdownAnchor
type="text"
/>
<div aria-labelledby="outboundPatternDropdownButton"
class="dropdown-menu scrollable-dropdown-menu w-100 "
ngbDropdownMenu>
<div class="scrollable-menu" role="listbox">
<button (click)="selectOutboundPattern(pattern, i); $event.stopPropagation()"
*ngFor="let pattern of outboundPatterns; let internalIndex = index"
[title]="'ldn-service.form.pattern.' + pattern + '.description' | translate"
class="dropdown-item collection-item text-truncate w-100"
ngbDropdownItem
type="button">
<div>{{ 'ldn-service.form.pattern.' + pattern + '.label' | translate }}</div>
<div
class="small-text">{{ 'ldn-service.form.pattern.' + pattern + '.description' | translate }}</div>
</button>
</div>
</div>
</div>
</div>
</div>
<div class="col">
<ng-container
*ngIf="!!(formModel.get('notifyServiceOutboundPatterns')['controls'][i].value.pattern)">
<div #outboundItemfilterDropdown="ngbDropdown" class="w-100" id="constraint{{i}}"
ngbDropdown
placement="bottom-start">
<div class="position-relative right-addon" role="combobox">
<i aria-hidden="true" class="position-absolute scrollable-dropdown-toggle"
ngbDropdownToggle></i>
<input
(click)="outboundItemfilterDropdown.open();"
[readonly]="true"
[value]="selectedOutboundItemfilters"
class="form-control w-100 scrollable-dropdown-input"
formControlName="constraint"
id="outboundItemfilterDropdown"
ngbDropdownAnchor
type="text"
/>
<div aria-labelledby="outboundItemfilterDropdownButton"
class="dropdown-menu scrollable-dropdown-menu w-100 "
ngbDropdownMenu>
<div class="scrollable-menu" role="listbox">
<button (click)="selectOutboundItemFilter('', i); $event.stopPropagation()"
class="dropdown-item collection-item text-truncate w-100" ngbDropdownItem type="button">
<span> {{'ldn-service.control-constaint-select-none' | translate}} </span>
</button>
<button (click)="selectOutboundItemFilter(constraint.id, i); $event.stopPropagation()"
*ngFor="let constraint of (itemfiltersRD$ | async)?.payload?.page; let internalIndex = index"
class="dropdown-item collection-item text-truncate w-100"
ngbDropdownItem
type="button">
<div>{{ constraint.id }}</div>
</button>
</div>
</div>
</div>
</div>
</ng-container>
</div>
<div [style.visibility]="'hidden'" class="col-sm-1">
<input hidden id="automatic{{i}}" name="automatic{{i}}" type="checkbox">
<div
class="toggle-switch">
<div class="slider"></div>
</div>
</div>
<div class="col-sm-2">
<div class="btn-group">
<button (click)="markForOutboundPatternDeletion(i)"
class="btn btn-outline-dark trash-button" type="button">
<i class="fas fa-trash"></i>
</button>
<button (click)="unmarkForOutboundPatternDeletion(i)"
*ngIf="markedForDeletionOutboundPattern.includes(i)"
class="btn btn-warning "
type="button">
<i class="fas fa-undo"></i>
</button>
</div>
</div>
</div>
</ng-container>
</div>
<div
(click)="addOutboundPattern()"
class="add-pattern-link mb-4">{{ 'ldn-new-service.form.label.addPattern' | translate }}
</div>
<div class="submission-form-footer my-1 position-sticky d-flex justify-content-between" role="group">
<button (click)="openResetFormModal(resetFormModal)" class="btn btn-danger" type="button">
<span><i class="fas fa-trash"></i>&nbsp;{{ 'submission.general.discard.submit' | translate }}</span>
</button>
<button class="btn btn-primary" type="submit">
<span><i class="fas fa-save"></i>&nbsp;{{ 'ldn-new-service.form.label.submit' | translate }}</span>
</button>
</div>
</form>
</div>
<ng-template #confirmModal>
<div class="modal-header">
<h4>{{'service.overview.edit.modal' | translate }}</h4>
<button (click)="closeModal()" aria-label="Close"
class="close" type="button">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div>
{{ 'service.overview.edit.body' | translate }}
</div>
</div>
<div class="modal-footer">
<button (click)="closeModal()" class="btn btn-danger mr-2"
id="delete-confirm">{{ 'service.detail.return' | translate }}
</button>
<button (click)="patchService()"
class="btn btn-primary">{{ 'service.detail.update' | translate }}
</button>
</div>
</ng-template>
<ng-template #resetFormModal>
<div class="modal-header">
<h4 class="text-danger">{{'service.overview.reset-form.modal' | translate }}</h4>
<button (click)="closeModal()" aria-label="Close"
class="close" type="button">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<span>
{{ 'service.overview.reset-form.body' | translate }}
</span>
</div>
<div class="modal-footer">
<button (click)="closeModal()"
class="btn btn-primary"
id="reset-confirm">{{ 'service.overview.reset-form.reset-return' | translate }}
</button>
<button (click)="resetFormAndLeave()" class="mr-2 btn btn-danger"
id="reset-delete">{{ 'service.overview.reset-form.reset-confirm' | translate }}
</button>
</div>
</ng-template>

View File

@@ -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%);
}

View File

@@ -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<LdnServiceFormEditComponent>;
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();
});
});

View File

@@ -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<any>;
@ViewChild('resetFormModal', {static: true}) resetFormModal: TemplateRef<any>;
public inboundPatterns: string[] = notifyPatterns;
public outboundPatterns: string[] = notifyPatterns;
itemfiltersRD$: Observable<RemoteData<PaginatedList<Itemfilter>>>;
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<LdnService>) => {
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<LdnService>) => {
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: '',
});
}
}

View File

@@ -1,11 +1,21 @@
<div class="container"> <div class="container">
<form (ngSubmit)="onSubmit()" [formGroup]="formModel"> <form (ngSubmit)="onSubmit()" [formGroup]="formModel">
<div class="d-flex mb-5"> <div class="d-flex">
<h2 class="flex-grow-1">{{ 'ldn-create-service.title' | translate }}</h2> <h2 class="flex-grow-1">{{ isNewForm ? ('ldn-create-service.title' | translate) : ('ldn-edit-registered-service.title' | translate) }}</h2>
</div> </div>
<!-- In the name section --> <!-- In the toggle section -->
<div class="toggle-switch-container" *ngIf="!isNewForm">
<label class="status-label font-weight-bold" for="enabled">{{ 'ldn-service-status' | translate }}</label>
<div>
<input formControlName="enabled" hidden id="enabled" name="enabled" type="checkbox">
<div (click)="toggleEnabled()" [class.checked]="formModel.get('enabled').value" class="toggle-switch">
<div class="slider"></div>
</div>
</div>
</div>
<!-- In the Name section -->
<div class="mb-5"> <div class="mb-5">
<label for="name">{{ 'ldn-new-service.form.label.name' | translate }}</label> <label for="name" class="font-weight-bold">{{ 'ldn-new-service.form.label.name' | translate }}</label>
<input [class.invalid-field]="formModel.get('name').invalid && formModel.get('name').touched" <input [class.invalid-field]="formModel.get('name').invalid && formModel.get('name').touched"
[placeholder]="'ldn-new-service.form.placeholder.name' | translate" class="form-control" [placeholder]="'ldn-new-service.form.placeholder.name' | translate" class="form-control"
formControlName="name" formControlName="name"
@@ -19,15 +29,14 @@
<!-- In the description section --> <!-- In the description section -->
<div class="mb-5 mt-5 d-flex flex-column"> <div class="mb-5 mt-5 d-flex flex-column">
<label for="description">{{ 'ldn-new-service.form.label.description' | translate }}</label> <label for="description" class="font-weight-bold">{{ 'ldn-new-service.form.label.description' | translate }}</label>
<textarea [placeholder]="'ldn-new-service.form.placeholder.description' | translate" <textarea [placeholder]="'ldn-new-service.form.placeholder.description' | translate"
class="form-control" formControlName="description" id="description" name="description"></textarea> class="form-control" formControlName="description" id="description" name="description"></textarea>
</div> </div>
<!-- In the url section --> <!-- In the url section -->
<div class="mb-5 mt-5"> <div class="mb-5 mt-5">
<label for="url">{{ 'ldn-new-service.form.label.url' | translate }}</label> <label for="url" class="font-weight-bold">{{ 'ldn-new-service.form.label.url' | translate }}</label>
<input [class.invalid-field]="formModel.get('url').invalid && formModel.get('url').touched" <input [class.invalid-field]="formModel.get('url').invalid && formModel.get('url').touched"
[placeholder]="'ldn-new-service.form.placeholder.url' | translate" class="form-control" [placeholder]="'ldn-new-service.form.placeholder.url' | translate" class="form-control"
formControlName="url" formControlName="url"
@@ -39,10 +48,9 @@
</div> </div>
</div> </div>
<!-- In the ldnUrl section --> <!-- In the ldnUrl section -->
<div class="mb-5 mt-5"> <div class="mb-5 mt-5">
<label for="ldnUrl">{{ 'ldn-new-service.form.label.ldnUrl' | translate }}</label> <label for="ldnUrl" class="font-weight-bold">{{ 'ldn-new-service.form.label.ldnUrl' | translate }}</label>
<input [class.invalid-field]="formModel.get('ldnUrl').invalid && formModel.get('ldnUrl').touched" <input [class.invalid-field]="formModel.get('ldnUrl').invalid && formModel.get('ldnUrl').touched"
[placeholder]="'ldn-new-service.form.placeholder.ldnUrl' | translate" class="form-control" [placeholder]="'ldn-new-service.form.placeholder.ldnUrl' | translate" class="form-control"
formControlName="ldnUrl" formControlName="ldnUrl"
@@ -53,9 +61,10 @@
{{ 'ldn-new-service.form.error.ldnurl' | translate }} {{ 'ldn-new-service.form.error.ldnurl' | translate }}
</div> </div>
</div> </div>
<!-- In the score section --> <!-- In the score section -->
<div class="mb-2"> <div class="mb-2">
<label for="score">{{ 'ldn-new-service.form.label.score' | translate }}</label> <label for="score" class="font-weight-bold">{{ 'ldn-new-service.form.label.score' | translate }}</label>
<input [class.invalid-field]="formModel.get('score').invalid && formModel.get('score').touched" <input [class.invalid-field]="formModel.get('score').invalid && formModel.get('score').touched"
[placeholder]="'ldn-new-service.form.placeholder.score' | translate" formControlName="score" [placeholder]="'ldn-new-service.form.placeholder.score' | translate" formControlName="score"
id="score" id="score"
@@ -71,24 +80,25 @@
</div> </div>
<!-- In the Inbound Patterns Labels section --> <!-- In the Inbound Patterns Labels section -->
<div class="row mb-2 mt-5"> <div class="row mb-1 mt-5">
<div class="col"> <div class="col">
<label>{{ 'ldn-new-service.form.label.inboundPattern' | translate }} </label> <label class="font-weight-bold">{{ 'ldn-new-service.form.label.inboundPattern' | translate }} </label>
</div> </div>
<ng-container *ngIf="!!(formModel.get('notifyServiceInboundPatterns')['controls'][0]?.value?.pattern)"> <ng-container *ngIf="!!(formModel.get('notifyServiceInboundPatterns')['controls'][0]?.value?.pattern)">
<div class="col"> <div class="col">
<label>{{ 'ldn-new-service.form.label.ItemFilter' | translate }}</label> <label class="font-weight-bold">{{ 'ldn-new-service.form.label.ItemFilter' | translate }}</label>
</div> </div>
<div class="col-sm-1"> <div class="col-sm-1">
<label class="">{{ 'ldn-new-service.form.label.automatic' | translate }}</label> <label class="font-weight-bold">{{ 'ldn-new-service.form.label.automatic' | translate }}</label>
</div> </div>
</ng-container> </ng-container>
<div class="col-sm-1"> <div class="col-sm-2">
</div> </div>
</div> </div>
<!-- In the Inbound Patterns section --> <!-- In the Inbound Patterns section -->
<div *ngFor="let patternGroup of formModel.get('notifyServiceInboundPatterns')['controls']; let i = index" <div *ngFor="let patternGroup of formModel.get('notifyServiceInboundPatterns')['controls']; let i = index"
[class.marked-for-deletion]="markedForDeletionInboundPattern.includes(i)"
formGroupName="notifyServiceInboundPatterns"> formGroupName="notifyServiceInboundPatterns">
<ng-container [formGroupName]="i"> <ng-container [formGroupName]="i">
@@ -96,18 +106,17 @@
<div class="row mb-1"> <div class="row mb-1">
<div class="col"> <div class="col">
<div #inboundPatternDropdown="ngbDropdown" class="w-100" id="additionalInboundPattern{{i}}" ngbDropdown <div #inboundPatternDropdown="ngbDropdown" class="w-80" display="dynamic"
placement="bottom-start"> id="additionalInboundPattern{{i}}"
ngbDropdown placement="bottom-start">
<div class="position-relative right-addon" role="combobox"> <div class="position-relative right-addon" role="combobox">
<i aria-hidden="true" class="position-absolute scrollable-dropdown-toggle" <i aria-hidden="true" class="position-absolute scrollable-dropdown-toggle"
ngbDropdownToggle> ngbDropdownToggle></i>
</i>
<input <input
(click)="inboundPatternDropdown.open();" (click)="inboundPatternDropdown.open();"
[readonly]="true" [readonly]="true"
[value]="selectedInboundPatterns" [value]="selectedInboundPatterns"
class="form-control w-100 scrollable-dropdown-input" class="form-control w-80 scrollable-dropdown-input"
formControlName="patternLabel" formControlName="patternLabel"
id="inboundPatternDropdownButton" id="inboundPatternDropdownButton"
ngbDropdownAnchor ngbDropdownAnchor
@@ -118,7 +127,7 @@
ngbDropdownMenu> ngbDropdownMenu>
<div class="scrollable-menu" role="listbox"> <div class="scrollable-menu" role="listbox">
<button (click)="selectInboundPattern(pattern, i); $event.stopPropagation()" <button (click)="selectInboundPattern(pattern, i); $event.stopPropagation()"
*ngFor="let pattern of inboundPatterns" *ngFor="let pattern of inboundPatterns; let internalIndex = index"
[title]="'ldn-service.form.pattern.' + pattern + '.description' | translate" [title]="'ldn-service.form.pattern.' + pattern + '.description' | translate"
class="dropdown-item collection-item text-truncate w-100" class="dropdown-item collection-item text-truncate w-100"
ngbDropdownItem ngbDropdownItem
@@ -133,7 +142,6 @@
</div> </div>
</div> </div>
<div class="col"> <div class="col">
<ng-container <ng-container
*ngIf="!!(formModel.get('notifyServiceInboundPatterns')['controls'][i].value.pattern)"> *ngIf="!!(formModel.get('notifyServiceInboundPatterns')['controls'][i].value.pattern)">
@@ -160,7 +168,7 @@
class="dropdown-item collection-item text-truncate w-100" ngbDropdownItem type="button"> class="dropdown-item collection-item text-truncate w-100" ngbDropdownItem type="button">
<span> {{'ldn-service.control-constaint-select-none' | translate}} </span> <span> {{'ldn-service.control-constaint-select-none' | translate}} </span>
</button> </button>
<button (click)="selectInboundItemFilter(constraint.id, i); $event.stopPropagation() " <button (click)="selectInboundItemFilter(constraint.id, i); $event.stopPropagation()"
*ngFor="let constraint of (itemfiltersRD$ | async)?.payload?.page; let internalIndex = index" *ngFor="let constraint of (itemfiltersRD$ | async)?.payload?.page; let internalIndex = index"
class="dropdown-item collection-item text-truncate w-100" class="dropdown-item collection-item text-truncate w-100"
ngbDropdownItem ngbDropdownItem
@@ -175,7 +183,7 @@
</div> </div>
<div <div
[style.visibility]="formModel.get('notifyServiceInboundPatterns')['controls'][i]?.value?.pattern ? 'visible' : 'hidden'" [style.visibility]="formModel.get('notifyServiceInboundPatterns')['controls'][i].value.pattern ? 'visible' : 'hidden'"
class="col-sm-1"> class="col-sm-1">
<input formControlName="automatic" hidden id="automatic{{i}}" name="automatic{{i}}" <input formControlName="automatic" hidden id="automatic{{i}}" name="automatic{{i}}"
type="checkbox"> type="checkbox">
@@ -186,36 +194,53 @@
</div> </div>
</div> </div>
<div class="col-sm-1">
<button (click)="removeInboundPattern(i)" class="btn btn-outline-dark trash-button">
<i class="fas fa-trash"></i>
</button>
</div>
<div class="col-sm-2">
<div class="btn-group">
<button (click)="markForInboundPatternDeletion(i)" class="btn btn-outline-dark trash-button"
type="button">
<i class="fas fa-trash"></i>
</button>
<button (click)="unmarkForInboundPatternDeletion(i)"
*ngIf="markedForDeletionInboundPattern.includes(i)"
class="btn btn-warning "
type="button">
<i class="fas fa-undo"></i>
</button>
</div>
</div>
</div> </div>
</ng-container> </ng-container>
</div> </div>
<span (click)="addInboundPattern()"
class="add-pattern-link mb-4">{{ 'ldn-new-service.form.label.addPattern' | translate }}</span>
<span (click)="addInboundPattern()"
class="add-pattern-link mb-2">{{ 'ldn-new-service.form.label.addPattern' | translate }}</span>
<!-- In the Outbound Patterns Labels section --> <!-- In the Outbound Patterns Labels section -->
<div class="row mb-1 mt-5"> <div class="row mb-1 mt-5">
<div class="col"> <div class="col">
<label>{{ 'ldn-new-service.form.label.outboundPattern' | translate }}</label> <label class="font-weight-bold">{{ 'ldn-new-service.form.label.outboundPattern' | translate }} </label>
</div> </div>
<ng-container *ngIf="!!(formModel.get('notifyServiceOutboundPatterns')['controls'][0]?.value?.pattern)"> <ng-container *ngIf="!!(formModel.get('notifyServiceOutboundPatterns')['controls'][0]?.value?.pattern)">
<div class="col"> <div class="col">
<label class="">{{ 'ldn-new-service.form.label.ItemFilter' | translate }}</label> <label class="font-weight-bold">{{ 'ldn-new-service.form.label.ItemFilter' | translate }}</label>
</div> </div>
</ng-container> </ng-container>
<div class="col-sm-2"> <div class="col-sm-1 ">
<label class="label-box-2" style="visibility: hidden;">
{{ 'ldn-new-service.form.label.automatic' | translate }}
</label>
</div>
<div class="col-sm-2 ">
</div> </div>
</div> </div>
<!-- In the Outbound Patterns section --> <!-- In the Outbound Patterns section -->
<div *ngFor="let patternGroup of formModel.get('notifyServiceOutboundPatterns')['controls']; let i = index" <div *ngFor="let patternGroup of formModel.get('notifyServiceOutboundPatterns')['controls']; let i = index"
[class.marked-for-deletion]="markedForDeletionOutboundPattern.includes(i)"
formGroupName="notifyServiceOutboundPatterns"> formGroupName="notifyServiceOutboundPatterns">
<ng-container [formGroupName]="i"> <ng-container [formGroupName]="i">
@@ -243,7 +268,7 @@
ngbDropdownMenu> ngbDropdownMenu>
<div class="scrollable-menu" role="listbox"> <div class="scrollable-menu" role="listbox">
<button (click)="selectOutboundPattern(pattern, i); $event.stopPropagation()" <button (click)="selectOutboundPattern(pattern, i); $event.stopPropagation()"
*ngFor="let pattern of outboundPatterns" *ngFor="let pattern of outboundPatterns; let internalIndex = index"
[title]="'ldn-service.form.pattern.' + pattern + '.description' | translate" [title]="'ldn-service.form.pattern.' + pattern + '.description' | translate"
class="dropdown-item collection-item text-truncate w-100" class="dropdown-item collection-item text-truncate w-100"
ngbDropdownItem ngbDropdownItem
@@ -257,7 +282,6 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col"> <div class="col">
<ng-container <ng-container
*ngIf="!!(formModel.get('notifyServiceOutboundPatterns')['controls'][i].value.pattern)"> *ngIf="!!(formModel.get('notifyServiceOutboundPatterns')['controls'][i].value.pattern)">
@@ -300,42 +324,51 @@
</div> </div>
<div [style.visibility]="'hidden'" class="col-sm-1"> <div [style.visibility]="'hidden'" class="col-sm-1">
<input hidden id="automatic{{i}}" name="automatic{{i}}" <input hidden id="automatic{{i}}" name="automatic{{i}}" type="checkbox">
type="checkbox">
<div <div
class="toggle-switch"> class="toggle-switch">
<div class="slider"></div> <div class="slider"></div>
</div> </div>
</div> </div>
<div class="col-sm-1"> <div class="col-sm-2">
<button (click)="removeOutboundPattern(i)" class="btn btn-outline-dark trash-button"> <div class="btn-group">
<i class="fas fa-trash"></i> <button (click)="markForOutboundPatternDeletion(i)"
</button> class="btn btn-outline-dark trash-button" type="button">
<i class="fas fa-trash"></i>
</button>
<button (click)="unmarkForOutboundPatternDeletion(i)"
*ngIf="markedForDeletionOutboundPattern.includes(i)"
class="btn btn-warning "
type="button">
<i class="fas fa-undo"></i>
</button>
</div>
</div> </div>
</div> </div>
</ng-container> </ng-container>
</div> </div>
<div (click)="addOutboundPattern()" <div
class="add-pattern-link mb-4">{{ 'ldn-new-service.form.label.addPattern' | translate }} (click)="addOutboundPattern()"
class="add-pattern-link mb-4">{{ 'ldn-new-service.form.label.addPattern' | translate }}
</div> </div>
<div class="submission-form-footer my-1 position-sticky d-flex justify-content-between" role="group"> <div class="submission-form-footer my-1 position-sticky d-flex justify-content-between" role="group">
<button (click)="this.openResetFormModal(this.resetFormModal)" class="btn btn-danger" type="button"> <button (click)="openResetFormModal(resetFormModal)" class="btn btn-danger" type="button">
<span><i class="fas fa-trash"></i>&nbsp;{{ 'submission.general.discard.submit' | translate }}</span> <span><i class="fas fa-trash"></i>&nbsp;{{ 'submission.general.discard.submit' | translate }}</span>
</button> </button>
<button class="btn btn-primary" type="submit"> <button class="btn btn-primary" type="submit">
<span><i class="fas fa-save"></i>&nbsp;{{ 'ldn-new-service.form.label.submit' | translate }}</span> <span><i class="fas fa-save"></i>&nbsp;{{ 'ldn-new-service.form.label.submit' | translate }}</span>
</button> </button>
</div> </div>
</form> </form>
</div> </div>
<ng-template #confirmModal> <ng-template #confirmModal>
<div class="modal-header"> <div class="modal-header">
<h4>{{'service.overview.create.modal' | translate }}</h4> <h4 *ngIf="!isNewForm">{{'service.overview.edit.modal' | translate }}</h4>
<h4 *ngIf="isNewForm">{{'service.overview.create.modal' | translate }}</h4>
<button (click)="closeModal()" aria-label="Close" <button (click)="closeModal()" aria-label="Close"
class="close" type="button"> class="close" type="button">
<span aria-hidden="true">×</span> <span aria-hidden="true">×</span>
@@ -343,23 +376,36 @@
</div> </div>
<div class="modal-body"> <div class="modal-body">
<span> <div *ngIf="!isNewForm">
{{ 'service.overview.edit.body' | translate }}
</div>
<span *ngIf="isNewForm">
{{ 'service.overview.create.body' | translate }} {{ 'service.overview.create.body' | translate }}
</span> </span>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button (click)="closeModal()" class="btn btn-danger mr-2 " <div *ngIf="!isNewForm">
id="delete-confirm">{{ 'service.refuse.create' | translate }} <button (click)="closeModal()" class="btn btn-danger mr-2"
</button> id="delete-confirm-edit">{{ 'service.detail.return' | translate }}
<button (click)="createService()" </button>
class="btn btn-primary">{{ 'service.confirm.create' | translate }} <button *ngIf="!isNewForm" (click)="patchService()"
</button> class="btn btn-primary">{{ 'service.detail.update' | translate }}
</div> </button>
</div>
<div *ngIf="isNewForm">
<button (click)="closeModal()" class="btn btn-danger mr-2 "
id="delete-confirm-new">{{ 'service.refuse.create' | translate }}
</button>
<button (click)="createService()"
class="btn btn-primary">{{ 'service.confirm.create' | translate }}
</button>
</div>
</div>
</ng-template> </ng-template>
<ng-template #resetFormModal> <ng-template #resetFormModal>
<div class="modal-header"> <div class="modal-header">
<h4 class="text-danger">{{'service.overview.reset-form.modal' | translate }}</h4> <h4 class="text-danger">{{'service.overview.reset-form.modal' | translate }}</h4>
<button (click)="closeModal()" aria-label="Close" <button (click)="closeModal()" aria-label="Close"
class="close" type="button"> class="close" type="button">
<span aria-hidden="true">×</span> <span aria-hidden="true">×</span>
@@ -370,17 +416,15 @@
<span> <span>
{{ 'service.overview.reset-form.body' | translate }} {{ 'service.overview.reset-form.body' | translate }}
</span> </span>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button (click)="closeModal()" <button (click)="closeModal()"
class="btn btn-primary mr-2" class="btn btn-primary"
id="reset-confirm">{{ 'service.overview.reset-form.reset-return' | translate }} id="reset-confirm">{{ 'service.overview.reset-form.reset-return' | translate }}
</button> </button>
<button (click)="resetFormAndLeave()" class="btn btn-danger" <button (click)="resetFormAndLeave()" class="mr-2 btn btn-danger"
id="reset-delete">{{ 'service.overview.reset-form.reset-confirm' | translate }} id="reset-delete">{{ 'service.overview.reset-form.reset-confirm' | translate }}
</button> </button>
</div> </div>
</ng-template> </ng-template>

View File

@@ -6,10 +6,6 @@ form {
position: relative; position: relative;
} }
label {
font-weight: bold;
}
input[type="text"], input[type="text"],
select { select {
max-width: 100%; max-width: 100%;
@@ -43,11 +39,6 @@ textarea {
margin-left: 10px; margin-left: 10px;
} }
.small-text {
font-size: 0.7em;
color: #888;
}
.status-checkbox { .status-checkbox {
margin-top: 5px; margin-top: 5px;
} }
@@ -110,8 +101,27 @@ textarea {
margin-top: 10px; margin-top: 10px;
} }
.small-text {
font-size: 0.7em;
color: #888;
}
.toggle-switch { .toggle-switch {
cursor: pointer; 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 { .submission-form-footer {
@@ -122,6 +132,9 @@ textarea {
z-index: var(--ds-submission-footer-z-index); z-index: var(--ds-submission-footer-z-index);
} }
.marked-for-deletion {
background-color: lighten($red, 30%);
}

View File

@@ -1,30 +1,30 @@
import {ComponentFixture, TestBed} from '@angular/core/testing'; import {ComponentFixture, TestBed} from '@angular/core/testing';
import {NgbDropdownModule, NgbModal} from '@ng-bootstrap/ng-bootstrap';
import {LdnServiceFormComponent} from './ldn-service-form.component'; import {LdnServiceFormComponent} from './ldn-service-form.component';
import {ChangeDetectorRef, EventEmitter} from '@angular/core';
import {FormBuilder, ReactiveFormsModule} from '@angular/forms'; import {FormBuilder, ReactiveFormsModule} from '@angular/forms';
import {RouterTestingModule} from '@angular/router/testing'; import {ActivatedRoute, Router} from '@angular/router';
import {NgbDropdownModule, NgbModal, NgbModalModule} from '@ng-bootstrap/ng-bootstrap';
import {TranslateModule, TranslateService} from '@ngx-translate/core'; 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 {LdnItemfiltersService} from '../ldn-services-data/ldn-itemfilters-data.service';
import {LdnServicesService} from '../ldn-services-data/ldn-services-data.service'; import {LdnServicesService} from '../ldn-services-data/ldn-services-data.service';
import {NotificationsService} from 'src/app/shared/notifications/notifications.service'; import {RouterStub} from '../../../shared/testing/router.stub';
import {Router} from '@angular/router'; import {MockActivatedRoute} from '../../../shared/mocks/active-router.mock';
import {RouterStub} from 'src/app/shared/testing/router.stub'; import {NotificationsServiceStub} from '../../../shared/testing/notifications-service.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 {of} from 'rxjs'; 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 component: LdnServiceFormComponent;
let fixture: ComponentFixture<LdnServiceFormComponent>; let fixture: ComponentFixture<LdnServiceFormComponent>;
let ldnServicesService: any; let ldnServicesService: any;
let ldnItemfiltersService: any; let ldnItemfiltersService: any;
let notificationsService: any; let cdRefStub: any;
let modalService: any;
const itemFiltersRdPL$ = createSuccessfulRemoteDataObject$(createPaginatedList([new Itemfilter()]));
const translateServiceStub = { const translateServiceStub = {
get: () => of('translated-text'), get: () => of('translated-text'),
@@ -32,53 +32,45 @@ describe('LdnServiceFormComponent', () => {
onLangChange: new EventEmitter(), onLangChange: new EventEmitter(),
onTranslationChange: new EventEmitter(), onTranslationChange: new EventEmitter(),
onDefaultLangChange: new EventEmitter() onDefaultLangChange: new EventEmitter()
}; };
beforeEach(async () => { beforeEach(async () => {
ldnItemfiltersService = jasmine.createSpyObj('ldnItemfiltersService', { ldnServicesService = {
findAll: jasmine.createSpy('findAll'), update: () => ({}),
}); };
ldnItemfiltersService = {
ldnServicesService = jasmine.createSpyObj('ldnServicesService', { findAll: () => of(['item1', 'item2']),
create: jasmine.createSpy('create'), };
}); cdRefStub = Object.assign({
detectChanges: () => fixture.detectChanges()
notificationsService = jasmine.createSpyObj('notificationsService', {
success: jasmine.createSpy('success'),
error: jasmine.createSpy('error'),
}); });
modalService = {
open: () => {/*comment*/
}
};
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [ imports: [ReactiveFormsModule, TranslateModule.forRoot(), NgbDropdownModule],
ReactiveFormsModule, declarations: [LdnServiceFormComponent],
RouterTestingModule,
NgbModalModule,
TranslateModule.forRoot(),
NgbDropdownModule
],
providers: [ providers: [
{provide: LdnItemfiltersService, useValue: ldnItemfiltersService},
{provide: LdnServicesService, useValue: ldnServicesService}, {provide: LdnServicesService, useValue: ldnServicesService},
{provide: NotificationsService, useValue: notificationsService}, {provide: LdnItemfiltersService, useValue: ldnItemfiltersService},
{provide: TranslateService, useValue: translateServiceStub},
{provide: Router, useValue: new RouterStub()}, {provide: Router, useValue: new RouterStub()},
{ {provide: ActivatedRoute, useValue: new MockActivatedRoute()},
provide: NgbModal, useValue: { {provide: ChangeDetectorRef, useValue: cdRefStub},
open: () => {/*comment*/ {provide: NgbModal, useValue: modalService},
} {provide: NotificationsService, useValue: NotificationsServiceStub},
} {provide: TranslateService, useValue: translateServiceStub},
}, {provide: PaginationService, useValue: {}},
FormBuilder FormBuilder,
], RouteService,
declarations: [LdnServiceFormComponent] provideMockStore({}),
]
}) })
.compileComponents(); .compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(LdnServiceFormComponent); fixture = TestBed.createComponent(LdnServiceFormComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
ldnItemfiltersService.findAll.and.returnValue(itemFiltersRdPL$);
fixture.detectChanges(); fixture.detectChanges();
}); });

View File

@@ -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 {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 {LdnServicesService} from '../ldn-services-data/ldn-services-data.service';
import {notifyPatterns} from '../ldn-services-patterns/ldn-service-coar-patterns'; 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 {animate, state, style, transition, trigger} from '@angular/animations';
import {getFirstCompletedRemoteData} from '../../../core/shared/operators'; import {NgbModal} from '@ng-bootstrap/ng-bootstrap';
import {RemoteData} from '../../../core/data/remote-data';
import {LdnService} from '../ldn-services-model/ldn-services.model';
import {NotificationsService} from '../../../shared/notifications/notifications.service'; import {NotificationsService} from '../../../shared/notifications/notifications.service';
import {TranslateService} from '@ngx-translate/core'; import {TranslateService} from '@ngx-translate/core';
import {PaginatedList} from '../../../core/data/paginated-list.model'; import {LdnService} from '../ldn-services-model/ldn-services.model';
import {Itemfilter} from '../ldn-services-model/ldn-service-itemfilters'; import {RemoteData} from 'src/app/core/data/remote-data';
import {Observable} from 'rxjs'; import {Operation} from 'fast-json-patch';
import {FindListOptions} from '../../../core/data/find-list-options.model'; import {getFirstCompletedRemoteData} from '../../../core/shared/operators';
import {PaginationComponentOptions} from '../../../shared/pagination/pagination-component-options.model';
import {LdnItemfiltersService} from '../ldn-services-data/ldn-itemfilters-data.service'; import {LdnItemfiltersService} from '../ldn-services-data/ldn-itemfilters-data.service';
import {NgbModal} from '@ng-bootstrap/ng-bootstrap'; import {Itemfilter} from '../ldn-services-model/ldn-service-itemfilters';
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 {NotifyServicePattern} from '../ldn-services-model/ldn-service-patterns.model';
/** /**
* Angular component representing the form for creating or editing LDN services. * Component for editing LDN service through a form that allows to create or edit the properties of a service
* This component handles the creation, validation, and submission of LDN service data.
*/ */
@Component({ @Component({
selector: 'ds-ldn-service-form', 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; formModel: FormGroup;
@ViewChild('confirmModal', {static: true}) confirmModal: TemplateRef<any>; @ViewChild('confirmModal', {static: true}) confirmModal: TemplateRef<any>;
@ViewChild('resetFormModal', {static: true}) resetFormModal: TemplateRef<any>; @ViewChild('resetFormModal', {static: true}) resetFormModal: TemplateRef<any>;
public inboundPatterns: string[] = notifyPatterns; public inboundPatterns: string[] = notifyPatterns;
public outboundPatterns: string[] = notifyPatterns; public outboundPatterns: string[] = notifyPatterns;
public isNewForm: boolean;
itemfiltersRD$: Observable<RemoteData<PaginatedList<Itemfilter>>>; itemfiltersRD$: Observable<RemoteData<PaginatedList<Itemfilter>>>;
config: FindListOptions = Object.assign(new FindListOptions(), { config: FindListOptions = Object.assign(new FindListOptions(), {
elementsPerPage: 20 elementsPerPage: 20
}); });
pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
id: 'po',
pageSize: 20
});
@Input() public name: string; @Input() public name: string;
@Input() public description: string; @Input() public description: string;
@Input() public url: string; @Input() public url: string;
@Input() public score: string;
@Input() public ldnUrl: string; @Input() public ldnUrl: string;
@Input() public score: number;
@Input() public inboundPattern: string; @Input() public inboundPattern: string;
@Input() public outboundPattern: string; @Input() public outboundPattern: string;
@Input() public constraint: string; @Input() public constraint: string;
@@ -61,82 +71,75 @@ export class LdnServiceFormComponent implements OnInit {
@Input() public headerKey: string; @Input() public headerKey: string;
@Output() submitForm: EventEmitter<any> = new EventEmitter(); @Output() submitForm: EventEmitter<any> = new EventEmitter();
@Output() cancelForm: EventEmitter<any> = new EventEmitter(); @Output() cancelForm: EventEmitter<any> = new EventEmitter();
markedForDeletionInboundPattern: number[] = [];
markedForDeletionOutboundPattern: number[] = [];
selectedOutboundPatterns: string[]; selectedOutboundPatterns: string[];
selectedInboundPatterns: string[]; selectedInboundPatterns: string[];
selectedInboundItemfilters: string[]; selectedInboundItemfilters: string[];
selectedOutboundItemfilters: string[]; selectedOutboundItemfilters: string[];
hasInboundPattern: boolean; protected serviceId: string;
hasOutboundPattern: boolean; private deletedInboundPatterns: number[] = [];
isScoreValid: boolean; private deletedOutboundPatterns: number[] = [];
private modalRef: any; private modalRef: any;
private service: LdnService;
private selectPatternDefaultLabeli18Key = 'ldn-service.form.label.placeholder.default-select'; private selectPatternDefaultLabeli18Key = 'ldn-service.form.label.placeholder.default-select';
private routeSubscription: Subscription;
constructor( constructor(
private ldnServicesService: LdnServicesService, protected ldnServicesService: LdnServicesService,
private ldnItemfiltersService: LdnItemfiltersService, private ldnItemfiltersService: LdnItemfiltersService,
private formBuilder: FormBuilder, private formBuilder: FormBuilder,
private router: Router, private router: Router,
private notificationsService: NotificationsService, private route: ActivatedRoute,
private translateService: TranslateService,
private cdRef: ChangeDetectorRef, private cdRef: ChangeDetectorRef,
protected modalService: NgbModal, protected modalService: NgbModal,
private notificationService: NotificationsService,
private translateService: TranslateService,
protected paginationService: PaginationService
) { ) {
this.formModel = this.formBuilder.group({ this.formModel = this.formBuilder.group({
enabled: true,
id: [''], id: [''],
name: ['', Validators.required], name: ['', Validators.required],
description: [''], description: [''],
url: ['', Validators.required], url: ['', Validators.required],
score: ['', [Validators.required, Validators.pattern('^0*(\.[0-9]+)?$|^1(\.0+)?$')]],
ldnUrl: ['', Validators.required], ldnUrl: ['', Validators.required],
inboundPattern: [''], score: ['', [Validators.required, Validators.pattern('^0*(\.[0-9]+)?$|^1(\.0+)?$')]], inboundPattern: [''],
outboundPattern: [''], outboundPattern: [''],
constraintPattern: [''], constraintPattern: [''],
notifyServiceInboundPatterns: this.formBuilder.array([this.createInboundPatternFormGroup()]), enabled: [''],
notifyServiceOutboundPatterns: this.formBuilder.array([this.createOutboundPatternFormGroup()]),
type: LDN_SERVICE.value, type: LDN_SERVICE.value,
}); });
} }
ngOnInit(): void { ngOnInit(): void {
this.setItemfilters(); 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() { setItemfilters() {
this.itemfiltersRD$ = this.ldnItemfiltersService.findAll().pipe( this.itemfiltersRD$ = this.ldnItemfiltersService.findAll().pipe(
getFirstCompletedRemoteData()); 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, * Handles the creation of an LDN service by retrieving and validating form fields,
* and submitting the form data to the LDN services endpoint. * 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 hasInboundPattern = this.checkPatterns(this.formModel.get('notifyServiceInboundPatterns') as FormArray);
const hasOutboundPattern = this.checkPatterns(this.formModel.get('notifyServiceOutboundPatterns') 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(); this.closeModal();
return; return;
} }
if (!hasInboundPattern || !hasOutboundPattern) { if (!hasInboundPattern || !hasOutboundPattern) {
this.notificationsService.warning(this.translateService.get('ldn-service-notification.created.warning.title')); this.notificationService.warning(this.translateService.get('ldn-service-notification.created.warning.title'));
this.closeModal(); this.closeModal();
return; return;
} }
@@ -180,7 +183,7 @@ export class LdnServiceFormComponent implements OnInit {
return rest; return rest;
}); });
const values = this.formModel.value; const values = {...this.formModel.value, enabled: true};
const ldnServiceData = this.ldnServicesService.create(values); const ldnServiceData = this.ldnServicesService.create(values);
@@ -188,13 +191,13 @@ export class LdnServiceFormComponent implements OnInit {
getFirstCompletedRemoteData() getFirstCompletedRemoteData()
).subscribe((rd: RemoteData<LdnService>) => { ).subscribe((rd: RemoteData<LdnService>) => {
if (rd.hasSucceeded) { 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.translateService.get('ldn-service-notification.created.success.body'));
this.sendBack(); this.sendBack();
this.closeModal(); this.closeModal();
} else { } 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.translateService.get('ldn-service-notification.created.failure.body'));
this.closeModal(); this.closeModal();
} }
@@ -218,23 +221,113 @@ 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() { fetchServiceData(serviceId: string): void {
this.sendBack(); this.ldnServicesService.findById(serviceId).pipe(
this.closeModal(); getFirstCompletedRemoteData()
).subscribe(
(data: RemoteData<LdnService>) => {
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() { filterPatternObjectsAndPickLabel(formArrayName: string, isOutbound: boolean) {
this.modalRef.close(); const PatternsArray = this.formModel.get(formArrayName) as FormArray;
this.cdRef.detectChanges(); 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
*/
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() { addInboundPattern() {
const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray;
@@ -242,18 +335,7 @@ export class LdnServiceFormComponent implements OnInit {
} }
/** /**
* Removes the inbound pattern form group at the specified index from the notifyServiceInboundPatterns form array. * Adds a new outbound pattern form group to the array of outbound patterns in the form
*
* @param {number} index - The index of the inbound pattern form group to remove.
* @memberof LdnServiceFormComponent
*/
removeInboundPattern(index: number) {
const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray;
notifyServiceInboundPatternsArray.removeAt(index);
}
/**
* Adds a new outbound pattern form group to the notifyServiceOutboundPatterns form array.
*/ */
addOutboundPattern() { addOutboundPattern() {
const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; 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. * Selects an outbound pattern by updating its values based on the provided pattern value and index
* * @param patternValue - The selected pattern value
* @param {number} index - The index of the outbound pattern form group to remove. * @param index - The index of the outbound pattern in the array
*/ */
removeOutboundPattern(index: number) { selectOutboundPattern(patternValue: string, index: number): void {
const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; const patternArray = (this.formModel.get('notifyServiceOutboundPatterns') as FormArray);
notifyServiceOutboundPatternsArray.removeAt(index); 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. * Selects an outbound item filter by updating its value based on the provided filter value and index
* * @param filterValue - The selected filter value
* @param {number} i - The index of the 'automatic' control to toggle. * @param index - The index of the inbound pattern in the array
* @memberof LdnServiceFormComponent */
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) { toggleAutomatic(i: number) {
const automaticControl = this.formModel.get(`notifyServiceInboundPatterns.${i}.automatic`); 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. * Toggles the enabled status of the LDN service by sending a patch request
*
* @param {string} patternValue - The selected pattern value.
* @param {number} index - The index of the outbound pattern in the form array.
*/ */
selectOutboundPattern(patternValue: string, index: number): void { toggleEnabled() {
const patternArray = (this.formModel.get('notifyServiceOutboundPatterns') as FormArray); const newStatus = !this.formModel.get('enabled').value;
patternArray.controls[index].patchValue({pattern: patternValue});
patternArray.controls[index].patchValue({patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternValue + '.label')});
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. * Closes the modal
*
* @param {string} patternValue - The selected pattern value.
* @param {number} index - The index of the inbound pattern in the form array.
*/ */
selectInboundPattern(patternValue: string, index: number): void { closeModal() {
const patternArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray); this.modalRef.close();
patternArray.controls[index].patchValue({pattern: patternValue}); this.cdRef.detectChanges();
patternArray.controls[index].patchValue({patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternValue + '.label')});
} }
/** /**
* Selects an inbound item filter for a specific index in the form array. * Opens a confirmation modal with the specified content
* * @param content - The content to be displayed in the modal
* @param {string} filterValue - The selected item filter value.
* @param {number} index - The index of the inbound item filter in the form array.
*/ */
selectInboundItemFilter(filterValue: string, index: number): void { openConfirmModal(content) {
const filterArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray); this.modalRef = this.modalService.open(content);
filterArray.controls[index].patchValue({constraint: filterValue});
} }
/** /**
* Selects an outbound item filter for a specific index in the form array. * Opens a reset form modal with the specified content
* * @param content - The content to be displayed in the modal
* @param {string} filterValue - The selected item filter value.
* @param {number} index - The index of the outbound item filter in the form array.
*/ */
selectOutboundItemFilter(filterValue: string, index: number) { openResetFormModal(content) {
const filterArray = (this.formModel.get('notifyServiceOutboundPatterns') as FormArray); this.modalRef = this.modalService.open(content);
filterArray.controls[index].patchValue({constraint: filterValue});
} }
/** /**
* Sends the user back to the LDN services list. * 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<LdnService>) => {
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() { private sendBack() {
this.router.navigateByUrl('admin/ldn/services'); this.router.navigateByUrl('admin/ldn/services');
} }
/** /**
* Creates a form group for an outbound pattern in the notifyServiceOutboundPatterns form array. * Creates a form group for outbound patterns
* * @returns The form group for outbound patterns
* @private
* @returns {FormGroup} - The created form group.
*/ */
private createOutboundPatternFormGroup(): FormGroup { private createOutboundPatternFormGroup(): FormGroup {
return this.formBuilder.group({ const outBoundFormGroup = {
pattern: [''], pattern: '',
constraint: [''],
patternLabel: this.translateService.instant(this.selectPatternDefaultLabeli18Key), patternLabel: this.translateService.instant(this.selectPatternDefaultLabeli18Key),
constraint: '',
}
if(!this.isNewForm) {
outBoundFormGroup['isNew'] = true;
}
return this.formBuilder.group(outBoundFormGroup);
}
/**
* Creates a form group for inbound patterns
* @returns The form group for inbound patterns
*/
private createInboundPatternFormGroup(): FormGroup {
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: '',
}); });
} }
/** /**
* Creates a form group for an inbound pattern in the notifyServiceInboundPatterns form array. * Initializes an existing form group for inbound patterns
* * @returns The initialized form group for inbound patterns
* @private
* @returns {FormGroup} - The created form group.
*/ */
private createInboundPatternFormGroup(): FormGroup { private initializeInboundPatternFormGroup(): FormGroup {
return this.formBuilder.group({ return this.formBuilder.group({
pattern: [''], pattern: '',
constraint: [''], patternLabel: '',
automatic: false, constraint: '',
patternLabel: this.translateService.instant(this.selectPatternDefaultLabeli18Key), automatic: '',
}); });
} }
} }

View File

@@ -1 +0,0 @@
<ds-ldn-service-form></ds-ldn-service-form>

View File

@@ -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<LdnServiceNewComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [LdnServiceNewComponent]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(LdnServiceNewComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -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 {
}