From 24a0af1e9a32002a2d7c7a1c667a401a41f0a321 Mon Sep 17 00:00:00 2001 From: Sondissimo Date: Mon, 18 Sep 2023 13:26:10 +0200 Subject: [PATCH 1/6] CST-11048 First commit --- .../admin-ldn-services-routing.module.ts | 30 ++++ .../admin-ldn-services.module.ts | 23 +++ .../ldn-service-form.component.html | 96 ++++++++++++ .../ldn-service-form.component.scss | 51 +++++++ .../ldn-service-form.component.spec.ts | 25 +++ .../ldn-service-form.component.ts | 142 ++++++++++++++++++ .../ldn-service-new.component.html | 1 + .../ldn-service-new.component.scss | 0 .../ldn-service-new.component.spec.ts | 25 +++ .../ldn-service-new.component.ts | 28 ++++ .../ldnServicesRD$-mock.ts | 73 +++++++++ .../ldn-services-data.service.ts | 90 +++++++++++ .../ldn-services-directory.component.html | 85 +++++++++++ .../ldn-services-directory.component.scss | 0 .../ldn-services-directory.component.spec.ts | 25 +++ .../ldn-services-directory.component.ts | 105 +++++++++++++ .../ldn-services-guard.service.ts | 29 ++++ .../ldn-services.guard.spec.ts | 17 +++ .../ldn-service-constraint.model.ts | 26 ++++ .../ldn-service-status.model.ts | 8 + .../ldn-service.resource-type.ts | 9 ++ .../ldn-services-model/ldn-services.model.ts | 58 +++++++ .../service-constrain-type.model.ts | 10 ++ .../ldn-service-coar-patterns.ts | 73 +++++++++ .../ldn-directory.service.spec.ts | 17 +++ .../ldn-directory.service.ts | 54 +++++++ .../ldn-service-bulk-delete.service.spec.ts | 17 +++ .../ldn-service-bulk-delete.service.ts | 117 +++++++++++++++ src/app/admin/admin-routing-paths.ts | 2 + src/app/admin/admin-routing.module.ts | 14 +- src/app/core/core.module.ts | 4 +- src/assets/i18n/en.json5 | 45 ++++++ 32 files changed, 1297 insertions(+), 2 deletions(-) create mode 100644 src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts create mode 100644 src/app/admin/admin-ldn-services/admin-ldn-services.module.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html create mode 100644 src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss create mode 100644 src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.spec.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.html create mode 100644 src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.scss create mode 100644 src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.spec.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html create mode 100644 src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.scss create mode 100644 src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services-guard.service.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services.guard.spec.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-constraint.model.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-status.model.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-model/ldn-services.model.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-model/service-constrain-type.model.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-patterns/ldn-service-coar-patterns.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.spec.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service.spec.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service.ts diff --git a/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts b/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts new file mode 100644 index 0000000000..740cd39621 --- /dev/null +++ b/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts @@ -0,0 +1,30 @@ +import { NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; +import { I18nBreadcrumbResolver } from 'src/app/core/breadcrumbs/i18n-breadcrumb.resolver'; +import { LdnServicesOverviewComponent } from './ldn-services-directory/ldn-services-directory.component'; +import { LdnServicesGuard } from './ldn-services-guard/ldn-services-guard.service'; +import { LdnServiceNewComponent } from './ldn-service-new/ldn-service-new.component'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + { + path: '', + pathMatch: 'full', + component: LdnServicesOverviewComponent, + resolve: { breadcrumb: I18nBreadcrumbResolver }, + data: { title: 'ldn-registered-services.title', breadcrumbKey: 'ldn-registered-services.new' }, + canActivate: [LdnServicesGuard] + }, + { + path: 'new', + resolve: { breadcrumb: I18nBreadcrumbResolver }, + component: LdnServiceNewComponent, + data: { title: 'ldn-register-new-service.title', breadcrumbKey: 'ldn-register-new-service' } + }, + ]), + ] +}) +export class AdminLdnServicesRoutingModule { + +} diff --git a/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts b/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts new file mode 100644 index 0000000000..c03c16109e --- /dev/null +++ b/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts @@ -0,0 +1,23 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { AdminLdnServicesRoutingModule } from './admin-ldn-services-routing.module'; +import { LdnServicesOverviewComponent } from './ldn-services-directory/ldn-services-directory.component'; +import { SharedModule } from '../../shared/shared.module'; +import { LdnServiceNewComponent } from './ldn-service-new/ldn-service-new.component'; +import { LdnServiceFormComponent } from './ldn-service-form/ldn-service-form.component'; + + + +@NgModule({ + imports: [ + CommonModule, + SharedModule, + AdminLdnServicesRoutingModule, + ], + declarations: [ + LdnServicesOverviewComponent, + LdnServiceNewComponent, + LdnServiceFormComponent, + ] +}) +export class AdminLdnServicesModule { } diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html new file mode 100644 index 0000000000..64146b31a1 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html @@ -0,0 +1,96 @@ +
+ +
+ + + + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + + + + + + +
+ + + + + +
+ + - Remove + +
+ +
+ + + Add more + + +
+ + + + + + + + - Remove + + + +
+ + + Add more + + + +
diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss new file mode 100644 index 0000000000..53bc21d1b3 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss @@ -0,0 +1,51 @@ + +form { + display: flex; + flex-direction: column; + align-items: flex-start; + margin: 0 auto; + max-width: 600px; + font-size: 14px; +} + + +.form-group input[type="text"], +.form-group select { + max-width: 100%; + width: 100%; + padding: 8px; + margin-bottom: 5px; + box-sizing: border-box; + font-size: 14px; +} + + +.description { + height: 9em; + width: 100%; +} + + +.form-group select { + position: relative; + z-index: 1; +} + + +.form-group select option { + font-weight: bold; +} + +.add-pattern-link{ + color: #0048ff; + cursor: pointer; + margin-left: 10px; +} +.remove-pattern-link{ + color: #e34949; + cursor: pointer; + margin-left: 10px; +} + + + diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.spec.ts b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.spec.ts new file mode 100644 index 0000000000..3ae834d642 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { LdnServiceFormComponent } from './ldn-service-form.component'; + +describe('LdnServiceFormComponent', () => { + let component: LdnServiceFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ LdnServiceFormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(LdnServiceFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts new file mode 100644 index 0000000000..b17cc6902d --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts @@ -0,0 +1,142 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { FormBuilder, FormGroup, Validators, FormArray } from '@angular/forms'; +import { HttpClient, HttpHeaders } from '@angular/common/http'; +import { Router } from '@angular/router'; + +import { LdnServicesService } from '../ldn-services-data/ldn-services-data.service'; +import { LdnServiceConstraint } from '../ldn-services-model/ldn-service-constraint.model'; +import { notifyPatterns } from '../ldn-services-patterns/ldn-service-coar-patterns'; +import { LdnDirectoryService } from '../ldn-services-services/ldn-directory.service'; +import { LDN_SERVICE } from '../ldn-services-model/ldn-service.resource-type'; + +@Component({ + selector: 'ds-ldn-service-form', + templateUrl: './ldn-service-form.component.html', + styleUrls: ['./ldn-service-form.component.scss'], +}) +export class LdnServiceFormComponent implements OnInit { + formModel: FormGroup; + + showItemFilterDropdown = false; + + public inboundPatterns: object[] = notifyPatterns; + public outboundPatterns: object[] = notifyPatterns; + public itemFilterList: LdnServiceConstraint[]; + additionalOutboundPatterns: FormGroup[] = []; + additionalInboundPatterns: FormGroup[] = []; + + @Input() public name: string; + @Input() public description: string; + @Input() public url: string; + @Input() public ldnUrl: string; + @Input() public inboundPattern: string; + @Input() public outboundPattern: string; + @Input() public constraint: string; + @Input() public automatic: boolean; + + @Input() public headerKey: string; + + constructor( + private ldnServicesService: LdnServicesService, + private ldnDirectoryService: LdnDirectoryService, + private formBuilder: FormBuilder, + private http: HttpClient, + private router: Router + ) { + + this.formModel = this.formBuilder.group({ + id: [''], + name: ['', Validators.required], + description: ['', Validators.required], + url: ['', Validators.required], + ldnUrl: ['', Validators.required], + inboundPattern: [''], + outboundPattern: [''], + constraintPattern: [''], + notifyServiceInboundPatterns: this.formBuilder.array([this.createInboundPatternFormGroup()]), + notifyServiceOutboundPatterns: this.formBuilder.array([this.createOutboundPatternFormGroup()]), + type: LDN_SERVICE.value, + }); + } + + ngOnInit(): void { + this.ldnDirectoryService.getItemFilters().subscribe((itemFilters) => { + console.log(itemFilters); + this.itemFilterList = itemFilters._embedded.itemfilters.map((filter: { id: string; }) => ({ + name: filter.id + })); + console.log(this.itemFilterList); + }); + + } + + submitForm() { + this.formModel.removeControl('inboundPattern'); + this.formModel.removeControl('outboundPattern'); + this.formModel.removeControl('constraintPattern'); + console.log('JSON Data:', this.formModel.value); + + const apiUrl = 'http://localhost:8080/server/api/ldn/ldnservices'; + + this.http.post(apiUrl, this.formModel.value ).subscribe( + (response) => { + console.log('Service created successfully:', response); + this.formModel.reset(); + this.sendBack(); + }, + (error) => { + console.error('Error creating service:', error); + } + ); + } + + private validateForm(form: FormGroup): boolean { + let valid = true; + Object.keys(form.controls).forEach((key) => { + if (form.controls[key].invalid) { + form.controls[key].markAsDirty(); + valid = false; + } + }); + return valid; + } + + private sendBack() { + this.router.navigateByUrl('admin/ldn/services'); + } + + addInboundPattern() { + const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; + notifyServiceInboundPatternsArray.push(this.createInboundPatternFormGroup()); + } + + removeInboundPattern(patternGroup: FormGroup) { + const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; + notifyServiceInboundPatternsArray.removeAt(notifyServiceInboundPatternsArray.controls.indexOf(patternGroup)); + } + + addOutboundPattern() { + const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; + notifyServiceOutboundPatternsArray.push(this.createOutboundPatternFormGroup()); + } + + removeOutboundPattern(patternGroup: FormGroup) { + const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; + notifyServiceOutboundPatternsArray.removeAt(notifyServiceOutboundPatternsArray.controls.indexOf(patternGroup)); + } + + private createOutboundPatternFormGroup(): FormGroup { + return this.formBuilder.group({ + pattern: [''], + constraint: [''], + }); + } + + private createInboundPatternFormGroup(): FormGroup { + return this.formBuilder.group({ + pattern: [''], + constraint: [''], + automatic: [true] + }); + } +} diff --git a/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.html b/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.html new file mode 100644 index 0000000000..9567cb1abe --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.html @@ -0,0 +1 @@ + diff --git a/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.scss b/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.spec.ts b/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.spec.ts new file mode 100644 index 0000000000..4994823004 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { LdnServiceNewComponent } from './ldn-service-new.component'; + +describe('LdnServiceNewComponent', () => { + let component: LdnServiceNewComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ LdnServiceNewComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(LdnServiceNewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.ts b/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.ts new file mode 100644 index 0000000000..daf1653cd1 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-new/ldn-service-new.component.ts @@ -0,0 +1,28 @@ +import { Component, OnInit } from '@angular/core'; +import { Observable } from 'rxjs'; +import { LdnService } from "../ldn-services-model/ldn-services.model"; +import { ActivatedRoute } from "@angular/router"; +import { ProcessDataService } from "../../../core/data/processes/process-data.service"; +import { LinkService } from "../../../core/cache/builders/link.service"; +import { getFirstSucceededRemoteDataPayload } from "../../../core/shared/operators"; + +@Component({ + selector: 'ds-ldn-service-new', + templateUrl: './ldn-service-new.component.html', + styleUrls: ['./ldn-service-new.component.scss'] +}) +export class LdnServiceNewComponent implements OnInit { + /** + * Emits preselected process if there is one + */ + ldnService$?: Observable; + + constructor(private route: ActivatedRoute, private processService: ProcessDataService, private linkService: LinkService) { + } + + /** + * If there's an id parameter, use this the process with this identifier as presets for the form + */ + ngOnInit() { + } +} diff --git a/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts b/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts new file mode 100644 index 0000000000..fccb374b5f --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts @@ -0,0 +1,73 @@ +import { LdnService } from '../ldn-services-model/ldn-services.model'; +import { LDN_SERVICE } from '../ldn-services-model/ldn-service.resource-type'; +import { RemoteData } from '../../../core/data/remote-data'; +import { PaginatedList } from '../../../core/data/paginated-list.model'; +import { Observable, of } from 'rxjs'; +// Create a mock data object for a single LDN notify service +export const mockLdnService: LdnService = { + id: 1, + name: 'Service Name', + description: 'Service Description', + url: 'Service URL', + ldnUrl: 'Service LDN URL', + notifyServiceInboundPatterns: [ + { + pattern: 'patternA', + constraint: 'itemFilterA', + automatic: false, + }, + { + pattern: 'patternB', + constraint: 'itemFilterB', + automatic: true, + }, + ], + notifyServiceOutboundPatterns: [ + { + pattern: 'patternC', + constraint: 'itemFilterC', + }, + ], + type: LDN_SERVICE, + _links: { + self: { + href: 'http://localhost/api/ldn/ldnservices/1', + }, + }, +}; + + + + +const mockLdnServices = { + payload: { + elementsPerPage: 20, + totalPages: 1, + totalElements: 1, + currentPage: 1, + first: undefined, + prev: undefined, + next: undefined, + last: undefined, + page: [mockLdnService], + type: LDN_SERVICE, + self: undefined, + getPageLength: function() { + return this.page.length; + }, + _links: { + self: { + href: 'http://localhost/api/ldn/ldnservices/1', + }, + page: [], + }, + }, + hasSucceeded: true, + msToLive: 0, +}; + + + + +// Create a mock ldnServicesRD$ observable +export const mockLdnServicesRD$: Observable>> = of((mockLdnServices as unknown) as RemoteData>); diff --git a/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts new file mode 100644 index 0000000000..43755adb3c --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts @@ -0,0 +1,90 @@ + import { Injectable } from '@angular/core'; +import { dataService } from '../../../core/data/base/data-service.decorator'; +import { LDN_SERVICE } from '../ldn-services-model/ldn-service.resource-type'; +import { IdentifiableDataService } from '../../../core/data/base/identifiable-data.service'; +import { FindAllData, FindAllDataImpl } from '../../../core/data/base/find-all-data'; +import { DeleteData, DeleteDataImpl } from '../../../core/data/base/delete-data'; +import { RequestService } from '../../../core/data/request.service'; +import { RemoteDataBuildService } from '../../../core/cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../../../core/cache/object-cache.service'; +import { HALEndpointService } from '../../../core/shared/hal-endpoint.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { FindListOptions } from '../../../core/data/find-list-options.model'; +import { FollowLinkConfig } from '../../../shared/utils/follow-link-config.model'; +import { Observable } from 'rxjs'; +import { RemoteData } from '../../../core/data/remote-data'; +import { PaginatedList } from '../../../core/data/paginated-list.model'; +import { NoContent } from '../../../core/shared/NoContent.model'; +import { map, take } from 'rxjs/operators'; +import { URLCombiner } from '../../../core/url-combiner/url-combiner'; +import { MultipartPostRequest } from '../../../core/data/request.models'; +import { RestRequest } from '../../../core/data/rest-request.model'; +import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; +import { hasValue } from '../../../shared/empty.util'; + +import { LdnService } from '../ldn-services-model/ldn-services.model'; +import { LdnServiceConstraint } from '../ldn-services-model/ldn-service-constraint.model'; + +@Injectable() +@dataService(LDN_SERVICE) +export class LdnServicesService extends IdentifiableDataService implements FindAllData, DeleteData { + private findAllData: FindAllDataImpl; // Corrected the type + private deleteData: DeleteDataImpl; // Corrected the type + + constructor( + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected notificationsService: NotificationsService, + ) { + super('ldnservices', requestService, rdbService, objectCache, halService); + + this.findAllData = new FindAllDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive); + this.deleteData = new DeleteDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, notificationsService, this.responseMsToLive, this.constructIdEndpoint); + } + + findAll(options?: FindListOptions, useCachedVersionIfAvailable?: boolean, reRequestOnStale?: boolean, ...linksToFollow: FollowLinkConfig[]): Observable>> { + return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + } + + public delete(objectId: string, copyVirtualMetadata?: string[]): Observable> { + return this.deleteData.delete(objectId, copyVirtualMetadata); + } + + public deleteByHref(href: string, copyVirtualMetadata?: string[]): Observable> { + return this.deleteData.deleteByHref(href, copyVirtualMetadata); + } + + public invoke(serviceName: string, parameters: LdnServiceConstraint[], files: File[]): Observable> { + const requestId = this.requestService.generateRequestId(); + this.getBrowseEndpoint().pipe( + take(1), + map((endpoint: string) => new URLCombiner(endpoint, serviceName, 'processes').toString()), + map((endpoint: string) => { + const body = this.getInvocationFormData(parameters, files); + return new MultipartPostRequest(requestId, endpoint, body); + }) + ).subscribe((request: RestRequest) => this.requestService.send(request)); + + return this.rdbService.buildFromRequestUUID(requestId); + } + + private getInvocationFormData(constrain: LdnServiceConstraint[], files: File[]): FormData { + const form: FormData = new FormData(); + form.set('properties', JSON.stringify(constrain)); + files.forEach((file: File) => { + form.append('file', file); + }); + return form; + } + + public ldnServiceWithNameExistsAndCanExecute(scriptName: string): Observable { + return this.findById(scriptName).pipe( + getFirstCompletedRemoteData(), + map((rd: RemoteData) => { + return hasValue(rd.payload); + }), + ); + } +} diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html new file mode 100644 index 0000000000..bd2ec0d418 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html @@ -0,0 +1,85 @@ +
+ {{ldnServicesRD$ | async | json }} +
+

{{'ldn-registered-services.title' | translate}}

+
+
+ + + + +
+ +
+ + + + + + + + + + + + + + + + +
{{'service.overview.table.name' | translate}}{{'service.overview.table.description' | translate}}{{'service.overview.table.status' | translate}}{{'service.overview.table.actions' | translate}}
{{ldnService.id}}{{ldnService.description}} + +
+
+
+
+ + + +
+ + + + +
+ + +
+ diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.scss b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts new file mode 100644 index 0000000000..bedcabb271 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ServicesDirectoryComponent } from './services-directory.component'; + +describe('ServicesDirectoryComponent', () => { + let component: ServicesDirectoryComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ServicesDirectoryComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ServicesDirectoryComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts new file mode 100644 index 0000000000..e8c81ea873 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts @@ -0,0 +1,105 @@ +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { LdnDirectoryService } from '../ldn-services-services/ldn-directory.service'; +import { Observable, Subscription } from 'rxjs'; +import { RemoteData } from '../../../core/data/remote-data'; +import { PaginatedList } from '../../../core/data/paginated-list.model'; +import { FindListOptions } from '../../../core/data/find-list-options.model'; +import { LdnService } from '../ldn-services-model/ldn-services.model'; +import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; +import { switchMap } from 'rxjs/operators'; +import { LdnServicesService } from 'src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service'; +import { PaginationService } from 'src/app/core/pagination/pagination.service'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { LdnServicesBulkDeleteService } from 'src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service'; +import { hasValue } from '../../../shared/empty.util'; +import { HttpClient } from '@angular/common/http'; + +@Component({ + selector: 'ds-ldn-services-directory', + templateUrl: './ldn-services-directory.component.html', + styleUrls: ['./ldn-services-directory.component.scss'], +}) +export class LdnServicesOverviewComponent implements OnInit, OnDestroy { + + ldnServicesRD$: Observable>>; + config: FindListOptions = Object.assign(new FindListOptions(), { + elementsPerPage: 20 + }); + pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { + id: 'po', + pageSize: 20 + }); + private modalRef: any; + isProcessingSub: Subscription; + + constructor( + protected processLdnService: LdnServicesService, + protected paginationService: PaginationService, + protected modalService: NgbModal, + public ldnServicesBulkDeleteService: LdnServicesBulkDeleteService, + public ldnDirectoryService: LdnDirectoryService, + private http: HttpClient + ) {} + + ngOnInit(): void { + this.setLdnServices(); + this.ldnDirectoryService.listLdnServices(); + this.searchByLdnUrl(); + } + + setLdnServices() { + debugger; + this.ldnServicesRD$ = this.paginationService.getFindListOptions(this.pageConfig.id, this.config).pipe( + switchMap((config) => this.processLdnService.findAll(config, true, false)) + ); + console.log() + } + + ngOnDestroy(): void { + this.paginationService.clearPagination(this.pageConfig.id); + if (hasValue(this.isProcessingSub)) { + this.isProcessingSub.unsubscribe(); + } + } + + openDeleteModal(content) { + this.modalRef = this.modalService.open(content); + } + + closeModal() { + this.modalRef.close(); + } + + + findByLdnUrl(): Observable { + const url = 'http://localhost:8080/server/api/ldn/ldnservices'; + + return this.http.get(url); + } + + searchByLdnUrl(): void { + this.findByLdnUrl().subscribe( + (response) => { + console.log('Search results:', response); + }, + (error) => { + console.error('Error:', error); + } + ); + } + + deleteSelected() { + this.ldnServicesBulkDeleteService.deleteSelectedLdnServices(); + + if (hasValue(this.isProcessingSub)) { + this.isProcessingSub.unsubscribe(); + } + this.isProcessingSub = this.ldnServicesBulkDeleteService.isProcessing$() + .subscribe((isProcessing) => { + if (!isProcessing) { + this.closeModal(); + this.setLdnServices(); + } + }); + } +} diff --git a/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services-guard.service.ts b/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services-guard.service.ts new file mode 100644 index 0000000000..85235b4370 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services-guard.service.ts @@ -0,0 +1,29 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root' +}) +export class LdnServicesGuard implements CanActivate { + + constructor( + //private notifyInfoService: NotifyInfoService, + private router: Router + ) {} + canActivate( + route: ActivatedRouteSnapshot, + state: RouterStateSnapshot): Observable | Promise | boolean | UrlTree { + return true; + /*return this.notifyInfoService.isCoarConfigEnabled().pipe( + map(coarLdnEnabled => { + if (coarLdnEnabled) { + return true; + } else { + return this.router.parseUrl('/404'); + } + }) + );*/ + } +} diff --git a/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services.guard.spec.ts b/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services.guard.spec.ts new file mode 100644 index 0000000000..30af31cab8 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-guard/ldn-services.guard.spec.ts @@ -0,0 +1,17 @@ +import { TestBed } from '@angular/core/testing'; + +import { LdnServicesGuard } from './ldn-services-guard.service'; + +describe('LdnServicesGuard', () => { + let guard: LdnServicesGuard; + + beforeEach(() => { + TestBed.configureTestingModule({}); + guard = TestBed.inject(LdnServicesGuard); + }); + + it('should be created', () => { + // @ts-ignore + expect(guard).toBeTruthy(); + }); +}); diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-constraint.model.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-constraint.model.ts new file mode 100644 index 0000000000..704a3e7d8c --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-constraint.model.ts @@ -0,0 +1,26 @@ + +/** + * A cosntrain that can be used when running a service + */ +export class LdnServiceConstraint { + /** + * The name of the constrain + */ + name: string; + + /** + * The value of the constrain + */ + value: string; +} + +export const EndorsmentConstrain = [ + { + name: 'Type 1 Item', + value: 'Type1' + }, + { + name: 'Type 2 Item', + value: 'Type2' + }, +]; diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-status.model.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-status.model.ts new file mode 100644 index 0000000000..040e4d37b8 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-status.model.ts @@ -0,0 +1,8 @@ +/** + * List of services statuses + */ +export enum LdnServiceStatus { + UNKOWN, + DISABLED, + ENABLED, +} diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts new file mode 100644 index 0000000000..c00d241ee8 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts @@ -0,0 +1,9 @@ +/** + * The resource type for Ldn-Services + * + * Needs to be in a separate file to prevent circular + * dependencies in webpack. + */ +import { ResourceType } from '../../../core/shared/resource-type'; + +export const LDN_SERVICE = new ResourceType('notifyservice'); diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-services.model.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-services.model.ts new file mode 100644 index 0000000000..bdb8bc5123 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-services.model.ts @@ -0,0 +1,58 @@ +import { ResourceType } from '../../../core/shared/resource-type'; +import { CacheableObject } from '../../../core/cache/cacheable-object.model'; +import { autoserialize, deserialize } from 'cerialize'; +import { LDN_SERVICE } from './ldn-service.resource-type'; +import { excludeFromEquals } from '../../../core/utilities/equals.decorators'; +import { typedObject } from '../../../core/cache/builders/build-decorators'; + + +@typedObject +export class LdnService extends CacheableObject { + static type = LDN_SERVICE; + + @excludeFromEquals + @autoserialize + type: ResourceType; + + @autoserialize + id?: number; + + @autoserialize + name: string; + + @autoserialize + description: string; + + @autoserialize + url: string; + + @autoserialize + ldnUrl: string; + + @autoserialize + notifyServiceInboundPatterns?: NotifyServicePattern[]; + + @autoserialize + notifyServiceOutboundPatterns?: NotifyServicePattern[]; + + @deserialize + _links: { + self: { + href: string; + }; + }; + + get self(): string { + return this._links.self.href; + } +} + + +class NotifyServicePattern { + @autoserialize + pattern: string; + @autoserialize + constraint?: string; + @autoserialize + automatic?: boolean; +} diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/service-constrain-type.model.ts b/src/app/admin/admin-ldn-services/ldn-services-model/service-constrain-type.model.ts new file mode 100644 index 0000000000..d3f55c815e --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-model/service-constrain-type.model.ts @@ -0,0 +1,10 @@ +/** + * List of parameter types used for scripts + */ +export enum LdnServiceConstrainType { + STRING = 'String', + DATE = 'date', + BOOLEAN = 'boolean', + FILE = 'InputStream', + OUTPUT = 'OutputStream' +} diff --git a/src/app/admin/admin-ldn-services/ldn-services-patterns/ldn-service-coar-patterns.ts b/src/app/admin/admin-ldn-services/ldn-services-patterns/ldn-service-coar-patterns.ts new file mode 100644 index 0000000000..14d227c131 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-patterns/ldn-service-coar-patterns.ts @@ -0,0 +1,73 @@ +export const notifyPatterns = [ + { + name: 'Acknowledge and Accept', + description: 'This pattern is used to acknowledge and accept a request (offer). It implies an intention to act on the request.', + category: 'Acknowledgements' + }, + { + name: 'Acknowledge and Reject', + description: 'This pattern is used to acknowledge and reject a request (offer). It signifies no further action regarding the request.', + category: 'Acknowledgements' + }, + { + name: 'Acknowledge and Tentatively Accept', + description: 'This pattern is used to acknowledge and tentatively accept a request (offer). It implies an intention to act, which may change.', + category: 'Acknowledgements' + }, + { + name: 'Acknowledge and Tentatively Reject', + description: 'This pattern is used to acknowledge and tentatively reject a request (offer). It signifies no further action, subject to change.', + category: 'Acknowledgements' + }, + { + name: 'Announce Endorsement', + description: 'This pattern is used to announce the existence of an endorsement, referencing the endorsed resource.', + category: 'Announcements' + }, + { + name: 'Announce Ingest', + description: 'This pattern is used to announce that a resource has been ingested.', + category: 'Announcements' + }, + { + name: 'Announce Relationship', + description: 'This pattern is used to announce a relationship between two resources.', + category: 'Announcements' + }, + { + name: 'Announce Review', + description: 'This pattern is used to announce the existence of a review, referencing the reviewed resource.', + category: 'Announcements' + }, + { + name: 'Announce Service Result', + description: 'This pattern is used to announce the existence of a "service result", referencing the relevant resource.', + category: 'Announcements' + }, + { + name: 'Request Endorsement', + description: 'This pattern is used to request endorsement of a resource owned by the origin system.', + category: 'Requests' + }, + { + name: 'Request Ingest', + description: 'This pattern is used to request that the target system ingest a resource.', + category: 'Requests' + }, + { + name: 'Request Review', + description: 'This pattern is used to request a review of a resource owned by the origin system.', + category: 'Requests' + }, + { + name: 'Undo Offer', + description: 'This pattern is used to undo (retract) an offer previously made.', + category: 'Undo' + } +]; + + +const pattern = notifyPatterns[0]; +console.log(`Pattern Name: ${pattern.name}`); +console.log(`Pattern Description: ${pattern.description}`); +console.log(`Pattern Category: ${pattern.category}`); diff --git a/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.spec.ts b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.spec.ts new file mode 100644 index 0000000000..e24508e942 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.spec.ts @@ -0,0 +1,17 @@ +import { TestBed } from '@angular/core/testing'; + +import { LdnDirectoryService } from './ldn-directory.service'; + +describe('LdnDirectoryService', () => { + let service: LdnDirectoryService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(LdnDirectoryService); + }); + + it('should be created', () => { + // @ts-ignore + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.ts b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.ts new file mode 100644 index 0000000000..d06057800b --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.ts @@ -0,0 +1,54 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { LdnService } from '../ldn-services-model/ldn-services.model'; + +@Injectable({ + providedIn: 'root', +}) +export class LdnDirectoryService { + private baseUrl = 'http://localhost:8080/server/api/ldn/ldnservices'; + private itemFilterEndpoint = 'http://localhost:8080/server/api/config/itemfilters'; + + + constructor(private http: HttpClient) {} + + + public listLdnServices(): Observable { + const endpoint = `${this.baseUrl}`; + return this.http.get(endpoint); + } + + public getLdnServiceById(id: string): Observable { + const endpoint = `${this.baseUrl}/${id}`; + return this.http.get(endpoint); + } + + public createLdnService(ldnService: LdnService): Observable { + return this.http.post(this.baseUrl, ldnService); + } + + public updateLdnService(id: string, ldnService: LdnService): Observable { + const endpoint = `${this.baseUrl}/${id}`; + return this.http.put(endpoint, ldnService); + } + + public deleteLdnService(id: string): Observable { + const endpoint = `${this.baseUrl}/${id}`; + return this.http.delete(endpoint); + } + + public searchLdnServicesByLdnUrl(ldnUrl: string): Observable { + const endpoint = `${this.baseUrl}/search/byLdnUrl?ldnUrl=${ldnUrl}`; + return this.http.get(endpoint); + } + + public getItemFilters(): Observable { + const endpoint = `${this.itemFilterEndpoint}`; + return this.http.get(endpoint); + } + +} + + + diff --git a/src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service.spec.ts b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service.spec.ts new file mode 100644 index 0000000000..38e1a4de2b --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service.spec.ts @@ -0,0 +1,17 @@ +import { TestBed } from '@angular/core/testing'; + +import { LdnServicesBulkDeleteService } from './ldn-service-bulk-delete.service'; + +describe('LdnServiceBulkDeleteService', () => { + let service: LdnServicesBulkDeleteService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(LdnServicesBulkDeleteService); + }); + + it('should be created', () => { + // @ts-ignore + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service.ts b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service.ts new file mode 100644 index 0000000000..6805cd7f93 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service.ts @@ -0,0 +1,117 @@ +import { Injectable } from '@angular/core'; +import { BehaviorSubject, count, from } from 'rxjs'; +import { LdnServicesService } from '../ldn-services-data/ldn-services-data.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { TranslateService } from '@ngx-translate/core'; +import { isNotEmpty } from '../../../shared/empty.util'; +import { concatMap, filter, tap } from 'rxjs/operators'; +import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; +import { RemoteData } from '../../../core/data/remote-data'; +import { LdnService } from '../ldn-services-model/ldn-services.model'; +@Injectable({ + providedIn: 'root' +}) +/** + * Service to facilitate removing ldn services in bulk. + */ +export class LdnServicesBulkDeleteService { + + /** + * Array to track the services to be deleted + */ + ldnServicesToDelete: string[] = []; + + /** + * Behavior subject to track whether the delete is processing + * @protected + */ + protected isProcessingBehaviorSubject: BehaviorSubject = new BehaviorSubject(false); + + constructor( + protected processLdnService: LdnServicesService, + protected notificationsService: NotificationsService, + protected translateService: TranslateService + ) { + } + + /** + * Add or remove a process id to/from the list + * If the id is already present it will be removed, otherwise it will be added. + * + * @param notifyServiceName - The process id to add or remove + */ + toggleDelete(notifyServiceName: string) { + if (this.isToBeDeleted(notifyServiceName)) { + this.ldnServicesToDelete.splice(this.ldnServicesToDelete.indexOf(notifyServiceName), 1); + } else { + this.ldnServicesToDelete.push(notifyServiceName); + } + } + + /** + * Checks if the provided service id is present in the to be deleted list + * @param notifyServiceName + */ + isToBeDeleted(notifyServiceName: string) { + return this.ldnServicesToDelete.includes(notifyServiceName); + } + + /** + * Clear the list of services to be deleted + */ + clearAllServices() { + this.ldnServicesToDelete.splice(0); + } + + /** + * Get the amount of processes selected for deletion + */ + getAmountOfSelectedServices() { + return this.ldnServicesToDelete.length; + } + + /** + * Returns a behavior subject to indicate whether the bulk delete is processing + */ + isProcessing$() { + return this.isProcessingBehaviorSubject; + } + + /** + * Returns whether there currently are values selected for deletion + */ + hasSelected(): boolean { + return isNotEmpty(this.ldnServicesToDelete); + } + + /** + * Delete all selected processes one by one + * When the deletion for a process fails, an error notification will be shown with the process id, + * but it will continue deleting the other processes. + * At the end it will show a notification stating the amount of successful deletes + * The successfully deleted processes will be removed from the list of selected values, the failed ones will be retained. + */ + deleteSelectedLdnServices() { + this.isProcessingBehaviorSubject.next(true); + + from([...this.ldnServicesToDelete]).pipe( + concatMap((notifyServiceName) => { + return this.processLdnService.delete(notifyServiceName).pipe( + getFirstCompletedRemoteData(), + tap((rd: RemoteData) => { + if (rd.hasFailed) { + this.notificationsService.error(this.translateService.get('process.bulk.delete.error.head'), this.translateService.get('process.bulk.delete.error.body', {processId: notifyServiceName})); + } else { + this.toggleDelete(notifyServiceName); + } + }) + ); + }), + filter((rd: RemoteData) => rd.hasSucceeded), + count(), + ).subscribe((value) => { + this.notificationsService.success(this.translateService.get('process.bulk.delete.success', {count: value})); + this.isProcessingBehaviorSubject.next(false); + }); + } +} diff --git a/src/app/admin/admin-routing-paths.ts b/src/app/admin/admin-routing-paths.ts index 30f801cecb..df0459ff53 100644 --- a/src/app/admin/admin-routing-paths.ts +++ b/src/app/admin/admin-routing-paths.ts @@ -11,3 +11,5 @@ export function getRegistriesModuleRoute() { export function getNotificationsModuleRoute() { return new URLCombiner(getAdminModuleRoute(), NOTIFICATIONS_MODULE_PATH).toString(); } + +export const LDN_PATH = 'ldn'; diff --git a/src/app/admin/admin-routing.module.ts b/src/app/admin/admin-routing.module.ts index a7d19a6935..5cca6d3e22 100644 --- a/src/app/admin/admin-routing.module.ts +++ b/src/app/admin/admin-routing.module.ts @@ -7,6 +7,7 @@ import { AdminWorkflowPageComponent } from './admin-workflow-page/admin-workflow import { I18nBreadcrumbsService } from '../core/breadcrumbs/i18n-breadcrumbs.service'; import { AdminCurationTasksComponent } from './admin-curation-tasks/admin-curation-tasks.component'; import { REGISTRIES_MODULE_PATH, NOTIFICATIONS_MODULE_PATH } from './admin-routing-paths'; +import { LDN_PATH, REGISTRIES_MODULE_PATH } from './admin-routing-paths'; import { BatchImportPageComponent } from './admin-import-batch-page/batch-import-page.component'; @NgModule({ @@ -52,13 +53,24 @@ import { BatchImportPageComponent } from './admin-import-batch-page/batch-import component: BatchImportPageComponent, data: { title: 'admin.batch-import.title', breadcrumbKey: 'admin.batch-import' } }, + { + path: LDN_PATH, + children: [ + { path: '', pathMatch: 'full', redirectTo: 'services' }, + { + path: 'services', + loadChildren: () => import('./admin-ldn-services/admin-ldn-services.module') + .then((m) => m.AdminLdnServicesModule), + } + ] + }, { path: 'system-wide-alert', resolve: { breadcrumb: I18nBreadcrumbResolver }, loadChildren: () => import('../system-wide-alert/system-wide-alert.module').then((m) => m.SystemWideAlertModule), data: {title: 'admin.system-wide-alert.title', breadcrumbKey: 'admin.system-wide-alert'} }, - ]) + ]), ], providers: [ I18nBreadcrumbResolver, diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index 7acf132df9..e1b1fc8811 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -187,6 +187,7 @@ import { NonHierarchicalBrowseDefinition } from './shared/non-hierarchical-brows import { BulkAccessConditionOptions } from './config/models/bulk-access-condition-options.model'; import { SuggestionTarget } from './suggestion-notifications/reciter-suggestions/models/suggestion-target.model'; import { SuggestionSource } from './suggestion-notifications/reciter-suggestions/models/suggestion-source.model'; +import { LdnServicesService } from '../admin/admin-ldn-services/ldn-services-data/ldn-services-data.service'; /** * When not in production, endpoint responses can be mocked for testing purposes @@ -309,7 +310,8 @@ const PROVIDERS = [ OrcidAuthService, OrcidQueueDataService, OrcidHistoryDataService, - SupervisionOrderDataService + SupervisionOrderDataService, + LdnServicesService, ]; /** diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 0d90ca693d..9f5249e92f 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -890,6 +890,28 @@ "claimed-declined-task-search-result-list-element.title": "Declined, sent back to Review Manager's workflow", + "ldn-registered-services.title": "Registered Services", + "ldn-registered-services.table.name":"Name", + "ldn-registered-services.table.description": "Description", + "ldn-registered-services.table.status": "Status", + "ldn-registered-services.table.action": "Action", + "ldn-registered-services.new": "NEW", + "ldn-registered-services.new.breadcrumbs": "Registered Services", + + "ldn-register-new-service.title": "Register a new service", + "ldn-register-new-service.name": "Name", + "ldn-register-new-service.url": "Service URL", + "ldn-register-new-service.ldn.inbox.url": "LDN InBox URL", + "ldn-register-new-service.inbound": "Inbound- Patterns supported by the service (i.e. messages that the service is able to receive and understand)", + "ldn-register-new-service.outbound": "Outbound- Patterns supported by the service (i.e. messages that the service is likely to generate and that should be processed by DSpace)", + "ldn-register-new-service.addmore": "+ Add more", + "ldn-register-new-service.breadcrumbs": "New Service", + + "ldn-register-new-service.notification.error.title": "Error", + "ldn-register-new-service.notification.error.content": "An error occurred while creating this process", + "ldn-register-new-service.notification.success.title": "Success", + "ldn-register-new-service.notification.success.content": "The process was successfully created", + "collection.create.head": "Create a Collection", "collection.create.notifications.success": "Successfully created the Collection", @@ -3328,6 +3350,10 @@ "process.new.breadcrumbs": "Create a new process", + + + + "process.detail.arguments": "Arguments", "process.detail.arguments.empty": "This process doesn't contain any arguments", @@ -3410,6 +3436,25 @@ "process.bulk.delete.success": "{{count}} process(es) have been succesfully deleted", + "service.overview.table.id": "Services ID", + + "service.overview.table.name": "Name", + + "service.overview.table.start": "Start time (UTC)", + + "service.overview.table.status": "Status", + + "service.overview.table.user": "User", + + "service.overview.title": "Services Overview", + + "service.overview.breadcrumbs": "Services Overview", + + "service.overview.table.actions": "Actions", + + "service.overview.table.description": "Description", + + "profile.breadcrumbs": "Update Profile", "profile.card.identify": "Identify", From 4805b5061a7af9884040fafae50056fd1913b552 Mon Sep 17 00:00:00 2001 From: Sondissimo Date: Mon, 18 Sep 2023 13:36:57 +0200 Subject: [PATCH 2/6] CST-11048 First commit +fix for admin routing --- src/app/admin/admin-routing.module.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/app/admin/admin-routing.module.ts b/src/app/admin/admin-routing.module.ts index 5cca6d3e22..3acc219bce 100644 --- a/src/app/admin/admin-routing.module.ts +++ b/src/app/admin/admin-routing.module.ts @@ -6,8 +6,7 @@ import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.reso import { AdminWorkflowPageComponent } from './admin-workflow-page/admin-workflow-page.component'; import { I18nBreadcrumbsService } from '../core/breadcrumbs/i18n-breadcrumbs.service'; import { AdminCurationTasksComponent } from './admin-curation-tasks/admin-curation-tasks.component'; -import { REGISTRIES_MODULE_PATH, NOTIFICATIONS_MODULE_PATH } from './admin-routing-paths'; -import { LDN_PATH, REGISTRIES_MODULE_PATH } from './admin-routing-paths'; +import { LDN_PATH, REGISTRIES_MODULE_PATH, NOTIFICATIONS_MODULE_PATH } from './admin-routing-paths'; import { BatchImportPageComponent } from './admin-import-batch-page/batch-import-page.component'; @NgModule({ From 1c9fbd46297a5aaa2ae3bcd67cdc5eccf7b486e5 Mon Sep 17 00:00:00 2001 From: Sondissimo Date: Tue, 26 Sep 2023 11:12:19 +0200 Subject: [PATCH 3/6] CST-11048 FInished the angular implementation for the ldn inbox, needs cleanup --- .../admin-ldn-services-routing.module.ts | 7 + .../admin-ldn-services.module.ts | 2 + .../ldn-service-form-edit.component.html | 117 ++++++++ .../ldn-service-form-edit.component.scss | 51 ++++ .../ldn-service-form-edit.component.spec.ts | 23 ++ .../ldn-service-form-edit.component.ts | 250 ++++++++++++++++++ .../ldn-service-form.component.html | 154 +++++++---- .../ldn-service-form.component.scss | 49 ++-- .../ldn-service-form.component.ts | 48 ++-- .../ldn-services-directory.component.html | 146 +++++----- .../ldn-services-directory.component.scss | 29 ++ .../ldn-services-directory.component.ts | 210 +++++++++------ .../ldn-service.resource-type.ts | 2 +- .../ldn-directory.service.ts | 12 +- src/app/menu.resolver.ts | 25 ++ src/assets/i18n/en.json5 | 69 ++++- 16 files changed, 933 insertions(+), 261 deletions(-) create mode 100644 src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html create mode 100644 src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss create mode 100644 src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.spec.ts create mode 100644 src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts diff --git a/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts b/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts index 740cd39621..4f05bca9e3 100644 --- a/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts +++ b/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts @@ -4,6 +4,7 @@ import { I18nBreadcrumbResolver } from 'src/app/core/breadcrumbs/i18n-breadcrumb import { LdnServicesOverviewComponent } from './ldn-services-directory/ldn-services-directory.component'; import { LdnServicesGuard } from './ldn-services-guard/ldn-services-guard.service'; import { LdnServiceNewComponent } from './ldn-service-new/ldn-service-new.component'; +import { LdnServiceFormEditComponent } from './ldn-service-form-edit/ldn-service-form-edit.component'; @NgModule({ imports: [ @@ -22,6 +23,12 @@ import { LdnServiceNewComponent } from './ldn-service-new/ldn-service-new.compon component: LdnServiceNewComponent, data: { title: 'ldn-register-new-service.title', breadcrumbKey: 'ldn-register-new-service' } }, + { + path: 'edit/:serviceId', + resolve: { breadcrumb: I18nBreadcrumbResolver }, + component: LdnServiceFormEditComponent, + data: { title: 'ldn-edit-service.title', breadcrumbKey: 'ldn-edit-service' } + }, ]), ] }) diff --git a/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts b/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts index c03c16109e..1fd67d53b9 100644 --- a/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts +++ b/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts @@ -5,6 +5,7 @@ import { LdnServicesOverviewComponent } from './ldn-services-directory/ldn-servi import { SharedModule } from '../../shared/shared.module'; import { LdnServiceNewComponent } from './ldn-service-new/ldn-service-new.component'; import { LdnServiceFormComponent } from './ldn-service-form/ldn-service-form.component'; +import { LdnServiceFormEditComponent } from './ldn-service-form-edit/ldn-service-form-edit.component'; @@ -18,6 +19,7 @@ import { LdnServiceFormComponent } from './ldn-service-form/ldn-service-form.com LdnServicesOverviewComponent, LdnServiceNewComponent, LdnServiceFormComponent, + LdnServiceFormEditComponent, ] }) export class AdminLdnServicesModule { } diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html new file mode 100644 index 0000000000..263725e8ad --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html @@ -0,0 +1,117 @@ +
+ +
+ + + + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + + + + + + +
+ + + + + +
+ + +
+ +
+ + +
+ +
+ + {{ 'ldn-edit-service.form.label.addInboundPattern' | translate }} + + +
+ + + + + + + +
+ + + + + +
+ + + +
+ +
+ + {{ 'ldn-edit-service.form.label.addOutboundPattern' | translate }} + + + +
diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss new file mode 100644 index 0000000000..53bc21d1b3 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss @@ -0,0 +1,51 @@ + +form { + display: flex; + flex-direction: column; + align-items: flex-start; + margin: 0 auto; + max-width: 600px; + font-size: 14px; +} + + +.form-group input[type="text"], +.form-group select { + max-width: 100%; + width: 100%; + padding: 8px; + margin-bottom: 5px; + box-sizing: border-box; + font-size: 14px; +} + + +.description { + height: 9em; + width: 100%; +} + + +.form-group select { + position: relative; + z-index: 1; +} + + +.form-group select option { + font-weight: bold; +} + +.add-pattern-link{ + color: #0048ff; + cursor: pointer; + margin-left: 10px; +} +.remove-pattern-link{ + color: #e34949; + cursor: pointer; + margin-left: 10px; +} + + + diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.spec.ts b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.spec.ts new file mode 100644 index 0000000000..8320ec9042 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { LdnServiceFormEditComponent } from './ldn-service-form-edit.component'; + +describe('LdnServiceFormEditComponent', () => { + let component: LdnServiceFormEditComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ LdnServiceFormEditComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(LdnServiceFormEditComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts new file mode 100644 index 0000000000..82f7b212d1 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts @@ -0,0 +1,250 @@ +import { Component, Input } from '@angular/core'; +import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { LDN_SERVICE } from '../ldn-services-model/ldn-service.resource-type'; +import { Router } from '@angular/router'; +import { HttpClient } from '@angular/common/http'; +import { LdnDirectoryService } from '../ldn-services-services/ldn-directory.service'; +import { LdnServicesService } from '../ldn-services-data/ldn-services-data.service'; +import { LdnServiceConstraint } from '../ldn-services-model/ldn-service-constraint.model'; +import { notifyPatterns } from '../ldn-services-patterns/ldn-service-coar-patterns'; +import { ActivatedRoute } from '@angular/router'; // Import ActivatedRoute and Params + +@Component({ + selector: 'ds-ldn-service-form-edit', + templateUrl: './ldn-service-form-edit.component.html', + styleUrls: ['./ldn-service-form-edit.component.scss'] +}) +export class LdnServiceFormEditComponent { + formModel: FormGroup; + + showItemFilterDropdown = false; + + public inboundPatterns: object[] = notifyPatterns; + public outboundPatterns: object[] = notifyPatterns; + public itemFilterList: LdnServiceConstraint[]; + + @Input() public name: string; + @Input() public description: string; + @Input() public url: string; + @Input() public ldnUrl: string; + @Input() public inboundPattern: string; + @Input() public outboundPattern: string; + @Input() public constraint: string; + @Input() public automatic: boolean; + + @Input() public headerKey: string; + private serviceId: string; + + constructor( + private ldnServicesService: LdnServicesService, + private ldnDirectoryService: LdnDirectoryService, + private formBuilder: FormBuilder, + private http: HttpClient, + private router: Router, + private route: ActivatedRoute + ) { + + this.formModel = this.formBuilder.group({ + id: [''], + name: ['', Validators.required], + description: ['', Validators.required], + url: ['', Validators.required], + ldnUrl: ['', Validators.required], + inboundPattern: [''], + outboundPattern: [''], + constraintPattern: [''], + 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.ldnDirectoryService.getItemFilters().subscribe((itemFilters) => { + console.log(itemFilters); + this.itemFilterList = itemFilters._embedded.itemfilters.map((filter: { id: string; }) => ({ + name: filter.id + })); + console.log(this.itemFilterList); + }); + } + + fetchServiceData(serviceId: string): void { + const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${serviceId}`; + + this.http.get(apiUrl).subscribe( + (data: any) => { + console.log(data); + + this.formModel.patchValue({ + id: data.id, + name: data.name, + description: data.description, + url: data.url, + ldnUrl: data.ldnUrl, + notifyServiceInboundPatterns: data.notifyServiceInboundPatterns, + notifyServiceOutboundPatterns: data.notifyServiceOutboundPatterns + }); + }, + (error) => { + console.error('Error fetching service data:', error); + } + ); + } + + generatePatchOperations(): any[] { + const patchOperations: any[] = []; + + if (this.formModel.get('name').dirty) { + patchOperations.push({ + op: 'replace', + path: '/name', + value: this.formModel.get('name').value, + }); + } + + if (this.formModel.get('description').dirty) { + patchOperations.push({ + op: 'replace', + path: '/description', + value: this.formModel.get('description').value, + }); + } + + if (this.formModel.get('ldnUrl').dirty) { + patchOperations.push({ + op: 'replace', + path: '/ldnUrl', + value: this.formModel.get('ldnUrl').value, + }); + } + + if (this.formModel.get('url').dirty) { + patchOperations.push({ + op: 'replace', + path: '/url', + value: this.formModel.get('url').value, + }); + } + + const inboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; + const inboundPatternsControls = inboundPatternsArray.controls; + + if (inboundPatternsArray.dirty) { + const inboundPatternsValue = []; + + for (let i = 0; i < inboundPatternsControls.length; i++) { + const patternGroup = inboundPatternsControls[i] as FormGroup; + const patternValue = patternGroup.value; + + if (patternGroup.dirty) { + inboundPatternsValue.push(patternValue); + } + } + + if (inboundPatternsValue.length > 0) { + patchOperations.push({ + op: 'replace', + path: '/notifyServiceInboundPatterns', + value: inboundPatternsValue, + }); + } else { + patchOperations.push({ + op: 'remove', + path: '/notifyServiceInboundPatterns', + }); + } + } + + + const outboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; + const outboundPatternsControls = outboundPatternsArray.controls; + + if (outboundPatternsArray.dirty) { + const outboundPatternsValue = []; + + for (let i = 0; i < outboundPatternsControls.length; i++) { + const patternGroup = outboundPatternsControls[i] as FormGroup; + const patternValue = patternGroup.value; + + if (patternGroup.dirty) { + outboundPatternsValue.push(patternValue); + } + } + + if (outboundPatternsValue.length > 0) { + patchOperations.push({ + op: 'replace', + path: '/notifyServiceOutboundPatterns', + value: outboundPatternsValue, + }); + } else { + patchOperations.push({ + op: 'remove', + path: '/notifyServiceOutboundPatterns', + }); + } + } + + return patchOperations; + } + + submitForm() { + const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${this.serviceId}`; + const patchOperations = this.generatePatchOperations(); + + this.http.patch(apiUrl, patchOperations).subscribe( + (response) => { + console.log('Service updated successfully:', response); + }, + (error) => { + console.error('Error updating service:', error); + } + ); + } + + addInboundPattern() { + const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; + notifyServiceInboundPatternsArray.push(this.createInboundPatternFormGroup()); + } + + removeInboundPattern(patternGroup: FormGroup) { + const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; + notifyServiceInboundPatternsArray.removeAt(notifyServiceInboundPatternsArray.controls.indexOf(patternGroup)); + } + + addOutboundPattern() { + const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; + notifyServiceOutboundPatternsArray.push(this.createOutboundPatternFormGroup()); + } + + removeOutboundPattern(patternGroup: FormGroup) { + const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; + notifyServiceOutboundPatternsArray.removeAt(notifyServiceOutboundPatternsArray.controls.indexOf(patternGroup)); + } + + private sendBack() { + this.router.navigateByUrl('admin/ldn/services'); + } + + private createOutboundPatternFormGroup(): FormGroup { + return this.formBuilder.group({ + pattern: '', + constraint: '' + }); + } + + private createInboundPatternFormGroup(): FormGroup { + return this.formBuilder.group({ + pattern: '', + constraint: '', + automatic: '' + }); + } +} diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html index 64146b31a1..a3272ffc44 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html @@ -1,96 +1,136 @@
-
- - - - +
+ +
-
- - +
+ +
-
- - +
+ +
-
- - +
+ +
-
+
- +
+ - - - + + - + +
-
+ - +
+ + + +
+ +
+ +
+ +
+
+ +
+ +
+ +
+ + + +
+ + {{ 'ldn-new-service.form.label.addPattern' | translate }} + + +
+ + + +
+ + + +
+ +
+ +
- - Remove +
+ +
- + Add more - - -
- - - - - - - - - Remove - - - -
- - + Add more + {{ 'ldn-new-service.form.label.addPattern' | translate }} + - diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss index 53bc21d1b3..d98ebb3dee 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss @@ -1,41 +1,38 @@ - form { display: flex; flex-direction: column; align-items: flex-start; - margin: 0 auto; - max-width: 600px; + max-width: 800px; font-size: 14px; + margin-left: 300px; + + & > * { + width: 100%; + } } - -.form-group input[type="text"], -.form-group select { +input[type="text"], +select { max-width: 100%; width: 100%; padding: 8px; - margin-bottom: 5px; - box-sizing: border-box; font-size: 14px; } - -.description { - height: 9em; - width: 100%; -} - - -.form-group select { - position: relative; - z-index: 1; -} - - -.form-group select option { +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; @@ -47,5 +44,13 @@ form { margin-left: 10px; } +.status-checkbox { + margin-top: 5px; +} +.invalid-field { + border: 1px solid red; + background-color: #e89f9f; + color: #000000; +} diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts index b17cc6902d..54934913c7 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts @@ -1,6 +1,6 @@ import { Component, Input, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators, FormArray } from '@angular/forms'; -import { HttpClient, HttpHeaders } from '@angular/common/http'; +import { HttpClient } from '@angular/common/http'; import { Router } from '@angular/router'; import { LdnServicesService } from '../ldn-services-data/ldn-services-data.service'; @@ -17,14 +17,17 @@ import { LDN_SERVICE } from '../ldn-services-model/ldn-service.resource-type'; export class LdnServiceFormComponent implements OnInit { formModel: FormGroup; - showItemFilterDropdown = false; + + + //showItemFilterDropdown = false; public inboundPatterns: object[] = notifyPatterns; public outboundPatterns: object[] = notifyPatterns; public itemFilterList: LdnServiceConstraint[]; - additionalOutboundPatterns: FormGroup[] = []; - additionalInboundPatterns: FormGroup[] = []; + //additionalOutboundPatterns: FormGroup[] = []; + //additionalInboundPatterns: FormGroup[] = []; + //@Input() public status: boolean; @Input() public name: string; @Input() public description: string; @Input() public url: string; @@ -36,6 +39,12 @@ export class LdnServiceFormComponent implements OnInit { @Input() public headerKey: string; + /* + get notifyServiceInboundPatternsFormArray(): FormArray { + return this.formModel.get('notifyServiceInboundPatterns') as FormArray; + } + */ + constructor( private ldnServicesService: LdnServicesService, private ldnDirectoryService: LdnDirectoryService, @@ -45,9 +54,10 @@ export class LdnServiceFormComponent implements OnInit { ) { this.formModel = this.formBuilder.group({ + //enabled: true, id: [''], name: ['', Validators.required], - description: ['', Validators.required], + description: [''], url: ['', Validators.required], ldnUrl: ['', Validators.required], inboundPattern: [''], @@ -65,12 +75,23 @@ export class LdnServiceFormComponent implements OnInit { this.itemFilterList = itemFilters._embedded.itemfilters.map((filter: { id: string; }) => ({ name: filter.id })); - console.log(this.itemFilterList); }); } submitForm() { + this.formModel.get('name').markAsTouched(); + this.formModel.get('url').markAsTouched(); + this.formModel.get('ldnUrl').markAsTouched(); + + const name = this.formModel.get('name').value; + const url = this.formModel.get('url').value; + const ldnUrl = this.formModel.get('ldnUrl').value; + + if (!name || !url || !ldnUrl) { + return; + } + this.formModel.removeControl('inboundPattern'); this.formModel.removeControl('outboundPattern'); this.formModel.removeControl('constraintPattern'); @@ -78,7 +99,7 @@ export class LdnServiceFormComponent implements OnInit { const apiUrl = 'http://localhost:8080/server/api/ldn/ldnservices'; - this.http.post(apiUrl, this.formModel.value ).subscribe( + this.http.post(apiUrl, this.formModel.value).subscribe( (response) => { console.log('Service created successfully:', response); this.formModel.reset(); @@ -90,16 +111,6 @@ export class LdnServiceFormComponent implements OnInit { ); } - private validateForm(form: FormGroup): boolean { - let valid = true; - Object.keys(form.controls).forEach((key) => { - if (form.controls[key].invalid) { - form.controls[key].markAsDirty(); - valid = false; - } - }); - return valid; - } private sendBack() { this.router.navigateByUrl('admin/ldn/services'); @@ -136,7 +147,8 @@ export class LdnServiceFormComponent implements OnInit { return this.formBuilder.group({ pattern: [''], constraint: [''], - automatic: [true] + automatic: false }); } + } diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html index bd2ec0d418..7d02ffe513 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html @@ -1,85 +1,81 @@
- {{ldnServicesRD$ | async | json }} -
-

{{'ldn-registered-services.title' | translate}}

-
-
- - - - -
- -
- - - - - - - - - - - - - - - - -
{{'service.overview.table.name' | translate}}{{'service.overview.table.description' | translate}}{{'service.overview.table.status' | translate}}{{'service.overview.table.actions' | translate}}
{{ldnService.id}}{{ldnService.description}} - -
+ {{ ldnServicesRD$ | async | json }} +
+

{{ 'ldn-registered-services.title' | translate }}

- +
+ +
+ +
+ + + + + + + + + + + + + + + + + +
{{ 'service.overview.table.name' | translate }}{{ 'service.overview.table.description' | translate }}{{ 'service.overview.table.status' | translate }}{{ 'service.overview.table.actions' | translate }}
{{ ldnService.name }}{{ ldnService.description }} + + {{ ldnService.status ? ('ldn-service.overview.table.enabled' | translate) : ('ldn-service.overview.table.disabled' | translate) }} + + + + +
+
+
-
+
- - - -
- - diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.scss b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.scss index e69de29bb2..07377d63d5 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.scss +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.scss @@ -0,0 +1,29 @@ +.status-indicator { + padding: 2.5px 25px 2.5px 25px; + border-radius: 4px; + cursor: pointer; + transition: background-color 0.5s; +} + +.status-enabled { + background-color: #daf7a6; + color: #4f5359; + font-size: 85%; + font-weight: bold; + +} + +.status-enabled:hover { + background-color: #faa0a0; +} + +.status-disabled { + background-color: #faa0a0; + color: #4f5359; + font-size: 85%; + font-weight: bold; +} + +.status-disabled:hover { + background-color: #daf7a6; +} diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts index e8c81ea873..ceaaebdd4f 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts @@ -1,4 +1,4 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core'; import { LdnDirectoryService } from '../ldn-services-services/ldn-directory.service'; import { Observable, Subscription } from 'rxjs'; import { RemoteData } from '../../../core/data/remote-data'; @@ -10,96 +10,152 @@ import { switchMap } from 'rxjs/operators'; import { LdnServicesService } from 'src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service'; import { PaginationService } from 'src/app/core/pagination/pagination.service'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; -import { LdnServicesBulkDeleteService } from 'src/app/admin/admin-ldn-services/ldn-services-services/ldn-service-bulk-delete.service'; import { hasValue } from '../../../shared/empty.util'; import { HttpClient } from '@angular/common/http'; @Component({ - selector: 'ds-ldn-services-directory', - templateUrl: './ldn-services-directory.component.html', - styleUrls: ['./ldn-services-directory.component.scss'], + selector: 'ds-ldn-services-directory', + templateUrl: './ldn-services-directory.component.html', + styleUrls: ['./ldn-services-directory.component.scss'], }) export class LdnServicesOverviewComponent implements OnInit, OnDestroy { - ldnServicesRD$: Observable>>; - config: FindListOptions = Object.assign(new FindListOptions(), { - elementsPerPage: 20 - }); - pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { - id: 'po', - pageSize: 20 - }); - private modalRef: any; - isProcessingSub: Subscription; + selectedServiceId: number | null = null; + servicesData: any[] = []; + @ViewChild('deleteModal', {static: true}) deleteModal: TemplateRef; + ldnServicesRD$: Observable>>; + config: FindListOptions = Object.assign(new FindListOptions(), { + elementsPerPage: 20 + }); + pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { + id: 'po', + pageSize: 20 + }); + isProcessingSub: Subscription; + private modalRef: any; - constructor( - protected processLdnService: LdnServicesService, - protected paginationService: PaginationService, - protected modalService: NgbModal, - public ldnServicesBulkDeleteService: LdnServicesBulkDeleteService, - public ldnDirectoryService: LdnDirectoryService, - private http: HttpClient - ) {} - - ngOnInit(): void { - this.setLdnServices(); - this.ldnDirectoryService.listLdnServices(); - this.searchByLdnUrl(); - } - - setLdnServices() { - debugger; - this.ldnServicesRD$ = this.paginationService.getFindListOptions(this.pageConfig.id, this.config).pipe( - switchMap((config) => this.processLdnService.findAll(config, true, false)) - ); - console.log() - } - - ngOnDestroy(): void { - this.paginationService.clearPagination(this.pageConfig.id); - if (hasValue(this.isProcessingSub)) { - this.isProcessingSub.unsubscribe(); + constructor( + protected processLdnService: LdnServicesService, + protected paginationService: PaginationService, + protected modalService: NgbModal, + public ldnDirectoryService: LdnDirectoryService, + private http: HttpClient + ) { } - } - openDeleteModal(content) { - this.modalRef = this.modalService.open(content); - } + ngOnInit(): void { + /*this.ldnDirectoryService.listLdnServices();*/ + this.findAllServices(); + this.setLdnServices(); + /*this.ldnServicesRD$.subscribe(data => { + console.log('searchByLdnUrl()', data); + });*/ - closeModal() { - this.modalRef.close(); - } + /*this.ldnServicesRD$.pipe( + tap(data => { + console.log('ldnServicesRD$ data:', data); + }) + ).subscribe(() => { + this.searchByLdnUrl(); + });*/ + } - findByLdnUrl(): Observable { - const url = 'http://localhost:8080/server/api/ldn/ldnservices'; + setLdnServices() { + this.ldnServicesRD$ = this.paginationService.getFindListOptions(this.pageConfig.id, this.config).pipe( + switchMap((config) => this.processLdnService.findAll(config, true, false)) + ); + console.log(); + } - return this.http.get(url); - } - - searchByLdnUrl(): void { - this.findByLdnUrl().subscribe( - (response) => { - console.log('Search results:', response); - }, - (error) => { - console.error('Error:', error); + ngOnDestroy(): void { + this.paginationService.clearPagination(this.pageConfig.id); + if (hasValue(this.isProcessingSub)) { + this.isProcessingSub.unsubscribe(); } - ); - } - - deleteSelected() { - this.ldnServicesBulkDeleteService.deleteSelectedLdnServices(); - - if (hasValue(this.isProcessingSub)) { - this.isProcessingSub.unsubscribe(); } - this.isProcessingSub = this.ldnServicesBulkDeleteService.isProcessing$() - .subscribe((isProcessing) => { - if (!isProcessing) { - this.closeModal(); - this.setLdnServices(); - } - }); - } + + openDeleteModal(content) { + this.modalRef = this.modalService.open(content); + } + + closeModal() { + this.modalRef.close(); + } + + + findAllServices(): void { + this.retrieveAll().subscribe( + (response) => { + this.servicesData = response._embedded.ldnservices; + console.log('ServicesData =', this.servicesData); + }, + (error) => { + console.error('Error:', error); + } + ); + } + + retrieveAll(): Observable { + const url = 'http://localhost:8080/server/api/ldn/ldnservices'; + return this.http.get(url); + } + + + + + deleteSelected() { + if (this.selectedServiceId !== null) { + const deleteUrl = `http://localhost:8080/server/api/ldn/ldnservices/${this.selectedServiceId}`; + this.http.delete(deleteUrl).subscribe( + () => { + this.closeModal(); + this.findAllServices(); + }, + (error) => { + console.error('Error deleting service:', error); + } + ); + } + } + + selectServiceToDelete(serviceId: number) { + this.selectedServiceId = serviceId; + this.openDeleteModal(this.deleteModal); + } + + toggleStatus(ldnService: any): void { + const newStatus = !ldnService.status; + + const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${ldnService.id}`; + const patchOperation = { + op: 'replace', + path: '/enabled', + value: newStatus, + }; + + this.http.patch(apiUrl, [patchOperation]).subscribe( + () => { + console.log('Status updated successfully.'); + // After a successful update, fetch the data to refresh the view + this.fetchServiceData(ldnService.id); + }, + (error) => { + console.error('Error updating status:', error); + } + ); + } + + fetchServiceData(serviceId: string): void { + const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${serviceId}`; + + this.http.get(apiUrl).subscribe( + (data: any) => { + console.log(data); + }, + (error) => { + console.error('Error fetching service data:', error); + } + ); + } } diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts index c00d241ee8..937fac255d 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts @@ -6,4 +6,4 @@ */ import { ResourceType } from '../../../core/shared/resource-type'; -export const LDN_SERVICE = new ResourceType('notifyservice'); +export const LDN_SERVICE = new ResourceType('ldnservices'); diff --git a/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.ts b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.ts index d06057800b..5ed32f5bb7 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-services/ldn-directory.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; -import { Observable } from 'rxjs'; +import { Observable, tap } from 'rxjs'; import { LdnService } from '../ldn-services-model/ldn-services.model'; @Injectable({ @@ -16,7 +16,11 @@ export class LdnDirectoryService { public listLdnServices(): Observable { const endpoint = `${this.baseUrl}`; - return this.http.get(endpoint); + return this.http.get(endpoint).pipe( + tap(data => { + console.log('listLdnServices() Data:', data); + }) + ); } public getLdnServiceById(id: string): Observable { @@ -44,8 +48,8 @@ export class LdnDirectoryService { } public getItemFilters(): Observable { - const endpoint = `${this.itemFilterEndpoint}`; - return this.http.get(endpoint); + const itemFiltersEndpoint = `${this.itemFilterEndpoint}`; + return this.http.get(itemFiltersEndpoint); } } diff --git a/src/app/menu.resolver.ts b/src/app/menu.resolver.ts index 70e2b6462f..23ba31b103 100644 --- a/src/app/menu.resolver.ts +++ b/src/app/menu.resolver.ts @@ -222,6 +222,18 @@ export class MenuResolver implements Resolve { text: 'menu.section.new_process', link: '/processes/new' } as LinkMenuItemModel, + },/* ldn_services */ + { + id: 'ldn_services_new', + parentID: 'new', + active: false, + visible: isSiteAdmin, + model: { + type: MenuItemType.LINK, + text: 'menu.section.services_new', + link: '/admin/ldn/services/new' + } as LinkMenuItemModel, + icon: '', }, ]; const editSubMenuList = [ @@ -350,6 +362,19 @@ export class MenuResolver implements Resolve { icon: 'terminal', index: 10 }, + /* LDN Services */ + { + id: 'ldn_services', + active: false, + visible: isSiteAdmin, + model: { + type: MenuItemType.LINK, + text: 'menu.section.services', + link: '/admin/ldn/services' + } as LinkMenuItemModel, + icon: 'inbox', + index: 14 + }, { id: 'health', active: false, diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 78d4c1b3e1..b5307414e3 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -902,7 +902,7 @@ "coar-notify-support.message-moderation.content": "To ensure a secure and productive environment, all incoming LDN messages are moderated. If you are planning to exchange information with us, kindly reach out via our dedicated Feedback form. You can access the Feedback form by clicking here.", - + "service.overview.delete.header": "Delete Service", "ldn-registered-services.title": "Registered Services", "ldn-registered-services.table.name":"Name", @@ -912,14 +912,49 @@ "ldn-registered-services.new": "NEW", "ldn-registered-services.new.breadcrumbs": "Registered Services", + "ldn-service.overview.table.enabled": "Enabled", + "ldn-service.overview.table.disabled": "Disabled", + "ldn-service.overview.table.clickToEnable": "Click to enable", + "ldn-service.overview.table.clickToDisable": "Click to disable", + "ldn-register-new-service.title": "Register a new service", - "ldn-register-new-service.name": "Name", - "ldn-register-new-service.url": "Service URL", - "ldn-register-new-service.ldn.inbox.url": "LDN InBox URL", - "ldn-register-new-service.inbound": "Inbound- Patterns supported by the service (i.e. messages that the service is able to receive and understand)", - "ldn-register-new-service.outbound": "Outbound- Patterns supported by the service (i.e. messages that the service is likely to generate and that should be processed by DSpace)", - "ldn-register-new-service.addmore": "+ Add more", + "ldn-new-service.form.label.name": "Name", + "ldn-new-service.form.label.description": "Description", + "ldn-new-service.form.label.url": "Service URL", + "ldn-new-service.form.label.ldnUrl": "LDN Inbox URL", + "ldn-new-service.form.placeholder.name": "Please provide service name", + "ldn-new-service.form.placeholder.description": "Please provide a description regarding your service", + "ldn-new-service.form.placeholder.url": "Please input the URL for users to check out more information about the service", + "ldn-new-service.form.placeholder.ldnUrl": "Please specify the URL of the LDN Inbox", + "ldn-new-service.form.label.inboundPattern": "Inbound Pattern", + "ldn-new-service.form.label.placeholder.inboundPattern": "No Inbound Pattern", + "ldn-new-service.form.label.placeholder.selectedItemFilter": "No Item Filter Selected", + "ldn-new-service.form.label.ItemFilter": "Item Filter", + "ldn-new-service.form.label.automatic": "Automatic", + "ldn-new-service.form.label.outboundPattern": "Outbound Pattern", + "ldn-new-service.form.label.placeholder.outboundPattern": "No Outbound Pattern", + "ldn-new-service.form.label.addPattern": "+ Add more", + "ldn-new-service.form.label.removeItemFilter": "Remove", "ldn-register-new-service.breadcrumbs": "New Service", + "service.overview.delete.body": "Are you sure you want to delete this service?", + "service.overview.delete": "Delete service", + "ldn-edit-service.title": "Edit service", + "ldn-edit-service.form.label.name": "Name", + "ldn-edit-service.form.label.description": "Description", + "ldn-edit-service.form.label.url": "Service URL", + "ldn-edit-service.form.label.ldnUrl": "LDN Inbox URL", + "ldn-edit-service.form.label.inboundPattern": "Inbound Pattern", + "ldn-edit-service.form.label.noInboundPatternSelected": "No Inbound Pattern", + "ldn-edit-service.form.label.selectedItemFilter": "Selected Item Filter", + "ldn-edit-service.form.label.selectItemFilter": "No Item Filter", + "ldn-edit-service.form.label.automatic": "Automatic", + "ldn-edit-service.form.label.addInboundPattern": "+ Add more", + "ldn-edit-service.form.label.outboundPattern": "Outbound Pattern", + "ldn-edit-service.form.label.noOutboundPatternSelected": "No Outbound Pattern", + "ldn-edit-service.form.label.addOutboundPattern": "+ Add more", + "ldn-edit-service.form.label.submit": "Submit", + "ldn-edit-service.breadcrumbs": "Edit Service", + "ldn-register-new-service.notification.error.title": "Error", "ldn-register-new-service.notification.error.content": "An error occurred while creating this process", @@ -2942,6 +2977,8 @@ "menu.section.icon.notifications": "Notifications menu section", + "menu.section.icon.ldn_services": "LDN Services overview", + "menu.section.import": "Import", "menu.section.import_batch": "Batch Import (ZIP)", @@ -2980,6 +3017,10 @@ "menu.section.registries_metadata": "Metadata", + "menu.section.services": "LDN Services", + + "menu.section.services_new": "LDN Service", + "menu.section.statistics": "Statistics", "menu.section.statistics_task": "Statistics Task", @@ -3454,6 +3495,20 @@ "process.bulk.delete.success": "{{count}} process(es) have been succesfully deleted", + "service.detail.delete.cancel": "Cancel", + + "service.detail.delete.button": "Delete service", + + "service.detail.delete.header": "Delete service", + + "service.detail.delete.body": "Are you sure you want to delete the current service?", + + "service.detail.delete.confirm": "Delete service", + + "service.detail.delete.success": "The service was successfully deleted.", + + "service.detail.delete.error": "Something went wrong when deleting the service", + "service.overview.table.id": "Services ID", "service.overview.table.name": "Name", From 11f9258d40daf99a1b80dd9539c821462270c2b9 Mon Sep 17 00:00:00 2001 From: Sondissimo Date: Fri, 6 Oct 2023 01:02:49 +0200 Subject: [PATCH 4/6] CST-11048 Form Styling --- .../ldn-service-form-edit.component.html | 188 ++++++----- .../ldn-service-form-edit.component.scss | 92 ++++-- .../ldn-service-form-edit.component.ts | 312 ++++++++++++------ .../ldn-service-form.component.html | 11 +- .../ldn-service-form.component.scss | 46 ++- .../ldn-service-form.component.ts | 19 +- .../ldn-services-directory.component.html | 6 +- .../ldn-services-directory.component.ts | 14 +- src/assets/i18n/en.json5 | 6 +- 9 files changed, 471 insertions(+), 223 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html index 263725e8ad..8640b922e3 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html @@ -1,117 +1,139 @@
-
- - - -
+
+ + +
- -
- - -
+
+   +
- -
- - -
+
+ + +
- -
- - -
+
+   +
- -
+
+ + +
- +
+   +
- +
+ + +
- + -
+
+ + +
- + - - -
- - -
+
+ + +
+
+ +
+ +
+
+
+
- -
+ -
+
+ +
- {{ 'ldn-edit-service.form.label.addInboundPattern' | translate }} +
- -
+
- + {{ 'ldn-new-service.form.label.addPattern' | translate }} - +
+   +
- +
+ + +
-
+
+ + +
- +
+ +
- -
- - - -
- -
- - {{ 'ldn-edit-service.form.label.addOutboundPattern' | translate }} - - + {{ 'ldn-new-service.form.label.addPattern' | translate }} +
diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss index 53bc21d1b3..ef38297649 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss @@ -1,41 +1,38 @@ - form { display: flex; flex-direction: column; align-items: flex-start; - margin: 0 auto; - max-width: 600px; + max-width: 800px; font-size: 14px; + margin-left: 300px; + + & > * { + width: 100%; + } } - -.form-group input[type="text"], -.form-group select { +input[type="text"], +select { max-width: 100%; width: 100%; padding: 8px; - margin-bottom: 5px; - box-sizing: border-box; font-size: 14px; } - -.description { - height: 9em; - width: 100%; -} - - -.form-group select { - position: relative; - z-index: 1; -} - - -.form-group select option { +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; @@ -47,5 +44,56 @@ form { margin-left: 10px; } +.status-checkbox { + margin-top: 5px; +} + + +.invalid-field { + border: 1px solid red; + background-color: #e89f9f; + color: #000000; +} + +.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); +} + + diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts index 82f7b212d1..d86371d441 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts @@ -1,4 +1,4 @@ -import { Component, Input } from '@angular/core'; +import { ChangeDetectorRef, Component, Input } from '@angular/core'; import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms'; import { LDN_SERVICE } from '../ldn-services-model/ldn-service.resource-type'; import { Router } from '@angular/router'; @@ -7,18 +7,28 @@ import { LdnDirectoryService } from '../ldn-services-services/ldn-directory.serv import { LdnServicesService } from '../ldn-services-data/ldn-services-data.service'; import { LdnServiceConstraint } from '../ldn-services-model/ldn-service-constraint.model'; import { notifyPatterns } from '../ldn-services-patterns/ldn-service-coar-patterns'; -import { ActivatedRoute } from '@angular/router'; // Import ActivatedRoute and Params +import { ActivatedRoute } from '@angular/router'; +import { animate, state, style, transition, trigger } from '@angular/animations'; @Component({ selector: 'ds-ldn-service-form-edit', templateUrl: './ldn-service-form-edit.component.html', - styleUrls: ['./ldn-service-form-edit.component.scss'] + 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 { formModel: FormGroup; showItemFilterDropdown = false; + private originalInboundPatterns: any[] = []; + private originalOutboundPatterns: any[] = []; public inboundPatterns: object[] = notifyPatterns; public outboundPatterns: object[] = notifyPatterns; public itemFilterList: LdnServiceConstraint[]; @@ -41,7 +51,8 @@ export class LdnServiceFormEditComponent { private formBuilder: FormBuilder, private http: HttpClient, private router: Router, - private route: ActivatedRoute + private route: ActivatedRoute, + private cdRef: ChangeDetectorRef ) { this.formModel = this.formBuilder.group({ @@ -67,14 +78,34 @@ export class LdnServiceFormEditComponent { } }); this.ldnDirectoryService.getItemFilters().subscribe((itemFilters) => { - console.log(itemFilters); this.itemFilterList = itemFilters._embedded.itemfilters.map((filter: { id: string; }) => ({ name: filter.id })); - console.log(this.itemFilterList); + this.cdRef.detectChanges(); + }); } + private getOriginalPattern(formArrayName: string, patternId: number): any { + let originalPatterns: any[] = []; + + if (formArrayName === 'notifyServiceInboundPatterns') { + originalPatterns = this.originalInboundPatterns; + } else if (formArrayName === 'notifyServiceOutboundPatterns') { + originalPatterns = this.originalOutboundPatterns; + } + + return originalPatterns.find((pattern) => pattern.id === patternId); + } + + private patternsAreEqual(patternA: any, patternB: any): boolean { + return ( + patternA.pattern === patternB.pattern && + patternA.constraint === patternB.constraint && + patternA.automatic === patternB.automatic + ); + } + fetchServiceData(serviceId: string): void { const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${serviceId}`; @@ -88,9 +119,35 @@ export class LdnServiceFormEditComponent { description: data.description, url: data.url, ldnUrl: data.ldnUrl, - notifyServiceInboundPatterns: data.notifyServiceInboundPatterns, - notifyServiceOutboundPatterns: data.notifyServiceOutboundPatterns + type: data.type }); + + const inboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; + inboundPatternsArray.clear(); // Clear existing rows + + data.notifyServiceInboundPatterns.forEach((pattern: any) => { + console.log(pattern); + const patternFormGroup = this.initializeInboundPatternFormGroup(); + console.log(); + patternFormGroup.patchValue(pattern); + inboundPatternsArray.push(patternFormGroup); + this.cdRef.detectChanges(); + }); + + // Initialize rows for notifyServiceOutboundPatterns + const outboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; + outboundPatternsArray.clear(); + + data.notifyServiceOutboundPatterns.forEach((pattern: any) => { + const patternFormGroup = this.initializeOutboundPatternFormGroup(); + patternFormGroup.patchValue(pattern); + outboundPatternsArray.push(patternFormGroup); + + this.cdRef.detectChanges(); + }); + this.originalInboundPatterns = [...data.notifyServiceInboundPatterns]; + + this.originalOutboundPatterns = [...data.notifyServiceOutboundPatterns]; }, (error) => { console.error('Error fetching service data:', error); @@ -98,103 +155,76 @@ export class LdnServiceFormEditComponent { ); } + generatePatchOperations(): any[] { const patchOperations: any[] = []; - if (this.formModel.get('name').dirty) { - patchOperations.push({ - op: 'replace', - path: '/name', - value: this.formModel.get('name').value, - }); - } + this.addReplaceOperation(patchOperations, 'name', '/name'); + this.addReplaceOperation(patchOperations, 'description', '/description'); + this.addReplaceOperation(patchOperations, 'ldnUrl', '/ldnurl'); + this.addReplaceOperation(patchOperations, 'url', '/url'); - if (this.formModel.get('description').dirty) { - patchOperations.push({ - op: 'replace', - path: '/description', - value: this.formModel.get('description').value, - }); - } + // Handle notifyServiceInboundPatterns + this.handlePatterns(patchOperations, 'notifyServiceInboundPatterns'); - if (this.formModel.get('ldnUrl').dirty) { - patchOperations.push({ - op: 'replace', - path: '/ldnUrl', - value: this.formModel.get('ldnUrl').value, - }); - } - - if (this.formModel.get('url').dirty) { - patchOperations.push({ - op: 'replace', - path: '/url', - value: this.formModel.get('url').value, - }); - } - - const inboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; - const inboundPatternsControls = inboundPatternsArray.controls; - - if (inboundPatternsArray.dirty) { - const inboundPatternsValue = []; - - for (let i = 0; i < inboundPatternsControls.length; i++) { - const patternGroup = inboundPatternsControls[i] as FormGroup; - const patternValue = patternGroup.value; - - if (patternGroup.dirty) { - inboundPatternsValue.push(patternValue); - } - } - - if (inboundPatternsValue.length > 0) { - patchOperations.push({ - op: 'replace', - path: '/notifyServiceInboundPatterns', - value: inboundPatternsValue, - }); - } else { - patchOperations.push({ - op: 'remove', - path: '/notifyServiceInboundPatterns', - }); - } - } - - - const outboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; - const outboundPatternsControls = outboundPatternsArray.controls; - - if (outboundPatternsArray.dirty) { - const outboundPatternsValue = []; - - for (let i = 0; i < outboundPatternsControls.length; i++) { - const patternGroup = outboundPatternsControls[i] as FormGroup; - const patternValue = patternGroup.value; - - if (patternGroup.dirty) { - outboundPatternsValue.push(patternValue); - } - } - - if (outboundPatternsValue.length > 0) { - patchOperations.push({ - op: 'replace', - path: '/notifyServiceOutboundPatterns', - value: outboundPatternsValue, - }); - } else { - patchOperations.push({ - op: 'remove', - path: '/notifyServiceOutboundPatterns', - }); - } - } + // Handle notifyServiceOutboundPatterns + this.handlePatterns(patchOperations, 'notifyServiceOutboundPatterns'); return patchOperations; } + private addReplaceOperation(patchOperations: any[], formControlName: string, path: string): void { + if (this.formModel.get(formControlName).dirty) { + patchOperations.push({ + op: 'replace', + path, + value: this.formModel.get(formControlName).value, + }); + } + } + + private handlePatterns(patchOperations: any[], formArrayName: string): void { + const patternsArray = this.formModel.get(formArrayName) as FormArray; + + if (patternsArray.dirty) { + for (let i = 0; i < patternsArray.length; i++) { + const patternGroup = patternsArray.at(i) as FormGroup; + const patternValue = patternGroup.value; + + // patternValue.automatic = patternValue.automatic ? 'true' : 'false'; + + if (patternValue.isNew) { + console.log(this.getOriginalPatternsForFormArray(formArrayName)); + console.log(patternGroup); + delete patternValue.isNew; + const addOperation = { + op: 'add', + path: `${formArrayName}/-`, + value: patternValue, + }; + patchOperations.push(addOperation); + } else if (patternGroup.dirty) { + const replaceOperation = { + op: 'replace', + path: `${formArrayName}[${i}]`, + value: patternValue, + }; + patchOperations.push(replaceOperation); + console.log(patternValue.id); + } + } + } + } + + private getOriginalPatternsForFormArray(formArrayName: string): any[] { + if (formArrayName === 'notifyServiceInboundPatterns') { + return this.originalInboundPatterns; + } else if (formArrayName === 'notifyServiceOutboundPatterns') { + return this.originalOutboundPatterns; + } + return []; + } + submitForm() { const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${this.serviceId}`; const patchOperations = this.generatePatchOperations(); @@ -202,21 +232,50 @@ export class LdnServiceFormEditComponent { this.http.patch(apiUrl, patchOperations).subscribe( (response) => { console.log('Service updated successfully:', response); + this.sendBack(); }, (error) => { console.error('Error updating service:', error); } ); + } + addInboundPattern() { const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; notifyServiceInboundPatternsArray.push(this.createInboundPatternFormGroup()); } - removeInboundPattern(patternGroup: FormGroup) { + removeInboundPattern(index: number) { const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; - notifyServiceInboundPatternsArray.removeAt(notifyServiceInboundPatternsArray.controls.indexOf(patternGroup)); + if (index >= 0 && index < notifyServiceInboundPatternsArray.length) { + // Get the service ID + const serviceId = this.formModel.get('id').value; + + // Construct the patch operation + const patchOperation = [ + { + op: 'remove', + path: `notifyServiceInboundPatterns[${index}]` + } + ]; + + // Make an HTTP PATCH request to apply the patch operation + const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${serviceId}`; + + this.http.patch(apiUrl, patchOperation).subscribe( + (response) => { + console.log('Pattern removed successfully:', response); + + // After successful removal from the server, also remove it from the form array + notifyServiceInboundPatternsArray.removeAt(index); + }, + (error) => { + console.error('Error removing pattern:', error); + } + ); + } } addOutboundPattern() { @@ -224,9 +283,34 @@ export class LdnServiceFormEditComponent { notifyServiceOutboundPatternsArray.push(this.createOutboundPatternFormGroup()); } - removeOutboundPattern(patternGroup: FormGroup) { + removeOutboundPattern(index: number) { const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; - notifyServiceOutboundPatternsArray.removeAt(notifyServiceOutboundPatternsArray.controls.indexOf(patternGroup)); + if (index >= 0 && index < notifyServiceOutboundPatternsArray.length) { + // Get the service ID + const serviceId = this.formModel.get('id').value; + + // Construct the patch operation + const patchOperation = [ + { + op: 'remove', + path: `notifyServiceOutboundPatterns[${index}]` + } + ]; + + // Make an HTTP PATCH request to apply the patch operation + const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${serviceId}`; + + this.http.patch(apiUrl, patchOperation).subscribe( + (response) => { + console.log('Pattern removed successfully:', response); + + notifyServiceOutboundPatternsArray.removeAt(index); + }, + (error) => { + console.error('Error removing pattern:', error); + } + ); + } } private sendBack() { @@ -236,7 +320,8 @@ export class LdnServiceFormEditComponent { private createOutboundPatternFormGroup(): FormGroup { return this.formBuilder.group({ pattern: '', - constraint: '' + constraint: '', + isNew: true, }); } @@ -244,7 +329,30 @@ export class LdnServiceFormEditComponent { return this.formBuilder.group({ pattern: '', constraint: '', - automatic: '' + automatic: '', + isNew: true }); } + + private initializeOutboundPatternFormGroup(): FormGroup { + return this.formBuilder.group({ + pattern: '', + constraint: '', + }); + } + + private initializeInboundPatternFormGroup(): FormGroup { + return this.formBuilder.group({ + pattern: '', + constraint: '', + automatic: '', + }); + } + + toggleAutomatic(i: number) { + const automaticControl = this.formModel.get(`notifyServiceInboundPatterns.${i}.automatic`); + if (automaticControl) { + automaticControl.setValue(!automaticControl.value); + } + } } diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html index a3272ffc44..db55ec285a 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html @@ -67,14 +67,19 @@
- + +
+
+
+ +
-
@@ -119,7 +124,7 @@
-
diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss index d98ebb3dee..ade0744d4c 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss @@ -23,6 +23,10 @@ option:not(:first-child) { font-weight: bold; } +select { + width: 90%; +} + .trash-button { width: 40px; height: 40px; @@ -51,6 +55,46 @@ textarea { .invalid-field { border: 1px solid red; - background-color: #e89f9f; color: #000000; } + + +.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); +} + diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts index 54934913c7..608a7ada23 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts @@ -8,11 +8,19 @@ import { LdnServiceConstraint } from '../ldn-services-model/ldn-service-constrai import { notifyPatterns } from '../ldn-services-patterns/ldn-service-coar-patterns'; import { LdnDirectoryService } from '../ldn-services-services/ldn-directory.service'; import { LDN_SERVICE } from '../ldn-services-model/ldn-service.resource-type'; +import { animate, state, style, transition, trigger } from '@angular/animations'; @Component({ selector: 'ds-ldn-service-form', templateUrl: './ldn-service-form.component.html', styleUrls: ['./ldn-service-form.component.scss'], + animations: [ + trigger('toggleAnimation', [ + state('true', style({})), // Define animation states (empty style) + state('false', style({})), + transition('true <=> false', animate('300ms ease-in')), // Define animation transition with duration + ]), + ], }) export class LdnServiceFormComponent implements OnInit { formModel: FormGroup; @@ -27,6 +35,7 @@ export class LdnServiceFormComponent implements OnInit { //additionalOutboundPatterns: FormGroup[] = []; //additionalInboundPatterns: FormGroup[] = []; + //@Input() public status: boolean; @Input() public name: string; @Input() public description: string; @@ -54,7 +63,7 @@ export class LdnServiceFormComponent implements OnInit { ) { this.formModel = this.formBuilder.group({ - //enabled: true, + enabled: true, id: [''], name: ['', Validators.required], description: [''], @@ -151,4 +160,12 @@ export class LdnServiceFormComponent implements OnInit { }); } + toggleAutomatic(i: number) { + const automaticControl = this.formModel.get(`notifyServiceInboundPatterns.${i}.automatic`); + if (automaticControl) { + automaticControl.setValue(!automaticControl.value); + } + } + + } diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html index 7d02ffe513..481989092e 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html @@ -28,10 +28,10 @@ {{ ldnService.name }} {{ ldnService.description }} - - {{ ldnService.status ? ('ldn-service.overview.table.enabled' | translate) : ('ldn-service.overview.table.disabled' | translate) }} + [title]="ldnService.enabled ? ('ldn-service.overview.table.clickToDisable' | translate) : ('ldn-service.overview.table.clickToEnable' | translate)"> + {{ ldnService.enabled ? ('ldn-service.overview.table.enabled' | translate) : ('ldn-service.overview.table.disabled' | translate) }} diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts index ceaaebdd4f..9d19ad56c7 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts @@ -1,4 +1,4 @@ -import { Component, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core'; +import { ChangeDetectorRef, Component, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core'; import { LdnDirectoryService } from '../ldn-services-services/ldn-directory.service'; import { Observable, Subscription } from 'rxjs'; import { RemoteData } from '../../../core/data/remote-data'; @@ -12,7 +12,6 @@ import { PaginationService } from 'src/app/core/pagination/pagination.service'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { hasValue } from '../../../shared/empty.util'; import { HttpClient } from '@angular/common/http'; - @Component({ selector: 'ds-ldn-services-directory', templateUrl: './ldn-services-directory.component.html', @@ -39,7 +38,8 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { protected paginationService: PaginationService, protected modalService: NgbModal, public ldnDirectoryService: LdnDirectoryService, - private http: HttpClient + private http: HttpClient, + private cdRef: ChangeDetectorRef ) { } @@ -81,6 +81,7 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { closeModal() { this.modalRef.close(); + this.cdRef.detectChanges(); } @@ -89,6 +90,7 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { (response) => { this.servicesData = response._embedded.ldnservices; console.log('ServicesData =', this.servicesData); + this.cdRef.detectChanges(); }, (error) => { console.error('Error:', error); @@ -125,7 +127,7 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { } toggleStatus(ldnService: any): void { - const newStatus = !ldnService.status; + const newStatus = !ldnService.enabled; const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${ldnService.id}`; const patchOperation = { @@ -137,8 +139,8 @@ export class LdnServicesOverviewComponent implements OnInit, OnDestroy { this.http.patch(apiUrl, [patchOperation]).subscribe( () => { console.log('Status updated successfully.'); - // After a successful update, fetch the data to refresh the view - this.fetchServiceData(ldnService.id); + ldnService.enabled = newStatus; + this.cdRef.detectChanges(); }, (error) => { console.error('Error updating status:', error); diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index b5307414e3..60b7e3cf5d 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -918,6 +918,7 @@ "ldn-service.overview.table.clickToDisable": "Click to disable", "ldn-register-new-service.title": "Register a new service", + "ldn-new-service.form.label.submit": "Submit", "ldn-new-service.form.label.name": "Name", "ldn-new-service.form.label.description": "Description", "ldn-new-service.form.label.url": "Service URL", @@ -927,12 +928,12 @@ "ldn-new-service.form.placeholder.url": "Please input the URL for users to check out more information about the service", "ldn-new-service.form.placeholder.ldnUrl": "Please specify the URL of the LDN Inbox", "ldn-new-service.form.label.inboundPattern": "Inbound Pattern", - "ldn-new-service.form.label.placeholder.inboundPattern": "No Inbound Pattern", + "ldn-new-service.form.label.placeholder.inboundPattern": "Select an Inbound Pattern", "ldn-new-service.form.label.placeholder.selectedItemFilter": "No Item Filter Selected", "ldn-new-service.form.label.ItemFilter": "Item Filter", "ldn-new-service.form.label.automatic": "Automatic", "ldn-new-service.form.label.outboundPattern": "Outbound Pattern", - "ldn-new-service.form.label.placeholder.outboundPattern": "No Outbound Pattern", + "ldn-new-service.form.label.placeholder.outboundPattern": "Select an Outbound Pattern", "ldn-new-service.form.label.addPattern": "+ Add more", "ldn-new-service.form.label.removeItemFilter": "Remove", "ldn-register-new-service.breadcrumbs": "New Service", @@ -956,6 +957,7 @@ "ldn-edit-service.breadcrumbs": "Edit Service", + "ldn-register-new-service.notification.error.title": "Error", "ldn-register-new-service.notification.error.content": "An error occurred while creating this process", "ldn-register-new-service.notification.success.title": "Success", From f893c6f2f37de2ce4a411904ea1fc44938ba3b2f Mon Sep 17 00:00:00 2001 From: Sondissimo Date: Fri, 6 Oct 2023 12:25:23 +0200 Subject: [PATCH 5/6] CST-11048 Implemented enabled slider in edit --- .../ldn-service-form-edit.component.html | 10 +++++ .../ldn-service-form-edit.component.scss | 16 +++++++ .../ldn-service-form-edit.component.ts | 42 +++++++++++++------ .../ldn-services-directory.component.html | 1 - src/assets/i18n/en.json5 | 1 + 5 files changed, 56 insertions(+), 14 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html index 8640b922e3..f887eb2a2a 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html @@ -1,5 +1,15 @@ +
+
+ +
+ +
+
+
+
+
diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss index ef38297649..9a35ee9ad2 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss @@ -94,6 +94,22 @@ textarea { transform: translateX(30px); } +.toggle-switch-container { + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: flex-end; + margin-top: 10px; +} + +.toggle-switch { + cursor: pointer; +} + + + + + diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts index d86371d441..90a0546671 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.ts @@ -64,6 +64,7 @@ export class LdnServiceFormEditComponent { inboundPattern: [''], outboundPattern: [''], constraintPattern: [''], + enabled: [''], notifyServiceInboundPatterns: this.formBuilder.array([this.createInboundPatternFormGroup()]), notifyServiceOutboundPatterns: this.formBuilder.array([this.createOutboundPatternFormGroup()]), type: LDN_SERVICE.value, @@ -119,7 +120,8 @@ export class LdnServiceFormEditComponent { description: data.description, url: data.url, ldnUrl: data.ldnUrl, - type: data.type + type: data.type, + enabled: data.enabled }); const inboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; @@ -134,7 +136,6 @@ export class LdnServiceFormEditComponent { this.cdRef.detectChanges(); }); - // Initialize rows for notifyServiceOutboundPatterns const outboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; outboundPatternsArray.clear(); @@ -164,10 +165,8 @@ export class LdnServiceFormEditComponent { this.addReplaceOperation(patchOperations, 'ldnUrl', '/ldnurl'); this.addReplaceOperation(patchOperations, 'url', '/url'); - // Handle notifyServiceInboundPatterns this.handlePatterns(patchOperations, 'notifyServiceInboundPatterns'); - // Handle notifyServiceOutboundPatterns this.handlePatterns(patchOperations, 'notifyServiceOutboundPatterns'); return patchOperations; @@ -191,8 +190,6 @@ export class LdnServiceFormEditComponent { const patternGroup = patternsArray.at(i) as FormGroup; const patternValue = patternGroup.value; - // patternValue.automatic = patternValue.automatic ? 'true' : 'false'; - if (patternValue.isNew) { console.log(this.getOriginalPatternsForFormArray(formArrayName)); console.log(patternGroup); @@ -250,10 +247,8 @@ export class LdnServiceFormEditComponent { removeInboundPattern(index: number) { const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; if (index >= 0 && index < notifyServiceInboundPatternsArray.length) { - // Get the service ID const serviceId = this.formModel.get('id').value; - // Construct the patch operation const patchOperation = [ { op: 'remove', @@ -261,14 +256,12 @@ export class LdnServiceFormEditComponent { } ]; - // Make an HTTP PATCH request to apply the patch operation const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${serviceId}`; this.http.patch(apiUrl, patchOperation).subscribe( (response) => { console.log('Pattern removed successfully:', response); - // After successful removal from the server, also remove it from the form array notifyServiceInboundPatternsArray.removeAt(index); }, (error) => { @@ -286,10 +279,9 @@ export class LdnServiceFormEditComponent { removeOutboundPattern(index: number) { const notifyServiceOutboundPatternsArray = this.formModel.get('notifyServiceOutboundPatterns') as FormArray; if (index >= 0 && index < notifyServiceOutboundPatternsArray.length) { - // Get the service ID const serviceId = this.formModel.get('id').value; - // Construct the patch operation + const patchOperation = [ { op: 'remove', @@ -297,7 +289,6 @@ export class LdnServiceFormEditComponent { } ]; - // Make an HTTP PATCH request to apply the patch operation const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${serviceId}`; this.http.patch(apiUrl, patchOperation).subscribe( @@ -355,4 +346,29 @@ export class LdnServiceFormEditComponent { automaticControl.setValue(!automaticControl.value); } } + + toggleEnabled() { + const newStatus = !this.formModel.get('enabled').value; + const serviceId = this.formModel.get('id').value; + const status = this.formModel.get('enabled').value; + + const apiUrl = `http://localhost:8080/server/api/ldn/ldnservices/${serviceId}`; + const patchOperation = { + op: 'replace', + path: '/enabled', + value: newStatus, + }; + + this.http.patch(apiUrl, [patchOperation]).subscribe( + () => { + console.log('Status updated successfully.'); + this.formModel.get('enabled').setValue(newStatus); + console.log(this.formModel.get('enabled')); + this.cdRef.detectChanges(); + }, + (error) => { + console.error('Error updating status:', error); + } + ); + } } diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html index 481989092e..e3795d6e96 100644 --- a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html @@ -1,5 +1,4 @@
- {{ ldnServicesRD$ | async | json }}

{{ 'ldn-registered-services.title' | translate }}

diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 60b7e3cf5d..67ccaa0320 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -917,6 +917,7 @@ "ldn-service.overview.table.clickToEnable": "Click to enable", "ldn-service.overview.table.clickToDisable": "Click to disable", + "ldn-service-status": "Status", "ldn-register-new-service.title": "Register a new service", "ldn-new-service.form.label.submit": "Submit", "ldn-new-service.form.label.name": "Name", From c75f61840fc319f21d8d2f42e3d33a1560a26cbf Mon Sep 17 00:00:00 2001 From: Mattia Vianelli Date: Fri, 6 Oct 2023 13:04:52 +0200 Subject: [PATCH 6/6] CST-11048 Spaced form updated error behaviour --- .../ldn-service-form-edit.component.html | 8 +++- .../ldn-service-form-edit.component.scss | 1 - .../ldn-service-form.component.html | 38 +++++++++++++++---- .../ldn-service-form.component.scss | 26 ++++++++++--- src/assets/i18n/en.json5 | 4 +- 5 files changed, 59 insertions(+), 18 deletions(-) diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html index f887eb2a2a..6402e0b953 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.html @@ -143,7 +143,13 @@
- {{ 'ldn-new-service.form.label.addPattern' | translate }} + {{ 'ldn-new-service.form.label.addPattern' | translate }} + + +
+   +
diff --git a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss index 9a35ee9ad2..92ac744aed 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss +++ b/src/app/admin/admin-ldn-services/ldn-service-form-edit/ldn-service-form-edit.component.scss @@ -51,7 +51,6 @@ textarea { .invalid-field { border: 1px solid red; - background-color: #e89f9f; color: #000000; } diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html index db55ec285a..d1f13baf32 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html @@ -9,6 +9,10 @@ type="text">
+
+   +
+
@@ -16,6 +20,10 @@ formControlName="description" id="description" name="description">
+
+   +
+
@@ -25,6 +33,10 @@ type="text">
+
+   +
+
@@ -34,6 +46,10 @@ type="text">
+
+   +
+
@@ -41,7 +57,7 @@
- + @@ -65,7 +81,7 @@
- +
@@ -91,6 +107,10 @@ {{ 'ldn-new-service.form.label.addPattern' | translate }} +
+   +
+
@@ -98,7 +118,7 @@
- + @@ -135,7 +155,9 @@ {{ 'ldn-new-service.form.label.addPattern' | translate }} - - - + +
+   +
+ diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss index ade0744d4c..92ac744aed 100644 --- a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss @@ -7,7 +7,7 @@ form { margin-left: 300px; & > * { - width: 100%; + width: 100%; } } @@ -23,10 +23,6 @@ option:not(:first-child) { font-weight: bold; } -select { - width: 90%; -} - .trash-button { width: 40px; height: 40px; @@ -58,7 +54,6 @@ textarea { color: #000000; } - .toggle-switch { display: flex; align-items: center; @@ -98,3 +93,22 @@ textarea { transform: translateX(30px); } +.toggle-switch-container { + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: flex-end; + margin-top: 10px; +} + +.toggle-switch { + cursor: pointer; +} + + + + + + + + diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 67ccaa0320..7a68fc60c8 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -928,12 +928,12 @@ "ldn-new-service.form.placeholder.description": "Please provide a description regarding your service", "ldn-new-service.form.placeholder.url": "Please input the URL for users to check out more information about the service", "ldn-new-service.form.placeholder.ldnUrl": "Please specify the URL of the LDN Inbox", - "ldn-new-service.form.label.inboundPattern": "Inbound Pattern", + "ldn-new-service.form.label.inboundPattern": "Inbound Patterns", "ldn-new-service.form.label.placeholder.inboundPattern": "Select an Inbound Pattern", "ldn-new-service.form.label.placeholder.selectedItemFilter": "No Item Filter Selected", "ldn-new-service.form.label.ItemFilter": "Item Filter", "ldn-new-service.form.label.automatic": "Automatic", - "ldn-new-service.form.label.outboundPattern": "Outbound Pattern", + "ldn-new-service.form.label.outboundPattern": "Outbound Patterns", "ldn-new-service.form.label.placeholder.outboundPattern": "Select an Outbound Pattern", "ldn-new-service.form.label.addPattern": "+ Add more", "ldn-new-service.form.label.removeItemFilter": "Remove",