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 index 7b0c25e832..6fd20679c9 100644 --- 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 @@ -45,17 +45,17 @@ export const notifyPatterns = [ category: 'Announcements' }, { - name: 'Request Endorsement', + name: 'endorsement', description: 'This pattern is used to request endorsement of a resource owned by the origin system.', category: 'Requests' }, { - name: 'Request Ingest', + name: 'ingest', description: 'This pattern is used to request that the target system ingest a resource.', category: 'Requests' }, { - name: 'Request Review', + name: 'review', description: 'This pattern is used to request a review of a resource owned by the origin system.', category: 'Requests' }, diff --git a/src/app/submission/sections/section-coar-notify/section-coar-notify-model.ts b/src/app/submission/sections/section-coar-notify/section-coar-notify-model.ts deleted file mode 100644 index c8904fdca3..0000000000 --- a/src/app/submission/sections/section-coar-notify/section-coar-notify-model.ts +++ /dev/null @@ -1,74 +0,0 @@ -export const REQUEST_REVIEW_DROPDOWN = { - element: { - container: 'custom-control custom-select pl-1', - control: 'custom-select', - label: 'custom-control-label pt-1' - } -}; - -export const REQUEST_ENDORSEMENT_DROPDOWN = { - element: { - container: 'custom-control custom-select pl-1', - control: 'custom-select', - label: 'custom-control-label pt-1' - } -}; - -export const REQUEST_INGEST_DROPDOWN = { - element: { - container: 'custom-control custom-select pl-1', - control: 'custom-select', - label: 'custom-control-label pt-1' - } -}; - -export const SECTION_COAR_FORM_LAYOUT = { - requestReview: REQUEST_REVIEW_DROPDOWN, - requestEndorsement: REQUEST_ENDORSEMENT_DROPDOWN, - requestIngest: REQUEST_INGEST_DROPDOWN -}; - -export const SECTION_COAR_FORM_MODEL = [ - { - id: 'requestReview', - label: 'submission.sections.license.request-review-label', - required: false, - value: '', - validators: { - required: null - }, - errorMessages: { - required: 'submission.sections.license.required', - notgranted: 'submission.sections.license.notgranted' - }, - type: 'SELECT', - }, - { - id: 'requestEndorsement', - label: 'submission.sections.license.request-endorsement-label', - required: false, - value: '', - validators: { - required: null - }, - errorMessages: { - required: 'submission.sections.license.required', - notgranted: 'submission.sections.license.notgranted' - }, - type: 'SELECT', - }, - { - id: 'requestIngest', - label: 'submission.sections.license.request-ingest-label', - required: false, - value: '', - validators: { - required: null - }, - errorMessages: { - required: 'submission.sections.license.required', - notgranted: 'submission.sections.license.notgranted' - }, - type: 'SELECT', - } -]; diff --git a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.html b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.html index faae0b2292..cd287912ef 100644 --- a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.html +++ b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.html @@ -1,7 +1,7 @@ -
- -
-
-
{{'submission.section.section-coar-notify.small.notification' | translate : {pattern : pattern} }} + + + {{ error.message | translate}} + +
-
- {{ 'submission.section.section-coar-notify.selection.description' | translate }} -
- {{ ldnServiceByPattern[pattern][serviceIndex].description }} +
+
{{ 'submission.section.section-coar-notify.selection.description' | translate }}
+
+ {{ ldnServiceByPattern[pattern][serviceIndex].description }} +
+ + + {{ 'submission.section.section-coar-notify.selection.no-description' | translate }} + +
-
- +
-
+
{{ 'submission.section.section-coar-notify.notification.error' | translate }} @@ -114,12 +114,11 @@
-
+ +

+ {{'submission.section.section-coar-notify.info.no-pattern' | translate }} +

+
diff --git a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.scss b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.scss index ba543aea55..3ac8827f74 100644 --- a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.scss +++ b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.scss @@ -1,3 +1,4 @@ +// Getting styles for NgbDropdown @import '../../../shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.scss'; @import '../../../shared/form/form.component.scss'; diff --git a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.spec.ts b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.spec.ts index c83479284a..a12e027480 100644 --- a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.spec.ts +++ b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.spec.ts @@ -2,7 +2,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { SubmissionSectionCoarNotifyComponent } from './section-coar-notify.component'; -describe('LdnServiceComponent', () => { +fdescribe('LdnServiceComponent', () => { let component: SubmissionSectionCoarNotifyComponent; let fixture: ComponentFixture; diff --git a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.ts b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.ts index d60a8a3101..83dad65f3b 100644 --- a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.ts +++ b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.ts @@ -1,5 +1,5 @@ import { ChangeDetectorRef, Component, Inject } from '@angular/core'; -import { Observable, Subscription, of } from 'rxjs'; +import { Observable, Subscription } from 'rxjs'; import { SectionModelComponent } from '../models/section.model'; import { renderSectionFor } from '../sections-decorator'; import { SectionsType } from '../sections-type'; @@ -9,18 +9,15 @@ import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/jso import { SectionsService } from '../sections.service'; import { SectionDataObject } from '../models/section-data.model'; -import { hasNoValue, hasValue, isNotEmpty } from '../../../shared/empty.util'; +import { hasNoValue, hasValue, isEmpty, isNotEmpty } from '../../../shared/empty.util'; import { getFirstCompletedRemoteData, getPaginatedListPayload, getRemoteDataPayload } from '../../../core/shared/operators'; import { LdnServicesService } from '../../../admin/admin-ldn-services/ldn-services-data/ldn-services-data.service'; import { LdnService } from '../../../admin/admin-ldn-services/ldn-services-model/ldn-services.model'; import { CoarNotifyConfigDataService } from './coar-notify-config-data.service'; -import { filter, map, tap } from 'rxjs/operators'; +import { filter, map, take, tap } from 'rxjs/operators'; import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap'; - -export interface CoarNotifyDropdownSelector { - ldnService: LdnService; -} +import { SubmissionSectionError } from '../../objects/submission-section-error.model'; /** * This component represents a section that contains the submission section-coar-notify form. @@ -34,7 +31,14 @@ export interface CoarNotifyDropdownSelector { @renderSectionFor(SectionsType.CoarNotify) export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent { + /** + * Contains an array of string patterns. + */ patterns: string[] = []; + /** + * An object that maps string keys to arrays of LdnService objects. + * Used to store LdnService objects by pattern. + */ ldnServiceByPattern: { [key: string]: LdnService[] } = {}; /** * A map representing all services for each pattern @@ -49,8 +53,6 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent */ previousServices: { [key: string]: {[key: number]: number} } = {}; - private _ldnServicesPerPattern: Map = new Map(); - /** * The [[JsonPatchOperationPathCombiner]] object * @type {JsonPatchOperationPathCombiner} @@ -84,6 +86,7 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent */ onSectionInit() { this.setCoarNotifyConfig(); + this.getSectionServerErrorsAndSetErrorsToDisplay(); this.pathCombiner = new JsonPatchOperationPathCombiner('sections', this.sectionData.id); } @@ -93,14 +96,14 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent */ setCoarNotifyConfig() { this.subs.push( - this.coarNotifyConfigDataService.findAll().pipe( - getFirstCompletedRemoteData() - ).subscribe((data) => { - if (data.hasSucceeded) { - this.patterns = data.payload.page[0].patterns; - this.initSelectedServicesByPattern(); - } - })); + this.coarNotifyConfigDataService.findAll().pipe( + getFirstCompletedRemoteData() + ).subscribe((data) => { + if (data.hasSucceeded) { + this.patterns = data.payload.page[0].patterns; + this.initSelectedServicesByPattern(); + } + })); } /** @@ -162,7 +165,6 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent this.filterServices(pattern) .subscribe((services: LdnService[]) => { const selectedServices = services.filter((service) => { - this._ldnServicesPerPattern.set(pattern, services); const selection = (this.sectionData.data[pattern] as LdnService[]).find((s: LdnService) => s.id === service.id); this.addService(pattern, selection); return this.sectionData.data[pattern].includes(service.id); @@ -177,6 +179,11 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent }); } + /** + * Adds a new service to the selected services for the given pattern. + * @param pattern - The pattern to add the new service to. + * @param newService - The new service to add. + */ addService(pattern: string, newService: LdnService) { // Your logic to add a new service to the selected services for the pattern // Example: Push the newService to the array corresponding to the pattern @@ -186,6 +193,10 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent this.ldnServiceByPattern[pattern].push(newService); } + /** + * Removes the service at the specified index from the array corresponding to the pattern. + * (part of next phase of implementation) + */ removeService(pattern: string, serviceIndex: number) { if (this.ldnServiceByPattern[pattern]) { // Remove the service at the specified index from the array @@ -193,45 +204,6 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent } } - /** - * Check if the specified form field has already a value stored - * - * @param fieldId - * the section data retrieved from the serverù - * @param index - * the section data retrieved from the server - */ - hasStoredValue(fieldId, index): boolean { - if (isNotEmpty(this.sectionData.data)) { - return this.sectionData.data.hasOwnProperty(fieldId) && - isNotEmpty(this.sectionData.data[fieldId][index]) && - !this.isFieldToRemove(fieldId, index); - } else { - return false; - } - } - - /** - * Check if the specified field is on the way to be removed - * - * @param fieldId - * the section data retrieved from the serverù - * @param index - * the section data retrieved from the server - */ - isFieldToRemove(fieldId, index) { - return this.fieldsOnTheirWayToBeRemoved.has(fieldId) && this.fieldsOnTheirWayToBeRemoved.get(fieldId).includes(index); - } - - /** - * Unsubscribe from all subscriptions - */ - onSectionDestroy() { - this.subs - .filter((subscription) => hasValue(subscription)) - .forEach((subscription) => subscription.unsubscribe()); - } - /** * Method called when dropdowns for the section are initialized * Retrieve services with corresponding patterns to the dropdowns. @@ -252,15 +224,71 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent ); } + /** + * Checks if the given service has the specified inbound pattern type. + * @param service - The service to check. + * @param patternType - The inbound pattern type to look for. + * @returns True if the service has the specified inbound pattern type, false otherwise. + */ hasInboundPattern(service: any, patternType: string): boolean { return service.notifyServiceInboundPatterns.some((pattern: { pattern: string }) => { return pattern.pattern === patternType; }); } - protected getSectionStatus(): Observable { - // TODO: check if section is valid - return of(true); + /** + * Retrieves server errors for the current section and sets them to display. + * @returns An Observable that emits the validation errors for the current section. + */ + private getSectionServerErrorsAndSetErrorsToDisplay() { + this.subs.push( + this.sectionService.getSectionServerErrors(this.submissionId, this.sectionData.id).pipe( + take(1), + filter((validationErrors) => isNotEmpty(validationErrors)), + ).subscribe((validationErrors: SubmissionSectionError[]) => { + if (isNotEmpty(validationErrors)) { + validationErrors.forEach((error) => { + this.sectionService.setSectionError(this.submissionId, this.sectionData.id, error); + }); + } + })); } + /** + * Returns an observable of the errors for the current section that match the given pattern and index. + * @param pattern - The pattern to match against the error paths. + * @param index - The index to match against the error paths. + * @returns An observable of the errors for the current section that match the given pattern and index. + */ + public getShownSectionErrors$(pattern: string, index: number): Observable { + return this.sectionService.getShownSectionErrors(this.submissionId, this.sectionData.id, this.sectionData.sectionType) + .pipe( + take(1), + filter((validationErrors) => isNotEmpty(validationErrors)), + map((validationErrors: SubmissionSectionError[]) => { + return validationErrors.filter((error) => { + const path = `${pattern}/${index}`; + return error.path.includes(path); + }); + }) + ); + } + + /** + * @returns An observable that emits a boolean indicating whether the section has any server errors or not. + */ + protected getSectionStatus(): Observable { + return this.sectionService.getSectionServerErrors(this.submissionId, this.sectionData.id).pipe( + map((validationErrors) => isEmpty(validationErrors) + )); + } + + /** + * Unsubscribe from all subscriptions + */ + onSectionDestroy() { + this.subs + .filter((subscription) => hasValue(subscription)) + .forEach((subscription) => subscription.unsubscribe()); + } } diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 14b4c406e5..566a429934 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -5020,7 +5020,13 @@ "submission.section.section-coar-notify.selection.description": "Selected service's description:", - "submission.section.section-coar-notify.notification.error": "The selected service is not suitable for the current item.Please check the description for details about which record can be managed by this service.", + "submission.section.section-coar-notify.selection.no-description": "No further information is available", + + "submission.section.section-coar-notify.notification.error": "The selected service is not suitable for the current item. Please check the description for details about which record can be managed by this service.", + + "submission.section.section-coar-notify.info.no-pattern": "No patterns found in the submission.", + + "error.validation.coarnotify.invalidfilter": "Invalid filter, try to select another service or none.", "submitter.empty": "N/A",