diff --git a/qodana.yaml b/qodana.yaml new file mode 100644 index 0000000000..29f8f8c1fb --- /dev/null +++ b/qodana.yaml @@ -0,0 +1,29 @@ +#-------------------------------------------------------------------------------# +# Qodana analysis is configured by qodana.yaml file # +# https://www.jetbrains.com/help/qodana/qodana-yaml.html # +#-------------------------------------------------------------------------------# +version: "1.0" + +#Specify inspection profile for code analysis +profile: + name: qodana.starter + +#Enable inspections +#include: +# - name: + +#Disable inspections +#exclude: +# - name: +# paths: +# - + +#Execute shell command before Qodana execution (Applied in CI/CD pipeline) +#bootstrap: sh ./prepare-qodana.sh + +#Install IDE plugins before Qodana execution (Applied in CI/CD pipeline) +#plugins: +# - id: #(plugin id can be found at https://plugins.jetbrains.com) + +#Specify Qodana linter for analysis (Applied in CI/CD pipeline) +linter: jetbrains/qodana-js:latest 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 447c09b2e2..aadccb8be0 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 @@ -14,46 +14,40 @@ -
+
+
+ {{ 'ldn-new-service.form.error.name' | translate }}
- -
-  
-
+
-
-   -
- -
+
+
+ {{ 'ldn-new-service.form.error.url' | translate }}
- -
-  
-
+
+
+ {{ 'ldn-new-service.form.error.ldnurl' | translate }} +
-
-   + +
+ + +
+ {{ 'ldn-new-service.form.error.score' | translate }} +
-
+ +
@@ -171,20 +178,21 @@
-
- +
@@ -192,23 +200,22 @@ {{ 'ldn-new-service.form.label.addPattern' | translate }} -
-   -
-
+
- +
- +
- -
-
-
- +
-
+ +
+ +
+
@@ -295,14 +302,15 @@
- +
@@ -313,9 +321,7 @@ class="add-pattern-link mb-2">{{ 'ldn-new-service.form.label.addPattern' | translate }} -
-   -
+ -
+
+
+ {{ 'ldn-new-service.form.error.name' | translate }}
- -
-  
-
+
-
-   -
+ -
+
+
+ {{ 'ldn-new-service.form.error.url' | translate }} +
-
-   -
-
- - +
+ + +
+ {{ 'ldn-new-service.form.error.ldnurl' | translate }} +
- -
-   + +
+ + +
+ {{ 'ldn-new-service.form.error.score' | translate }} +
-
+
@@ -70,7 +78,7 @@
-
+
@@ -82,37 +90,14 @@
-
-
- - - -
+ +
+ {{ 'ldn-new-service.form.error.patterns' | translate }}
@@ -173,15 +158,13 @@
{{ 'ldn-new-service.form.label.addPattern' | translate }} + class="add-pattern-link mb-4">{{ 'ldn-new-service.form.label.addPattern' | translate }} + -
-   -
-
+
@@ -190,9 +173,12 @@
-
+
+
-
+
@@ -289,7 +275,7 @@
{{ 'ldn-new-service.form.label.addPattern' | translate }} + class="add-pattern-link mb-4">{{ '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 01dd34d12f..3b1cead16e 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 @@ -58,6 +58,12 @@ textarea { color: #000000; } +.error-text { + color: red; + font-size: 0.8em; + margin-top: 5px; +} + .toggle-switch { display: flex; align-items: center; 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 a4b2f0a143..54dfc2996c 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 @@ -49,7 +49,8 @@ export class LdnServiceFormComponent implements OnInit { @Input() public name: string; @Input() public description: string; @Input() public url: string; - @Input() public ldnUrl: string; + @Input() public score: string; + @Input() public ldnUrl: string; @Input() public inboundPattern: string; @Input() public outboundPattern: string; @Input() public constraint: string; @@ -62,6 +63,9 @@ export class LdnServiceFormComponent implements OnInit { selectedInboundItemfilters: string[]; selectedOutboundItemfilters: string[]; private modalRef: any; + hasInboundPattern: boolean; + hasOutboundPattern: boolean; + isScoreValid: boolean; constructor( private ldnServicesService: LdnServicesService, @@ -80,7 +84,7 @@ export class LdnServiceFormComponent implements OnInit { name: ['', Validators.required], description: [''], url: ['', Validators.required], - ldnUrl: ['', Validators.required], + score: ['', [Validators.required, Validators.pattern('^0*(\.[0-9]+)?$|^1(\.0+)?$')]],ldnUrl: ['', Validators.required], inboundPattern: [''], outboundPattern: [''], constraintPattern: [''], @@ -115,14 +119,19 @@ export class LdnServiceFormComponent implements OnInit { createService() { this.formModel.get('name').markAsTouched(); - this.formModel.get('url').markAsTouched(); - this.formModel.get('ldnUrl').markAsTouched(); + this.formModel.get('score').markAsTouched();this.formModel.get('url').markAsTouched(); + this.formModel.get('ldnUrl').markAsTouched();this.formModel.get('notifyServiceInboundPatterns').markAsTouched(); + this.formModel.get('notifyServiceOutboundPatterns').markAsTouched(); const name = this.formModel.get('name').value; const url = this.formModel.get('url').value; + const score = this.formModel.get('score').value; const ldnUrl = this.formModel.get('ldnUrl').value; - if (!name || !url || !ldnUrl) { + const hasInboundPattern = this.checkPatterns(this.formModel.get('notifyServiceInboundPatterns') as FormArray); + const hasOutboundPattern = this.checkPatterns(this.formModel.get('notifyServiceOutboundPatterns') as FormArray); + + if (!name || !url || !ldnUrl || !score || (!hasInboundPattern && !hasOutboundPattern)) { this.closeModal(); return; } @@ -157,9 +166,20 @@ export class LdnServiceFormComponent implements OnInit { this.sendBack(); this.closeModal(); } else { - this.notificationsService.error(this.translateService.get('notification.created.failure')); - } - }); + this.notificationsService.error(this.translateService.get('ldn-service-notification.created.failure.title'), + this.translateService.get('ldn-service-notification.created.failure.body')); + this.closeModal(); + } + }); + } + checkPatterns(formArray: FormArray): boolean { + for (let i = 0; i < formArray.length; i++) { + const pattern = formArray.at(i).get('pattern').value; + if (pattern) { + return true; + } + } + return false; } 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 index 631434f7f0..ae6803ca2e 100644 --- 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 @@ -33,6 +33,9 @@ export class LdnService extends CacheableObject { url: string; @autoserialize + score: number; + + @autoserialize enabled: boolean; @autoserialize diff --git a/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.html b/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.html index 7f1b166d24..d5e8a5c709 100644 --- a/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.html +++ b/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.html @@ -4,13 +4,19 @@

{{'notifications.events.title'| translate}} - + {{'quality-assurance.events.back' | translate}}

- + + + + + + {{(getTargetItemTitle() | async)}} +
@@ -157,7 +163,7 @@
- + {{'quality-assurance.events.back' | translate}} diff --git a/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.spec.ts b/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.spec.ts index 04ece87fbb..a4254962b2 100644 --- a/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.spec.ts +++ b/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.spec.ts @@ -42,6 +42,7 @@ import { SortDirection, SortOptions } from '../../../core/cache/models/sort-opti import { PaginationService } from '../../../core/pagination/pagination.service'; import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; import { FindListOptions } from '../../../core/data/find-list-options.model'; +import { ItemDataService } from 'src/app/core/data/item-data.service'; describe('QualityAssuranceEventsComponent test suite', () => { let fixture: ComponentFixture; @@ -118,6 +119,7 @@ describe('QualityAssuranceEventsComponent test suite', () => { { provide: NotificationsService, useValue: new NotificationsServiceStub() }, { provide: TranslateService, useValue: getMockTranslateService() }, { provide: PaginationService, useValue: paginationService }, + { provide: ItemDataService, useValue: {} }, QualityAssuranceEventsComponent ], schemas: [NO_ERRORS_SCHEMA] diff --git a/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.ts b/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.ts index 742047e76f..fee2557a12 100644 --- a/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.ts +++ b/src/app/suggestion-notifications/qa/events/quality-assurance-events.component.ts @@ -1,5 +1,6 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; +import { Location } from '@angular/common'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { TranslateService } from '@ngx-translate/core'; @@ -26,10 +27,12 @@ import { ProjectEntryImportModalComponent, QualityAssuranceEventData } from '../project-entry-import-modal/project-entry-import-modal.component'; -import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; +import { getFirstCompletedRemoteData, getRemoteDataPayload } from '../../../core/shared/operators'; import { PaginationService } from '../../../core/pagination/pagination.service'; import { Item } from '../../../core/shared/item.model'; import { FindListOptions } from '../../../core/data/find-list-options.model'; +import { getItemPageRoute } from '../../../item-page/item-page-routing-paths'; +import { ItemDataService } from '../../../core/data/item-data.service'; /** * Component to display the Quality Assurance event list. @@ -105,6 +108,26 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { */ protected subs: Subscription[] = []; + /** + * The target item id, retrieved from the topic-id composition. + */ + public targetId: string; + + /** + * The URL of the item page/target. + */ + public itemPageUrl: string; + + /** + * Plain topic name (without the source id) + */ + public selectedTopicName: string; + + /** + * The source id, retrieved from the topic-id composition. + */ + public sourceId: string; + /** * Initialize the component variables. * @param {ActivatedRoute} activatedRoute @@ -120,7 +143,9 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { private notificationsService: NotificationsService, private qualityAssuranceEventRestService: QualityAssuranceEventDataService, private paginationService: PaginationService, - private translateService: TranslateService + private translateService: TranslateService, + private itemService: ItemDataService, + private _location: Location ) { } @@ -137,6 +162,10 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { const regEx = /!/g; this.showTopic = id.replace(regEx, '/'); this.topic = id; + const splitList = this.showTopic?.split(':'); + this.targetId = splitList.length > 2 ? splitList.pop() : null; + this.sourceId = splitList[0]; + this.selectedTopicName = splitList[1]; return this.getQualityAssuranceEvents(); }) ).subscribe((events: QualityAssuranceEventData[]) => { @@ -423,4 +452,37 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { last() ); } + + /** + * Returns the page route for the given item. + * @param item The item to get the page route for. + * @returns The page route for the given item. + */ + public getItemPageRoute(item: Item): string { + return getItemPageRoute(item); + } + + /** + * Returns an Observable that emits the title of the target item. + * The target item is retrieved by its ID using the itemService. + * The title is extracted from the first metadata value of the item. + * The item page URL is also set in the component. + * @returns An Observable that emits the title of the target item. + */ + public getTargetItemTitle(): Observable { + return this.itemService.findById(this.targetId).pipe( + take(1), + getFirstCompletedRemoteData(), + getRemoteDataPayload(), + tap((item: Item) => this.itemPageUrl = getItemPageRoute(item)), + map((item: Item) => item.firstMetadataValue('dc.title')) + ); + } + + /** + * Navigates back to the previous location in the browser's history stack. + */ + public goBack() { + this._location.back(); + } } diff --git a/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.component.html b/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.component.html index 68de6aec7a..5fa32d46fc 100644 --- a/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.component.html +++ b/src/app/suggestion-notifications/qa/topics/quality-assurance-topics.component.html @@ -44,7 +44,7 @@ diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index d0b3e19e03..fecd9113d6 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -994,6 +994,12 @@ "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.error.name": "Name is required", + "ldn-new-service.form.error.url": "URL is required", + "ldn-new-service.form.error.ldnurl": "LDN URL is required", + "ldn-new-service.form.error.patterns": "At least a pattern is required", + "ldn-new-service.form.error.score": "Please enter a valid score (between 0 and 1). Use the “.” as decimal separator", + "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", @@ -3313,7 +3319,9 @@ "quality-assurance.source.error.service.retrieve": "An error occurred while loading the Quality Assurance source", - "quality-assurance.events.description": "Below the list of all the suggestions for the selected topic.", + "quality-assurance.events.description": "Below the list of all the suggestions for the selected topic {{topic}}, related to {{source}}.", + + "quality-assurance.events.description-with-topic-and-target": "Below the list of all the suggestions for the selected topic {{topic}}, related to {{source}} and ", "quality-assurance.loading": "Loading ...",