From 6fff475a5a0a8a2a234b114307e3df897400da60 Mon Sep 17 00:00:00 2001 From: Michael Spalti Date: Thu, 16 Nov 2023 19:38:13 -0800 Subject: [PATCH 01/44] File edit component updated to work for forms without access conditions. Fixed unit test Fixed accidental reformatting --- ...section-upload-file-edit.component.spec.ts | 25 ++++++ .../section-upload-file-edit.component.ts | 84 ++++++++++--------- 2 files changed, 68 insertions(+), 41 deletions(-) diff --git a/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.spec.ts b/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.spec.ts index d008bf61f1c..72c555f39ca 100644 --- a/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.spec.ts +++ b/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.spec.ts @@ -80,6 +80,9 @@ describe('SubmissionSectionUploadFileEditComponent test suite', () => { const fileData: any = mockUploadFiles[0]; const pathCombiner = new JsonPatchOperationPathCombiner('sections', sectionId, 'files', fileIndex); + let noAccessConditionsMock = Object.assign({}, mockFileFormData); + delete noAccessConditionsMock.accessConditions; + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [ @@ -299,6 +302,28 @@ describe('SubmissionSectionUploadFileEditComponent test suite', () => { })); + it('should update Bitstream data properly when access options are omitted', fakeAsync(() => { + compAsAny.formRef = {formGroup: null}; + compAsAny.fileData = fileData; + compAsAny.pathCombiner = pathCombiner; + formService.validateAllFormFields.and.callFake(() => null); + formService.isValid.and.returnValue(of(true)); + formService.getFormData.and.returnValue(of(noAccessConditionsMock)); + const response = [ + Object.assign(mockSubmissionObject, { + sections: { + upload: { + files: mockUploadFiles + } + } + }) + ]; + operationsService.jsonPatchByResourceID.and.returnValue(of(response)); + comp.saveBitstreamData(); + tick(); + expect(uploadService.updateFileData).toHaveBeenCalled(); + })); + it('should not save Bitstream File data properly when form is not valid', fakeAsync(() => { compAsAny.formRef = {formGroup: null}; compAsAny.pathCombiner = pathCombiner; diff --git a/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.ts b/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.ts index 9ee4a7dda5e..eb4dc5aaf86 100644 --- a/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.ts +++ b/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.ts @@ -416,56 +416,58 @@ export class SubmissionSectionUploadFileEditComponent this.operationsBuilder.remove(this.pathCombiner.getPath(path)); }); const accessConditionsToSave = []; - formData.accessConditions - .map((accessConditions) => accessConditions.accessConditionGroup) - .filter((accessCondition) => isNotEmpty(accessCondition)) - .forEach((accessCondition) => { - let accessConditionOpt; - - this.availableAccessConditionOptions - .filter((element) => isNotNull(accessCondition.name) && element.name === accessCondition.name[0].value) - .forEach((element) => accessConditionOpt = element); - - if (accessConditionOpt) { - const currentAccessCondition = Object.assign({}, accessCondition); - currentAccessCondition.name = this.retrieveValueFromField(accessCondition.name); - - /* When start and end date fields are deactivated, their values may be still present in formData, - therefore it is necessary to delete them if they're not allowed by the current access condition option. */ - if (!accessConditionOpt.hasStartDate) { - delete currentAccessCondition.startDate; - } else if (accessCondition.startDate) { - const startDate = this.retrieveValueFromField(accessCondition.startDate); - // Clamp the start date to the maximum, if any, since the - // datepicker sometimes exceeds it. - let startDateDate = new Date(startDate); - if (accessConditionOpt.maxStartDate) { + if (formData.hasOwnProperty('accessConditions')) { + formData.accessConditions + .filter((accessConditions) => isNotNull(accessConditions)) + .map((accessConditions) => accessConditions.accessConditionGroup) + .filter((accessCondition) => isNotEmpty(accessCondition)) + .forEach((accessCondition) => { + let accessConditionOpt; + + this.availableAccessConditionOptions + .filter((element) => isNotNull(accessCondition.name) && element.name === accessCondition.name[0].value) + .forEach((element) => accessConditionOpt = element); + + if (accessConditionOpt) { + const currentAccessCondition = Object.assign({}, accessCondition); + currentAccessCondition.name = this.retrieveValueFromField(accessCondition.name); + + /* When start and end date fields are deactivated, their values may be still present in formData, + therefore it is necessary to delete them if they're not allowed by the current access condition option. */ + if (!accessConditionOpt.hasStartDate) { + delete currentAccessCondition.startDate; + } else if (accessCondition.startDate) { + const startDate = this.retrieveValueFromField(accessCondition.startDate); + // Clamp the start date to the maximum, if any, since the + // datepicker sometimes exceeds it. + let startDateDate = new Date(startDate); + if (accessConditionOpt.maxStartDate) { const maxStartDateDate = new Date(accessConditionOpt.maxStartDate); if (startDateDate > maxStartDateDate) { - startDateDate = maxStartDateDate; + startDateDate = maxStartDateDate; } + } + currentAccessCondition.startDate = dateToISOFormat(startDateDate); } - currentAccessCondition.startDate = dateToISOFormat(startDateDate); - } - if (!accessConditionOpt.hasEndDate) { - delete currentAccessCondition.endDate; - } else if (accessCondition.endDate) { - const endDate = this.retrieveValueFromField(accessCondition.endDate); - // Clamp the end date to the maximum, if any, since the - // datepicker sometimes exceeds it. - let endDateDate = new Date(endDate); - if (accessConditionOpt.maxEndDate) { + if (!accessConditionOpt.hasEndDate) { + delete currentAccessCondition.endDate; + } else if (accessCondition.endDate) { + const endDate = this.retrieveValueFromField(accessCondition.endDate); + // Clamp the end date to the maximum, if any, since the + // datepicker sometimes exceeds it. + let endDateDate = new Date(endDate); + if (accessConditionOpt.maxEndDate) { const maxEndDateDate = new Date(accessConditionOpt.maxEndDate); if (endDateDate > maxEndDateDate) { - endDateDate = maxEndDateDate; + endDateDate = maxEndDateDate; } + } + currentAccessCondition.endDate = dateToISOFormat(endDateDate); } - currentAccessCondition.endDate = dateToISOFormat(endDateDate); + accessConditionsToSave.push(currentAccessCondition); } - accessConditionsToSave.push(currentAccessCondition); - } - }); - + }); + } if (isNotEmpty(accessConditionsToSave)) { this.operationsBuilder.add(this.pathCombiner.getPath('accessConditions'), accessConditionsToSave, true); } From e7f5c48d8cf499024b1efbf6b0a19a1bf4dfb0bf Mon Sep 17 00:00:00 2001 From: Vincenzo Mecca Date: Wed, 13 Dec 2023 18:00:06 +0100 Subject: [PATCH 02/44] [CST-12825] Ror integration --- .../org-unit/org-unit.component.html | 8 +++++ .../metadata-values.component.html | 11 +++++-- .../metadata-values.component.ts | 2 ++ src/app/item-page/item-shared.module.ts | 33 ++++++++++++++----- .../generic-item-page-field.component.ts | 2 ++ .../item-page-field.component.html | 1 + .../item-page-field.component.ts | 2 ++ src/assets/i18n/en.json5 | 24 +++++++++++++- src/assets/images/ror-icon.svg | 16 +++++++++ 9 files changed, 87 insertions(+), 12 deletions(-) create mode 100644 src/assets/images/ror-icon.svg diff --git a/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html b/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html index c79d19e267c..30bf7c40834 100644 --- a/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html +++ b/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html @@ -14,6 +14,14 @@ > + + diff --git a/src/app/item-page/field-components/metadata-values/metadata-values.component.html b/src/app/item-page/field-components/metadata-values/metadata-values.component.html index 61088edd164..2f822e11be8 100644 --- a/src/app/item-page/field-components/metadata-values/metadata-values.component.html +++ b/src/app/item-page/field-components/metadata-values/metadata-values.component.html @@ -3,8 +3,8 @@ - + @@ -23,6 +23,13 @@ + + + + + {{value}} diff --git a/src/app/item-page/field-components/metadata-values/metadata-values.component.ts b/src/app/item-page/field-components/metadata-values/metadata-values.component.ts index cbbae9006da..2ec31159bca 100644 --- a/src/app/item-page/field-components/metadata-values/metadata-values.component.ts +++ b/src/app/item-page/field-components/metadata-values/metadata-values.component.ts @@ -55,6 +55,8 @@ export class MetadataValuesComponent implements OnChanges { @Input() browseDefinition?: BrowseDefinition; + @Input() img?: string; + ngOnChanges(changes: SimpleChanges): void { this.renderMarkdown = !!this.appConfig.markdown.enabled && this.enableMarkdown; } diff --git a/src/app/item-page/item-shared.module.ts b/src/app/item-page/item-shared.module.ts index 9c2bbba6194..7a0ac436299 100644 --- a/src/app/item-page/item-shared.module.ts +++ b/src/app/item-page/item-shared.module.ts @@ -1,17 +1,31 @@ -import { RelatedEntitiesSearchComponent } from './simple/related-entities/related-entities-search/related-entities-search.component'; +import { + RelatedEntitiesSearchComponent +} from './simple/related-entities/related-entities-search/related-entities-search.component'; import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; +import { CommonModule, NgOptimizedImage } from '@angular/common'; import { SearchModule } from '../shared/search/search.module'; import { SharedModule } from '../shared/shared.module'; import { TranslateModule } from '@ngx-translate/core'; import { DYNAMIC_FORM_CONTROL_MAP_FN } from '@ng-dynamic-forms/core'; -import { dsDynamicFormControlMapFn } from '../shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component'; -import { TabbedRelatedEntitiesSearchComponent } from './simple/related-entities/tabbed-related-entities-search/tabbed-related-entities-search.component'; -import { ItemVersionsDeleteModalComponent } from './versions/item-versions-delete-modal/item-versions-delete-modal.component'; -import { ItemVersionsSummaryModalComponent } from './versions/item-versions-summary-modal/item-versions-summary-modal.component'; +import { + dsDynamicFormControlMapFn +} from '../shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component'; +import { + TabbedRelatedEntitiesSearchComponent +} from './simple/related-entities/tabbed-related-entities-search/tabbed-related-entities-search.component'; +import { + ItemVersionsDeleteModalComponent +} from './versions/item-versions-delete-modal/item-versions-delete-modal.component'; +import { + ItemVersionsSummaryModalComponent +} from './versions/item-versions-summary-modal/item-versions-summary-modal.component'; import { MetadataValuesComponent } from './field-components/metadata-values/metadata-values.component'; -import { GenericItemPageFieldComponent } from './simple/field-components/specific-field/generic/generic-item-page-field.component'; -import { MetadataRepresentationListComponent } from './simple/metadata-representation-list/metadata-representation-list.component'; +import { + GenericItemPageFieldComponent +} from './simple/field-components/specific-field/generic/generic-item-page-field.component'; +import { + MetadataRepresentationListComponent +} from './simple/metadata-representation-list/metadata-representation-list.component'; import { RelatedItemsComponent } from './simple/related-items/related-items-component'; import { ThemedMetadataRepresentationListComponent @@ -42,7 +56,8 @@ const COMPONENTS = [ CommonModule, SearchModule, SharedModule, - TranslateModule + TranslateModule, + NgOptimizedImage ], exports: [ ...COMPONENTS diff --git a/src/app/item-page/simple/field-components/specific-field/generic/generic-item-page-field.component.ts b/src/app/item-page/simple/field-components/specific-field/generic/generic-item-page-field.component.ts index 53d2f6aa20d..99a68745c1c 100644 --- a/src/app/item-page/simple/field-components/specific-field/generic/generic-item-page-field.component.ts +++ b/src/app/item-page/simple/field-components/specific-field/generic/generic-item-page-field.component.ts @@ -45,5 +45,7 @@ export class GenericItemPageFieldComponent extends ItemPageFieldComponent { */ @Input() urlRegex?: string; + @Input() img?: string; + } diff --git a/src/app/item-page/simple/field-components/specific-field/item-page-field.component.html b/src/app/item-page/simple/field-components/specific-field/item-page-field.component.html index 91d40b0ad70..f45d4657a46 100644 --- a/src/app/item-page/simple/field-components/specific-field/item-page-field.component.html +++ b/src/app/item-page/simple/field-components/specific-field/item-page-field.component.html @@ -6,5 +6,6 @@ [enableMarkdown]="enableMarkdown" [urlRegex]="urlRegex" [browseDefinition]="browseDefinition|async" + [img]="img" > diff --git a/src/app/item-page/simple/field-components/specific-field/item-page-field.component.ts b/src/app/item-page/simple/field-components/specific-field/item-page-field.component.ts index fc526dabcc5..99e5ae7d36f 100644 --- a/src/app/item-page/simple/field-components/specific-field/item-page-field.component.ts +++ b/src/app/item-page/simple/field-components/specific-field/item-page-field.component.ts @@ -51,6 +51,8 @@ export class ItemPageFieldComponent { */ urlRegex?: string; + img?: string; + /** * Return browse definition that matches any field used in this component if it is configured as a browse * link in dspace.cfg (webui.browse.link.) diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 643a3ce0d18..325dc9daab5 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -3114,6 +3114,8 @@ "orgunit.page.titleprefix": "Organizational Unit: ", + "orgunit.page.ror": "ROR Identifier", + "pagination.options.description": "Pagination options", "pagination.results-per-page": "Results Per Page", @@ -4074,6 +4076,8 @@ "submission.import-external.source.lcname": "Library of Congress Names", + "submission.import-external.source.ror": "Research Organization Registry (ROR)", + "submission.import-external.preview.title": "Item Preview", "submission.import-external.preview.title.Publication": "Publication Preview", @@ -4166,6 +4170,8 @@ "submission.sections.describe.relationship-lookup.external-source.import-modal.head.arxiv": "Importing from arXiv", + "submission.sections.describe.relationship-lookup.external-source.import-modal.head.ror": "Import from ROR", + "submission.sections.describe.relationship-lookup.external-source.import-modal.import": "Import", "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal.title": "Import Remote Journal", @@ -4188,6 +4194,12 @@ "submission.sections.describe.relationship-lookup.external-source.import-modal.select": "Select a local match:", + "submission.sections.describe.relationship-lookup.external-source.import-modal.isOrgUnitOfProject.title": "Import Remote Organization", + + "submission.sections.describe.relationship-lookup.external-source.import-modal.isOrgUnitOfProject.added.local-entity": "Successfully added local organization to the selection", + + "submission.sections.describe.relationship-lookup.external-source.import-modal.isOrgUnitOfProject.added.new-entity": "Successfully imported and added external organization to the selection", + "submission.sections.describe.relationship-lookup.search-tab.deselect-all": "Deselect all", "submission.sections.describe.relationship-lookup.search-tab.deselect-page": "Deselect page", @@ -4244,6 +4256,8 @@ "submission.sections.describe.relationship-lookup.search-tab.tab-title.arxiv": "arXiv ({{ count }})", + "submission.sections.describe.relationship-lookup.search-tab.tab-title.ror": "ROR ({{ count }})", + "submission.sections.describe.relationship-lookup.search-tab.tab-title.isFundingAgencyOfPublication": "Search for Funding Agencies", "submission.sections.describe.relationship-lookup.search-tab.tab-title.isFundingOfPublication": "Search for Funding", @@ -4258,6 +4272,8 @@ "submission.sections.describe.relationship-lookup.search-tab.tab-title.isPublicationOfAuthor": "Publication of the Author", + "submission.sections.describe.relationship-lookup.search-tab.tab-title.isOrgUnitOfProject": "OrgUnit of the Project", + "submission.sections.describe.relationship-lookup.selection-tab.title.openAIREFunding": "Funding OpenAIRE API", "submission.sections.describe.relationship-lookup.selection-tab.title.isProjectOfPublication": "Project", @@ -4304,6 +4320,8 @@ "submission.sections.describe.relationship-lookup.title.isPublicationOfAuthor": "Publication", + "submission.sections.describe.relationship-lookup.title.isOrgUnitOfProject": "OrgUnit", + "submission.sections.describe.relationship-lookup.search-tab.toggle-dropdown": "Toggle dropdown", "submission.sections.describe.relationship-lookup.selection-tab.settings": "Settings", @@ -4366,6 +4384,8 @@ "submission.sections.describe.relationship-lookup.selection-tab.title.wos": "Search Results", + "submission.sections.describe.relationship-lookup.selection-tab.title.ror": "Search Results", + "submission.sections.describe.relationship-lookup.selection-tab.title": "Search Results", "submission.sections.describe.relationship-lookup.name-variant.notification.content": "Would you like to save \"{{ value }}\" as a name variant for this person so you and others can reuse it for future submissions? If you don't you can still use it for this submission.", @@ -4836,6 +4856,8 @@ "supervision.search.results.head": "Workflow and Workspace tasks", + "orgunit.search.results.head": "Organizational Unit Search Results", + "workflow-item.edit.breadcrumbs": "Edit workflowitem", "workflow-item.edit.title": "Edit workflowitem", @@ -5294,6 +5316,6 @@ "access-control-option-end-date-note": "Select the date until which the related access condition is applied", - "vocabulary-treeview.search.form.add": "Add", + "vocabulary-treeview.search.form.add": "Add" } diff --git a/src/assets/images/ror-icon.svg b/src/assets/images/ror-icon.svg new file mode 100644 index 00000000000..24735df519b --- /dev/null +++ b/src/assets/images/ror-icon.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + From 56d33387b5d5345ed38c8a8078d3aa2228e855a6 Mon Sep 17 00:00:00 2001 From: Vincenzo Mecca Date: Fri, 15 Dec 2023 10:05:03 +0100 Subject: [PATCH 03/44] [CST-12825] Fixes ROR metadata display --- .../item-pages/org-unit/org-unit.component.html | 16 ++++++++-------- .../metadata-values.component.html | 3 ++- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html b/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html index 30bf7c40834..2fd9031c9b2 100644 --- a/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html +++ b/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html @@ -14,14 +14,6 @@ > - - @@ -40,6 +32,14 @@
+ + From d979ea5c9f4dc8ae8d0020398ea8262c4785ffbb Mon Sep 17 00:00:00 2001 From: Vincenzo Mecca Date: Wed, 20 Dec 2023 11:47:33 +0100 Subject: [PATCH 04/44] [CST-12825] Removed unecessary escape --- .../item-pages/org-unit/org-unit.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html b/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html index 2fd9031c9b2..92a13e96726 100644 --- a/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html +++ b/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html @@ -37,7 +37,7 @@ [img]="'./assets/images/ror-icon.svg'" [item]="object" [label]="'orgunit.page.ror'" - [urlRegex]="'(.*)ror\.org'" + [urlRegex]="'(.*)ror.org'" > Date: Wed, 20 Dec 2023 11:56:25 +0100 Subject: [PATCH 05/44] [CST-12825] Fixes comma in en.json5 --- src/assets/i18n/en.json5 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 325dc9daab5..a3a6942909f 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -5316,6 +5316,6 @@ "access-control-option-end-date-note": "Select the date until which the related access condition is applied", - "vocabulary-treeview.search.form.add": "Add" + "vocabulary-treeview.search.form.add": "Add", } From e5cf16c4896a29a5ae40d3de5545ef8597a7197e Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Thu, 21 Dec 2023 14:52:39 +0100 Subject: [PATCH 06/44] fix lint --- src/app/core/data/data.service.ts | 1 - src/app/shared/mocks/suggestion.mock.ts | 1 - src/app/suggestions-page/suggestions-page-routing.module.ts | 1 - 3 files changed, 3 deletions(-) diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index 1433ebacce2..43b60f874d0 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -25,7 +25,6 @@ import { RequestParam } from '../cache/models/request-param.model'; import { ObjectCacheEntry } from '../cache/object-cache.reducer'; import { ObjectCacheService } from '../cache/object-cache.service'; import { DSpaceSerializer } from '../dspace-rest/dspace.serializer'; -import { DSpaceObject } from '../shared/dspace-object.model'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { getFirstCompletedRemoteData, getFirstSucceededRemoteData, getRemoteDataPayload } from '../shared/operators'; import { URLCombiner } from '../url-combiner/url-combiner'; diff --git a/src/app/shared/mocks/suggestion.mock.ts b/src/app/shared/mocks/suggestion.mock.ts index fd1a7c41f1e..8b1ab7acd55 100644 --- a/src/app/shared/mocks/suggestion.mock.ts +++ b/src/app/shared/mocks/suggestion.mock.ts @@ -1,7 +1,6 @@ import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { Item } from '../../core/shared/item.model'; import { SearchResult } from '../search/models/search-result.model'; -import { SuggestionsService } from '../../suggestion-notifications/reciter-suggestions/suggestions.service'; // REST Mock --------------------------------------------------------------------- // ------------------------------------------------------------------------------- diff --git a/src/app/suggestions-page/suggestions-page-routing.module.ts b/src/app/suggestions-page/suggestions-page-routing.module.ts index 20ed658707e..05dc6321b70 100644 --- a/src/app/suggestions-page/suggestions-page-routing.module.ts +++ b/src/app/suggestions-page/suggestions-page-routing.module.ts @@ -5,7 +5,6 @@ import { SuggestionsPageResolver } from './suggestions-page.resolver'; import { SuggestionsPageComponent } from './suggestions-page.component'; import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver'; -import { SiteAdministratorGuard } from '../core/data/feature-authorization/feature-authorization-guard/site-administrator.guard'; @NgModule({ imports: [ From 4106e438d6f1cc304bd7bd1ba1c2ff1f90dcedc6 Mon Sep 17 00:00:00 2001 From: frabacche Date: Fri, 22 Dec 2023 12:18:58 +0100 Subject: [PATCH 07/44] CST-5249_suggestion test fixes --- .../workspaceitem-data.service.spec.ts | 11 ++++-- .../submission/workspaceitem-data.service.ts | 37 ++++++++++++++++++- .../suggestions-popup.component.spec.ts | 1 + src/config/app-config.interface.ts | 2 +- src/environments/environment.test.ts | 1 + 5 files changed, 46 insertions(+), 6 deletions(-) diff --git a/src/app/core/submission/workspaceitem-data.service.spec.ts b/src/app/core/submission/workspaceitem-data.service.spec.ts index e766a6a039c..50bc03a6538 100644 --- a/src/app/core/submission/workspaceitem-data.service.spec.ts +++ b/src/app/core/submission/workspaceitem-data.service.spec.ts @@ -77,23 +77,26 @@ describe('WorkspaceitemDataService test', () => { const notificationsService = {} as NotificationsService; const http = {} as HttpClient; const comparator = {} as any; - const comparatorEntry = {} as any; const store = {} as Store; const pageInfo = new PageInfo(); function initTestService() { hrefOnlyDataService = getMockHrefOnlyDataService(); return new WorkspaceitemDataService( + comparator, + halService, + http, + notificationsService, requestService, rdbService, objectCache, - halService, - notificationsService, + store ); } describe('composition', () => { - const initService = () => new WorkspaceitemDataService(null, null, null, null, null); + const initService = () => new WorkspaceitemDataService(null, null, + null, null, null, null, null, null); testSearchDataImplementation(initService); testDeleteDataImplementation(initService); }); diff --git a/src/app/core/submission/workspaceitem-data.service.ts b/src/app/core/submission/workspaceitem-data.service.ts index 8a036f64439..7352718c537 100644 --- a/src/app/core/submission/workspaceitem-data.service.ts +++ b/src/app/core/submission/workspaceitem-data.service.ts @@ -23,15 +23,19 @@ import {hasValue} from '../../shared/empty.util'; import { IdentifiableDataService } from '../data/base/identifiable-data.service'; import { NoContent } from '../shared/NoContent.model'; import { DeleteData, DeleteDataImpl } from '../data/base/delete-data'; +import { SearchData, SearchDataImpl } from '../data/base/search-data'; +import { Bitstream } from '../shared/bitstream.model'; +import { PaginatedList } from '../data/paginated-list.model'; /** * A service that provides methods to make REST requests with workspaceitems endpoint. */ @Injectable() @dataService(WorkspaceItem.type) -export class WorkspaceitemDataService extends IdentifiableDataService { +export class WorkspaceitemDataService extends IdentifiableDataService implements SearchData, DeleteData { protected linkPath = 'workspaceitems'; protected searchByItemLinkPath = 'item'; + private searchData: SearchDataImpl; private deleteData: DeleteData; constructor( @@ -45,6 +49,7 @@ export class WorkspaceitemDataService extends IdentifiableDataService) { super('workspaceitems', requestService, rdbService, objectCache, halService); this.deleteData = new DeleteDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, notificationsService, this.responseMsToLive, this.constructIdEndpoint); + this.searchData = new SearchDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive); } public delete(objectId: string, copyVirtualMetadata?: string[]): Observable> { @@ -93,4 +98,34 @@ export class WorkspaceitemDataService extends IdentifiableDataService>} + * Return an observable that emits response from the server + */ + public searchBy(searchMethod: string, options?: FindListOptions, useCachedVersionIfAvailable?: boolean, reRequestOnStale?: boolean, ...linksToFollow: FollowLinkConfig[]): Observable>> { + return this.searchData.searchBy(searchMethod, options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + } + + /** + * Delete an existing object on the server + * @param href The self link of the object to be removed + * @param copyVirtualMetadata (optional parameter) the identifiers of the relationship types for which the virtual + * metadata should be saved as real metadata + * @return A RemoteData observable with an empty payload, but still representing the state of the request: statusCode, + * errorMessage, timeCompleted, etc + * Only emits once all request related to the DSO has been invalidated. + */ + deleteByHref(href: string, copyVirtualMetadata?: string[]): Observable> { + return this.deleteData.deleteByHref(href, copyVirtualMetadata); + } } diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.spec.ts b/src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.spec.ts index 67678354caf..e276b7d5d39 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.spec.ts +++ b/src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.spec.ts @@ -71,6 +71,7 @@ describe('SuggestionsPopupComponent', () => { }); it('should show a notification when new publication suggestions are available', () => { + expect((component as any).notificationsService.success).toHaveBeenCalled(); expect(suggestionStateService.dispatchMarkUserSuggestionsAsVisitedAction).toHaveBeenCalled(); }); diff --git a/src/config/app-config.interface.ts b/src/config/app-config.interface.ts index a0d91564150..f89623e0184 100644 --- a/src/config/app-config.interface.ts +++ b/src/config/app-config.interface.ts @@ -14,7 +14,7 @@ import { AuthConfig } from './auth-config.interfaces'; import { UIServerConfig } from './ui-server-config.interface'; import { MediaViewerConfig } from './media-viewer-config.interface'; import { BrowseByConfig } from './browse-by-config.interface'; -import {SuggestionConfig} from './layout-config.interfaces'; +import { SuggestionConfig } from './layout-config.interfaces'; import { BundleConfig } from './bundle-config.interface'; import { ActuatorsConfig } from './actuators.config'; import { InfoConfig } from './info-config.interface'; diff --git a/src/environments/environment.test.ts b/src/environments/environment.test.ts index 8b906764620..0573aebebc3 100644 --- a/src/environments/environment.test.ts +++ b/src/environments/environment.test.ts @@ -4,6 +4,7 @@ import { RestRequestMethod } from '../app/core/data/rest-request-method'; import { NotificationAnimationsType } from '../app/shared/notifications/models/notification-animations-type'; export const environment: BuildConfig = { + suggestion: [], production: false, // Angular Universal settings From 5feaa1b5a66fe6a36d33b9b48dbbd0232daa9f75 Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Wed, 27 Dec 2023 13:00:55 +0100 Subject: [PATCH 08/44] fix tests --- .../workspaceitem-data.service.spec.ts | 26 +++++++++++-------- .../submission/workspaceitem-data.service.ts | 14 ++++++++-- .../suggestions-popup.component.spec.ts | 10 ++++--- src/environments/environment.test.ts | 4 ++- 4 files changed, 37 insertions(+), 17 deletions(-) diff --git a/src/app/core/submission/workspaceitem-data.service.spec.ts b/src/app/core/submission/workspaceitem-data.service.spec.ts index e766a6a039c..039e9423170 100644 --- a/src/app/core/submission/workspaceitem-data.service.spec.ts +++ b/src/app/core/submission/workspaceitem-data.service.spec.ts @@ -21,6 +21,9 @@ import { RequestEntry } from '../data/request-entry.model'; import { CoreState } from '../core-state.model'; import { testSearchDataImplementation } from '../data/base/search-data.spec'; import { testDeleteDataImplementation } from '../data/base/delete-data.spec'; +import { SearchData } from '../data/base/search-data'; +import { DeleteData } from '../data/base/delete-data'; +import { RequestParam } from '../cache/models/request-param.model'; describe('WorkspaceitemDataService test', () => { let scheduler: TestScheduler; @@ -68,15 +71,12 @@ describe('WorkspaceitemDataService test', () => { const wsiRD = createSuccessfulRemoteDataObject(wsi); const endpointURL = `https://rest.api/rest/api/submission/workspaceitems`; - const searchRequestURL = `https://rest.api/rest/api/submission/workspaceitems/search/item?uuid=1234-1234`; - const searchRequestURL$ = observableOf(searchRequestURL); const requestUUID = '8b3c613a-5a4b-438b-9686-be1d5b4a1c5a'; objectCache = {} as ObjectCacheService; const notificationsService = {} as NotificationsService; const http = {} as HttpClient; - const comparator = {} as any; const comparatorEntry = {} as any; const store = {} as Store; const pageInfo = new PageInfo(); @@ -84,18 +84,23 @@ describe('WorkspaceitemDataService test', () => { function initTestService() { hrefOnlyDataService = getMockHrefOnlyDataService(); return new WorkspaceitemDataService( + comparatorEntry, + halService, + http, + notificationsService, requestService, rdbService, objectCache, - halService, - notificationsService, + store ); } describe('composition', () => { - const initService = () => new WorkspaceitemDataService(null, null, null, null, null); - testSearchDataImplementation(initService); - testDeleteDataImplementation(initService); + const initSearchService = () => new WorkspaceitemDataService(null, null, null, null, null, null, null, null) as unknown as SearchData; + const initDeleteService = () => new WorkspaceitemDataService(null, null, null, null, null, null, null, null) as unknown as DeleteData; + + testSearchDataImplementation(initSearchService); + testDeleteDataImplementation(initDeleteService); }); describe('', () => { @@ -126,7 +131,6 @@ describe('WorkspaceitemDataService test', () => { service = initTestService(); spyOn((service as any), 'findByHref').and.callThrough(); - spyOn((service as any), 'getSearchByHref').and.returnValue(searchRequestURL$); }); afterEach(() => { @@ -137,8 +141,8 @@ describe('WorkspaceitemDataService test', () => { it('should proxy the call to DataService.findByHref', () => { scheduler.schedule(() => service.findByItem('1234-1234', true, true, pageInfo)); scheduler.flush(); - - expect((service as any).findByHref).toHaveBeenCalledWith(searchRequestURL$, true, true); + const searchUrl = service.getIDHref('item', [new RequestParam('uuid', encodeURIComponent('1234-1234'))]); + expect((service as any).findByHref).toHaveBeenCalledWith(searchUrl, true, true); }); it('should return a RemoteData for the search', () => { diff --git a/src/app/core/submission/workspaceitem-data.service.ts b/src/app/core/submission/workspaceitem-data.service.ts index 8a036f64439..e2e7274e10d 100644 --- a/src/app/core/submission/workspaceitem-data.service.ts +++ b/src/app/core/submission/workspaceitem-data.service.ts @@ -23,16 +23,19 @@ import {hasValue} from '../../shared/empty.util'; import { IdentifiableDataService } from '../data/base/identifiable-data.service'; import { NoContent } from '../shared/NoContent.model'; import { DeleteData, DeleteDataImpl } from '../data/base/delete-data'; +import { SearchData, SearchDataImpl } from '../data/base/search-data'; +import { PaginatedList } from '../data/paginated-list.model'; /** * A service that provides methods to make REST requests with workspaceitems endpoint. */ @Injectable() @dataService(WorkspaceItem.type) -export class WorkspaceitemDataService extends IdentifiableDataService { +export class WorkspaceitemDataService extends IdentifiableDataService implements DeleteData, SearchData{ protected linkPath = 'workspaceitems'; protected searchByItemLinkPath = 'item'; private deleteData: DeleteData; + private searchData: SearchData; constructor( protected comparator: DSOChangeAnalyzer, @@ -45,7 +48,7 @@ export class WorkspaceitemDataService extends IdentifiableDataService) { super('workspaceitems', requestService, rdbService, objectCache, halService); this.deleteData = new DeleteDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, notificationsService, this.responseMsToLive, this.constructIdEndpoint); - + this.searchData = new SearchDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive); } public delete(objectId: string, copyVirtualMetadata?: string[]): Observable> { return this.deleteData.delete(objectId, copyVirtualMetadata); @@ -93,4 +96,11 @@ export class WorkspaceitemDataService extends IdentifiableDataService> { + return this.deleteData.deleteByHref(href, copyVirtualMetadata); + } + + searchBy(searchMethod: string, options?: FindListOptions, useCachedVersionIfAvailable?: boolean, reRequestOnStale?: boolean, ...linksToFollow: FollowLinkConfig[]): Observable>> { + return this.searchData.searchBy(searchMethod, options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + } } diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.spec.ts b/src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.spec.ts index 67678354caf..aade2c78fa1 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.spec.ts +++ b/src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.spec.ts @@ -13,11 +13,13 @@ import { SuggestionsService } from '../suggestions.service'; describe('SuggestionsPopupComponent', () => { let component: SuggestionsPopupComponent; let fixture: ComponentFixture; + let notificationsService: NotificationsService; const suggestionStateService = jasmine.createSpyObj('SuggestionTargetsStateService', { hasUserVisitedSuggestions: jasmine.createSpy('hasUserVisitedSuggestions'), getCurrentUserSuggestionTargets: jasmine.createSpy('getCurrentUserSuggestionTargets'), - dispatchMarkUserSuggestionsAsVisitedAction: jasmine.createSpy('dispatchMarkUserSuggestionsAsVisitedAction') + dispatchMarkUserSuggestionsAsVisitedAction: jasmine.createSpy('dispatchMarkUserSuggestionsAsVisitedAction'), + dispatchRefreshUserSuggestionsAction: jasmine.createSpy('dispatchRefreshUserSuggestionsAction') }); const mockNotificationInterpolation = { count: 12, source: 'source', suggestionId: 'id', displayName: 'displayName' }; @@ -60,18 +62,20 @@ describe('SuggestionsPopupComponent', () => { describe('when there are publication suggestions', () => { beforeEach(() => { - suggestionStateService.hasUserVisitedSuggestions.and.returnValue(observableOf(false)); suggestionStateService.getCurrentUserSuggestionTargets.and.returnValue(observableOf([mockSuggestionTargetsObjectOne])); suggestionStateService.dispatchMarkUserSuggestionsAsVisitedAction.and.returnValue(observableOf(null)); + suggestionStateService.dispatchRefreshUserSuggestionsAction.and.returnValue(observableOf(null)); fixture = TestBed.createComponent(SuggestionsPopupComponent); component = fixture.componentInstance; + notificationsService = (component as any).notificationsService; fixture.detectChanges(); }); it('should show a notification when new publication suggestions are available', () => { - expect((component as any).notificationsService.success).toHaveBeenCalled(); + expect(notificationsService.success).toHaveBeenCalled(); + expect(suggestionStateService.dispatchRefreshUserSuggestionsAction).toHaveBeenCalled(); expect(suggestionStateService.dispatchMarkUserSuggestionsAsVisitedAction).toHaveBeenCalled(); }); diff --git a/src/environments/environment.test.ts b/src/environments/environment.test.ts index 8b906764620..afc4082dde3 100644 --- a/src/environments/environment.test.ts +++ b/src/environments/environment.test.ts @@ -319,5 +319,7 @@ export const environment: BuildConfig = { vocabulary: 'srsc', enabled: true } - ] + ], + + suggestion: [] }; From ffd118abf9b427245b6a0ca502f0c55aea910966 Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Wed, 27 Dec 2023 13:26:04 +0100 Subject: [PATCH 09/44] align with github --- src/environments/environment.test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/environments/environment.test.ts b/src/environments/environment.test.ts index 0573aebebc3..afc4082dde3 100644 --- a/src/environments/environment.test.ts +++ b/src/environments/environment.test.ts @@ -4,7 +4,6 @@ import { RestRequestMethod } from '../app/core/data/rest-request-method'; import { NotificationAnimationsType } from '../app/shared/notifications/models/notification-animations-type'; export const environment: BuildConfig = { - suggestion: [], production: false, // Angular Universal settings @@ -320,5 +319,7 @@ export const environment: BuildConfig = { vocabulary: 'srsc', enabled: true } - ] + ], + + suggestion: [] }; From 3149842bcbcfd769dc69e8b6ec14450282d7bd7b Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Tue, 9 Jan 2024 16:17:50 +0100 Subject: [PATCH 10/44] add data services tests --- .../workspaceitem-data.service.spec.ts | 26 +++- .../source/suggestion-source-data.service.ts | 21 ++- .../suggestions-source-data.service.spec.ts | 115 +++++++++++++++ .../suggestions-data.service.ts | 12 +- .../target/suggestion-target-data.service.ts | 61 +++++--- .../suggestions-target-data.service.spec.ts | 138 ++++++++++++++++++ 6 files changed, 336 insertions(+), 37 deletions(-) create mode 100644 src/app/core/suggestion-notifications/reciter-suggestions/source/suggestions-source-data.service.spec.ts create mode 100644 src/app/core/suggestion-notifications/reciter-suggestions/target/suggestions-target-data.service.spec.ts diff --git a/src/app/core/submission/workspaceitem-data.service.spec.ts b/src/app/core/submission/workspaceitem-data.service.spec.ts index 039e9423170..34548c1e53f 100644 --- a/src/app/core/submission/workspaceitem-data.service.spec.ts +++ b/src/app/core/submission/workspaceitem-data.service.spec.ts @@ -1,4 +1,4 @@ -import { HttpClient } from '@angular/common/http'; +import { HttpClient, HttpHeaders } from '@angular/common/http'; import { of as observableOf } from 'rxjs'; import { TestScheduler } from 'rxjs/testing'; @@ -8,7 +8,7 @@ import { ObjectCacheService } from '../cache/object-cache.service'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { RequestService } from '../data/request.service'; import { PageInfo } from '../shared/page-info.model'; -import { createSuccessfulRemoteDataObject } from '../../shared/remote-data.utils'; +import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; import { HrefOnlyDataService } from '../data/href-only-data.service'; import { getMockHrefOnlyDataService } from '../../shared/mocks/href-only-data.service.mock'; import { WorkspaceitemDataService } from './workspaceitem-data.service'; @@ -24,6 +24,8 @@ import { testDeleteDataImplementation } from '../data/base/delete-data.spec'; import { SearchData } from '../data/base/search-data'; import { DeleteData } from '../data/base/delete-data'; import { RequestParam } from '../cache/models/request-param.model'; +import { PostRequest } from '../data/request.models'; +import { HttpOptions } from '../dspace-rest/dspace-rest.service'; describe('WorkspaceitemDataService test', () => { let scheduler: TestScheduler; @@ -109,7 +111,7 @@ describe('WorkspaceitemDataService test', () => { scheduler = getTestScheduler(); halService = jasmine.createSpyObj('halService', { - getEndpoint: cold('a', { a: endpointURL }) + getEndpoint: observableOf(endpointURL) }); responseCacheEntry = new RequestEntry(); responseCacheEntry.request = { href: 'https://rest.api/' } as any; @@ -125,7 +127,8 @@ describe('WorkspaceitemDataService test', () => { rdbService = jasmine.createSpyObj('rdbService', { buildSingle: hot('a|', { a: wsiRD - }) + }), + buildFromRequestUUID: createSuccessfulRemoteDataObject$({}) }); service = initTestService(); @@ -154,6 +157,19 @@ describe('WorkspaceitemDataService test', () => { }); }); - }); + describe('importExternalSourceEntry', () => { + it('should send a POST request containing the provided item request', (done) => { + const options: HttpOptions = Object.create({}); + let headers = new HttpHeaders(); + headers = headers.append('Content-Type', 'text/uri-list'); + options.headers = headers; + + service.importExternalSourceEntry('externalHref', 'testId').subscribe(() => { + expect(requestService.send).toHaveBeenCalledWith(new PostRequest(requestUUID, `${endpointURL}?owningCollection=testId`, 'externalHref', options)); + done(); + }); + }); + }); + }); }); diff --git a/src/app/core/suggestion-notifications/reciter-suggestions/source/suggestion-source-data.service.ts b/src/app/core/suggestion-notifications/reciter-suggestions/source/suggestion-source-data.service.ts index c3e142044e1..15b067f2ed1 100644 --- a/src/app/core/suggestion-notifications/reciter-suggestions/source/suggestion-source-data.service.ts +++ b/src/app/core/suggestion-notifications/reciter-suggestions/source/suggestion-source-data.service.ts @@ -53,7 +53,7 @@ export class SuggestionSourceDataService extends IdentifiableDataService[]): Observable>> { - return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + return this.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); } /** @@ -71,4 +71,23 @@ export class SuggestionSourceDataService extends IdentifiableDataService[]): Observable> { return this.findById(id, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); } + + + /** + * Returns {@link RemoteData} of all object with a list of {@link FollowLinkConfig}, to indicate which embedded + * info should be added to the objects + * + * @param options Find list options object + * @param useCachedVersionIfAvailable If this is true, the request will only be sent if there's + * no valid cached version. Defaults to true + * @param reRequestOnStale Whether or not the request should automatically be re- + * requested after the response becomes stale + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which + * {@link HALLink}s should be automatically resolved + * @return {Observable>>} + * Return an observable that emits object list + */ + findAll(options: FindListOptions = {}, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable>> { + return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + } } diff --git a/src/app/core/suggestion-notifications/reciter-suggestions/source/suggestions-source-data.service.spec.ts b/src/app/core/suggestion-notifications/reciter-suggestions/source/suggestions-source-data.service.spec.ts new file mode 100644 index 00000000000..5f8d51a6410 --- /dev/null +++ b/src/app/core/suggestion-notifications/reciter-suggestions/source/suggestions-source-data.service.spec.ts @@ -0,0 +1,115 @@ +import { TestScheduler } from 'rxjs/testing'; +import { RequestService } from '../../../data/request.service'; +import { RemoteDataBuildService } from '../../../cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../../../cache/object-cache.service'; +import { HALEndpointService } from '../../../shared/hal-endpoint.service'; +import { RequestEntry } from '../../../data/request-entry.model'; +import { cold, getTestScheduler } from 'jasmine-marbles'; +import { RestResponse } from '../../../cache/response.models'; +import { of as observableOf } from 'rxjs'; +import { Store } from '@ngrx/store'; +import { CoreState } from '../../../core-state.model'; +import { HttpClient } from '@angular/common/http'; +import { NotificationsService } from '../../../../shared/notifications/notifications.service'; +import { DefaultChangeAnalyzer } from '../../../data/default-change-analyzer.service'; +import { testFindAllDataImplementation } from '../../../data/base/find-all-data.spec'; +import { FindAllData } from '../../../data/base/find-all-data'; +import { GetRequest } from '../../../data/request.models'; +import { + createSuccessfulRemoteDataObject$ +} from '../../../../shared/remote-data.utils'; +import { RemoteData } from '../../../data/remote-data'; +import { RequestEntryState } from '../../../data/request-entry-state.model'; +import { SuggestionSourceDataService } from './suggestion-source-data.service'; +import { SuggestionSource } from '../models/suggestion-source.model'; + +describe('SuggestionSourceDataService test', () => { + let scheduler: TestScheduler; + let service: SuggestionSourceDataService; + let requestService: RequestService; + let rdbService: RemoteDataBuildService; + let objectCache: ObjectCacheService; + let halService: HALEndpointService; + let notificationsService: NotificationsService; + let http: HttpClient; + let comparator: DefaultChangeAnalyzer; + let responseCacheEntry: RequestEntry; + + const store = {} as Store; + const endpointURL = `https://rest.api/rest/api/suggestionsources`; + const requestUUID = '8b3c613a-5a4b-438b-9686-be1d5b4a1c5a'; + + const remoteDataMocks = { + Success: new RemoteData(null, null, null, RequestEntryState.Success, null, null, 200), + }; + + function initTestService() { + return new SuggestionSourceDataService( + requestService, + rdbService, + store, + objectCache, + halService, + notificationsService, + http, + comparator + ); + } + + beforeEach(() => { + scheduler = getTestScheduler(); + + objectCache = {} as ObjectCacheService; + http = {} as HttpClient; + notificationsService = {} as NotificationsService; + comparator = {} as DefaultChangeAnalyzer; + responseCacheEntry = new RequestEntry(); + responseCacheEntry.request = { href: 'https://rest.api/' } as any; + responseCacheEntry.response = new RestResponse(true, 200, 'Success'); + + requestService = jasmine.createSpyObj('requestService', { + generateRequestId: requestUUID, + send: true, + removeByHrefSubstring: {}, + getByHref: observableOf(responseCacheEntry), + getByUUID: observableOf(responseCacheEntry), + }); + + halService = jasmine.createSpyObj('halService', { + getEndpoint: observableOf(endpointURL) + }); + + rdbService = jasmine.createSpyObj('rdbService', { + buildSingle: createSuccessfulRemoteDataObject$({}, 500), + buildList: cold('a', { a: remoteDataMocks.Success }) + }); + + + service = initTestService(); + }); + + describe('composition', () => { + const initFindAllService = () => new SuggestionSourceDataService(null, null, null, null, null, null, null, null) as unknown as FindAllData; + testFindAllDataImplementation(initFindAllService); + }); + + describe('getSources', () => { + it('should send a new GetRequest', () => { + const expected = new GetRequest(requestService.generateRequestId(), `${endpointURL}`); + scheduler.schedule(() => service.getSources().subscribe()); + scheduler.flush(); + + expect(requestService.send).toHaveBeenCalledWith(expected, true); + }); + }); + + describe('getSource', () => { + it('should send a new GetRequest', () => { + const expected = new GetRequest(requestService.generateRequestId(), `${endpointURL}/testId`); + scheduler.schedule(() => service.getSource('testId').subscribe()); + scheduler.flush(); + + expect(requestService.send).toHaveBeenCalledWith(expected, true); + }); + }); +}); diff --git a/src/app/core/suggestion-notifications/reciter-suggestions/suggestions-data.service.ts b/src/app/core/suggestion-notifications/reciter-suggestions/suggestions-data.service.ts index 944a13e3a3c..407ea6a7e65 100644 --- a/src/app/core/suggestion-notifications/reciter-suggestions/suggestions-data.service.ts +++ b/src/app/core/suggestion-notifications/reciter-suggestions/suggestions-data.service.ts @@ -33,7 +33,7 @@ import { SuggestionTargetDataService } from './target/suggestion-target-data.ser /** * A private DataService implementation to delegate specific methods to. */ -class SuggestionDataServiceImpl extends DataService { +export class SuggestionDataServiceImpl extends DataService { /** * The REST endpoint. */ @@ -70,7 +70,6 @@ class SuggestionDataServiceImpl extends DataService { @dataService(SUGGESTION) export class SuggestionsDataService { protected searchFindBySourceMethod = 'findBySource'; - protected searchFindByTargetMethod = 'findByTarget'; protected searchFindByTargetAndSourceMethod = 'findByTargetAndSource'; /** @@ -168,7 +167,6 @@ export class SuggestionsDataService { ...linksToFollow: FollowLinkConfig[] ): Observable>> { options.searchParams = [new RequestParam('target', userId)]; - //return this.suggestionTargetsDataService.getTargetsByUser(this.searchFindByTargetMethod, options, ...linksToFollow); return this.suggestionTargetsDataService.getTargetsByUser(userId, options, ...linksToFollow); } @@ -193,14 +191,6 @@ export class SuggestionsDataService { return this.suggestionsDataService.delete(suggestionId); } - /** - * Used to fetch Suggestion notification for user - * @suggestionId - */ - public getSuggestion(suggestionId: string, ...linksToFollow: FollowLinkConfig[]): Observable> { - return this.suggestionsDataService.findById(suggestionId, true, true, ...linksToFollow); - } - /** * Return the list of Suggestion for a given target and source * diff --git a/src/app/core/suggestion-notifications/reciter-suggestions/target/suggestion-target-data.service.ts b/src/app/core/suggestion-notifications/reciter-suggestions/target/suggestion-target-data.service.ts index ce5f131c1d5..5a5f91a87b2 100644 --- a/src/app/core/suggestion-notifications/reciter-suggestions/target/suggestion-target-data.service.ts +++ b/src/app/core/suggestion-notifications/reciter-suggestions/target/suggestion-target-data.service.ts @@ -28,10 +28,9 @@ export class SuggestionTargetDataService extends IdentifiableDataService; - private searchBy: SearchData; + private searchData: SearchData; protected searchFindBySourceMethod = 'findBySource'; protected searchFindByTargetMethod = 'findByTarget'; - protected searchFindByTargetAndSourceMethod = 'findByTargetAndSource'; constructor( protected requestService: RequestService, @@ -44,7 +43,7 @@ export class SuggestionTargetDataService extends IdentifiableDataService) { super('suggestiontargets', requestService, rdbService, objectCache, halService); this.findAllData = new FindAllDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive); - this.searchBy = new SearchDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive); + this.searchData = new SearchDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive); } /** * Return the list of Suggestion Target for a given source @@ -65,22 +64,7 @@ export class SuggestionTargetDataService extends IdentifiableDataService>> { options.searchParams = [new RequestParam('source', source)]; - return this.searchBy.searchBy(this.searchFindBySourceMethod, options, true, true, ...linksToFollow); - } - /** - * Return a single Suggestion target. - * - * @param id The Suggestion Target id - * @param useCachedVersionIfAvailable If this is true, the request will only be sent if there's - * no valid cached version. Defaults to true - * @param reRequestOnStale Whether or not the request should automatically be re- - * requested after the response becomes stale - * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved. - * - * @return Observable> The Quality Assurance source. - */ - public getTarget(id: string, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable> { - return this.findById(id, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + return this.searchBy(this.searchFindBySourceMethod, options, true, true, ...linksToFollow); } /** @@ -102,7 +86,7 @@ export class SuggestionTargetDataService extends IdentifiableDataService>> { options.searchParams = [new RequestParam('target', userId)]; - return this.searchBy.searchBy(this.searchFindByTargetMethod, options, true, true, ...linksToFollow); + return this.searchBy(this.searchFindByTargetMethod, options, true, true, ...linksToFollow); } /** * Return a Suggestion Target for a given id @@ -117,4 +101,41 @@ export class SuggestionTargetDataService extends IdentifiableDataService>} + * Return an observable that emits response from the server + */ + public searchBy(searchMethod: string, options?: FindListOptions, useCachedVersionIfAvailable?: boolean, reRequestOnStale?: boolean, ...linksToFollow: FollowLinkConfig[]): Observable>> { + return this.searchData.searchBy(searchMethod, options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + } + + + /** + * Returns {@link RemoteData} of all object with a list of {@link FollowLinkConfig}, to indicate which embedded + * info should be added to the objects + * + * @param options Find list options object + * @param useCachedVersionIfAvailable If this is true, the request will only be sent if there's + * no valid cached version. Defaults to true + * @param reRequestOnStale Whether or not the request should automatically be re- + * requested after the response becomes stale + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which + * {@link HALLink}s should be automatically resolved + * @return {Observable>>} + * Return an observable that emits object list + */ + findAll(options: FindListOptions = {}, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable>> { + return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + } + } diff --git a/src/app/core/suggestion-notifications/reciter-suggestions/target/suggestions-target-data.service.spec.ts b/src/app/core/suggestion-notifications/reciter-suggestions/target/suggestions-target-data.service.spec.ts new file mode 100644 index 00000000000..ba5900b79fa --- /dev/null +++ b/src/app/core/suggestion-notifications/reciter-suggestions/target/suggestions-target-data.service.spec.ts @@ -0,0 +1,138 @@ +import { TestScheduler } from 'rxjs/testing'; +import { RequestService } from '../../../data/request.service'; +import { RemoteDataBuildService } from '../../../cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../../../cache/object-cache.service'; +import { HALEndpointService } from '../../../shared/hal-endpoint.service'; +import { RequestEntry } from '../../../data/request-entry.model'; +import { cold, getTestScheduler } from 'jasmine-marbles'; +import { RestResponse } from '../../../cache/response.models'; +import { of as observableOf } from 'rxjs'; +import { Store } from '@ngrx/store'; +import { CoreState } from '../../../core-state.model'; +import { HttpClient } from '@angular/common/http'; +import { NotificationsService } from '../../../../shared/notifications/notifications.service'; +import { SearchData } from '../../../data/base/search-data'; +import { testSearchDataImplementation } from '../../../data/base/search-data.spec'; +import { SuggestionTargetDataService } from './suggestion-target-data.service'; +import { DefaultChangeAnalyzer } from '../../../data/default-change-analyzer.service'; +import { SuggestionTarget } from '../models/suggestion-target.model'; +import { testFindAllDataImplementation } from '../../../data/base/find-all-data.spec'; +import { FindAllData } from '../../../data/base/find-all-data'; +import { GetRequest } from '../../../data/request.models'; +import { + createSuccessfulRemoteDataObject$ +} from '../../../../shared/remote-data.utils'; +import { RequestParam } from '../../../cache/models/request-param.model'; +import { RemoteData } from '../../../data/remote-data'; +import { RequestEntryState } from '../../../data/request-entry-state.model'; + +describe('SuggestionTargetDataService test', () => { + let scheduler: TestScheduler; + let service: SuggestionTargetDataService; + let requestService: RequestService; + let rdbService: RemoteDataBuildService; + let objectCache: ObjectCacheService; + let halService: HALEndpointService; + let notificationsService: NotificationsService; + let http: HttpClient; + let comparator: DefaultChangeAnalyzer; + let responseCacheEntry: RequestEntry; + + const store = {} as Store; + const endpointURL = `https://rest.api/rest/api/suggestiontargets`; + const requestUUID = '8b3c613a-5a4b-438b-9686-be1d5b4a1c5a'; + + const remoteDataMocks = { + Success: new RemoteData(null, null, null, RequestEntryState.Success, null, null, 200), + }; + + function initTestService() { + return new SuggestionTargetDataService( + requestService, + rdbService, + store, + objectCache, + halService, + notificationsService, + http, + comparator + ); + } + + beforeEach(() => { + scheduler = getTestScheduler(); + + objectCache = {} as ObjectCacheService; + http = {} as HttpClient; + notificationsService = {} as NotificationsService; + comparator = {} as DefaultChangeAnalyzer; + responseCacheEntry = new RequestEntry(); + responseCacheEntry.request = { href: 'https://rest.api/' } as any; + responseCacheEntry.response = new RestResponse(true, 200, 'Success'); + + requestService = jasmine.createSpyObj('requestService', { + generateRequestId: requestUUID, + send: true, + removeByHrefSubstring: {}, + getByHref: observableOf(responseCacheEntry), + getByUUID: observableOf(responseCacheEntry), + }); + + halService = jasmine.createSpyObj('halService', { + getEndpoint: observableOf(endpointURL) + }); + + rdbService = jasmine.createSpyObj('rdbService', { + buildSingle: createSuccessfulRemoteDataObject$({}, 500), + buildList: cold('a', { a: remoteDataMocks.Success }) + }); + + + service = initTestService(); + }); + + describe('composition', () => { + const initSearchService = () => new SuggestionTargetDataService(null, null, null, null, null, null, null, null) as unknown as SearchData; + const initFindAllService = () => new SuggestionTargetDataService(null, null, null, null, null, null, null, null) as unknown as FindAllData; + testSearchDataImplementation(initSearchService); + testFindAllDataImplementation(initFindAllService); + }); + + describe('getTargetById', () => { + it('should send a new GetRequest', () => { + const expected = new GetRequest(requestService.generateRequestId(), endpointURL + '/testId'); + scheduler.schedule(() => service.getTargetById('testId').subscribe()); + scheduler.flush(); + + expect(requestService.send).toHaveBeenCalledWith(expected, true); + }); + }); + + describe('getTargetsByUser', () => { + it('should send a new GetRequest', () => { + const options = { + searchParams: [new RequestParam('target', 'testId')] + }; + const searchFindByTargetMethod = 'findByTarget'; + const expected = new GetRequest(requestService.generateRequestId(), `${endpointURL}/search/${searchFindByTargetMethod}?target=testId`); + scheduler.schedule(() => service.getTargetsByUser('testId', options).subscribe()); + scheduler.flush(); + + expect(requestService.send).toHaveBeenCalledWith(expected, true); + }); + }); + + describe('getTargets', () => { + it('should send a new GetRequest', () => { + const options = { + searchParams: [new RequestParam('source', 'testId')] + }; + const searchFindBySourceMethod = 'findBySource'; + const expected = new GetRequest(requestService.generateRequestId(), `${endpointURL}/search/${searchFindBySourceMethod}?source=testId`); + scheduler.schedule(() => service.getTargets('testId', options).subscribe()); + scheduler.flush(); + + expect(requestService.send).toHaveBeenCalledWith(expected, true); + }); + }); +}); From d16bf492687306cff03a053032aa696e928c0d31 Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Tue, 9 Jan 2024 21:48:27 +0100 Subject: [PATCH 11/44] add tests --- .../cache/builders/build-decorators.spec.ts | 8 +- .../suggestion-data.service.spec.ts | 173 ++++++++++++++++++ .../suggestions-data.service.ts | 2 +- ...o-selector-modal-wrapper.component.spec.ts | 30 ++- ...filter-input-suggestions.component.spec.ts | 27 +++ 5 files changed, 237 insertions(+), 3 deletions(-) create mode 100644 src/app/core/suggestion-notifications/reciter-suggestions/suggestion-data.service.spec.ts diff --git a/src/app/core/cache/builders/build-decorators.spec.ts b/src/app/core/cache/builders/build-decorators.spec.ts index 150a07f0066..90d4b4fef83 100644 --- a/src/app/core/cache/builders/build-decorators.spec.ts +++ b/src/app/core/cache/builders/build-decorators.spec.ts @@ -1,7 +1,7 @@ import { HALLink } from '../../shared/hal-link.model'; import { HALResource } from '../../shared/hal-resource.model'; import { ResourceType } from '../../shared/resource-type'; -import { getLinkDefinition, link } from './build-decorators'; +import { dataService, getLinkDefinition, link } from './build-decorators'; class TestHALResource implements HALResource { _links: { @@ -46,5 +46,11 @@ describe('build decorators', () => { expect(result).toBeUndefined(); }); }); + + describe(`set data service`, () => { + it(`should throw error`, () => { + expect(dataService(null)).toThrow(); + }); + }); }); }); diff --git a/src/app/core/suggestion-notifications/reciter-suggestions/suggestion-data.service.spec.ts b/src/app/core/suggestion-notifications/reciter-suggestions/suggestion-data.service.spec.ts new file mode 100644 index 00000000000..93b29eff068 --- /dev/null +++ b/src/app/core/suggestion-notifications/reciter-suggestions/suggestion-data.service.spec.ts @@ -0,0 +1,173 @@ +import { TestScheduler } from 'rxjs/testing'; +import { SuggestionDataServiceImpl, SuggestionsDataService } from './suggestions-data.service'; +import { RequestService } from '../../data/request.service'; +import { RemoteDataBuildService } from '../../cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../../cache/object-cache.service'; +import { HALEndpointService } from '../../shared/hal-endpoint.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { HttpClient } from '@angular/common/http'; +import { DefaultChangeAnalyzer } from '../../data/default-change-analyzer.service'; +import { Suggestion } from './models/suggestion.model'; +import { cold, getTestScheduler } from 'jasmine-marbles'; +import { RequestEntry } from '../../data/request-entry.model'; +import { RestResponse } from '../../cache/response.models'; +import { of as observableOf } from 'rxjs'; +import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; +import { RemoteData } from '../../data/remote-data'; +import { RequestEntryState } from '../../data/request-entry-state.model'; +import { SuggestionSource } from './models/suggestion-source.model'; +import { SuggestionTarget } from './models/suggestion-target.model'; +import { SuggestionSourceDataService } from './source/suggestion-source-data.service'; +import { SuggestionTargetDataService } from './target/suggestion-target-data.service'; +import { RequestParam } from '../../cache/models/request-param.model'; + +describe('SuggestionDataService test', () => { + let scheduler: TestScheduler; + let service: SuggestionsDataService; + let requestService: RequestService; + let rdbService: RemoteDataBuildService; + let objectCache: ObjectCacheService; + let halService: HALEndpointService; + let notificationsService: NotificationsService; + let http: HttpClient; + let comparatorSuggestion: DefaultChangeAnalyzer; + let comparatorSuggestionSource: DefaultChangeAnalyzer; + let comparatorSuggestionTarget: DefaultChangeAnalyzer; + let suggestionSourcesDataService: SuggestionSourceDataService; + let suggestionTargetsDataService: SuggestionTargetDataService; + let suggestionsDataService: SuggestionDataServiceImpl; + let responseCacheEntry: RequestEntry; + + + const testSource = 'test-source'; + const testUserId = '1234-4321'; + const endpointURL = `https://rest.api/rest/api/`; + const requestUUID = '8b3c613a-5a4b-438b-9686-be1d5b4a1c5a'; + const remoteDataMocks = { + Success: new RemoteData(null, null, null, RequestEntryState.Success, null, null, 200), + }; + + function initTestService() { + return new SuggestionsDataService( + requestService, + rdbService, + objectCache, + halService, + notificationsService, + http, + comparatorSuggestion, + comparatorSuggestionSource, + comparatorSuggestionTarget + ); + } + + beforeEach(() => { + scheduler = getTestScheduler(); + + objectCache = {} as ObjectCacheService; + http = {} as HttpClient; + notificationsService = {} as NotificationsService; + comparatorSuggestion = {} as DefaultChangeAnalyzer; + comparatorSuggestionTarget = {} as DefaultChangeAnalyzer; + comparatorSuggestionSource = {} as DefaultChangeAnalyzer; + responseCacheEntry = new RequestEntry(); + responseCacheEntry.request = { href: 'https://rest.api/' } as any; + responseCacheEntry.response = new RestResponse(true, 200, 'Success'); + + requestService = jasmine.createSpyObj('requestService', { + generateRequestId: requestUUID, + send: true, + removeByHrefSubstring: {}, + getByHref: observableOf(responseCacheEntry), + getByUUID: observableOf(responseCacheEntry), + setStaleByHrefSubstring: observableOf(true) + }); + + halService = jasmine.createSpyObj('halService', { + getEndpoint: observableOf(endpointURL) + }); + + rdbService = jasmine.createSpyObj('rdbService', { + buildSingle: createSuccessfulRemoteDataObject$({}, 500), + buildList: cold('a', { a: remoteDataMocks.Success }) + }); + + + suggestionSourcesDataService = jasmine.createSpyObj('suggestionSourcesDataService', { + getSources: observableOf(null), + }); + + suggestionTargetsDataService = jasmine.createSpyObj('suggestionTargetsDataService', { + getTargets: observableOf(null), + getTargetsByUser: observableOf(null), + findById: observableOf(null), + }); + + suggestionsDataService = jasmine.createSpyObj('suggestionsDataService', { + searchBy: observableOf(null), + delete: observableOf(null), + }); + + + service = initTestService(); + /* eslint-disable-next-line @typescript-eslint/dot-notation */ + service['suggestionSourcesDataService'] = suggestionSourcesDataService; + /* eslint-disable-next-line @typescript-eslint/dot-notation */ + service['suggestionTargetsDataService'] = suggestionTargetsDataService; + /* eslint-disable-next-line @typescript-eslint/dot-notation */ + service['suggestionsDataService'] = suggestionsDataService; + }); + + describe('Suggestion targets service', () => { + it('should call suggestionSourcesDataService.getTargets', () => { + const options = { + searchParams: [new RequestParam('source', testSource)] + }; + service.getTargets(testSource); + expect(suggestionTargetsDataService.getTargets).toHaveBeenCalledWith('findBySource', options); + }); + + it('should call suggestionSourcesDataService.getTargetsByUser', () => { + const options = { + searchParams: [new RequestParam('target', testUserId)] + }; + service.getTargetsByUser(testUserId); + expect(suggestionTargetsDataService.getTargetsByUser).toHaveBeenCalledWith(testUserId, options); + }); + + it('should call suggestionSourcesDataService.getTargetById', () => { + service.getTargetById('1'); + expect(suggestionTargetsDataService.findById).toHaveBeenCalledWith('1'); + }); + }); + + + describe('Suggestion sources service', () => { + it('should call suggestionSourcesDataService.getSources', () => { + service.getSources(); + expect(suggestionSourcesDataService.getSources).toHaveBeenCalled(); + }); + }); + + describe('Suggestion service', () => { + it('should call suggestionsDataService.searchBy', () => { + const options = { + searchParams: [new RequestParam('target', testUserId), new RequestParam('source', testSource)] + }; + service.getSuggestionsByTargetAndSource(testUserId, testSource); + expect(suggestionsDataService.searchBy).toHaveBeenCalledWith('findByTargetAndSource', options, true, true); + }); + + it('should call suggestionsDataService.delete', () => { + service.deleteSuggestion('1'); + expect(suggestionsDataService.delete).toHaveBeenCalledWith('1'); + }); + }); + + describe('Request service', () => { + it('should call requestService.setStaleByHrefSubstring', () => { + service.clearSuggestionRequests(); + expect(requestService.setStaleByHrefSubstring).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/app/core/suggestion-notifications/reciter-suggestions/suggestions-data.service.ts b/src/app/core/suggestion-notifications/reciter-suggestions/suggestions-data.service.ts index 407ea6a7e65..58fb1650319 100644 --- a/src/app/core/suggestion-notifications/reciter-suggestions/suggestions-data.service.ts +++ b/src/app/core/suggestion-notifications/reciter-suggestions/suggestions-data.service.ts @@ -116,7 +116,7 @@ export class SuggestionsDataService { } /** - * Return the list of Suggestion Target + * Return the list of Suggestion Sources * * @param options * Find list options object. diff --git a/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.spec.ts b/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.spec.ts index e2dbaaa0fff..edefff85922 100644 --- a/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.spec.ts +++ b/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.spec.ts @@ -5,13 +5,14 @@ import { DSpaceObjectType } from '../../../core/shared/dspace-object-type.model' import { Item } from '../../../core/shared/item.model'; import { DSOSelectorModalWrapperComponent, SelectorActionType } from './dso-selector-modal-wrapper.component'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; -import { ActivatedRoute } from '@angular/router'; +import { ActivatedRoute, ActivatedRouteSnapshot } from '@angular/router'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { By } from '@angular/platform-browser'; import { DSOSelectorComponent } from '../dso-selector/dso-selector.component'; import { MockComponent } from 'ng-mocks'; import { MetadataValue } from '../../../core/shared/metadata.models'; import { createSuccessfulRemoteDataObject } from '../../remote-data.utils'; +import { hasValue } from '../../empty.util'; describe('DSOSelectorModalWrapperComponent', () => { let component: DSOSelectorModalWrapperComponent; @@ -83,6 +84,20 @@ describe('DSOSelectorModalWrapperComponent', () => { }); }); + describe('selectObject with emit only', () => { + beforeEach(() => { + spyOn(component, 'navigate'); + spyOn(component, 'close'); + spyOn(component.select, 'emit'); + component.emitOnly = true; + component.selectObject(item); + }); + it('should call the close and navigate method on the component with the given DSO', () => { + expect(component.close).toHaveBeenCalled(); + expect(component.select.emit).toHaveBeenCalledWith(item); + }); + }); + describe('close', () => { beforeEach(() => { component.close(); @@ -113,6 +128,19 @@ describe('DSOSelectorModalWrapperComponent', () => { expect(component.close).toHaveBeenCalled(); }); }); + + describe('should find route data', () => { + beforeEach(() => { + spyOn(component, 'findRouteData'); + component.ngOnInit(); + }); + it('should call the findRouteData method on the component', () => { + expect(component.findRouteData).toHaveBeenCalled(); + }); + it('should return undefined', () => { + expect(component.findRouteData((route) => hasValue(route.data), {} as unknown as ActivatedRouteSnapshot)).toEqual(undefined); + }); + }); }); @Component({ diff --git a/src/app/shared/input-suggestions/filter-suggestions/filter-input-suggestions.component.spec.ts b/src/app/shared/input-suggestions/filter-suggestions/filter-input-suggestions.component.spec.ts index 6a0324d2ac4..6a67d84c288 100644 --- a/src/app/shared/input-suggestions/filter-suggestions/filter-input-suggestions.component.spec.ts +++ b/src/app/shared/input-suggestions/filter-suggestions/filter-input-suggestions.component.spec.ts @@ -54,4 +54,31 @@ describe('FilterInputSuggestionsComponent', () => { expect(comp.onClickSuggestion).toHaveBeenCalledWith(suggestions[clickedIndex]); }); }); + + describe('component methods', () => { + const testData = { + value: 'test-field' + } as unknown as any; + + beforeEach(() => { + spyOn(comp.submitSuggestion, 'emit'); + spyOn(comp.clickSuggestion, 'emit'); + spyOn(comp, 'close'); + }); + + it('should properly submit', () => { + comp.onSubmit(testData); + expect(comp.submitSuggestion.emit).toHaveBeenCalledWith(testData); + expect(comp.value).toBe(testData); + }); + + it('should update value on suggestion clicked', () => { + comp.onClickSuggestion(testData); + expect(comp.clickSuggestion.emit).toHaveBeenCalledWith(testData); + expect(comp.value).toBe(testData.value); + expect(comp.blockReopen).toBeTruthy(); + expect(comp.close).toHaveBeenCalled(); + }); + }); + }); From 6fda2cb4f78df2883fbdb60e1860b5d1fcae1211 Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Wed, 10 Jan 2024 12:57:13 +0100 Subject: [PATCH 12/44] add tests --- .../shared/mocks/reciter-suggestion.mock.ts | 2 +- src/app/shared/mocks/suggestion.mock.ts | 13 +- .../suggestion-list-element.component.spec.ts | 81 ++++++++ .../suggestion.service.spec.ts | 194 ++++++++++++++++++ .../suggestions-page.component.spec.ts | 112 +++++++++- 5 files changed, 398 insertions(+), 4 deletions(-) create mode 100644 src/app/suggestion-notifications/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.spec.ts create mode 100644 src/app/suggestion-notifications/reciter-suggestions/suggestion.service.spec.ts diff --git a/src/app/shared/mocks/reciter-suggestion.mock.ts b/src/app/shared/mocks/reciter-suggestion.mock.ts index aceca72fc8f..b2dd0e7b128 100644 --- a/src/app/shared/mocks/reciter-suggestion.mock.ts +++ b/src/app/shared/mocks/reciter-suggestion.mock.ts @@ -6,7 +6,7 @@ import { Suggestion } from '../../core/suggestion-notifications/reciter-suggesti import { SUGGESTION } from '../../core/suggestion-notifications/reciter-suggestions/models/suggestion-objects.resource-type'; export const mockSuggestionPublicationOne: Suggestion = { - id: '24694772', + id: '24694773', display: 'publication one', source: 'reciter', externalSourceUri: 'https://dspace7.4science.cloud/server/api/integration/reciterSourcesEntry/pubmed/entryValues/24694772', diff --git a/src/app/shared/mocks/suggestion.mock.ts b/src/app/shared/mocks/suggestion.mock.ts index 8b1ab7acd55..d4ada21bf8d 100644 --- a/src/app/shared/mocks/suggestion.mock.ts +++ b/src/app/shared/mocks/suggestion.mock.ts @@ -1,6 +1,7 @@ import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { Item } from '../../core/shared/item.model'; import { SearchResult } from '../search/models/search-result.model'; +import { of as observableOf } from 'rxjs'; // REST Mock --------------------------------------------------------------------- // ------------------------------------------------------------------------------- @@ -1333,7 +1334,8 @@ export function getMockSuggestionNotificationsStateService(): any { getOpenaireBrokerTopicsCurrentPage: jasmine.createSpy('getOpenaireBrokerTopicsCurrentPage'), getOpenaireBrokerTopicsTotals: jasmine.createSpy('getOpenaireBrokerTopicsTotals'), dispatchRetrieveOpenaireBrokerTopics: jasmine.createSpy('dispatchRetrieveOpenaireBrokerTopics'), - dispatchMarkUserSuggestionsAsVisitedAction: jasmine.createSpy('dispatchMarkUserSuggestionsAsVisitedAction') + dispatchMarkUserSuggestionsAsVisitedAction: jasmine.createSpy('dispatchMarkUserSuggestionsAsVisitedAction'), + dispatchRefreshUserSuggestionsAction: undefined }); } /** @@ -1342,10 +1344,17 @@ export function getMockSuggestionNotificationsStateService(): any { export function getMockSuggestionsService(): any { return jasmine.createSpyObj('SuggestionsService', { getTargets: jasmine.createSpy('getTargets'), - getSuggestions: jasmine.createSpy('getSuggestions'), + getSuggestions: observableOf([]), clearSuggestionRequests: jasmine.createSpy('clearSuggestionRequests'), deleteReviewedSuggestion: jasmine.createSpy('deleteReviewedSuggestion'), retrieveCurrentUserSuggestions: jasmine.createSpy('retrieveCurrentUserSuggestions'), getTargetUuid: jasmine.createSpy('getTargetUuid'), + notMine: observableOf(null), + notMineMultiple: observableOf({success: 1, fails: 0}), + approveAndImportMultiple: observableOf({success: 1, fails: 0}), + approveAndImport: observableOf({id: '1234'}), + isCollectionFixed: false, + translateSuggestionSource: 'testSource', + translateSuggestionType: 'testType', }); } diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.spec.ts b/src/app/suggestion-notifications/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.spec.ts new file mode 100644 index 00000000000..544b53774e7 --- /dev/null +++ b/src/app/suggestion-notifications/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.spec.ts @@ -0,0 +1,81 @@ +import { SuggestionListElementComponent } from './suggestion-list-element.component'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { TestScheduler } from 'rxjs/testing'; +import { getTestScheduler } from 'jasmine-marbles'; +import { mockSuggestionPublicationOne } from '../../../shared/mocks/reciter-suggestion.mock'; +import { Item } from '../../../core/shared/item.model'; + + +describe('SuggestionListElementComponent', () => { + let component: SuggestionListElementComponent; + let fixture: ComponentFixture; + let scheduler: TestScheduler; + + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + TranslateModule.forRoot() + ], + declarations: [SuggestionListElementComponent], + providers: [ + NgbModal + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents().then(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SuggestionListElementComponent); + component = fixture.componentInstance; + scheduler = getTestScheduler(); + + component.object = mockSuggestionPublicationOne; + }); + + describe('SuggestionListElementComponent test', () => { + + it('should create', () => { + scheduler.schedule(() => fixture.detectChanges()); + scheduler.flush(); + const expectedIndexableObject = Object.assign(new Item(), { + id: mockSuggestionPublicationOne.id, + metadata: mockSuggestionPublicationOne.metadata + }); + expect(component).toBeTruthy(); + expect(component.listableObject.hitHighlights).toEqual({}); + expect(component.listableObject.indexableObject).toEqual(expectedIndexableObject); + }); + + it('should check if has evidence', () => { + expect(component.hasEvidences()).toBeTruthy(); + }); + + it('should set seeEvidences', () => { + component.onSeeEvidences(true); + expect(component.seeEvidence).toBeTruthy(); + }); + + it('should emit selection', () => { + spyOn(component.selected, 'next'); + component.changeSelected({target: { checked: true}}); + expect(component.selected.next).toHaveBeenCalledWith(true); + }); + + it('should emit for deletion', () => { + spyOn(component.notMineClicked, 'emit'); + component.onNotMine('1234'); + expect(component.notMineClicked.emit).toHaveBeenCalledWith('1234'); + }); + + it('should emit for approve and import', () => { + const event = {collectionId:'1234', suggestion: mockSuggestionPublicationOne}; + spyOn(component.approveAndImport, 'emit'); + component.onApproveAndImport(event); + expect(component.approveAndImport.emit).toHaveBeenCalledWith(event); + }); + }); +}); diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestion.service.spec.ts b/src/app/suggestion-notifications/reciter-suggestions/suggestion.service.spec.ts new file mode 100644 index 00000000000..6abed7a1ce1 --- /dev/null +++ b/src/app/suggestion-notifications/reciter-suggestions/suggestion.service.spec.ts @@ -0,0 +1,194 @@ +import { SuggestionsService } from './suggestions.service'; +import { AuthService } from '../../core/auth/auth.service'; +import { ResearcherProfileDataService } from '../../core/profile/researcher-profile-data.service'; +import { + SuggestionsDataService +} from '../../core/suggestion-notifications/reciter-suggestions/suggestions-data.service'; +import { + SuggestionSourceDataService +} from '../../core/suggestion-notifications/reciter-suggestions/source/suggestion-source-data.service'; +import { + SuggestionTargetDataService +} from '../../core/suggestion-notifications/reciter-suggestions/target/suggestion-target-data.service'; +import { TestScheduler } from 'rxjs/testing'; +import { getTestScheduler } from 'jasmine-marbles'; +import { of as observableOf } from 'rxjs'; +import { FindListOptions } from '../../core/data/find-list-options.model'; +import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; +import { ResearcherProfile } from '../../core/profile/model/researcher-profile.model'; +import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; +import { WorkspaceitemDataService } from '../../core/submission/workspaceitem-data.service'; +import { mockSuggestionPublicationOne } from '../../shared/mocks/reciter-suggestion.mock'; +import { ResourceType } from '../../core/shared/resource-type'; + + +import { + SuggestionTarget +} from '../../core/suggestion-notifications/reciter-suggestions/models/suggestion-target.model'; + +describe('SuggestionsService test', () => { + let scheduler: TestScheduler; + let service: SuggestionsService; + let authService: AuthService; + let researcherProfileService: ResearcherProfileDataService; + let suggestionsDataService: SuggestionsDataService; + let suggestionSourceDataService: SuggestionSourceDataService; + let suggestionTargetDataService: SuggestionTargetDataService; + let translateService: any = { + instant: (str) => str, + }; + const suggestionTarget = { + id: '1234:4321', + display: 'display', + source: 'source', + total: 8, + type: new ResourceType('suggestiontarget') + }; + + const mockResercherProfile = { + id: '1234', + uuid: '1234', + visible: true + }; + + function initTestService() { + return new SuggestionsService( + authService, + researcherProfileService, + suggestionsDataService, + suggestionSourceDataService, + suggestionTargetDataService, + translateService + ); + } + + beforeEach(() => { + scheduler = getTestScheduler(); + + + suggestionSourceDataService = jasmine.createSpyObj('suggestionSourcesDataService', { + getSources: observableOf(null), + }); + + researcherProfileService = jasmine.createSpyObj('researcherProfileService', { + findById: createSuccessfulRemoteDataObject$(mockResercherProfile as ResearcherProfile), + findRelatedItemId: observableOf('1234'), + }); + + suggestionTargetDataService = jasmine.createSpyObj('suggestionTargetsDataService', { + getTargets: observableOf(null), + findById: observableOf(null), + }); + + suggestionsDataService = jasmine.createSpyObj('suggestionsDataService', { + searchBy: observableOf(null), + delete: observableOf(null), + deleteSuggestion: createSuccessfulRemoteDataObject$({}), + getSuggestionsByTargetAndSource : observableOf(null), + clearSuggestionRequests : null, + getTargetsByUser: observableOf(null), + }); + + service = initTestService(); + + }); + + describe('Suggestion service', () => { + it('should create', () => { + expect(service).toBeDefined(); + }); + + it('should get targets', () => { + const sortOptions = new SortOptions('display', SortDirection.ASC); + const findListOptions: FindListOptions = { + elementsPerPage: 10, + currentPage: 1, + sort: sortOptions + }; + service.getTargets('source', 10, 1); + expect(suggestionTargetDataService.getTargets).toHaveBeenCalledWith('source', findListOptions); + }); + + it('should get suggestions', () => { + const sortOptions = new SortOptions('display', SortDirection.ASC); + const findListOptions: FindListOptions = { + elementsPerPage: 10, + currentPage: 1, + sort: sortOptions + }; + service.getSuggestions('source:target', 10, 1, sortOptions); + expect(suggestionsDataService.getSuggestionsByTargetAndSource).toHaveBeenCalledWith('target', 'source', findListOptions); + }); + + it('should clear suggestions', () => { + service.clearSuggestionRequests(); + expect(suggestionsDataService.clearSuggestionRequests).toHaveBeenCalled(); + }); + + it('should delete reviewed suggestion', () => { + service.deleteReviewedSuggestion('1234'); + expect(suggestionsDataService.deleteSuggestion).toHaveBeenCalledWith('1234'); + }); + + it('should retrieve current user suggestions', () => { + service.retrieveCurrentUserSuggestions('1234'); + expect(researcherProfileService.findById).toHaveBeenCalledWith('1234'); + }); + + it('should approve and import suggestion', () => { + spyOn(service, 'resolveCollectionId'); + const workspaceitemService = {importExternalSourceEntry: (x,y) => observableOf(null)}; + service.approveAndImport(workspaceitemService as unknown as WorkspaceitemDataService, mockSuggestionPublicationOne, '1234'); + expect(service.resolveCollectionId).toHaveBeenCalled(); + }); + + it('should approve and import suggestions', () => { + spyOn(service, 'approveAndImport'); + const workspaceitemService = {importExternalSourceEntry: (x,y) => observableOf(null)}; + service.approveAndImportMultiple(workspaceitemService as unknown as WorkspaceitemDataService, [mockSuggestionPublicationOne], '1234'); + expect(service.approveAndImport).toHaveBeenCalledWith(workspaceitemService as unknown as WorkspaceitemDataService, mockSuggestionPublicationOne, '1234'); + }); + + it('should delete suggestion', () => { + spyOn(service, 'deleteReviewedSuggestion').and.returnValue(createSuccessfulRemoteDataObject$({})); + service.notMine('1234'); + expect(service.deleteReviewedSuggestion).toHaveBeenCalledWith('1234'); + }); + + it('should delete suggestions', () => { + spyOn(service, 'notMine'); + service.notMineMultiple([mockSuggestionPublicationOne]); + expect(service.notMine).toHaveBeenCalledWith(mockSuggestionPublicationOne.id); + }); + + it('should get target Uuid', () => { + expect(service.getTargetUuid(suggestionTarget as SuggestionTarget)).toBe('4321'); + expect(service.getTargetUuid({id: ''} as SuggestionTarget)).toBe(null); + }); + + it('should get suggestion interpolation', () => { + const result = service.getNotificationSuggestionInterpolation(suggestionTarget as SuggestionTarget); + expect(result.count).toEqual(suggestionTarget.total); + expect(result.source).toEqual('reciter.suggestion.source.' + suggestionTarget.source); + expect(result.type).toEqual('reciter.suggestion.type.' + suggestionTarget.source); + expect(result.suggestionId).toEqual(suggestionTarget.id); + expect(result.displayName).toEqual(suggestionTarget.display); + }); + + it('should translate suggestion type', () => { + expect(service.translateSuggestionType('source')).toEqual('reciter.suggestion.type.source'); + }); + + it('should translate suggestion source', () => { + expect(service.translateSuggestionSource('source')).toEqual('reciter.suggestion.source.source'); + }); + + it('should resolve collection id', () => { + expect(service.resolveCollectionId(mockSuggestionPublicationOne, '1234')).toEqual('1234'); + }); + + it('should check if collection is fixed', () => { + expect(service.isCollectionFixed([mockSuggestionPublicationOne])).toBeFalse(); + }); + }); +}); diff --git a/src/app/suggestions-page/suggestions-page.component.spec.ts b/src/app/suggestions-page/suggestions-page.component.spec.ts index 61e66a99cf7..0b0e235082d 100644 --- a/src/app/suggestions-page/suggestions-page.component.spec.ts +++ b/src/app/suggestions-page/suggestions-page.component.spec.ts @@ -7,7 +7,10 @@ import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { of as observableOf } from 'rxjs'; import { SuggestionsPageComponent } from './suggestions-page.component'; -import { SuggestionListElementComponent } from '../suggestion-notifications/reciter-suggestions/suggestion-list-element/suggestion-list-element.component'; +import { + SuggestionApproveAndImport, + SuggestionListElementComponent +} from '../suggestion-notifications/reciter-suggestions/suggestion-list-element/suggestion-list-element.component'; import { SuggestionsService } from '../suggestion-notifications/reciter-suggestions/suggestions.service'; import { getMockSuggestionNotificationsStateService, getMockSuggestionsService } from '../shared/mocks/suggestion.mock'; import { buildPaginatedList, PaginatedList } from '../core/data/paginated-list.model'; @@ -104,4 +107,111 @@ describe('SuggestionPageComponent', () => { expect(component.researcherName).toBe(mockSuggestionTargetsObjectOne.display); expect(component.updatePage).toHaveBeenCalled(); }); + + it('should update page on pagination change', () => { + spyOn(component, 'updatePage').and.stub(); + + scheduler.schedule(() => fixture.detectChanges()); + scheduler.flush(); + component.onPaginationChange(); + expect(component.updatePage).toHaveBeenCalled(); + }); + + it('should update suggestion on page update', (done) => { + spyOn(component.processing$, 'next'); + spyOn(component.suggestionsRD$, 'next'); + + scheduler.schedule(() => fixture.detectChanges()); + scheduler.flush(); + paginationService.getFindListOptions().subscribe(() => { + expect(component.processing$.next).toHaveBeenCalled(); + expect(mockSuggestionsService.getSuggestions).toHaveBeenCalled(); + expect(component.suggestionsRD$.next).toHaveBeenCalled(); + expect(mockSuggestionsService.clearSuggestionRequests).toHaveBeenCalled(); + done(); + }); + component.updatePage(); + }); + + it('should flag suggestion for deletion', () => { + spyOn(component, 'updatePage').and.stub(); + + scheduler.schedule(() => fixture.detectChanges()); + scheduler.flush(); + component.notMine('1'); + expect(mockSuggestionsService.notMine).toHaveBeenCalledWith('1'); + expect(mockSuggestionsTargetStateService.dispatchRefreshUserSuggestionsAction).toHaveBeenCalled(); + expect(component.updatePage).toHaveBeenCalled(); + }); + + it('should flag all suggestion for deletion', () => { + spyOn(component, 'updatePage').and.stub(); + + scheduler.schedule(() => fixture.detectChanges()); + scheduler.flush(); + component.notMineAllSelected(); + expect(mockSuggestionsService.notMineMultiple).toHaveBeenCalled(); + expect(mockSuggestionsTargetStateService.dispatchRefreshUserSuggestionsAction).toHaveBeenCalled(); + expect(component.updatePage).toHaveBeenCalled(); + }); + + it('should approve and import', () => { + spyOn(component, 'updatePage').and.stub(); + + scheduler.schedule(() => fixture.detectChanges()); + scheduler.flush(); + component.approveAndImport({collectionId: '1234'} as unknown as SuggestionApproveAndImport); + expect(mockSuggestionsService.approveAndImport).toHaveBeenCalled(); + expect(mockSuggestionsTargetStateService.dispatchRefreshUserSuggestionsAction).toHaveBeenCalled(); + expect(component.updatePage).toHaveBeenCalled(); + }); + + it('should approve and import multiple suggestions', () => { + spyOn(component, 'updatePage').and.stub(); + + scheduler.schedule(() => fixture.detectChanges()); + scheduler.flush(); + component.approveAndImportAllSelected({collectionId: '1234'} as unknown as SuggestionApproveAndImport); + expect(mockSuggestionsService.approveAndImportMultiple).toHaveBeenCalled(); + expect(mockSuggestionsTargetStateService.dispatchRefreshUserSuggestionsAction).toHaveBeenCalled(); + expect(component.updatePage).toHaveBeenCalled(); + }); + + it('should select and deselect suggestion', () => { + component.selectedSuggestions = {}; + component.onSelected(mockSuggestionPublicationOne, true); + expect(component.selectedSuggestions[mockSuggestionPublicationOne.id]).toBe(mockSuggestionPublicationOne); + component.onSelected(mockSuggestionPublicationOne, false); + expect(component.selectedSuggestions[mockSuggestionPublicationOne.id]).toBeUndefined(); + }); + + it('should toggle all suggestions', () => { + component.selectedSuggestions = {}; + component.onToggleSelectAll([mockSuggestionPublicationOne, mockSuggestionPublicationTwo]); + expect(component.selectedSuggestions[mockSuggestionPublicationOne.id]).toEqual(mockSuggestionPublicationOne); + expect(component.selectedSuggestions[mockSuggestionPublicationTwo.id]).toEqual(mockSuggestionPublicationTwo); + component.onToggleSelectAll([mockSuggestionPublicationOne, mockSuggestionPublicationTwo]); + expect(component.selectedSuggestions).toEqual({}); + }); + + it('should return all selected suggestions count', () => { + component.selectedSuggestions = {}; + component.onToggleSelectAll([mockSuggestionPublicationOne, mockSuggestionPublicationTwo]); + expect(component.getSelectedSuggestionsCount()).toEqual(2); + }); + + it('should check if all collection is fixed', () => { + component.isCollectionFixed([mockSuggestionPublicationOne, mockSuggestionPublicationTwo]); + expect(mockSuggestionsService.isCollectionFixed).toHaveBeenCalled(); + }); + + it('should translate suggestion source', () => { + component.translateSuggestionSource(); + expect(mockSuggestionsService.translateSuggestionSource).toHaveBeenCalled(); + }); + + it('should translate suggestion type', () => { + component.translateSuggestionType(); + expect(mockSuggestionsService.translateSuggestionType).toHaveBeenCalled(); + }); }); From 4dedda3f9f990d0f353d886d16afd83630239201 Mon Sep 17 00:00:00 2001 From: frabacche Date: Tue, 23 Jan 2024 14:30:07 +0100 Subject: [PATCH 13/44] CST-5249_suggestion refactor label name openaire --- src/assets/i18n/en.json5 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 29fa6a01800..0e5ea850740 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -3612,13 +3612,13 @@ "reciter.suggestion.suggestionFor": "Suggestion for", - "reciter.suggestion.source.oaire": "OpenAIRE Graph", + "reciter.suggestion.source.openaire": "OpenAIRE Graph", "reciter.suggestion.from.source": "from the ", "reciter.suggestion.totalScore": "Total Score", - "reciter.suggestion.type.oaire": "OpenAIRE", + "reciter.suggestion.type.openaire": "OpenAIRE", "register-email.title": "New user registration", From 2bb421c7cf06865a49773e8142cc6dd7f92ca42f Mon Sep 17 00:00:00 2001 From: frabacche Date: Tue, 23 Jan 2024 17:44:49 +0100 Subject: [PATCH 14/44] CST-5249_suggestion community first code review --- .../admin-notifications-routing-paths.ts | 2 +- .../admin-notifications-routing.module.ts | 4 +-- src/app/menu.resolver.ts | 4 +-- .../suggestion-actions.component.html | 7 ++-- .../suggestion-list-element.component.html | 4 ++- .../suggestion-targets.component.html | 4 +-- .../suggestion-targets.component.ts | 1 - .../suggestions-page.component.html | 6 ++-- src/assets/i18n/en.json5 | 4 --- src/themes/custom/eager-theme.module.ts | 33 ++++++++++--------- 10 files changed, 35 insertions(+), 34 deletions(-) diff --git a/src/app/admin/admin-notifications/admin-notifications-routing-paths.ts b/src/app/admin/admin-notifications/admin-notifications-routing-paths.ts index 870458fa9f1..7ae141335fd 100644 --- a/src/app/admin/admin-notifications/admin-notifications-routing-paths.ts +++ b/src/app/admin/admin-notifications/admin-notifications-routing-paths.ts @@ -2,7 +2,7 @@ import { URLCombiner } from '../../core/url-combiner/url-combiner'; import { getNotificationsModuleRoute } from '../admin-routing-paths'; export const QUALITY_ASSURANCE_EDIT_PATH = 'quality-assurance'; -export const NOTIFICATIONS_RECITER_SUGGESTION_PATH = 'suggestion-targets'; +export const PUBLICATION_CLAIMS_PATH = 'publication-claims'; export function getQualityAssuranceRoute(id: string) { return new URLCombiner(getNotificationsModuleRoute(), QUALITY_ASSURANCE_EDIT_PATH, id).toString(); diff --git a/src/app/admin/admin-notifications/admin-notifications-routing.module.ts b/src/app/admin/admin-notifications/admin-notifications-routing.module.ts index 9692b65d929..782c592e5de 100644 --- a/src/app/admin/admin-notifications/admin-notifications-routing.module.ts +++ b/src/app/admin/admin-notifications/admin-notifications-routing.module.ts @@ -4,7 +4,7 @@ import { RouterModule } from '@angular/router'; import { AuthenticatedGuard } from '../../core/auth/authenticated.guard'; import { I18nBreadcrumbResolver } from '../../core/breadcrumbs/i18n-breadcrumb.resolver'; import { I18nBreadcrumbsService } from '../../core/breadcrumbs/i18n-breadcrumbs.service'; -import { NOTIFICATIONS_RECITER_SUGGESTION_PATH } from './admin-notifications-routing-paths'; +import { PUBLICATION_CLAIMS_PATH } from './admin-notifications-routing-paths'; import { AdminNotificationsSuggestionTargetsPageComponent } from './admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component'; import { AdminNotificationsSuggestionTargetsPageResolver } from './admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page-resolver.service'; import { QUALITY_ASSURANCE_EDIT_PATH } from './admin-notifications-routing-paths'; @@ -25,7 +25,7 @@ import { RouterModule.forChild([ { canActivate: [ AuthenticatedGuard ], - path: `${NOTIFICATIONS_RECITER_SUGGESTION_PATH}`, + path: `${PUBLICATION_CLAIMS_PATH}`, component: AdminNotificationsSuggestionTargetsPageComponent, pathMatch: 'full', resolve: { diff --git a/src/app/menu.resolver.ts b/src/app/menu.resolver.ts index 506f30d6a5d..b5d8608d061 100644 --- a/src/app/menu.resolver.ts +++ b/src/app/menu.resolver.ts @@ -47,7 +47,7 @@ import { import { ExportBatchSelectorComponent } from './shared/dso-selector/modal-wrappers/export-batch-selector/export-batch-selector.component'; -import { NOTIFICATIONS_RECITER_SUGGESTION_PATH } from './admin/admin-notifications/admin-notifications-routing-paths'; +import { PUBLICATION_CLAIMS_PATH } from './admin/admin-notifications/admin-notifications-routing-paths'; /** * Creates all of the app's menus @@ -568,7 +568,7 @@ export class MenuResolver implements Resolve { model: { type: MenuItemType.LINK, text: 'menu.section.notifications_reciter', - link: '/admin/notifications/' + NOTIFICATIONS_RECITER_SUGGESTION_PATH + link: '/admin/notifications/' + PUBLICATION_CLAIMS_PATH } as LinkMenuItemModel, }, /* Admin Search */ diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestion-actions/suggestion-actions.component.html b/src/app/suggestion-notifications/reciter-suggestions/suggestion-actions/suggestion-actions.component.html index 7ec3e61395e..4d9fdb8b8e2 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/suggestion-actions/suggestion-actions.component.html +++ b/src/app/suggestion-notifications/reciter-suggestions/suggestion-actions/suggestion-actions.component.html @@ -21,8 +21,9 @@
- diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.html b/src/app/suggestion-notifications/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.html index f37d595c45b..5054f8806a5 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.html +++ b/src/app/suggestion-notifications/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.html @@ -4,7 +4,8 @@
+ [checked]="isSelected" (change)="changeSelected($event)" + [attr.aria-label]="object.display"/>
@@ -19,6 +20,7 @@ diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.component.html b/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.component.html index 280f574ec4c..04e967c3d54 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.component.html +++ b/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.component.html @@ -1,7 +1,7 @@
- +

{{'reciter.suggestion.title'| translate}}

{{'reciter.suggestion.title'| transla - {{targetElement.display}} + {{targetElement.display}}
diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.component.ts b/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.component.ts index e5524765da0..cfa168e2b83 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.component.ts +++ b/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.component.ts @@ -136,7 +136,6 @@ export class SuggestionTargetsComponent implements OnInit { distinctUntilChanged(), take(1) ).subscribe((options: PaginationComponentOptions) => { - console.log('HELLO suggestion called!', options); this.suggestionTargetsStateService.dispatchRetrieveReciterSuggestionTargets( this.source, options.pageSize, diff --git a/src/app/suggestions-page/suggestions-page.component.html b/src/app/suggestions-page/suggestions-page.component.html index fb5f08b6a4c..59b6f58c5fc 100644 --- a/src/app/suggestions-page/suggestions-page.component.html +++ b/src/app/suggestions-page/suggestions-page.component.html @@ -4,12 +4,12 @@
-

+

{{ translateSuggestionType() | translate }} {{'reciter.suggestion.suggestionFor' | translate}} - {{researcherName}} + {{researcherName}} {{'reciter.suggestion.from.source' | translate}} {{ translateSuggestionSource() | translate }} -

+
diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index dea20aa1a50..0e5ea850740 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1774,10 +1774,6 @@ "form.repeatable.sort.tip": "Drop the item in the new position", - "form.number-picker.decrement": "Decrement {{field}}", - - "form.number-picker.increment": "Increment {{field}}", - "grant-deny-request-copy.deny": "Don't send copy", "grant-deny-request-copy.email.back": "Back", diff --git a/src/themes/custom/eager-theme.module.ts b/src/themes/custom/eager-theme.module.ts index 31047e239ac..8889c0c3df1 100644 --- a/src/themes/custom/eager-theme.module.ts +++ b/src/themes/custom/eager-theme.module.ts @@ -102,21 +102,24 @@ const DECLARATIONS = [ ]; @NgModule({ - imports: [ - CommonModule, - SharedModule, - RootModule, - NavbarModule, - SharedBrowseByModule, - ResultsBackButtonModule, - ItemPageModule, - ItemSharedModule, - DsoPageModule, - ], - declarations: DECLARATIONS, - providers: [ - ...ENTRY_COMPONENTS.map((component) => ({provide: component})) - ], + imports: [ + CommonModule, + SharedModule, + RootModule, + NavbarModule, + SharedBrowseByModule, + ResultsBackButtonModule, + ItemPageModule, + ItemSharedModule, + DsoPageModule, + ], + declarations: DECLARATIONS, + providers: [ + ...ENTRY_COMPONENTS.map((component) => ({ provide: component })) + ], + exports: [ + ItemSearchResultListElementComponent + ] }) /** * This module is included in the main bundle that gets downloaded at first page load. So it should From afa6559b19e410cab444e865b26300a9e338babc Mon Sep 17 00:00:00 2001 From: frabacche Date: Wed, 24 Jan 2024 18:32:21 +0100 Subject: [PATCH 15/44] CST-5249_suggestion refactor deleting 'reciter', docs --- ...ublication-claim-page-resolver.service.ts} | 6 +- ...ons-publication-claim-page.component.html} | 0 ...ons-publication-claim-page.component.scss} | 0 ...-publication-claim-page.component.spec.ts} | 2 +- ...ations-publication-claim-page.component.ts | 10 +++ .../admin-notifications-routing-paths.ts | 2 +- .../admin-notifications-routing.module.ts | 12 ++-- ...tions-suggestion-targets-page.component.ts | 10 --- .../admin-notifications.module.ts | 2 +- src/app/core/core.module.ts | 4 +- .../suggestion-objects.resource-type.ts | 2 +- .../suggestion-source-object.resource-type.ts | 2 +- .../models/suggestion-source.model.ts | 10 +-- .../suggestion-target-object.resource-type.ts | 2 +- .../models/suggestion-target.model.ts | 10 +-- .../models/suggestion.model.ts | 15 ++-- .../source/suggestion-source-data.service.ts | 31 ++++---- .../suggestions-source-data.service.spec.ts | 30 ++++---- .../suggestion-data.service.spec.ts | 24 +++---- .../suggestions-data.service.ts | 32 ++++----- .../target/suggestion-target-data.service.ts | 32 ++++----- .../suggestions-target-data.service.spec.ts | 36 +++++----- src/app/menu.resolver.ts | 4 +- .../notifications/notifications-effects.ts | 2 +- src/app/notifications/notifications.module.ts | 22 +++--- .../notifications/notifications.reducer.ts | 2 +- ...k.ts => publication-claim-targets.mock.ts} | 2 +- ...tion.mock.ts => publication-claim.mock.ts} | 4 +- src/app/shared/mocks/suggestion.mock.ts | 4 +- .../{reciter-suggestions => }/selectors.ts | 56 +++++++-------- .../suggestion-actions.component.html | 4 +- .../suggestion-actions.component.scss | 0 .../suggestion-actions.component.ts | 21 +++--- .../suggestion-evidences.component.html | 0 .../suggestion-evidences.component.scss | 0 .../suggestion-evidences.component.ts | 7 +- .../suggestion-list-element.component.html | 2 +- .../suggestion-list-element.component.scss | 0 .../suggestion-list-element.component.spec.ts | 10 +-- .../suggestion-list-element.component.ts | 22 +++--- .../suggestion-targets.actions.ts | 4 +- .../suggestion-targets.component.html | 5 +- .../suggestion-targets.component.scss | 0 .../suggestion-targets.component.ts | 22 +++--- .../suggestion-targets.effects.ts | 6 +- .../suggestion-targets.reducer.ts | 2 +- .../suggestion-targets.state.service.ts | 70 +++++++++---------- .../suggestion.service.spec.ts | 32 ++++----- .../suggestions-notification.component.html | 0 .../suggestions-notification.component.scss | 0 .../suggestions-notification.component.ts | 11 +-- .../suggestions-popup.component.html | 0 .../suggestions-popup.component.scss | 0 .../suggestions-popup.component.spec.ts | 6 +- .../suggestions-popup.component.ts | 19 ++--- .../suggestions.service.ts | 47 +++++++------ .../suggestions-page-routing.module.ts | 11 +-- .../suggestions-page.component.html | 4 +- .../suggestions-page.component.spec.ts | 18 ++--- .../suggestions-page.component.ts | 18 ++--- .../suggestions-page.module.ts | 4 +- .../suggestions-page.resolver.ts | 4 +- src/assets/i18n/en.json5 | 68 +++++++++--------- 63 files changed, 410 insertions(+), 377 deletions(-) rename src/app/admin/admin-notifications/{admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page-resolver.service.ts => admin-notifications-publication-claim-page/admin-notifications-publication-claim-page-resolver.service.ts} (78%) rename src/app/admin/admin-notifications/{admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.html => admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.html} (100%) rename src/app/admin/admin-notifications/{admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.scss => admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.scss} (100%) rename src/app/admin/admin-notifications/{admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.spec.ts => admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.spec.ts} (95%) create mode 100644 src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.ts delete mode 100644 src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.ts rename src/app/core/suggestion-notifications/{reciter-suggestions => }/models/suggestion-objects.resource-type.ts (76%) rename src/app/core/suggestion-notifications/{reciter-suggestions => }/models/suggestion-source-object.resource-type.ts (77%) rename src/app/core/suggestion-notifications/{reciter-suggestions => }/models/suggestion-source.model.ts (71%) rename src/app/core/suggestion-notifications/{reciter-suggestions => }/models/suggestion-target-object.resource-type.ts (77%) rename src/app/core/suggestion-notifications/{reciter-suggestions => }/models/suggestion-target.model.ts (75%) rename src/app/core/suggestion-notifications/{reciter-suggestions => }/models/suggestion.model.ts (74%) rename src/app/core/suggestion-notifications/{reciter-suggestions => }/source/suggestion-source-data.service.ts (80%) rename src/app/core/suggestion-notifications/{reciter-suggestions => }/source/suggestions-source-data.service.spec.ts (76%) rename src/app/core/suggestion-notifications/{reciter-suggestions => }/suggestion-data.service.spec.ts (87%) rename src/app/core/suggestion-notifications/{reciter-suggestions => }/suggestions-data.service.ts (87%) rename src/app/core/suggestion-notifications/{reciter-suggestions => }/target/suggestion-target-data.service.ts (83%) rename src/app/core/suggestion-notifications/{reciter-suggestions => }/target/suggestions-target-data.service.spec.ts (77%) rename src/app/shared/mocks/{reciter-suggestion-targets.mock.ts => publication-claim-targets.mock.ts} (96%) rename src/app/shared/mocks/{reciter-suggestion.mock.ts => publication-claim.mock.ts} (98%) rename src/app/suggestion-notifications/{reciter-suggestions => }/selectors.ts (50%) rename src/app/suggestion-notifications/{reciter-suggestions => }/suggestion-actions/suggestion-actions.component.html (89%) rename src/app/suggestion-notifications/{reciter-suggestions => }/suggestion-actions/suggestion-actions.component.scss (100%) rename src/app/suggestion-notifications/{reciter-suggestions => }/suggestion-actions/suggestion-actions.component.ts (73%) rename src/app/suggestion-notifications/{reciter-suggestions => }/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.html (100%) rename src/app/suggestion-notifications/{reciter-suggestions => }/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.scss (100%) rename src/app/suggestion-notifications/{reciter-suggestions => }/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.ts (58%) rename src/app/suggestion-notifications/{reciter-suggestions => }/suggestion-list-element/suggestion-list-element.component.html (95%) rename src/app/suggestion-notifications/{reciter-suggestions => }/suggestion-list-element/suggestion-list-element.component.scss (100%) rename src/app/suggestion-notifications/{reciter-suggestions => }/suggestion-list-element/suggestion-list-element.component.spec.ts (88%) rename src/app/suggestion-notifications/{reciter-suggestions => }/suggestion-list-element/suggestion-list-element.component.ts (77%) rename src/app/suggestion-notifications/{reciter-suggestions => }/suggestion-targets/suggestion-targets.actions.ts (96%) rename src/app/suggestion-notifications/{reciter-suggestions => }/suggestion-targets/suggestion-targets.component.html (87%) rename src/app/suggestion-notifications/{reciter-suggestions => }/suggestion-targets/suggestion-targets.component.scss (100%) rename src/app/suggestion-notifications/{reciter-suggestions => }/suggestion-targets/suggestion-targets.component.ts (80%) rename src/app/suggestion-notifications/{reciter-suggestions => }/suggestion-targets/suggestion-targets.effects.ts (91%) rename src/app/suggestion-notifications/{reciter-suggestions => }/suggestion-targets/suggestion-targets.reducer.ts (95%) rename src/app/suggestion-notifications/{reciter-suggestions => }/suggestion-targets/suggestion-targets.state.service.ts (54%) rename src/app/suggestion-notifications/{reciter-suggestions => }/suggestion.service.spec.ts (83%) rename src/app/suggestion-notifications/{reciter-suggestions => }/suggestions-notification/suggestions-notification.component.html (100%) rename src/app/suggestion-notifications/{reciter-suggestions => }/suggestions-notification/suggestions-notification.component.scss (100%) rename src/app/suggestion-notifications/{reciter-suggestions => }/suggestions-notification/suggestions-notification.component.ts (75%) rename src/app/suggestion-notifications/{reciter-suggestions => }/suggestions-popup/suggestions-popup.component.html (100%) rename src/app/suggestion-notifications/{reciter-suggestions => }/suggestions-popup/suggestions-popup.component.scss (100%) rename src/app/suggestion-notifications/{reciter-suggestions => }/suggestions-popup/suggestions-popup.component.spec.ts (92%) rename src/app/suggestion-notifications/{reciter-suggestions => }/suggestions-popup/suggestions-popup.component.ts (75%) rename src/app/suggestion-notifications/{reciter-suggestions => }/suggestions.service.ts (84%) diff --git a/src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page-resolver.service.ts b/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page-resolver.service.ts similarity index 78% rename from src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page-resolver.service.ts rename to src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page-resolver.service.ts index df1f4b81e69..add9a504ddb 100644 --- a/src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page-resolver.service.ts +++ b/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page-resolver.service.ts @@ -4,7 +4,7 @@ import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/r /** * Interface for the route parameters. */ -export interface AdminNotificationsSuggestionTargetsPageParams { +export interface AdminNotificationsPublicationClaimPageParams { pageId?: string; pageSize?: number; currentPage?: number; @@ -14,7 +14,7 @@ export interface AdminNotificationsSuggestionTargetsPageParams { * This class represents a resolver that retrieve the route data before the route is activated. */ @Injectable() -export class AdminNotificationsSuggestionTargetsPageResolver implements Resolve { +export class AdminNotificationsPublicationClaimPageResolver implements Resolve { /** * Method for resolving the parameters in the current route. @@ -22,7 +22,7 @@ export class AdminNotificationsSuggestionTargetsPageResolver implements Resolve< * @param {RouterStateSnapshot} state The current RouterStateSnapshot * @returns AdminNotificationsSuggestionTargetsPageParams Emits the route parameters */ - resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): AdminNotificationsSuggestionTargetsPageParams { + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): AdminNotificationsPublicationClaimPageParams { return { pageId: route.queryParams.pageId, pageSize: parseInt(route.queryParams.pageSize, 10), diff --git a/src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.html b/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.html similarity index 100% rename from src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.html rename to src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.html diff --git a/src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.scss b/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.scss similarity index 100% rename from src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.scss rename to src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.scss diff --git a/src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.spec.ts b/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.spec.ts similarity index 95% rename from src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.spec.ts rename to src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.spec.ts index f9e407f4021..c0209da8988 100644 --- a/src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.spec.ts +++ b/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.spec.ts @@ -1,6 +1,6 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { AdminNotificationsSuggestionTargetsPageComponent } from './admin-notifications-suggestion-targets-page.component'; +import { AdminNotificationsSuggestionTargetsPageComponent } from './admin-notifications-publication-claim-page.component'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { CommonModule } from '@angular/common'; import { TranslateModule } from '@ngx-translate/core'; diff --git a/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.ts b/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.ts new file mode 100644 index 00000000000..10023ead934 --- /dev/null +++ b/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'ds-admin-notifications-publication-claim-page', + templateUrl: './admin-notifications-publication-claim-page.component.html', + styleUrls: ['./admin-notifications-publication-claim-page.component.scss'] +}) +export class AdminNotificationsSuggestionTargetsPageComponent { + +} diff --git a/src/app/admin/admin-notifications/admin-notifications-routing-paths.ts b/src/app/admin/admin-notifications/admin-notifications-routing-paths.ts index 7ae141335fd..f92a96d2422 100644 --- a/src/app/admin/admin-notifications/admin-notifications-routing-paths.ts +++ b/src/app/admin/admin-notifications/admin-notifications-routing-paths.ts @@ -2,7 +2,7 @@ import { URLCombiner } from '../../core/url-combiner/url-combiner'; import { getNotificationsModuleRoute } from '../admin-routing-paths'; export const QUALITY_ASSURANCE_EDIT_PATH = 'quality-assurance'; -export const PUBLICATION_CLAIMS_PATH = 'publication-claims'; +export const PUBLICATION_CLAIMS_PATH = 'publication-claim'; export function getQualityAssuranceRoute(id: string) { return new URLCombiner(getNotificationsModuleRoute(), QUALITY_ASSURANCE_EDIT_PATH, id).toString(); diff --git a/src/app/admin/admin-notifications/admin-notifications-routing.module.ts b/src/app/admin/admin-notifications/admin-notifications-routing.module.ts index 782c592e5de..648bdc0a1f1 100644 --- a/src/app/admin/admin-notifications/admin-notifications-routing.module.ts +++ b/src/app/admin/admin-notifications/admin-notifications-routing.module.ts @@ -5,8 +5,8 @@ import { AuthenticatedGuard } from '../../core/auth/authenticated.guard'; import { I18nBreadcrumbResolver } from '../../core/breadcrumbs/i18n-breadcrumb.resolver'; import { I18nBreadcrumbsService } from '../../core/breadcrumbs/i18n-breadcrumbs.service'; import { PUBLICATION_CLAIMS_PATH } from './admin-notifications-routing-paths'; -import { AdminNotificationsSuggestionTargetsPageComponent } from './admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component'; -import { AdminNotificationsSuggestionTargetsPageResolver } from './admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page-resolver.service'; +import { AdminNotificationsSuggestionTargetsPageComponent } from './admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component'; +import { AdminNotificationsPublicationClaimPageResolver } from './admin-notifications-publication-claim-page/admin-notifications-publication-claim-page-resolver.service'; import { QUALITY_ASSURANCE_EDIT_PATH } from './admin-notifications-routing-paths'; import { AdminQualityAssuranceTopicsPageComponent } from './admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component'; import { AdminQualityAssuranceEventsPageComponent } from './admin-quality-assurance-events-page/admin-quality-assurance-events-page.component'; @@ -30,11 +30,11 @@ import { pathMatch: 'full', resolve: { breadcrumb: I18nBreadcrumbResolver, - reciterSuggestionTargetParams: AdminNotificationsSuggestionTargetsPageResolver + suggestionTargetParams: AdminNotificationsPublicationClaimPageResolver }, data: { - title: 'admin.notifications.recitersuggestion.page.title', - breadcrumbKey: 'admin.notifications.recitersuggestion', + title: 'admin.notifications.publicationclaim.page.title', + breadcrumbKey: 'admin.notifications.publicationclaim', showBreadcrumbsFluid: false } }, @@ -89,7 +89,7 @@ import { providers: [ I18nBreadcrumbResolver, I18nBreadcrumbsService, - AdminNotificationsSuggestionTargetsPageResolver, + AdminNotificationsPublicationClaimPageResolver, SourceDataResolver, AdminQualityAssuranceSourcePageResolver, AdminQualityAssuranceTopicsPageResolver, diff --git a/src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.ts b/src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.ts deleted file mode 100644 index a9a77f50890..00000000000 --- a/src/app/admin/admin-notifications/admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component } from '@angular/core'; - -@Component({ - selector: 'ds-admin-notifications-reciter-page', - templateUrl: './admin-notifications-suggestion-targets-page.component.html', - styleUrls: ['./admin-notifications-suggestion-targets-page.component.scss'] -}) -export class AdminNotificationsSuggestionTargetsPageComponent { - -} diff --git a/src/app/admin/admin-notifications/admin-notifications.module.ts b/src/app/admin/admin-notifications/admin-notifications.module.ts index 93e184c9427..3566bdd91ad 100644 --- a/src/app/admin/admin-notifications/admin-notifications.module.ts +++ b/src/app/admin/admin-notifications/admin-notifications.module.ts @@ -3,7 +3,7 @@ import { NgModule } from '@angular/core'; import { CoreModule } from '../../core/core.module'; import { SharedModule } from '../../shared/shared.module'; import { AdminNotificationsRoutingModule } from './admin-notifications-routing.module'; -import { AdminNotificationsSuggestionTargetsPageComponent } from './admin-notifications-suggestion-targets-page/admin-notifications-suggestion-targets-page.component'; +import { AdminNotificationsSuggestionTargetsPageComponent } from './admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component'; import { AdminQualityAssuranceTopicsPageComponent } from './admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component'; import { AdminQualityAssuranceEventsPageComponent } from './admin-quality-assurance-events-page/admin-quality-assurance-events-page.component'; import { AdminQualityAssuranceSourcePageComponent } from './admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component'; diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index 987ab5e6034..f151f10f661 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -185,8 +185,8 @@ import { FlatBrowseDefinition } from './shared/flat-browse-definition.model'; import { ValueListBrowseDefinition } from './shared/value-list-browse-definition.model'; import { NonHierarchicalBrowseDefinition } from './shared/non-hierarchical-browse-definition'; 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 { SuggestionTarget } from './suggestion-notifications/models/suggestion-target.model'; +import { SuggestionSource } from './suggestion-notifications/models/suggestion-source.model'; /** * When not in production, endpoint responses can be mocked for testing purposes diff --git a/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-objects.resource-type.ts b/src/app/core/suggestion-notifications/models/suggestion-objects.resource-type.ts similarity index 76% rename from src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-objects.resource-type.ts rename to src/app/core/suggestion-notifications/models/suggestion-objects.resource-type.ts index 8f87027a8c5..8f83d86376b 100644 --- a/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-objects.resource-type.ts +++ b/src/app/core/suggestion-notifications/models/suggestion-objects.resource-type.ts @@ -1,4 +1,4 @@ -import { ResourceType } from '../../../shared/resource-type'; +import { ResourceType } from '../../shared/resource-type'; /** * The resource type for the Suggestion object diff --git a/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-source-object.resource-type.ts b/src/app/core/suggestion-notifications/models/suggestion-source-object.resource-type.ts similarity index 77% rename from src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-source-object.resource-type.ts rename to src/app/core/suggestion-notifications/models/suggestion-source-object.resource-type.ts index 2e26fe4301c..e319ed5109b 100644 --- a/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-source-object.resource-type.ts +++ b/src/app/core/suggestion-notifications/models/suggestion-source-object.resource-type.ts @@ -1,4 +1,4 @@ -import { ResourceType } from '../../../shared/resource-type'; +import { ResourceType } from '../../shared/resource-type'; /** * The resource type for the Suggestion Source object diff --git a/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-source.model.ts b/src/app/core/suggestion-notifications/models/suggestion-source.model.ts similarity index 71% rename from src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-source.model.ts rename to src/app/core/suggestion-notifications/models/suggestion-source.model.ts index 007520800d3..12d9d7e9d84 100644 --- a/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-source.model.ts +++ b/src/app/core/suggestion-notifications/models/suggestion-source.model.ts @@ -1,11 +1,11 @@ import { autoserialize, deserialize } from 'cerialize'; import { SUGGESTION_SOURCE } from './suggestion-source-object.resource-type'; -import { excludeFromEquals } from '../../../utilities/equals.decorators'; -import { ResourceType } from '../../../shared/resource-type'; -import { HALLink } from '../../../shared/hal-link.model'; -import { typedObject } from '../../../cache/builders/build-decorators'; -import {CacheableObject} from '../../../cache/cacheable-object.model'; +import { excludeFromEquals } from '../../utilities/equals.decorators'; +import { ResourceType } from '../../shared/resource-type'; +import { HALLink } from '../../shared/hal-link.model'; +import { typedObject } from '../../cache/builders/build-decorators'; +import {CacheableObject} from '../../cache/cacheable-object.model'; /** * The interface representing the Suggestion Source model diff --git a/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-target-object.resource-type.ts b/src/app/core/suggestion-notifications/models/suggestion-target-object.resource-type.ts similarity index 77% rename from src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-target-object.resource-type.ts rename to src/app/core/suggestion-notifications/models/suggestion-target-object.resource-type.ts index 71dd41912ac..81b1b5c2619 100644 --- a/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-target-object.resource-type.ts +++ b/src/app/core/suggestion-notifications/models/suggestion-target-object.resource-type.ts @@ -1,4 +1,4 @@ -import { ResourceType } from '../../../shared/resource-type'; +import { ResourceType } from '../../shared/resource-type'; /** * The resource type for the Suggestion Target object diff --git a/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-target.model.ts b/src/app/core/suggestion-notifications/models/suggestion-target.model.ts similarity index 75% rename from src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-target.model.ts rename to src/app/core/suggestion-notifications/models/suggestion-target.model.ts index 2afe170e777..99d9a8628ad 100644 --- a/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion-target.model.ts +++ b/src/app/core/suggestion-notifications/models/suggestion-target.model.ts @@ -1,12 +1,12 @@ import { autoserialize, deserialize } from 'cerialize'; -import { CacheableObject } from '../../../cache/cacheable-object.model'; +import { CacheableObject } from '../../cache/cacheable-object.model'; import { SUGGESTION_TARGET } from './suggestion-target-object.resource-type'; -import { excludeFromEquals } from '../../../utilities/equals.decorators'; -import { ResourceType } from '../../../shared/resource-type'; -import { HALLink } from '../../../shared/hal-link.model'; -import { typedObject } from '../../../cache/builders/build-decorators'; +import { excludeFromEquals } from '../../utilities/equals.decorators'; +import { ResourceType } from '../../shared/resource-type'; +import { HALLink } from '../../shared/hal-link.model'; +import { typedObject } from '../../cache/builders/build-decorators'; /** * The interface representing the Suggestion Target model diff --git a/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion.model.ts b/src/app/core/suggestion-notifications/models/suggestion.model.ts similarity index 74% rename from src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion.model.ts rename to src/app/core/suggestion-notifications/models/suggestion.model.ts index c36d36794b5..ad58b1cfe55 100644 --- a/src/app/core/suggestion-notifications/reciter-suggestions/models/suggestion.model.ts +++ b/src/app/core/suggestion-notifications/models/suggestion.model.ts @@ -1,13 +1,16 @@ import { autoserialize, autoserializeAs, deserialize } from 'cerialize'; import { SUGGESTION } from './suggestion-objects.resource-type'; -import { excludeFromEquals } from '../../../utilities/equals.decorators'; -import { ResourceType } from '../../../shared/resource-type'; -import { HALLink } from '../../../shared/hal-link.model'; -import { typedObject } from '../../../cache/builders/build-decorators'; -import { MetadataMap, MetadataMapSerializer } from '../../../shared/metadata.models'; -import {CacheableObject} from '../../../cache/cacheable-object.model'; +import { excludeFromEquals } from '../../utilities/equals.decorators'; +import { ResourceType } from '../../shared/resource-type'; +import { HALLink } from '../../shared/hal-link.model'; +import { typedObject } from '../../cache/builders/build-decorators'; +import { MetadataMap, MetadataMapSerializer } from '../../shared/metadata.models'; +import {CacheableObject} from '../../cache/cacheable-object.model'; +/** + * The interface representing Suggestion Evidences such as scores (authorScore, datescore) + */ export interface SuggestionEvidences { [sectionId: string]: { score: string; diff --git a/src/app/core/suggestion-notifications/reciter-suggestions/source/suggestion-source-data.service.ts b/src/app/core/suggestion-notifications/source/suggestion-source-data.service.ts similarity index 80% rename from src/app/core/suggestion-notifications/reciter-suggestions/source/suggestion-source-data.service.ts rename to src/app/core/suggestion-notifications/source/suggestion-source-data.service.ts index 15b067f2ed1..f00a84c95b5 100644 --- a/src/app/core/suggestion-notifications/reciter-suggestions/source/suggestion-source-data.service.ts +++ b/src/app/core/suggestion-notifications/source/suggestion-source-data.service.ts @@ -1,24 +1,27 @@ import { Injectable } from '@angular/core'; -import { dataService } from '../../../data/base/data-service.decorator'; +import { dataService } from '../../data/base/data-service.decorator'; import { SUGGESTION_SOURCE } from '../models/suggestion-source-object.resource-type'; -import { IdentifiableDataService } from '../../../data/base/identifiable-data.service'; +import { IdentifiableDataService } from '../../data/base/identifiable-data.service'; import { SuggestionSource } from '../models/suggestion-source.model'; -import { FindAllData, FindAllDataImpl } from '../../../data/base/find-all-data'; +import { FindAllData, FindAllDataImpl } from '../../data/base/find-all-data'; import { Store } from '@ngrx/store'; -import { RequestService } from '../../../data/request.service'; -import { RemoteDataBuildService } from '../../../cache/builders/remote-data-build.service'; -import { CoreState } from '../../../core-state.model'; -import { ObjectCacheService } from '../../../cache/object-cache.service'; -import { HALEndpointService } from '../../../shared/hal-endpoint.service'; -import { NotificationsService } from '../../../../shared/notifications/notifications.service'; +import { RequestService } from '../../data/request.service'; +import { RemoteDataBuildService } from '../../cache/builders/remote-data-build.service'; +import { CoreState } from '../../core-state.model'; +import { ObjectCacheService } from '../../cache/object-cache.service'; +import { HALEndpointService } from '../../shared/hal-endpoint.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; import { HttpClient } from '@angular/common/http'; -import { FindListOptions } from '../../../data/find-list-options.model'; -import { FollowLinkConfig } from '../../../../shared/utils/follow-link-config.model'; -import { PaginatedList } from '../../../data/paginated-list.model'; -import { RemoteData } from '../../../data/remote-data'; +import { FindListOptions } from '../../data/find-list-options.model'; +import { FollowLinkConfig } from '../../../shared/utils/follow-link-config.model'; +import { PaginatedList } from '../../data/paginated-list.model'; +import { RemoteData } from '../../data/remote-data'; import { Observable } from 'rxjs/internal/Observable'; -import { DefaultChangeAnalyzer } from '../../../data/default-change-analyzer.service'; +import { DefaultChangeAnalyzer } from '../../data/default-change-analyzer.service'; +/** + * Service that retrieves Suggestion Source data + */ @Injectable() @dataService(SUGGESTION_SOURCE) export class SuggestionSourceDataService extends IdentifiableDataService { diff --git a/src/app/core/suggestion-notifications/reciter-suggestions/source/suggestions-source-data.service.spec.ts b/src/app/core/suggestion-notifications/source/suggestions-source-data.service.spec.ts similarity index 76% rename from src/app/core/suggestion-notifications/reciter-suggestions/source/suggestions-source-data.service.spec.ts rename to src/app/core/suggestion-notifications/source/suggestions-source-data.service.spec.ts index 5f8d51a6410..28f34b863d8 100644 --- a/src/app/core/suggestion-notifications/reciter-suggestions/source/suggestions-source-data.service.spec.ts +++ b/src/app/core/suggestion-notifications/source/suggestions-source-data.service.spec.ts @@ -1,25 +1,25 @@ import { TestScheduler } from 'rxjs/testing'; -import { RequestService } from '../../../data/request.service'; -import { RemoteDataBuildService } from '../../../cache/builders/remote-data-build.service'; -import { ObjectCacheService } from '../../../cache/object-cache.service'; -import { HALEndpointService } from '../../../shared/hal-endpoint.service'; -import { RequestEntry } from '../../../data/request-entry.model'; +import { RequestService } from '../../data/request.service'; +import { RemoteDataBuildService } from '../../cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../../cache/object-cache.service'; +import { HALEndpointService } from '../../shared/hal-endpoint.service'; +import { RequestEntry } from '../../data/request-entry.model'; import { cold, getTestScheduler } from 'jasmine-marbles'; -import { RestResponse } from '../../../cache/response.models'; +import { RestResponse } from '../../cache/response.models'; import { of as observableOf } from 'rxjs'; import { Store } from '@ngrx/store'; -import { CoreState } from '../../../core-state.model'; +import { CoreState } from '../../core-state.model'; import { HttpClient } from '@angular/common/http'; -import { NotificationsService } from '../../../../shared/notifications/notifications.service'; -import { DefaultChangeAnalyzer } from '../../../data/default-change-analyzer.service'; -import { testFindAllDataImplementation } from '../../../data/base/find-all-data.spec'; -import { FindAllData } from '../../../data/base/find-all-data'; -import { GetRequest } from '../../../data/request.models'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { DefaultChangeAnalyzer } from '../../data/default-change-analyzer.service'; +import { testFindAllDataImplementation } from '../../data/base/find-all-data.spec'; +import { FindAllData } from '../../data/base/find-all-data'; +import { GetRequest } from '../../data/request.models'; import { createSuccessfulRemoteDataObject$ -} from '../../../../shared/remote-data.utils'; -import { RemoteData } from '../../../data/remote-data'; -import { RequestEntryState } from '../../../data/request-entry-state.model'; +} from '../../../shared/remote-data.utils'; +import { RemoteData } from '../../data/remote-data'; +import { RequestEntryState } from '../../data/request-entry-state.model'; import { SuggestionSourceDataService } from './suggestion-source-data.service'; import { SuggestionSource } from '../models/suggestion-source.model'; diff --git a/src/app/core/suggestion-notifications/reciter-suggestions/suggestion-data.service.spec.ts b/src/app/core/suggestion-notifications/suggestion-data.service.spec.ts similarity index 87% rename from src/app/core/suggestion-notifications/reciter-suggestions/suggestion-data.service.spec.ts rename to src/app/core/suggestion-notifications/suggestion-data.service.spec.ts index 93b29eff068..a854514c896 100644 --- a/src/app/core/suggestion-notifications/reciter-suggestions/suggestion-data.service.spec.ts +++ b/src/app/core/suggestion-notifications/suggestion-data.service.spec.ts @@ -1,25 +1,25 @@ import { TestScheduler } from 'rxjs/testing'; import { SuggestionDataServiceImpl, SuggestionsDataService } from './suggestions-data.service'; -import { RequestService } from '../../data/request.service'; -import { RemoteDataBuildService } from '../../cache/builders/remote-data-build.service'; -import { ObjectCacheService } from '../../cache/object-cache.service'; -import { HALEndpointService } from '../../shared/hal-endpoint.service'; -import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { RequestService } from '../data/request.service'; +import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../cache/object-cache.service'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; import { HttpClient } from '@angular/common/http'; -import { DefaultChangeAnalyzer } from '../../data/default-change-analyzer.service'; +import { DefaultChangeAnalyzer } from '../data/default-change-analyzer.service'; import { Suggestion } from './models/suggestion.model'; import { cold, getTestScheduler } from 'jasmine-marbles'; -import { RequestEntry } from '../../data/request-entry.model'; -import { RestResponse } from '../../cache/response.models'; +import { RequestEntry } from '../data/request-entry.model'; +import { RestResponse } from '../cache/response.models'; import { of as observableOf } from 'rxjs'; -import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; -import { RemoteData } from '../../data/remote-data'; -import { RequestEntryState } from '../../data/request-entry-state.model'; +import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; +import { RemoteData } from '../data/remote-data'; +import { RequestEntryState } from '../data/request-entry-state.model'; import { SuggestionSource } from './models/suggestion-source.model'; import { SuggestionTarget } from './models/suggestion-target.model'; import { SuggestionSourceDataService } from './source/suggestion-source-data.service'; import { SuggestionTargetDataService } from './target/suggestion-target-data.service'; -import { RequestParam } from '../../cache/models/request-param.model'; +import { RequestParam } from '../cache/models/request-param.model'; describe('SuggestionDataService test', () => { let scheduler: TestScheduler; diff --git a/src/app/core/suggestion-notifications/reciter-suggestions/suggestions-data.service.ts b/src/app/core/suggestion-notifications/suggestions-data.service.ts similarity index 87% rename from src/app/core/suggestion-notifications/reciter-suggestions/suggestions-data.service.ts rename to src/app/core/suggestion-notifications/suggestions-data.service.ts index 58fb1650319..72476f6a156 100644 --- a/src/app/core/suggestion-notifications/reciter-suggestions/suggestions-data.service.ts +++ b/src/app/core/suggestion-notifications/suggestions-data.service.ts @@ -5,26 +5,26 @@ import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; -import { HALEndpointService } from '../../shared/hal-endpoint.service'; -import { NotificationsService } from '../../../shared/notifications/notifications.service'; -import { RemoteDataBuildService } from '../../cache/builders/remote-data-build.service'; -import { ObjectCacheService } from '../../cache/object-cache.service'; -import { dataService } from '../../cache/builders/build-decorators'; -import { RequestService } from '../../data/request.service'; -import { DataService } from '../../data/data.service'; -import { ChangeAnalyzer } from '../../data/change-analyzer'; -import { DefaultChangeAnalyzer } from '../../data/default-change-analyzer.service'; -import { RemoteData } from '../../data/remote-data'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../cache/object-cache.service'; +import { dataService } from '../cache/builders/build-decorators'; +import { RequestService } from '../data/request.service'; +import { DataService } from '../data/data.service'; +import { ChangeAnalyzer } from '../data/change-analyzer'; +import { DefaultChangeAnalyzer } from '../data/default-change-analyzer.service'; +import { RemoteData } from '../data/remote-data'; import { SUGGESTION } from './models/suggestion-objects.resource-type'; -import { FollowLinkConfig } from '../../../shared/utils/follow-link-config.model'; -import { PaginatedList } from '../../data/paginated-list.model'; +import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; +import { PaginatedList } from '../data/paginated-list.model'; import { SuggestionSource } from './models/suggestion-source.model'; import { SuggestionTarget } from './models/suggestion-target.model'; import { Suggestion } from './models/suggestion.model'; -import { RequestParam } from '../../cache/models/request-param.model'; -import { NoContent } from '../../shared/NoContent.model'; -import {CoreState} from '../../core-state.model'; -import {FindListOptions} from '../../data/find-list-options.model'; +import { RequestParam } from '../cache/models/request-param.model'; +import { NoContent } from '../shared/NoContent.model'; +import {CoreState} from '../core-state.model'; +import {FindListOptions} from '../data/find-list-options.model'; import { SuggestionSourceDataService } from './source/suggestion-source-data.service'; import { SuggestionTargetDataService } from './target/suggestion-target-data.service'; diff --git a/src/app/core/suggestion-notifications/reciter-suggestions/target/suggestion-target-data.service.ts b/src/app/core/suggestion-notifications/target/suggestion-target-data.service.ts similarity index 83% rename from src/app/core/suggestion-notifications/reciter-suggestions/target/suggestion-target-data.service.ts rename to src/app/core/suggestion-notifications/target/suggestion-target-data.service.ts index 5a5f91a87b2..a2f1507b100 100644 --- a/src/app/core/suggestion-notifications/reciter-suggestions/target/suggestion-target-data.service.ts +++ b/src/app/core/suggestion-notifications/target/suggestion-target-data.service.ts @@ -1,25 +1,25 @@ import { Injectable } from '@angular/core'; -import { dataService } from '../../../data/base/data-service.decorator'; +import { dataService } from '../../data/base/data-service.decorator'; -import { IdentifiableDataService } from '../../../data/base/identifiable-data.service'; +import { IdentifiableDataService } from '../../data/base/identifiable-data.service'; import { SuggestionTarget } from '../models/suggestion-target.model'; -import { FindAllData, FindAllDataImpl } from '../../../data/base/find-all-data'; +import { FindAllData, FindAllDataImpl } from '../../data/base/find-all-data'; import { Store } from '@ngrx/store'; -import { RequestService } from '../../../data/request.service'; -import { RemoteDataBuildService } from '../../../cache/builders/remote-data-build.service'; -import { CoreState } from '../../../core-state.model'; -import { ObjectCacheService } from '../../../cache/object-cache.service'; -import { HALEndpointService } from '../../../shared/hal-endpoint.service'; -import { NotificationsService } from '../../../../shared/notifications/notifications.service'; +import { RequestService } from '../../data/request.service'; +import { RemoteDataBuildService } from '../../cache/builders/remote-data-build.service'; +import { CoreState } from '../../core-state.model'; +import { ObjectCacheService } from '../../cache/object-cache.service'; +import { HALEndpointService } from '../../shared/hal-endpoint.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; import { HttpClient } from '@angular/common/http'; -import { FindListOptions } from '../../../data/find-list-options.model'; -import { FollowLinkConfig } from '../../../../shared/utils/follow-link-config.model'; -import { PaginatedList } from '../../../data/paginated-list.model'; -import { RemoteData } from '../../../data/remote-data'; +import { FindListOptions } from '../../data/find-list-options.model'; +import { FollowLinkConfig } from '../../../shared/utils/follow-link-config.model'; +import { PaginatedList } from '../../data/paginated-list.model'; +import { RemoteData } from '../../data/remote-data'; import { Observable } from 'rxjs/internal/Observable'; -import { RequestParam } from '../../../cache/models/request-param.model'; -import { SearchData, SearchDataImpl } from '../../../data/base/search-data'; -import { DefaultChangeAnalyzer } from '../../../data/default-change-analyzer.service'; +import { RequestParam } from '../../cache/models/request-param.model'; +import { SearchData, SearchDataImpl } from '../../data/base/search-data'; +import { DefaultChangeAnalyzer } from '../../data/default-change-analyzer.service'; import { SUGGESTION_TARGET } from '../models/suggestion-target-object.resource-type'; @Injectable() diff --git a/src/app/core/suggestion-notifications/reciter-suggestions/target/suggestions-target-data.service.spec.ts b/src/app/core/suggestion-notifications/target/suggestions-target-data.service.spec.ts similarity index 77% rename from src/app/core/suggestion-notifications/reciter-suggestions/target/suggestions-target-data.service.spec.ts rename to src/app/core/suggestion-notifications/target/suggestions-target-data.service.spec.ts index ba5900b79fa..9207603a5ad 100644 --- a/src/app/core/suggestion-notifications/reciter-suggestions/target/suggestions-target-data.service.spec.ts +++ b/src/app/core/suggestion-notifications/target/suggestions-target-data.service.spec.ts @@ -1,30 +1,30 @@ import { TestScheduler } from 'rxjs/testing'; -import { RequestService } from '../../../data/request.service'; -import { RemoteDataBuildService } from '../../../cache/builders/remote-data-build.service'; -import { ObjectCacheService } from '../../../cache/object-cache.service'; -import { HALEndpointService } from '../../../shared/hal-endpoint.service'; -import { RequestEntry } from '../../../data/request-entry.model'; +import { RequestService } from '../../data/request.service'; +import { RemoteDataBuildService } from '../../cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../../cache/object-cache.service'; +import { HALEndpointService } from '../../shared/hal-endpoint.service'; +import { RequestEntry } from '../../data/request-entry.model'; import { cold, getTestScheduler } from 'jasmine-marbles'; -import { RestResponse } from '../../../cache/response.models'; +import { RestResponse } from '../../cache/response.models'; import { of as observableOf } from 'rxjs'; import { Store } from '@ngrx/store'; -import { CoreState } from '../../../core-state.model'; +import { CoreState } from '../../core-state.model'; import { HttpClient } from '@angular/common/http'; -import { NotificationsService } from '../../../../shared/notifications/notifications.service'; -import { SearchData } from '../../../data/base/search-data'; -import { testSearchDataImplementation } from '../../../data/base/search-data.spec'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { SearchData } from '../../data/base/search-data'; +import { testSearchDataImplementation } from '../../data/base/search-data.spec'; import { SuggestionTargetDataService } from './suggestion-target-data.service'; -import { DefaultChangeAnalyzer } from '../../../data/default-change-analyzer.service'; +import { DefaultChangeAnalyzer } from '../../data/default-change-analyzer.service'; import { SuggestionTarget } from '../models/suggestion-target.model'; -import { testFindAllDataImplementation } from '../../../data/base/find-all-data.spec'; -import { FindAllData } from '../../../data/base/find-all-data'; -import { GetRequest } from '../../../data/request.models'; +import { testFindAllDataImplementation } from '../../data/base/find-all-data.spec'; +import { FindAllData } from '../../data/base/find-all-data'; +import { GetRequest } from '../../data/request.models'; import { createSuccessfulRemoteDataObject$ -} from '../../../../shared/remote-data.utils'; -import { RequestParam } from '../../../cache/models/request-param.model'; -import { RemoteData } from '../../../data/remote-data'; -import { RequestEntryState } from '../../../data/request-entry-state.model'; +} from '../../../shared/remote-data.utils'; +import { RequestParam } from '../../cache/models/request-param.model'; +import { RemoteData } from '../../data/remote-data'; +import { RequestEntryState } from '../../data/request-entry-state.model'; describe('SuggestionTargetDataService test', () => { let scheduler: TestScheduler; diff --git a/src/app/menu.resolver.ts b/src/app/menu.resolver.ts index b5d8608d061..fc6eb00195c 100644 --- a/src/app/menu.resolver.ts +++ b/src/app/menu.resolver.ts @@ -561,13 +561,13 @@ export class MenuResolver implements Resolve { } as LinkMenuItemModel, }, { - id: 'notifications_reciter', + id: 'notifications_publication-claim', parentID: 'notifications', active: false, visible: authorized, model: { type: MenuItemType.LINK, - text: 'menu.section.notifications_reciter', + text: 'menu.section.notifications_publication-claim', link: '/admin/notifications/' + PUBLICATION_CLAIMS_PATH } as LinkMenuItemModel, }, diff --git a/src/app/notifications/notifications-effects.ts b/src/app/notifications/notifications-effects.ts index 9f19058aab4..a73fd04fc0e 100644 --- a/src/app/notifications/notifications-effects.ts +++ b/src/app/notifications/notifications-effects.ts @@ -1,6 +1,6 @@ import { QualityAssuranceSourceEffects } from './qa/source/quality-assurance-source.effects'; import { QualityAssuranceTopicsEffects } from './qa/topics/quality-assurance-topics.effects'; -import { SuggestionTargetsEffects } from '../suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.effects'; +import { SuggestionTargetsEffects } from '../suggestion-notifications/suggestion-targets/suggestion-targets.effects'; export const notificationsEffects = [ QualityAssuranceTopicsEffects, diff --git a/src/app/notifications/notifications.module.ts b/src/app/notifications/notifications.module.ts index 98832b86b78..cd8cb99811f 100644 --- a/src/app/notifications/notifications.module.ts +++ b/src/app/notifications/notifications.module.ts @@ -26,29 +26,29 @@ import { QualityAssuranceSourceService } from './qa/source/quality-assurance-sou import { QualityAssuranceSourceDataService } from '../core/notifications/qa/source/quality-assurance-source-data.service'; -import { SuggestionTargetsComponent } from '../suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.component'; -import { SuggestionActionsComponent } from '../suggestion-notifications/reciter-suggestions/suggestion-actions/suggestion-actions.component'; +import { SuggestionTargetsComponent } from '../suggestion-notifications/suggestion-targets/suggestion-targets.component'; +import { SuggestionActionsComponent } from '../suggestion-notifications/suggestion-actions/suggestion-actions.component'; import { SuggestionListElementComponent -} from '../suggestion-notifications/reciter-suggestions/suggestion-list-element/suggestion-list-element.component'; +} from '../suggestion-notifications/suggestion-list-element/suggestion-list-element.component'; import { SuggestionEvidencesComponent -} from '../suggestion-notifications/reciter-suggestions/suggestion-list-element/suggestion-evidences/suggestion-evidences.component'; -import { SuggestionsPopupComponent } from '../suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component'; +} from '../suggestion-notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component'; +import { SuggestionsPopupComponent } from '../suggestion-notifications/suggestions-popup/suggestions-popup.component'; import { SuggestionsNotificationComponent -} from '../suggestion-notifications/reciter-suggestions/suggestions-notification/suggestions-notification.component'; -import { SuggestionsService } from '../suggestion-notifications/reciter-suggestions/suggestions.service'; -import { SuggestionsDataService } from '../core/suggestion-notifications/reciter-suggestions/suggestions-data.service'; +} from '../suggestion-notifications/suggestions-notification/suggestions-notification.component'; +import { SuggestionsService } from '../suggestion-notifications/suggestions.service'; +import { SuggestionsDataService } from '../core/suggestion-notifications/suggestions-data.service'; import { SuggestionSourceDataService -} from '../core/suggestion-notifications/reciter-suggestions/source/suggestion-source-data.service'; +} from '../core/suggestion-notifications/source/suggestion-source-data.service'; import { SuggestionTargetDataService -} from '../core/suggestion-notifications/reciter-suggestions/target/suggestion-target-data.service'; +} from '../core/suggestion-notifications/target/suggestion-target-data.service'; import { SuggestionTargetsStateService -} from '../suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.state.service'; +} from '../suggestion-notifications/suggestion-targets/suggestion-targets.state.service'; const MODULES = [ diff --git a/src/app/notifications/notifications.reducer.ts b/src/app/notifications/notifications.reducer.ts index ba7fcc6c587..cced6755fa9 100644 --- a/src/app/notifications/notifications.reducer.ts +++ b/src/app/notifications/notifications.reducer.ts @@ -1,7 +1,7 @@ import { ActionReducerMap, createFeatureSelector } from '@ngrx/store'; import { qualityAssuranceSourceReducer, QualityAssuranceSourceState } from './qa/source/quality-assurance-source.reducer'; import { qualityAssuranceTopicsReducer, QualityAssuranceTopicState, } from './qa/topics/quality-assurance-topics.reducer'; -import { SuggestionTargetsReducer, SuggestionTargetState } from '../suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.reducer'; +import { SuggestionTargetsReducer, SuggestionTargetState } from '../suggestion-notifications/suggestion-targets/suggestion-targets.reducer'; /** * The OpenAIRE State diff --git a/src/app/shared/mocks/reciter-suggestion-targets.mock.ts b/src/app/shared/mocks/publication-claim-targets.mock.ts similarity index 96% rename from src/app/shared/mocks/reciter-suggestion-targets.mock.ts rename to src/app/shared/mocks/publication-claim-targets.mock.ts index 489bb7733d8..1d7688c1e3d 100644 --- a/src/app/shared/mocks/reciter-suggestion-targets.mock.ts +++ b/src/app/shared/mocks/publication-claim-targets.mock.ts @@ -1,5 +1,5 @@ import { ResourceType } from '../../core/shared/resource-type'; -import { SuggestionTarget } from '../../core/suggestion-notifications/reciter-suggestions/models/suggestion-target.model'; +import { SuggestionTarget } from '../../core/suggestion-notifications/models/suggestion-target.model'; // REST Mock --------------------------------------------------------------------- // ------------------------------------------------------------------------------- diff --git a/src/app/shared/mocks/reciter-suggestion.mock.ts b/src/app/shared/mocks/publication-claim.mock.ts similarity index 98% rename from src/app/shared/mocks/reciter-suggestion.mock.ts rename to src/app/shared/mocks/publication-claim.mock.ts index b2dd0e7b128..143b54d8dd7 100644 --- a/src/app/shared/mocks/reciter-suggestion.mock.ts +++ b/src/app/shared/mocks/publication-claim.mock.ts @@ -2,8 +2,8 @@ // REST Mock --------------------------------------------------------------------- // ------------------------------------------------------------------------------- -import { Suggestion } from '../../core/suggestion-notifications/reciter-suggestions/models/suggestion.model'; -import { SUGGESTION } from '../../core/suggestion-notifications/reciter-suggestions/models/suggestion-objects.resource-type'; +import { Suggestion } from '../../core/suggestion-notifications/models/suggestion.model'; +import { SUGGESTION } from '../../core/suggestion-notifications/models/suggestion-objects.resource-type'; export const mockSuggestionPublicationOne: Suggestion = { id: '24694773', diff --git a/src/app/shared/mocks/suggestion.mock.ts b/src/app/shared/mocks/suggestion.mock.ts index d4ada21bf8d..ed7f9045d56 100644 --- a/src/app/shared/mocks/suggestion.mock.ts +++ b/src/app/shared/mocks/suggestion.mock.ts @@ -1349,8 +1349,8 @@ export function getMockSuggestionsService(): any { deleteReviewedSuggestion: jasmine.createSpy('deleteReviewedSuggestion'), retrieveCurrentUserSuggestions: jasmine.createSpy('retrieveCurrentUserSuggestions'), getTargetUuid: jasmine.createSpy('getTargetUuid'), - notMine: observableOf(null), - notMineMultiple: observableOf({success: 1, fails: 0}), + ignoreSuggestion: observableOf(null), + ignoreSuggestionMultiple: observableOf({success: 1, fails: 0}), approveAndImportMultiple: observableOf({success: 1, fails: 0}), approveAndImport: observableOf({id: '1234'}), isCollectionFixed: false, diff --git a/src/app/suggestion-notifications/reciter-suggestions/selectors.ts b/src/app/suggestion-notifications/selectors.ts similarity index 50% rename from src/app/suggestion-notifications/reciter-suggestions/selectors.ts rename to src/app/suggestion-notifications/selectors.ts index f031b71711f..97ed3a83602 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/selectors.ts +++ b/src/app/suggestion-notifications/selectors.ts @@ -1,44 +1,44 @@ import {createFeatureSelector, createSelector, MemoizedSelector} from '@ngrx/store'; -import { suggestionNotificationsSelector, SuggestionNotificationsState } from '../../notifications/notifications.reducer'; -import { SuggestionTarget } from '../../core/suggestion-notifications/reciter-suggestions/models/suggestion-target.model'; +import { suggestionNotificationsSelector, SuggestionNotificationsState } from '../notifications/notifications.reducer'; +import { SuggestionTarget } from '../core/suggestion-notifications/models/suggestion-target.model'; import { SuggestionTargetState } from './suggestion-targets/suggestion-targets.reducer'; -import {subStateSelector} from '../../submission/selectors'; +import {subStateSelector} from '../submission/selectors'; /** * Returns the Reciter Suggestion Target state. - * @function _getReciterSuggestionTargetState + * @function _getSuggestionTargetState * @param {AppState} state Top level state. * @return {SuggestionNotificationsState} */ -const _getReciterSuggestionTargetState = createFeatureSelector('suggestionNotifications'); +const _getSuggestionTargetState = createFeatureSelector('suggestionNotifications'); // Reciter Suggestion Targets // ---------------------------------------------------------------------------- /** - * Returns the Reciter Suggestion Targets State. - * @function reciterSuggestionTargetStateSelector + * Returns the Suggestion Targets State. + * @function suggestionTargetStateSelector * @return {SuggestionNotificationsState} */ -export function reciterSuggestionTargetStateSelector(): MemoizedSelector { +export function suggestionTargetStateSelector(): MemoizedSelector { return subStateSelector(suggestionNotificationsSelector, 'suggestionTarget'); } /** - * Returns the Reciter Suggestion Targets list. - * @function reciterSuggestionTargetObjectSelector + * Returns the Suggestion Targets list. + * @function suggestionTargetObjectSelector * @return {SuggestionTarget[]} */ -export function reciterSuggestionTargetObjectSelector(): MemoizedSelector { - return subStateSelector(reciterSuggestionTargetStateSelector(), 'targets'); +export function suggestionTargetObjectSelector(): MemoizedSelector { + return subStateSelector(suggestionTargetStateSelector(), 'targets'); } /** - * Returns true if the Reciter Suggestion Targets are loaded. - * @function isReciterSuggestionTargetLoadedSelector + * Returns true if the Suggestion Targets are loaded. + * @function isSuggestionTargetLoadedSelector * @return {boolean} */ -export const isReciterSuggestionTargetLoadedSelector = createSelector(_getReciterSuggestionTargetState, +export const isSuggestionTargetLoadedSelector = createSelector(_getSuggestionTargetState, (state: SuggestionNotificationsState) => state.suggestionTarget.loaded ); @@ -47,51 +47,51 @@ export const isReciterSuggestionTargetLoadedSelector = createSelector(_getRecite * @function isDeduplicationSetsProcessingSelector * @return {boolean} */ -export const isReciterSuggestionTargetProcessingSelector = createSelector(_getReciterSuggestionTargetState, +export const isReciterSuggestionTargetProcessingSelector = createSelector(_getSuggestionTargetState, (state: SuggestionNotificationsState) => state.suggestionTarget.processing ); /** * Returns the total available pages of Reciter Suggestion Targets. - * @function getreciterSuggestionTargetTotalPagesSelector + * @function getSuggestionTargetTotalPagesSelector * @return {number} */ -export const getReciterSuggestionTargetTotalPagesSelector = createSelector(_getReciterSuggestionTargetState, +export const getSuggestionTargetTotalPagesSelector = createSelector(_getSuggestionTargetState, (state: SuggestionNotificationsState) => state.suggestionTarget.totalPages ); /** - * Returns the current page of Reciter Suggestion Targets. - * @function getreciterSuggestionTargetCurrentPageSelector + * Returns the current page of Suggestion Targets. + * @function getSuggestionTargetCurrentPageSelector * @return {number} */ -export const getReciterSuggestionTargetCurrentPageSelector = createSelector(_getReciterSuggestionTargetState, +export const getSuggestionTargetCurrentPageSelector = createSelector(_getSuggestionTargetState, (state: SuggestionNotificationsState) => state.suggestionTarget.currentPage ); /** - * Returns the total number of Reciter Suggestion Targets. - * @function getreciterSuggestionTargetTotalsSelector + * Returns the total number of Suggestion Targets. + * @function getSuggestionTargetTotalsSelector * @return {number} */ -export const getReciterSuggestionTargetTotalsSelector = createSelector(_getReciterSuggestionTargetState, +export const getSuggestionTargetTotalsSelector = createSelector(_getSuggestionTargetState, (state: SuggestionNotificationsState) => state.suggestionTarget.totalElements ); /** * Returns Suggestion Targets for the current user. - * @function getCurrentUserReciterSuggestionTargetSelector + * @function getCurrentUserSuggestionTargetSelector * @return {SuggestionTarget[]} */ -export const getCurrentUserSuggestionTargetsSelector = createSelector(_getReciterSuggestionTargetState, +export const getCurrentUserSuggestionTargetsSelector = createSelector(_getSuggestionTargetState, (state: SuggestionNotificationsState) => state.suggestionTarget.currentUserTargets ); /** * Returns whether or not the user has consulted their suggestions - * @function getCurrentUserReciterSuggestionTargetSelector + * @function getCurrentUserSuggestionTargetSelector * @return {boolean} */ -export const getCurrentUserSuggestionTargetsVisitedSelector = createSelector(_getReciterSuggestionTargetState, +export const getCurrentUserSuggestionTargetsVisitedSelector = createSelector(_getSuggestionTargetState, (state: SuggestionNotificationsState) => state.suggestionTarget.currentUserTargetsVisited ); diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestion-actions/suggestion-actions.component.html b/src/app/suggestion-notifications/suggestion-actions/suggestion-actions.component.html similarity index 89% rename from src/app/suggestion-notifications/reciter-suggestions/suggestion-actions/suggestion-actions.component.html rename to src/app/suggestion-notifications/suggestion-actions/suggestion-actions.component.html index 4d9fdb8b8e2..24e970a8182 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/suggestion-actions/suggestion-actions.component.html +++ b/src/app/suggestion-notifications/suggestion-actions/suggestion-actions.component.html @@ -19,8 +19,8 @@
- +
diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.scss b/src/app/suggestion-notifications/suggestion-list-element/suggestion-list-element.component.scss similarity index 100% rename from src/app/suggestion-notifications/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.scss rename to src/app/suggestion-notifications/suggestion-list-element/suggestion-list-element.component.scss diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.spec.ts b/src/app/suggestion-notifications/suggestion-list-element/suggestion-list-element.component.spec.ts similarity index 88% rename from src/app/suggestion-notifications/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.spec.ts rename to src/app/suggestion-notifications/suggestion-list-element/suggestion-list-element.component.spec.ts index 544b53774e7..61d1a19996c 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.spec.ts +++ b/src/app/suggestion-notifications/suggestion-list-element/suggestion-list-element.component.spec.ts @@ -5,8 +5,8 @@ import { NO_ERRORS_SCHEMA } from '@angular/core'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { TestScheduler } from 'rxjs/testing'; import { getTestScheduler } from 'jasmine-marbles'; -import { mockSuggestionPublicationOne } from '../../../shared/mocks/reciter-suggestion.mock'; -import { Item } from '../../../core/shared/item.model'; +import { mockSuggestionPublicationOne } from '../../shared/mocks/publication-claim.mock'; +import { Item } from '../../core/shared/item.model'; describe('SuggestionListElementComponent', () => { @@ -66,9 +66,9 @@ describe('SuggestionListElementComponent', () => { }); it('should emit for deletion', () => { - spyOn(component.notMineClicked, 'emit'); - component.onNotMine('1234'); - expect(component.notMineClicked.emit).toHaveBeenCalledWith('1234'); + spyOn(component.ignoreSuggestionClicked, 'emit'); + component.onIgnoreSuggestion('1234'); + expect(component.ignoreSuggestionClicked.emit).toHaveBeenCalledWith('1234'); }); it('should emit for approve and import', () => { diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.ts b/src/app/suggestion-notifications/suggestion-list-element/suggestion-list-element.component.ts similarity index 77% rename from src/app/suggestion-notifications/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.ts rename to src/app/suggestion-notifications/suggestion-list-element/suggestion-list-element.component.ts index a1ef454037b..f569054bb0d 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.ts +++ b/src/app/suggestion-notifications/suggestion-list-element/suggestion-list-element.component.ts @@ -2,16 +2,22 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; -import { fadeIn } from '../../../shared/animations/fade'; -import { Suggestion } from '../../../core/suggestion-notifications/reciter-suggestions/models/suggestion.model'; -import { Item } from '../../../core/shared/item.model'; -import { isNotEmpty } from '../../../shared/empty.util'; - +import { fadeIn } from '../../shared/animations/fade'; +import { Suggestion } from '../../core/suggestion-notifications/models/suggestion.model'; +import { Item } from '../../core/shared/item.model'; +import { isNotEmpty } from '../../shared/empty.util'; + +/** + * A simple interface to unite a specific suggestion and the id of the chosen collection + */ export interface SuggestionApproveAndImport { suggestion: Suggestion; collectionId: string; } +/** + * Show all the suggestions by researcher + */ @Component({ selector: 'ds-suggestion-list-item', styleUrls: ['./suggestion-list-element.component.scss'], @@ -33,7 +39,7 @@ export class SuggestionListElementComponent implements OnInit { /** * The component is used to Delete suggestion */ - @Output() notMineClicked = new EventEmitter(); + @Output() ignoreSuggestionClicked = new EventEmitter(); /** * The component is used to approve & import @@ -69,8 +75,8 @@ export class SuggestionListElementComponent implements OnInit { /** * Delete the suggestion */ - onNotMine(suggestionId: string) { - this.notMineClicked.emit(suggestionId); + onIgnoreSuggestion(suggestionId: string) { + this.ignoreSuggestionClicked.emit(suggestionId); } /** diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.actions.ts b/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.actions.ts similarity index 96% rename from src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.actions.ts rename to src/app/suggestion-notifications/suggestion-targets/suggestion-targets.actions.ts index 4e5b88d65c4..058fa367518 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.actions.ts +++ b/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.actions.ts @@ -1,7 +1,7 @@ /* eslint-disable max-classes-per-file */ import { Action } from '@ngrx/store'; -import { type } from '../../../shared/ngrx/type'; -import { SuggestionTarget } from '../../../core/suggestion-notifications/reciter-suggestions/models/suggestion-target.model'; +import { type } from '../../shared/ngrx/type'; +import { SuggestionTarget } from '../../core/suggestion-notifications/models/suggestion-target.model'; /** * For each action type in an action group, make a simple diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.component.html b/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.component.html similarity index 87% rename from src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.component.html rename to src/app/suggestion-notifications/suggestion-targets/suggestion-targets.component.html index 04e967c3d54..3d98082ba6e 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.component.html +++ b/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.component.html @@ -33,8 +33,9 @@

{{'reciter.suggestion.title'| transla
diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.component.scss b/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.component.scss similarity index 100% rename from src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.component.scss rename to src/app/suggestion-notifications/suggestion-targets/suggestion-targets.component.scss diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.component.ts b/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.component.ts similarity index 80% rename from src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.component.ts rename to src/app/suggestion-notifications/suggestion-targets/suggestion-targets.component.ts index cfa168e2b83..e469ac13869 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.component.ts +++ b/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.component.ts @@ -4,13 +4,13 @@ import { Router } from '@angular/router'; import { Observable, Subscription } from 'rxjs'; import { distinctUntilChanged, take } from 'rxjs/operators'; -import { SuggestionTarget } from '../../../core/suggestion-notifications/reciter-suggestions/models/suggestion-target.model'; -import { hasValue } from '../../../shared/empty.util'; -import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; +import { SuggestionTarget } from '../../core/suggestion-notifications/models/suggestion-target.model'; +import { hasValue } from '../../shared/empty.util'; +import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; import { SuggestionTargetsStateService } from './suggestion-targets.state.service'; -import { getSuggestionPageRoute } from '../../../suggestions-page/suggestions-page-routing-paths'; +import { getSuggestionPageRoute } from '../../suggestions-page/suggestions-page-routing-paths'; import { SuggestionsService } from '../suggestions.service'; -import { PaginationService } from '../../../core/pagination/pagination.service'; +import { PaginationService } from '../../core/pagination/pagination.service'; /** * Component to display the Suggestion Target list. @@ -69,8 +69,8 @@ export class SuggestionTargetsComponent implements OnInit { * Component initialization. */ ngOnInit(): void { - this.targets$ = this.suggestionTargetsStateService.getReciterSuggestionTargets(); - this.totalElements$ = this.suggestionTargetsStateService.getReciterSuggestionTargetsTotals(); + this.targets$ = this.suggestionTargetsStateService.getSuggestionTargets(); + this.totalElements$ = this.suggestionTargetsStateService.getSuggestionTargetsTotals(); } /** @@ -78,7 +78,7 @@ export class SuggestionTargetsComponent implements OnInit { */ ngAfterViewInit(): void { this.subs.push( - this.suggestionTargetsStateService.isReciterSuggestionTargetsLoaded().pipe( + this.suggestionTargetsStateService.isSuggestionTargetsLoaded().pipe( take(1) ).subscribe(() => { this.getSuggestionTargets(); @@ -93,7 +93,7 @@ export class SuggestionTargetsComponent implements OnInit { * 'true' if the targets are loading, 'false' otherwise. */ public isTargetsLoading(): Observable { - return this.suggestionTargetsStateService.isReciterSuggestionTargetsLoading(); + return this.suggestionTargetsStateService.isSuggestionTargetsLoading(); } /** @@ -103,7 +103,7 @@ export class SuggestionTargetsComponent implements OnInit { * 'true' if there are operations running on the targets (ex.: a REST call), 'false' otherwise. */ public isTargetsProcessing(): Observable { - return this.suggestionTargetsStateService.isReciterSuggestionTargetsProcessing(); + return this.suggestionTargetsStateService.isSuggestionTargetsProcessing(); } /** @@ -136,7 +136,7 @@ export class SuggestionTargetsComponent implements OnInit { distinctUntilChanged(), take(1) ).subscribe((options: PaginationComponentOptions) => { - this.suggestionTargetsStateService.dispatchRetrieveReciterSuggestionTargets( + this.suggestionTargetsStateService.dispatchRetrieveSuggestionTargets( this.source, options.pageSize, options.currentPage diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.effects.ts b/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.effects.ts similarity index 91% rename from src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.effects.ts rename to src/app/suggestion-notifications/suggestion-targets/suggestion-targets.effects.ts index 850c82972e1..63964b77214 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.effects.ts +++ b/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.effects.ts @@ -14,10 +14,10 @@ import { RetrieveTargetsBySourceAction, SuggestionTargetActionTypes, } from './suggestion-targets.actions'; -import { PaginatedList } from '../../../core/data/paginated-list.model'; +import { PaginatedList } from '../../core/data/paginated-list.model'; import { SuggestionsService } from '../suggestions.service'; -import { NotificationsService } from '../../../shared/notifications/notifications.service'; -import { SuggestionTarget } from '../../../core/suggestion-notifications/reciter-suggestions/models/suggestion-target.model'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { SuggestionTarget } from '../../core/suggestion-notifications/models/suggestion-target.model'; /** * Provides effect methods for the Suggestion Targets actions. diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.reducer.ts b/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.reducer.ts similarity index 95% rename from src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.reducer.ts rename to src/app/suggestion-notifications/suggestion-targets/suggestion-targets.reducer.ts index 2d315e69956..09ead019d11 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.reducer.ts +++ b/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.reducer.ts @@ -1,5 +1,5 @@ import { SuggestionTargetActionTypes, SuggestionTargetsActions } from './suggestion-targets.actions'; -import { SuggestionTarget } from '../../../core/suggestion-notifications/reciter-suggestions/models/suggestion-target.model'; +import { SuggestionTarget } from '../../core/suggestion-notifications/models/suggestion-target.model'; /** * The interface representing the OpenAIRE suggestion targets state. diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.state.service.ts b/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.state.service.ts similarity index 54% rename from src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.state.service.ts rename to src/app/suggestion-notifications/suggestion-targets/suggestion-targets.state.service.ts index da347a1e8b5..7e0e6ad8368 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.state.service.ts +++ b/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.state.service.ts @@ -7,20 +7,20 @@ import { map } from 'rxjs/operators'; import { getCurrentUserSuggestionTargetsSelector, getCurrentUserSuggestionTargetsVisitedSelector, - getReciterSuggestionTargetCurrentPageSelector, - getReciterSuggestionTargetTotalsSelector, - isReciterSuggestionTargetLoadedSelector, + getSuggestionTargetCurrentPageSelector, + getSuggestionTargetTotalsSelector, + isSuggestionTargetLoadedSelector, isReciterSuggestionTargetProcessingSelector, - reciterSuggestionTargetObjectSelector + suggestionTargetObjectSelector } from '../selectors'; -import { SuggestionTarget } from '../../../core/suggestion-notifications/reciter-suggestions/models/suggestion-target.model'; +import { SuggestionTarget } from '../../core/suggestion-notifications/models/suggestion-target.model'; import { ClearSuggestionTargetsAction, MarkUserSuggestionsAsVisitedAction, RefreshUserSuggestionsAction, RetrieveTargetsBySourceAction } from './suggestion-targets.actions'; -import { SuggestionNotificationsState } from '../../../notifications/notifications.reducer'; +import { SuggestionNotificationsState } from '../../notifications/notifications.reducer'; /** * The service handling the Suggestion targets State. @@ -35,80 +35,80 @@ export class SuggestionTargetsStateService { constructor(private store: Store) { } /** - * Returns the list of Reciter Suggestion Targets from the state. + * Returns the list of Suggestion Targets from the state. * - * @return Observable - * The list of Reciter Suggestion Targets. + * @return Observable + * The list of Suggestion Targets. */ - public getReciterSuggestionTargets(): Observable { - return this.store.pipe(select(reciterSuggestionTargetObjectSelector())); + public getSuggestionTargets(): Observable { + return this.store.pipe(select(suggestionTargetObjectSelector())); } /** - * Returns the information about the loading status of the Reciter Suggestion Targets (if it's running or not). + * Returns the information about the loading status of the Suggestion Targets (if it's running or not). * * @return Observable * 'true' if the targets are loading, 'false' otherwise. */ - public isReciterSuggestionTargetsLoading(): Observable { + public isSuggestionTargetsLoading(): Observable { return this.store.pipe( - select(isReciterSuggestionTargetLoadedSelector), + select(isSuggestionTargetLoadedSelector), map((loaded: boolean) => !loaded) ); } /** - * Returns the information about the loading status of the Reciter Suggestion Targets (whether or not they were loaded). + * Returns the information about the loading status of the Suggestion Targets (whether or not they were loaded). * * @return Observable * 'true' if the targets are loaded, 'false' otherwise. */ - public isReciterSuggestionTargetsLoaded(): Observable { - return this.store.pipe(select(isReciterSuggestionTargetLoadedSelector)); + public isSuggestionTargetsLoaded(): Observable { + return this.store.pipe(select(isSuggestionTargetLoadedSelector)); } /** - * Returns the information about the processing status of the Reciter Suggestion Targets (if it's running or not). + * Returns the information about the processing status of the Suggestion Targets (if it's running or not). * * @return Observable * 'true' if there are operations running on the targets (ex.: a REST call), 'false' otherwise. */ - public isReciterSuggestionTargetsProcessing(): Observable { + public isSuggestionTargetsProcessing(): Observable { return this.store.pipe(select(isReciterSuggestionTargetProcessingSelector)); } /** - * Returns, from the state, the total available pages of the Reciter Suggestion Targets. + * Returns, from the state, the total available pages of the Suggestion Targets. * * @return Observable - * The number of the Reciter Suggestion Targets pages. + * The number of the Suggestion Targets pages. */ - public getReciterSuggestionTargetsTotalPages(): Observable { - return this.store.pipe(select(getReciterSuggestionTargetTotalsSelector)); + public getSuggestionTargetsTotalPages(): Observable { + return this.store.pipe(select(getSuggestionTargetTotalsSelector)); } /** - * Returns the current page of the Reciter Suggestion Targets, from the state. + * Returns the current page of the Suggestion Targets, from the state. * * @return Observable - * The number of the current Reciter Suggestion Targets page. + * The number of the current Suggestion Targets page. */ - public getReciterSuggestionTargetsCurrentPage(): Observable { - return this.store.pipe(select(getReciterSuggestionTargetCurrentPageSelector)); + public getSuggestionTargetsCurrentPage(): Observable { + return this.store.pipe(select(getSuggestionTargetCurrentPageSelector)); } /** - * Returns the total number of the Reciter Suggestion Targets. + * Returns the total number of the Suggestion Targets. * * @return Observable - * The number of the Reciter Suggestion Targets. + * The number of the Suggestion Targets. */ - public getReciterSuggestionTargetsTotals(): Observable { - return this.store.pipe(select(getReciterSuggestionTargetTotalsSelector)); + public getSuggestionTargetsTotals(): Observable { + return this.store.pipe(select(getSuggestionTargetTotalsSelector)); } /** - * Dispatch a request to change the Reciter Suggestion Targets state, retrieving the targets from the server. + * Dispatch a request to change the Suggestion Targets state, retrieving the targets from the server. * * @param source * the source for which to retrieve suggestion targets @@ -117,15 +117,15 @@ export class SuggestionTargetsStateService { * @param currentPage * The number of the current page. */ - public dispatchRetrieveReciterSuggestionTargets(source: string, elementsPerPage: number, currentPage: number): void { + public dispatchRetrieveSuggestionTargets(source: string, elementsPerPage: number, currentPage: number): void { this.store.dispatch(new RetrieveTargetsBySourceAction(source, elementsPerPage, currentPage)); } /** - * Returns, from the state, the reciter suggestion targets for the current user. + * Returns, from the state, the suggestion targets for the current user. * * @return Observable - * The Reciter Suggestion Targets object. + * The Suggestion Targets object. */ public getCurrentUserSuggestionTargets(): Observable { return this.store.pipe(select(getCurrentUserSuggestionTargetsSelector)); diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestion.service.spec.ts b/src/app/suggestion-notifications/suggestion.service.spec.ts similarity index 83% rename from src/app/suggestion-notifications/reciter-suggestions/suggestion.service.spec.ts rename to src/app/suggestion-notifications/suggestion.service.spec.ts index 6abed7a1ce1..c7d0c7a4bf4 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/suggestion.service.spec.ts +++ b/src/app/suggestion-notifications/suggestion.service.spec.ts @@ -1,30 +1,30 @@ import { SuggestionsService } from './suggestions.service'; -import { AuthService } from '../../core/auth/auth.service'; -import { ResearcherProfileDataService } from '../../core/profile/researcher-profile-data.service'; +import { AuthService } from '../core/auth/auth.service'; +import { ResearcherProfileDataService } from '../core/profile/researcher-profile-data.service'; import { SuggestionsDataService -} from '../../core/suggestion-notifications/reciter-suggestions/suggestions-data.service'; +} from '../core/suggestion-notifications/suggestions-data.service'; import { SuggestionSourceDataService -} from '../../core/suggestion-notifications/reciter-suggestions/source/suggestion-source-data.service'; +} from '../core/suggestion-notifications/source/suggestion-source-data.service'; import { SuggestionTargetDataService -} from '../../core/suggestion-notifications/reciter-suggestions/target/suggestion-target-data.service'; +} from '../core/suggestion-notifications/target/suggestion-target-data.service'; import { TestScheduler } from 'rxjs/testing'; import { getTestScheduler } from 'jasmine-marbles'; import { of as observableOf } from 'rxjs'; -import { FindListOptions } from '../../core/data/find-list-options.model'; -import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; -import { ResearcherProfile } from '../../core/profile/model/researcher-profile.model'; -import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; -import { WorkspaceitemDataService } from '../../core/submission/workspaceitem-data.service'; -import { mockSuggestionPublicationOne } from '../../shared/mocks/reciter-suggestion.mock'; -import { ResourceType } from '../../core/shared/resource-type'; +import { FindListOptions } from '../core/data/find-list-options.model'; +import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model'; +import { ResearcherProfile } from '../core/profile/model/researcher-profile.model'; +import { createSuccessfulRemoteDataObject$ } from '../shared/remote-data.utils'; +import { WorkspaceitemDataService } from '../core/submission/workspaceitem-data.service'; +import { mockSuggestionPublicationOne } from '../shared/mocks/publication-claim.mock'; +import { ResourceType } from '../core/shared/resource-type'; import { SuggestionTarget -} from '../../core/suggestion-notifications/reciter-suggestions/models/suggestion-target.model'; +} from '../core/suggestion-notifications/models/suggestion-target.model'; describe('SuggestionsService test', () => { let scheduler: TestScheduler; @@ -151,14 +151,14 @@ describe('SuggestionsService test', () => { it('should delete suggestion', () => { spyOn(service, 'deleteReviewedSuggestion').and.returnValue(createSuccessfulRemoteDataObject$({})); - service.notMine('1234'); + service.ignoreSuggestion('1234'); expect(service.deleteReviewedSuggestion).toHaveBeenCalledWith('1234'); }); it('should delete suggestions', () => { spyOn(service, 'notMine'); - service.notMineMultiple([mockSuggestionPublicationOne]); - expect(service.notMine).toHaveBeenCalledWith(mockSuggestionPublicationOne.id); + service.ignoreSuggestionMultiple([mockSuggestionPublicationOne]); + expect(service.ignoreSuggestion).toHaveBeenCalledWith(mockSuggestionPublicationOne.id); }); it('should get target Uuid', () => { diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestions-notification/suggestions-notification.component.html b/src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.html similarity index 100% rename from src/app/suggestion-notifications/reciter-suggestions/suggestions-notification/suggestions-notification.component.html rename to src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.html diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestions-notification/suggestions-notification.component.scss b/src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.scss similarity index 100% rename from src/app/suggestion-notifications/reciter-suggestions/suggestions-notification/suggestions-notification.component.scss rename to src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.scss diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestions-notification/suggestions-notification.component.ts b/src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.ts similarity index 75% rename from src/app/suggestion-notifications/reciter-suggestions/suggestions-notification/suggestions-notification.component.ts rename to src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.ts index 23b34c4de99..dfa1e187e3b 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/suggestions-notification/suggestions-notification.component.ts +++ b/src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.ts @@ -1,11 +1,14 @@ import { Component, OnInit } from '@angular/core'; -import { SuggestionTarget } from '../../../core/suggestion-notifications/reciter-suggestions/models/suggestion-target.model'; +import { SuggestionTarget } from '../../core/suggestion-notifications/models/suggestion-target.model'; import { TranslateService } from '@ngx-translate/core'; import { SuggestionTargetsStateService } from '../suggestion-targets/suggestion-targets.state.service'; -import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; import { SuggestionsService } from '../suggestions.service'; import { Observable } from 'rxjs'; +/** + * Show suggestions notification, used on myDSpace and Profile pages + */ @Component({ selector: 'ds-suggestions-notification', templateUrl: './suggestions-notification.component.html', @@ -22,13 +25,13 @@ export class SuggestionsNotificationComponent implements OnInit { constructor( private translateService: TranslateService, - private reciterSuggestionStateService: SuggestionTargetsStateService, + private suggestionTargetsStateService: SuggestionTargetsStateService, private notificationsService: NotificationsService, private suggestionsService: SuggestionsService ) { } ngOnInit() { - this.suggestionsRD$ = this.reciterSuggestionStateService.getCurrentUserSuggestionTargets(); + this.suggestionsRD$ = this.suggestionTargetsStateService.getCurrentUserSuggestionTargets(); } /** diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.html b/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.html similarity index 100% rename from src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.html rename to src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.html diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.scss b/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.scss similarity index 100% rename from src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.scss rename to src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.scss diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.spec.ts b/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.spec.ts similarity index 92% rename from src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.spec.ts rename to src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.spec.ts index aade2c78fa1..8a5721968bc 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.spec.ts +++ b/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.spec.ts @@ -3,11 +3,11 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { SuggestionsPopupComponent } from './suggestions-popup.component'; import { TranslateModule } from '@ngx-translate/core'; import { SuggestionTargetsStateService } from '../suggestion-targets/suggestion-targets.state.service'; -import { NotificationsService } from '../../../shared/notifications/notifications.service'; -import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { of as observableOf } from 'rxjs'; -import { mockSuggestionTargetsObjectOne } from '../../../shared/mocks/reciter-suggestion-targets.mock'; +import { mockSuggestionTargetsObjectOne } from '../../shared/mocks/publication-claim-targets.mock'; import { SuggestionsService } from '../suggestions.service'; describe('SuggestionsPopupComponent', () => { diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.ts b/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.ts similarity index 75% rename from src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.ts rename to src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.ts index 39be112bd28..2eb5cec6dae 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.ts +++ b/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.ts @@ -1,13 +1,16 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { SuggestionTargetsStateService } from '../suggestion-targets/suggestion-targets.state.service'; -import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; import { SuggestionsService } from '../suggestions.service'; import { takeUntil } from 'rxjs/operators'; -import { SuggestionTarget } from '../../../core/suggestion-notifications/reciter-suggestions/models/suggestion-target.model'; -import { isNotEmpty } from '../../../shared/empty.util'; +import { SuggestionTarget } from '../../core/suggestion-notifications/models/suggestion-target.model'; +import { isNotEmpty } from '../../shared/empty.util'; import { combineLatest, Subject } from 'rxjs'; +/** + * Show suggestions on a popover window, used on the homepage + */ @Component({ selector: 'ds-suggestions-popup', templateUrl: './suggestions-popup.component.html', @@ -21,7 +24,7 @@ export class SuggestionsPopupComponent implements OnInit, OnDestroy { constructor( private translateService: TranslateService, - private reciterSuggestionStateService: SuggestionTargetsStateService, + private suggestionTargetsStateService: SuggestionTargetsStateService, private notificationsService: NotificationsService, private suggestionsService: SuggestionsService ) { } @@ -33,14 +36,14 @@ export class SuggestionsPopupComponent implements OnInit, OnDestroy { public initializePopup() { const notifier = new Subject(); this.subscription = combineLatest([ - this.reciterSuggestionStateService.getCurrentUserSuggestionTargets(), - this.reciterSuggestionStateService.hasUserVisitedSuggestions() + this.suggestionTargetsStateService.getCurrentUserSuggestionTargets(), + this.suggestionTargetsStateService.hasUserVisitedSuggestions() ]).pipe(takeUntil(notifier)).subscribe(([suggestions, visited]) => { - this.reciterSuggestionStateService.dispatchRefreshUserSuggestionsAction(); + this.suggestionTargetsStateService.dispatchRefreshUserSuggestionsAction(); if (isNotEmpty(suggestions)) { if (!visited) { suggestions.forEach((suggestionTarget: SuggestionTarget) => this.showNotificationForNewSuggestions(suggestionTarget)); - this.reciterSuggestionStateService.dispatchMarkUserSuggestionsAsVisitedAction(); + this.suggestionTargetsStateService.dispatchMarkUserSuggestionsAsVisitedAction(); notifier.next(null); notifier.complete(); } diff --git a/src/app/suggestion-notifications/reciter-suggestions/suggestions.service.ts b/src/app/suggestion-notifications/suggestions.service.ts similarity index 84% rename from src/app/suggestion-notifications/reciter-suggestions/suggestions.service.ts rename to src/app/suggestion-notifications/suggestions.service.ts index b760ddf34db..d4e8825f63e 100644 --- a/src/app/suggestion-notifications/reciter-suggestions/suggestions.service.ts +++ b/src/app/suggestion-notifications/suggestions.service.ts @@ -3,38 +3,41 @@ import { Injectable } from '@angular/core'; import { of, forkJoin, Observable } from 'rxjs'; import { catchError, map, mergeMap, take } from 'rxjs/operators'; -import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; -import { RemoteData } from '../../core/data/remote-data'; -import { PaginatedList } from '../../core/data/paginated-list.model'; -import { SuggestionTarget } from '../../core/suggestion-notifications/reciter-suggestions/models/suggestion-target.model'; -import { AuthService } from '../../core/auth/auth.service'; -import { hasValue, isNotEmpty } from '../../shared/empty.util'; -import { ResearcherProfile } from '../../core/profile/model/researcher-profile.model'; +import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model'; +import { RemoteData } from '../core/data/remote-data'; +import { PaginatedList } from '../core/data/paginated-list.model'; +import { SuggestionTarget } from '../core/suggestion-notifications/models/suggestion-target.model'; +import { AuthService } from '../core/auth/auth.service'; +import { hasValue, isNotEmpty } from '../shared/empty.util'; +import { ResearcherProfile } from '../core/profile/model/researcher-profile.model'; import { getAllSucceededRemoteDataPayload, getFinishedRemoteData, getFirstSucceededRemoteDataPayload, getFirstSucceededRemoteListPayload -} from '../../core/shared/operators'; -import { Suggestion } from '../../core/suggestion-notifications/reciter-suggestions/models/suggestion.model'; -import { WorkspaceitemDataService } from '../../core/submission/workspaceitem-data.service'; +} from '../core/shared/operators'; +import { Suggestion } from '../core/suggestion-notifications/models/suggestion.model'; +import { WorkspaceitemDataService } from '../core/submission/workspaceitem-data.service'; import { TranslateService } from '@ngx-translate/core'; -import { NoContent } from '../../core/shared/NoContent.model'; -import { environment } from '../../../environments/environment'; -import { WorkspaceItem } from '../../core/submission/models/workspaceitem.model'; -import {FindListOptions} from '../../core/data/find-list-options.model'; -import {SuggestionConfig} from '../../../config/layout-config.interfaces'; -import { ResearcherProfileDataService } from '../../core/profile/researcher-profile-data.service'; +import { NoContent } from '../core/shared/NoContent.model'; +import { environment } from '../../environments/environment'; +import { WorkspaceItem } from '../core/submission/models/workspaceitem.model'; +import {FindListOptions} from '../core/data/find-list-options.model'; +import {SuggestionConfig} from '../../config/layout-config.interfaces'; +import { ResearcherProfileDataService } from '../core/profile/researcher-profile-data.service'; import { SuggestionSourceDataService -} from '../../core/suggestion-notifications/reciter-suggestions/source/suggestion-source-data.service'; +} from '../core/suggestion-notifications/source/suggestion-source-data.service'; import { SuggestionTargetDataService -} from '../../core/suggestion-notifications/reciter-suggestions/target/suggestion-target-data.service'; +} from '../core/suggestion-notifications/target/suggestion-target-data.service'; import { SuggestionsDataService -} from '../../core/suggestion-notifications/reciter-suggestions/suggestions-data.service'; +} from '../core/suggestion-notifications/suggestions-data.service'; +/** + * useful for multiple approvals and ignores operation + * */ export interface SuggestionBulkResult { success: number; fails: number; @@ -199,7 +202,7 @@ export class SuggestionsService { * Perform the delete operation over a single suggestion. * @param suggestionId */ - public notMine(suggestionId): Observable> { + public ignoreSuggestion(suggestionId): Observable> { return this.deleteReviewedSuggestion(suggestionId).pipe( catchError((error) => of(null)) ); @@ -229,8 +232,8 @@ export class SuggestionsService { * Perform a bulk notMine operation. * @param suggestions the array containing the suggestions */ - public notMineMultiple(suggestions: Suggestion[]): Observable { - return forkJoin(suggestions.map((suggestion: Suggestion) => this.notMine(suggestion.id))) + public ignoreSuggestionMultiple(suggestions: Suggestion[]): Observable { + return forkJoin(suggestions.map((suggestion: Suggestion) => this.ignoreSuggestion(suggestion.id))) .pipe(map((results: RemoteData[]) => { return { success: results.filter((result) => result != null).length, diff --git a/src/app/suggestions-page/suggestions-page-routing.module.ts b/src/app/suggestions-page/suggestions-page-routing.module.ts index 05dc6321b70..0a7d9bd90c5 100644 --- a/src/app/suggestions-page/suggestions-page-routing.module.ts +++ b/src/app/suggestions-page/suggestions-page-routing.module.ts @@ -4,7 +4,7 @@ import { RouterModule } from '@angular/router'; import { SuggestionsPageResolver } from './suggestions-page.resolver'; import { SuggestionsPageComponent } from './suggestions-page.component'; import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; -import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver'; +import { ItemBreadcrumbResolver } from '../core/breadcrumbs/item-breadcrumb.resolver'; @NgModule({ imports: [ @@ -13,11 +13,11 @@ import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.reso path: ':targetId', resolve: { suggestionTargets: SuggestionsPageResolver, - breadcrumb: I18nBreadcrumbResolver + breadcrumb: ItemBreadcrumbResolver//I18nBreadcrumbResolver }, data: { - title: 'admin.notifications.recitersuggestion.page.title', - breadcrumbKey: 'admin.notifications.recitersuggestion', + title: 'admin.notifications.publicationclaim.page.title', + breadcrumbKey: 'admin.notifications.publicationclaim', showBreadcrumbsFluid: false }, canActivate: [AuthenticatedGuard], @@ -27,7 +27,8 @@ import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.reso ]) ], providers: [ - SuggestionsPageResolver + SuggestionsPageResolver, + ItemBreadcrumbResolver ] }) export class SuggestionsPageRoutingModule { diff --git a/src/app/suggestions-page/suggestions-page.component.html b/src/app/suggestions-page/suggestions-page.component.html index 59b6f58c5fc..f8b14f67286 100644 --- a/src/app/suggestions-page/suggestions-page.component.html +++ b/src/app/suggestions-page/suggestions-page.component.html @@ -19,7 +19,7 @@

[isBulk]="true" [isCollectionFixed]="isCollectionFixed(suggestionsRD.page)" (approveAndImport)="approveAndImportAllSelected($event)" - (notMineClicked)="notMineAllSelected()"> + (ignoreSuggestionClicked)="ignoreSuggestionAllSelected()">

@@ -35,7 +35,7 @@

[object]="object" [isSelected]="selectedSuggestions[object.id]" [isCollectionFixed]="isCollectionFixed([object])" - (notMineClicked)="notMine($event)" + (ignoreSuggestionClicked)="ignoreSuggestion($event)" (selected)="onSelected(object, $event)" (approveAndImport)="approveAndImport($event)"> diff --git a/src/app/suggestions-page/suggestions-page.component.spec.ts b/src/app/suggestions-page/suggestions-page.component.spec.ts index 0b0e235082d..78cf0873628 100644 --- a/src/app/suggestions-page/suggestions-page.component.spec.ts +++ b/src/app/suggestions-page/suggestions-page.component.spec.ts @@ -10,23 +10,23 @@ import { SuggestionsPageComponent } from './suggestions-page.component'; import { SuggestionApproveAndImport, SuggestionListElementComponent -} from '../suggestion-notifications/reciter-suggestions/suggestion-list-element/suggestion-list-element.component'; -import { SuggestionsService } from '../suggestion-notifications/reciter-suggestions/suggestions.service'; +} from '../suggestion-notifications/suggestion-list-element/suggestion-list-element.component'; +import { SuggestionsService } from '../suggestion-notifications/suggestions.service'; import { getMockSuggestionNotificationsStateService, getMockSuggestionsService } from '../shared/mocks/suggestion.mock'; import { buildPaginatedList, PaginatedList } from '../core/data/paginated-list.model'; -import { Suggestion } from '../core/suggestion-notifications/reciter-suggestions/models/suggestion.model'; -import { mockSuggestionPublicationOne, mockSuggestionPublicationTwo } from '../shared/mocks/reciter-suggestion.mock'; -import { SuggestionEvidencesComponent } from '../suggestion-notifications/reciter-suggestions/suggestion-list-element/suggestion-evidences/suggestion-evidences.component'; +import { Suggestion } from '../core/suggestion-notifications/models/suggestion.model'; +import { mockSuggestionPublicationOne, mockSuggestionPublicationTwo } from '../shared/mocks/publication-claim.mock'; +import { SuggestionEvidencesComponent } from '../suggestion-notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component'; import { ObjectKeysPipe } from '../shared/utils/object-keys-pipe'; import { VarDirective } from '../shared/utils/var.directive'; import { ActivatedRoute, Router } from '@angular/router'; import { RouterStub } from '../shared/testing/router.stub'; -import { mockSuggestionTargetsObjectOne } from '../shared/mocks/reciter-suggestion-targets.mock'; +import { mockSuggestionTargetsObjectOne } from '../shared/mocks/publication-claim-targets.mock'; import { AuthService } from '../core/auth/auth.service'; import { NotificationsService } from '../shared/notifications/notifications.service'; import { NotificationsServiceStub } from '../shared/testing/notifications-service.stub'; import { getMockTranslateService } from '../shared/mocks/translate.service.mock'; -import { SuggestionTargetsStateService } from '../suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.state.service'; +import { SuggestionTargetsStateService } from '../suggestion-notifications/suggestion-targets/suggestion-targets.state.service'; import { WorkspaceitemDataService } from '../core/submission/workspaceitem-data.service'; import { createSuccessfulRemoteDataObject } from '../shared/remote-data.utils'; import { PageInfo } from '../core/shared/page-info.model'; @@ -138,7 +138,7 @@ describe('SuggestionPageComponent', () => { scheduler.schedule(() => fixture.detectChanges()); scheduler.flush(); - component.notMine('1'); + component.ignoreSuggestion('1'); expect(mockSuggestionsService.notMine).toHaveBeenCalledWith('1'); expect(mockSuggestionsTargetStateService.dispatchRefreshUserSuggestionsAction).toHaveBeenCalled(); expect(component.updatePage).toHaveBeenCalled(); @@ -149,7 +149,7 @@ describe('SuggestionPageComponent', () => { scheduler.schedule(() => fixture.detectChanges()); scheduler.flush(); - component.notMineAllSelected(); + component.ignoreSuggestionAllSelected(); expect(mockSuggestionsService.notMineMultiple).toHaveBeenCalled(); expect(mockSuggestionsTargetStateService.dispatchRefreshUserSuggestionsAction).toHaveBeenCalled(); expect(component.updatePage).toHaveBeenCalled(); diff --git a/src/app/suggestions-page/suggestions-page.component.ts b/src/app/suggestions-page/suggestions-page.component.ts index b4ca0108d5a..4883ed8406e 100644 --- a/src/app/suggestions-page/suggestions-page.component.ts +++ b/src/app/suggestions-page/suggestions-page.component.ts @@ -9,14 +9,14 @@ import { SortDirection, SortOptions, } from '../core/cache/models/sort-options.m import { PaginatedList } from '../core/data/paginated-list.model'; import { RemoteData } from '../core/data/remote-data'; import { getFirstSucceededRemoteDataPayload } from '../core/shared/operators'; -import { SuggestionBulkResult, SuggestionsService } from '../suggestion-notifications/reciter-suggestions/suggestions.service'; +import { SuggestionBulkResult, SuggestionsService } from '../suggestion-notifications/suggestions.service'; import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model'; -import { Suggestion } from '../core/suggestion-notifications/reciter-suggestions/models/suggestion.model'; -import { SuggestionTarget } from '../core/suggestion-notifications/reciter-suggestions/models/suggestion-target.model'; +import { Suggestion } from '../core/suggestion-notifications/models/suggestion.model'; +import { SuggestionTarget } from '../core/suggestion-notifications/models/suggestion-target.model'; import { AuthService } from '../core/auth/auth.service'; -import { SuggestionApproveAndImport } from '../suggestion-notifications/reciter-suggestions/suggestion-list-element/suggestion-list-element.component'; +import { SuggestionApproveAndImport } from '../suggestion-notifications/suggestion-list-element/suggestion-list-element.component'; import { NotificationsService } from '../shared/notifications/notifications.service'; -import { SuggestionTargetsStateService } from '../suggestion-notifications/reciter-suggestions/suggestion-targets/suggestion-targets.state.service'; +import { SuggestionTargetsStateService } from '../suggestion-notifications/suggestion-targets/suggestion-targets.state.service'; import { WorkspaceitemDataService } from '../core/submission/workspaceitem-data.service'; import { PaginationService } from '../core/pagination/pagination.service'; import { WorkspaceItem } from '../core/submission/models/workspaceitem.model'; @@ -155,8 +155,8 @@ export class SuggestionsPageComponent implements OnInit { * Used to delete a suggestion. * @suggestionId */ - notMine(suggestionId) { - this.suggestionService.notMine(suggestionId).subscribe((res) => { + ignoreSuggestion(suggestionId) { + this.suggestionService.ignoreSuggestion(suggestionId).subscribe((res) => { this.suggestionTargetsStateService.dispatchRefreshUserSuggestionsAction(); this.updatePage(); }); @@ -165,10 +165,10 @@ export class SuggestionsPageComponent implements OnInit { /** * Used to delete all selected suggestions. */ - notMineAllSelected() { + ignoreSuggestionAllSelected() { this.isBulkOperationPending = true; this.suggestionService - .notMineMultiple(Object.values(this.selectedSuggestions)) + .ignoreSuggestionMultiple(Object.values(this.selectedSuggestions)) .subscribe((results: SuggestionBulkResult) => { this.suggestionTargetsStateService.dispatchRefreshUserSuggestionsAction(); this.updatePage(); diff --git a/src/app/suggestions-page/suggestions-page.module.ts b/src/app/suggestions-page/suggestions-page.module.ts index f5397cbdce4..e25e483e39a 100644 --- a/src/app/suggestions-page/suggestions-page.module.ts +++ b/src/app/suggestions-page/suggestions-page.module.ts @@ -4,8 +4,8 @@ import { CommonModule } from '@angular/common'; import { SuggestionsPageComponent } from './suggestions-page.component'; import { SharedModule } from '../shared/shared.module'; import { SuggestionsPageRoutingModule } from './suggestions-page-routing.module'; -import { SuggestionsService } from '../suggestion-notifications/reciter-suggestions/suggestions.service'; -import { SuggestionsDataService } from '../core/suggestion-notifications/reciter-suggestions/suggestions-data.service'; +import { SuggestionsService } from '../suggestion-notifications/suggestions.service'; +import { SuggestionsDataService } from '../core/suggestion-notifications/suggestions-data.service'; import { NotificationsModule } from '../notifications/notifications.module'; @NgModule({ diff --git a/src/app/suggestions-page/suggestions-page.resolver.ts b/src/app/suggestions-page/suggestions-page.resolver.ts index 6d05c0bc84a..dde5b847f5d 100644 --- a/src/app/suggestions-page/suggestions-page.resolver.ts +++ b/src/app/suggestions-page/suggestions-page.resolver.ts @@ -6,10 +6,10 @@ import { find } from 'rxjs/operators'; import { RemoteData } from '../core/data/remote-data'; import { hasValue } from '../shared/empty.util'; -import { SuggestionTarget } from '../core/suggestion-notifications/reciter-suggestions/models/suggestion-target.model'; +import { SuggestionTarget } from '../core/suggestion-notifications/models/suggestion-target.model'; import { SuggestionTargetDataService -} from '../core/suggestion-notifications/reciter-suggestions/target/suggestion-target-data.service'; +} from '../core/suggestion-notifications/target/suggestion-target-data.service'; /** * This class represents a resolver that requests a specific collection before the route is activated diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 0e5ea850740..989d2ea9fbc 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -24,9 +24,9 @@ "404.page-not-found": "page not found", - "admin.notifications.recitersuggestion.breadcrumbs": "Suggestions", + "admin.notifications.publicationclaim.breadcrumbs": "Suggestions", - "admin.notifications.recitersuggestion.page.title": "Suggestions", + "admin.notifications.publicationclaim.page.title": "Suggestions", "error-page.description.401": "unauthorized", @@ -2950,7 +2950,7 @@ "menu.section.quality-assurance": "Quality Assurance", - "menu.section.notifications_reciter": "Publication Claim", + "menu.section.notifications_publication-claim": "Publication Claim", "menu.section.pin": "Pin sidebar", @@ -3562,63 +3562,67 @@ "media-viewer.playlist": "Playlist", - "reciter.suggestion.loading": "Loading ...", + "suggestion.loading": "Loading ...", - "reciter.suggestion.title": "Suggestions", + "suggestion.title": "Publication Claims", - "reciter.suggestion.targets.description": "Below you can see all the suggestions ", + "suggestion.title.breadcrumbs": "Publication Claims", - "reciter.suggestion.targets": "Current Suggestions", + "suggestion.targets.description": "Below you can see all the suggestions ", - "reciter.suggestion.table.name": "Researcher Name", + "suggestion.targets": "Current Suggestions", - "reciter.suggestion.table.actions": "Actions", + "suggestion.table.name": "Researcher Name", - "reciter.suggestion.button.review": "Review {{ total }} suggestion(s)", + "suggestion.table.actions": "Actions", - "reciter.suggestion.noTargets": "No target found.", + "suggestion.button.review": "Review {{ total }} suggestion(s)", - "reciter.suggestion.target.error.service.retrieve": "An error occurred while loading the Suggestion targets", + "suggestion.button.review.title": "Review {{ total }} suggestion(s) for ", - "reciter.suggestion.evidence.type": "Type", + "suggestion.noTargets": "No target found.", - "reciter.suggestion.evidence.score": "Score", + "suggestion.target.error.service.retrieve": "An error occurred while loading the Suggestion targets", - "reciter.suggestion.evidence.notes": "Notes", + "suggestion.evidence.type": "Type", - "reciter.suggestion.approveAndImport": "Approve & import", + "suggestion.evidence.score": "Score", - "reciter.suggestion.approveAndImport.success": "The suggestion has been imported successfully. View.", + "suggestion.evidence.notes": "Notes", - "reciter.suggestion.approveAndImport.bulk": "Approve & import Selected", + "suggestion.approveAndImport": "Approve & import", - "reciter.suggestion.approveAndImport.bulk.success": "{{ count }} suggestions have been imported successfully ", + "suggestion.approveAndImport.success": "The suggestion has been imported successfully. View.", - "reciter.suggestion.approveAndImport.bulk.error": "{{ count }} suggestions haven't been imported due to unexpected server errors", + "suggestion.approveAndImport.bulk": "Approve & import Selected", - "reciter.suggestion.notMine": "Not mine", + ".suggestion.approveAndImport.bulk.success": "{{ count }} suggestions have been imported successfully ", - "reciter.suggestion.notMine.success": "The suggestion has been discarded", + "suggestion.approveAndImport.bulk.error": "{{ count }} suggestions haven't been imported due to unexpected server errors", - "reciter.suggestion.notMine.bulk": "Not mine Selected", + "suggestion.ignoreSuggestion": "Ignore Suggestion", - "reciter.suggestion.notMine.bulk.success": "{{ count }} suggestions have been discarded ", + "suggestion.ignoreSuggestion.success": "The suggestion has been discarded", - "reciter.suggestion.notMine.bulk.error": "{{ count }} suggestions haven't been discarded due to unexpected server errors", + "suggestion.ignoreSuggestion.bulk": "Ignore Suggestion Selected", - "reciter.suggestion.seeEvidence": "See evidence", + "suggestion.ignoreSuggestion.bulk.success": "{{ count }} suggestions have been discarded ", - "reciter.suggestion.hideEvidence": "Hide evidence", + "suggestion.ignoreSuggestion.bulk.error": "{{ count }} suggestions haven't been discarded due to unexpected server errors", - "reciter.suggestion.suggestionFor": "Suggestion for", + "suggestion.seeEvidence": "See evidence", - "reciter.suggestion.source.openaire": "OpenAIRE Graph", + "suggestion.hideEvidence": "Hide evidence", - "reciter.suggestion.from.source": "from the ", + "suggestion.suggestionFor": "Suggestion for", - "reciter.suggestion.totalScore": "Total Score", + "suggestion.source.openaire": "OpenAIRE Graph", - "reciter.suggestion.type.openaire": "OpenAIRE", + "suggestion.from.source": "from the ", + + "suggestion.totalScore": "Total Score", + + "suggestion.type.openaire": "OpenAIRE", "register-email.title": "New user registration", From 66cd035f87a2f777fe3d5d1e9ac52e254f6ee159 Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Thu, 25 Jan 2024 11:50:02 +0100 Subject: [PATCH 16/44] refactor, fix tests --- ...ions-publication-claim-page.component.html | 2 +- ...s-publication-claim-page.component.spec.ts | 14 +- ...ations-publication-claim-page.component.ts | 2 +- .../admin-notifications-routing.module.ts | 4 +- .../admin-notifications.module.ts | 4 +- src/app/core/data/base/base-data.service.ts | 8 +- src/app/core/data/base/create-data.ts | 2 +- src/app/core/data/base/find-all-data.ts | 2 +- src/app/core/data/base/patch-data.ts | 2 +- src/app/core/data/base/put-data.ts | 2 +- src/app/core/data/base/search-data.ts | 2 +- src/app/core/data/href-only-data.service.ts | 4 +- ...data.service.ts => update-data-service.ts} | 385 +++--------------- src/app/core/data/update-data.service.ts | 13 - .../core/data/version-data.service.spec.ts | 2 +- .../core/eperson/eperson-data.service.spec.ts | 2 +- .../workflowitem-data.service.spec.ts | 2 +- .../workspaceitem-data.service.spec.ts | 2 +- .../suggestions-data.service.ts | 28 +- .../dso-edit-metadata.component.ts | 2 +- .../themed-dso-edit-metadata.component.ts | 2 +- src/app/menu.resolver.ts | 2 +- src/app/notifications/notifications.module.ts | 4 +- .../eperson-group-list.component.ts | 2 +- .../mydspace-actions-service.factory.ts | 2 +- .../mydspace-actions/mydspace-actions.ts | 2 +- .../suggestion-actions.component.html | 4 +- .../publication-claim.component.html} | 16 +- .../publication-claim.component.scss} | 0 .../publication-claim.component.ts} | 22 +- .../suggestion.service.spec.ts | 2 +- .../suggestions-popup.component.ts | 4 +- .../suggestions.service.ts | 4 +- .../suggestions-page.component.spec.ts | 5 +- .../suggestions-page.component.ts | 14 +- src/assets/i18n/en.json5 | 4 +- src/config/app-config.interface.ts | 4 +- src/config/default-app-config.ts | 4 +- src/config/layout-config.interfaces.ts | 46 --- src/config/suggestion-config.interfaces.ts | 6 + 40 files changed, 143 insertions(+), 490 deletions(-) rename src/app/core/data/{data.service.ts => update-data-service.ts} (52%) delete mode 100644 src/app/core/data/update-data.service.ts rename src/app/suggestion-notifications/suggestion-targets/{suggestion-targets.component.html => publication-claim/publication-claim.component.html} (72%) rename src/app/suggestion-notifications/suggestion-targets/{suggestion-targets.component.scss => publication-claim/publication-claim.component.scss} (100%) rename src/app/suggestion-notifications/suggestion-targets/{suggestion-targets.component.ts => publication-claim/publication-claim.component.ts} (83%) delete mode 100644 src/config/layout-config.interfaces.ts create mode 100644 src/config/suggestion-config.interfaces.ts diff --git a/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.html b/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.html index 965b9e08c90..b04e7132f17 100644 --- a/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.html +++ b/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.html @@ -1 +1 @@ - + diff --git a/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.spec.ts b/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.spec.ts index c0209da8988..c5406023ce9 100644 --- a/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.spec.ts +++ b/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.spec.ts @@ -1,13 +1,13 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { AdminNotificationsSuggestionTargetsPageComponent } from './admin-notifications-publication-claim-page.component'; +import { AdminNotificationsPublicationClaimPageComponent } from './admin-notifications-publication-claim-page.component'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { CommonModule } from '@angular/common'; import { TranslateModule } from '@ngx-translate/core'; -describe('AdminNotificationsSuggestionTargetsPageComponent', () => { - let component: AdminNotificationsSuggestionTargetsPageComponent; - let fixture: ComponentFixture; +describe('AdminNotificationsPublicationClaimPageComponent', () => { + let component: AdminNotificationsPublicationClaimPageComponent; + let fixture: ComponentFixture; beforeEach(async(() => { TestBed.configureTestingModule({ @@ -16,10 +16,10 @@ describe('AdminNotificationsSuggestionTargetsPageComponent', () => { TranslateModule.forRoot() ], declarations: [ - AdminNotificationsSuggestionTargetsPageComponent + AdminNotificationsPublicationClaimPageComponent ], providers: [ - AdminNotificationsSuggestionTargetsPageComponent + AdminNotificationsPublicationClaimPageComponent ], schemas: [NO_ERRORS_SCHEMA] }) @@ -27,7 +27,7 @@ describe('AdminNotificationsSuggestionTargetsPageComponent', () => { })); beforeEach(() => { - fixture = TestBed.createComponent(AdminNotificationsSuggestionTargetsPageComponent); + fixture = TestBed.createComponent(AdminNotificationsPublicationClaimPageComponent); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.ts b/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.ts index 10023ead934..2256a1bc36a 100644 --- a/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.ts +++ b/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.ts @@ -5,6 +5,6 @@ import { Component } from '@angular/core'; templateUrl: './admin-notifications-publication-claim-page.component.html', styleUrls: ['./admin-notifications-publication-claim-page.component.scss'] }) -export class AdminNotificationsSuggestionTargetsPageComponent { +export class AdminNotificationsPublicationClaimPageComponent { } diff --git a/src/app/admin/admin-notifications/admin-notifications-routing.module.ts b/src/app/admin/admin-notifications/admin-notifications-routing.module.ts index 648bdc0a1f1..07a98aa080d 100644 --- a/src/app/admin/admin-notifications/admin-notifications-routing.module.ts +++ b/src/app/admin/admin-notifications/admin-notifications-routing.module.ts @@ -5,7 +5,7 @@ import { AuthenticatedGuard } from '../../core/auth/authenticated.guard'; import { I18nBreadcrumbResolver } from '../../core/breadcrumbs/i18n-breadcrumb.resolver'; import { I18nBreadcrumbsService } from '../../core/breadcrumbs/i18n-breadcrumbs.service'; import { PUBLICATION_CLAIMS_PATH } from './admin-notifications-routing-paths'; -import { AdminNotificationsSuggestionTargetsPageComponent } from './admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component'; +import { AdminNotificationsPublicationClaimPageComponent } from './admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component'; import { AdminNotificationsPublicationClaimPageResolver } from './admin-notifications-publication-claim-page/admin-notifications-publication-claim-page-resolver.service'; import { QUALITY_ASSURANCE_EDIT_PATH } from './admin-notifications-routing-paths'; import { AdminQualityAssuranceTopicsPageComponent } from './admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component'; @@ -26,7 +26,7 @@ import { { canActivate: [ AuthenticatedGuard ], path: `${PUBLICATION_CLAIMS_PATH}`, - component: AdminNotificationsSuggestionTargetsPageComponent, + component: AdminNotificationsPublicationClaimPageComponent, pathMatch: 'full', resolve: { breadcrumb: I18nBreadcrumbResolver, diff --git a/src/app/admin/admin-notifications/admin-notifications.module.ts b/src/app/admin/admin-notifications/admin-notifications.module.ts index 3566bdd91ad..d9efb4c2886 100644 --- a/src/app/admin/admin-notifications/admin-notifications.module.ts +++ b/src/app/admin/admin-notifications/admin-notifications.module.ts @@ -3,7 +3,7 @@ import { NgModule } from '@angular/core'; import { CoreModule } from '../../core/core.module'; import { SharedModule } from '../../shared/shared.module'; import { AdminNotificationsRoutingModule } from './admin-notifications-routing.module'; -import { AdminNotificationsSuggestionTargetsPageComponent } from './admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component'; +import { AdminNotificationsPublicationClaimPageComponent } from './admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component'; import { AdminQualityAssuranceTopicsPageComponent } from './admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component'; import { AdminQualityAssuranceEventsPageComponent } from './admin-quality-assurance-events-page/admin-quality-assurance-events-page.component'; import { AdminQualityAssuranceSourcePageComponent } from './admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component'; @@ -18,7 +18,7 @@ import { NotificationsModule } from '../../notifications/notifications.module'; NotificationsModule ], declarations: [ - AdminNotificationsSuggestionTargetsPageComponent, + AdminNotificationsPublicationClaimPageComponent, AdminQualityAssuranceTopicsPageComponent, AdminQualityAssuranceEventsPageComponent, AdminQualityAssuranceSourcePageComponent diff --git a/src/app/core/data/base/base-data.service.ts b/src/app/core/data/base/base-data.service.ts index c7cd5b0a705..84b1686024b 100644 --- a/src/app/core/data/base/base-data.service.ts +++ b/src/app/core/data/base/base-data.service.ts @@ -29,11 +29,11 @@ export const EMBED_SEPARATOR = '%2F'; /** * Common functionality for data services. * Specific functionality that not all services would need - * is implemented in "DataService feature" classes (e.g. {@link CreateData} + * is implemented in "UpdateDataServiceImpl feature" classes (e.g. {@link CreateData} * - * All DataService (or DataService feature) classes must + * All UpdateDataServiceImpl (or UpdateDataServiceImpl feature) classes must * - extend this class (or {@link IdentifiableDataService}) - * - implement any DataService features it requires in order to forward calls to it + * - implement any UpdateDataServiceImpl features it requires in order to forward calls to it * * ``` * export class SomeDataService extends BaseDataService implements CreateData, SearchData { @@ -385,7 +385,7 @@ export class BaseDataService implements HALDataServic /** * Return the links to traverse from the root of the api to the - * endpoint this DataService represents + * endpoint this UpdateDataServiceImpl represents * * e.g. if the api root links to 'foo', and the endpoint at 'foo' * links to 'bar' the linkPath for the BarDataService would be diff --git a/src/app/core/data/base/create-data.ts b/src/app/core/data/base/create-data.ts index 3ffcd9adf20..d2e009f6698 100644 --- a/src/app/core/data/base/create-data.ts +++ b/src/app/core/data/base/create-data.ts @@ -37,7 +37,7 @@ export interface CreateData { } /** - * A DataService feature to create objects. + * A UpdateDataServiceImpl feature to create objects. * * Concrete data services can use this feature by implementing {@link CreateData} * and delegating its method to an inner instance of this class. diff --git a/src/app/core/data/base/find-all-data.ts b/src/app/core/data/base/find-all-data.ts index 57884e537e5..bc0c1fb613e 100644 --- a/src/app/core/data/base/find-all-data.ts +++ b/src/app/core/data/base/find-all-data.ts @@ -42,7 +42,7 @@ export interface FindAllData { } /** - * A DataService feature to list all objects. + * A UpdateDataServiceImpl feature to list all objects. * * Concrete data services can use this feature by implementing {@link FindAllData} * and delegating its method to an inner instance of this class. diff --git a/src/app/core/data/base/patch-data.ts b/src/app/core/data/base/patch-data.ts index e30c394a347..1f93671458f 100644 --- a/src/app/core/data/base/patch-data.ts +++ b/src/app/core/data/base/patch-data.ts @@ -54,7 +54,7 @@ export interface PatchData { } /** - * A DataService feature to patch and update objects. + * A UpdateDataServiceImpl feature to patch and update objects. * * Concrete data services can use this feature by implementing {@link PatchData} * and delegating its method to an inner instance of this class. diff --git a/src/app/core/data/base/put-data.ts b/src/app/core/data/base/put-data.ts index bd2a8d29299..66ae73405eb 100644 --- a/src/app/core/data/base/put-data.ts +++ b/src/app/core/data/base/put-data.ts @@ -31,7 +31,7 @@ export interface PutData { } /** - * A DataService feature to send PUT requests. + * A UpdateDataServiceImpl feature to send PUT requests. * * Concrete data services can use this feature by implementing {@link PutData} * and delegating its method to an inner instance of this class. diff --git a/src/app/core/data/base/search-data.ts b/src/app/core/data/base/search-data.ts index 536d6d6e254..ff0b4929458 100644 --- a/src/app/core/data/base/search-data.ts +++ b/src/app/core/data/base/search-data.ts @@ -51,7 +51,7 @@ export interface SearchData { } /** - * A DataService feature to search for objects. + * A UpdateDataServiceImpl feature to search for objects. * * Concrete data services can use this feature by implementing {@link SearchData} * and delegating its method to an inner instance of this class. diff --git a/src/app/core/data/href-only-data.service.ts b/src/app/core/data/href-only-data.service.ts index 0a765de101b..8393d714605 100644 --- a/src/app/core/data/href-only-data.service.ts +++ b/src/app/core/data/href-only-data.service.ts @@ -17,8 +17,8 @@ import { HALDataService } from './base/hal-data-service.interface'; import { dataService } from './base/data-service.decorator'; /** - * A DataService with only findByHref methods. Its purpose is to be used for resources that don't - * need to be retrieved by ID, or have any way to update them, but require a DataService in order + * A UpdateDataServiceImpl with only findByHref methods. Its purpose is to be used for resources that don't + * need to be retrieved by ID, or have any way to update them, but require a UpdateDataServiceImpl in order * for their links to be resolved by the LinkService. * * an @dataService annotation can be added for any number of these resource types diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/update-data-service.ts similarity index 52% rename from src/app/core/data/data.service.ts rename to src/app/core/data/update-data-service.ts index 43b60f874d0..994cd0ee87b 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/update-data-service.ts @@ -42,46 +42,61 @@ import { } from './request.models'; import { RequestService } from './request.service'; import { RestRequestMethod } from './rest-request-method'; -import { UpdateDataService } from './update-data.service'; import { GenericConstructor } from '../shared/generic-constructor'; import { NoContent } from '../shared/NoContent.model'; import { CacheableObject } from '../cache/cacheable-object.model'; import { CoreState } from '../core-state.model'; import { FindListOptions } from './find-list-options.model'; +import { BaseDataService } from "./base/base-data.service"; +import { FindAllData, FindAllDataImpl } from "./base/find-all-data"; +import { SearchData, SearchDataImpl } from "./base/search-data"; +import { CreateData, CreateDataImpl } from "./base/create-data"; + +export interface UpdateDataService { + patch(dso: T, operations: Operation[]): Observable>; + update(object: T): Observable>; + commitUpdates(method?: RestRequestMethod); +} + + +/** + * Specific functionalities that not all services would need. + * Goal of the class is to update remote objects, handling custom methods that don't belong to BaseDataService + * + * Custom methods are: + * + * patch - Sends a patch request to modify current object + * update - Add a new patch to the object cache, diff between given object and cache + * commitUpdates - Sends the updates to the server + */ -export abstract class DataService implements UpdateDataService { - protected abstract requestService: RequestService; - protected abstract rdbService: RemoteDataBuildService; + +export abstract class UpdateDataServiceImpl extends BaseDataService implements UpdateDataService, FindAllData, SearchData, CreateData { protected abstract store: Store; - protected abstract linkPath: string; - protected abstract halService: HALEndpointService; - protected abstract objectCache: ObjectCacheService; - protected abstract notificationsService: NotificationsService; protected abstract http: HttpClient; protected abstract comparator: ChangeAnalyzer; - /** - * Allows subclasses to reset the response cache time. - */ - protected responseMsToLive: number; + private findAllData: FindAllDataImpl; + private searchData: SearchDataImpl; + private createData: CreateData; - /** - * Get the endpoint for browsing - * @param options The [[FindListOptions]] object - * @param linkPath The link path for the object - * @returns {Observable} - */ - getBrowseEndpoint(options: FindListOptions = {}, linkPath?: string): Observable { - return this.getEndpoint(); - } - /** - * Get the base endpoint for all requests - */ - protected getEndpoint(): Observable { - return this.halService.getEndpoint(this.linkPath); + constructor( + protected linkPath: string, + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected notificationsService: NotificationsService, + protected responseMsToLive: number, + ) { + super(linkPath, requestService, rdbService, objectCache, halService, responseMsToLive); + this.findAllData = new FindAllDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive); + this.searchData = new SearchDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive); + this.createData = new CreateDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, notificationsService ,this.responseMsToLive); } + /** * Create the HREF with given options object * @@ -92,16 +107,7 @@ export abstract class DataService implements UpdateDa * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved */ public getFindAllHref(options: FindListOptions = {}, linkPath?: string, ...linksToFollow: FollowLinkConfig[]): Observable { - let endpoint$: Observable; - const args = []; - - endpoint$ = this.getBrowseEndpoint(options).pipe( - filter((href: string) => isNotEmpty(href)), - map((href: string) => isNotEmpty(linkPath) ? `${href}/${linkPath}` : href), - distinctUntilChanged() - ); - - return endpoint$.pipe(map((result: string) => this.buildHrefFromFindOptions(result, options, args, ...linksToFollow))); + return this.findAllData.getFindAllHref(options, linkPath, ...linksToFollow) } /** @@ -114,149 +120,7 @@ export abstract class DataService implements UpdateDa * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved */ public getSearchByHref(searchMethod: string, options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig[]): Observable { - let result$: Observable; - const args = []; - - result$ = this.getSearchEndpoint(searchMethod); - - return result$.pipe(map((result: string) => this.buildHrefFromFindOptions(result, options, args, ...linksToFollow))); - } - - /** - * Turn an options object into a query string and combine it with the given HREF - * - * @param href The HREF to which the query string should be appended - * @param options The [[FindListOptions]] object - * @param extraArgs Array with additional params to combine with query string - * @return {Observable} - * Return an observable that emits created HREF - * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved - */ - public buildHrefFromFindOptions(href: string, options: FindListOptions, extraArgs: string[] = [], ...linksToFollow: FollowLinkConfig[]): string { - let args = [...extraArgs]; - - if (hasValue(options.currentPage) && typeof options.currentPage === 'number') { - /* TODO: this is a temporary fix for the pagination start index (0 or 1) discrepancy between the rest and the frontend respectively */ - args = this.addHrefArg(href, args, `page=${options.currentPage - 1}`); - } - if (hasValue(options.elementsPerPage)) { - args = this.addHrefArg(href, args, `size=${options.elementsPerPage}`); - } - if (hasValue(options.sort)) { - args = this.addHrefArg(href, args, `sort=${options.sort.field},${options.sort.direction}`); - } - if (hasValue(options.startsWith)) { - args = this.addHrefArg(href, args, `startsWith=${options.startsWith}`); - } - if (hasValue(options.searchParams)) { - options.searchParams.forEach((param: RequestParam) => { - args = this.addHrefArg(href, args, `${param.fieldName}=${param.fieldValue}`); - }); - } - args = this.addEmbedParams(href, args, ...linksToFollow); - if (isNotEmpty(args)) { - return new URLCombiner(href, `?${args.join('&')}`).toString(); - } else { - return href; - } - } - - /** - * Turn an array of RequestParam into a query string and combine it with the given HREF - * - * @param href The HREF to which the query string should be appended - * @param params Array with additional params to combine with query string - * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved - * - * @return {Observable} - * Return an observable that emits created HREF - */ - buildHrefWithParams(href: string, params: RequestParam[], ...linksToFollow: FollowLinkConfig[]): string { - - let args = []; - if (hasValue(params)) { - params.forEach((param: RequestParam) => { - args = this.addHrefArg(href, args, `${param.fieldName}=${param.fieldValue}`); - }); - } - - args = this.addEmbedParams(href, args, ...linksToFollow); - - if (isNotEmpty(args)) { - return new URLCombiner(href, `?${args.join('&')}`).toString(); - } else { - return href; - } - } - /** - * Adds the embed options to the link for the request - * @param href The href the params are to be added to - * @param args params for the query string - * @param linksToFollow links we want to embed in query string if shouldEmbed is true - */ - protected addEmbedParams(href: string, args: string[], ...linksToFollow: FollowLinkConfig[]) { - linksToFollow.forEach((linkToFollow: FollowLinkConfig) => { - if (hasValue(linkToFollow) && linkToFollow.shouldEmbed) { - const embedString = 'embed=' + String(linkToFollow.name); - // Add the embeds size if given in the FollowLinkConfig.FindListOptions - if (hasValue(linkToFollow.findListOptions) && hasValue(linkToFollow.findListOptions.elementsPerPage)) { - args = this.addHrefArg(href, args, - 'embed.size=' + String(linkToFollow.name) + '=' + linkToFollow.findListOptions.elementsPerPage); - } - // Adds the nested embeds and their size if given - if (isNotEmpty(linkToFollow.linksToFollow)) { - args = this.addNestedEmbeds(embedString, href, args, ...linkToFollow.linksToFollow); - } else { - args = this.addHrefArg(href, args, embedString); - } - } - }); - return args; - } - - /** - * Add a new argument to the list of arguments, only if it doesn't already exist in the given href, - * or the current list of arguments - * - * @param href The href the arguments are to be added to - * @param currentArgs The current list of arguments - * @param newArg The new argument to add - * @return The next list of arguments, with newArg included if it wasn't already. - * Note this function will not modify any of the input params. - */ - protected addHrefArg(href: string, currentArgs: string[], newArg: string): string[] { - if (href.includes(newArg) || currentArgs.includes(newArg)) { - return [...currentArgs]; - } else { - return [...currentArgs, newArg]; - } - } - - /** - * Add the nested followLinks to the embed param, separated by a /, and their sizes, recursively - * @param embedString embedString so far (recursive) - * @param href The href the params are to be added to - * @param args params for the query string - * @param linksToFollow links we want to embed in query string if shouldEmbed is true - */ - protected addNestedEmbeds(embedString: string, href: string, args: string[], ...linksToFollow: FollowLinkConfig[]): string[] { - let nestEmbed = embedString; - linksToFollow.forEach((linkToFollow: FollowLinkConfig) => { - if (hasValue(linkToFollow) && linkToFollow.shouldEmbed) { - nestEmbed = nestEmbed + '/' + String(linkToFollow.name); - // Add the nested embeds size if given in the FollowLinkConfig.FindListOptions - if (hasValue(linkToFollow.findListOptions) && hasValue(linkToFollow.findListOptions.elementsPerPage)) { - const nestedEmbedSize = 'embed.size=' + nestEmbed.split('=')[1] + '=' + linkToFollow.findListOptions.elementsPerPage; - args = this.addHrefArg(href, args, nestedEmbedSize); - } - if (hasValue(linkToFollow.linksToFollow) && isNotEmpty(linkToFollow.linksToFollow)) { - args = this.addNestedEmbeds(nestEmbed, href, args, ...linkToFollow.linksToFollow); - } else { - args = this.addHrefArg(href, args, nestEmbed); - } - } - }); - return args; + return this.searchData.getSearchByHref(searchMethod, options, ...linksToFollow) } /** @@ -274,7 +138,7 @@ export abstract class DataService implements UpdateDa * Return an observable that emits object list */ findAll(options: FindListOptions = {}, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable>> { - return this.findAllByHref(this.getFindAllHref(options), options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow) } /** @@ -337,118 +201,6 @@ export abstract class DataService implements UpdateDa }; } - /** - * Returns an observable of {@link RemoteData} of an object, based on an href, with a list of - * {@link FollowLinkConfig}, to automatically resolve {@link HALLink}s of the object - * @param href$ The url of object we want to retrieve. Can be a string or - * an Observable - * @param useCachedVersionIfAvailable If this is true, the request will only be sent if there's - * no valid cached version. Defaults to true - * @param reRequestOnStale Whether or not the request should automatically be re- - * requested after the response becomes stale - * @param linksToFollow List of {@link FollowLinkConfig} that indicate which - * {@link HALLink}s should be automatically resolved - */ - findByHref(href$: string | Observable, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable> { - if (typeof href$ === 'string') { - href$ = observableOf(href$); - } - - const requestHref$ = href$.pipe( - isNotEmptyOperator(), - take(1), - map((href: string) => this.buildHrefFromFindOptions(href, {}, [], ...linksToFollow)) - ); - - this.createAndSendGetRequest(requestHref$, useCachedVersionIfAvailable); - - return this.rdbService.buildSingle(requestHref$, ...linksToFollow).pipe( - // This skip ensures that if a stale object is present in the cache when you do a - // call it isn't immediately returned, but we wait until the remote data for the new request - // is created. If useCachedVersionIfAvailable is false it also ensures you don't get a - // cached completed object - skipWhile((rd: RemoteData) => useCachedVersionIfAvailable ? rd.isStale : rd.hasCompleted), - this.reRequestStaleRemoteData(reRequestOnStale, () => - this.findByHref(href$, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow)) - ); - } - - /** - * Returns a list of observables of {@link RemoteData} of objects, based on an href, with a list - * of {@link FollowLinkConfig}, to automatically resolve {@link HALLink}s of the object - * @param href$ The url of object we want to retrieve. Can be a string or - * an Observable - * @param findListOptions Find list options object - * @param useCachedVersionIfAvailable If this is true, the request will only be sent if there's - * no valid cached version. Defaults to true - * @param reRequestOnStale Whether or not the request should automatically be re- - * requested after the response becomes stale - * @param linksToFollow List of {@link FollowLinkConfig} that indicate which - * {@link HALLink}s should be automatically resolved - */ - findAllByHref(href$: string | Observable, findListOptions: FindListOptions = {}, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable>> { - if (typeof href$ === 'string') { - href$ = observableOf(href$); - } - - const requestHref$ = href$.pipe( - isNotEmptyOperator(), - take(1), - map((href: string) => this.buildHrefFromFindOptions(href, findListOptions, [], ...linksToFollow)) - ); - - this.createAndSendGetRequest(requestHref$, useCachedVersionIfAvailable); - - return this.rdbService.buildList(requestHref$, ...linksToFollow).pipe( - // This skip ensures that if a stale object is present in the cache when you do a - // call it isn't immediately returned, but we wait until the remote data for the new request - // is created. If useCachedVersionIfAvailable is false it also ensures you don't get a - // cached completed object - skipWhile((rd: RemoteData>) => useCachedVersionIfAvailable ? rd.isStale : rd.hasCompleted), - this.reRequestStaleRemoteData(reRequestOnStale, () => - this.findAllByHref(href$, findListOptions, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow)) - ); - } - - /** - * Create a GET request for the given href, and send it. - * - * @param href$ The url of object we want to retrieve. Can be a string or - * an Observable - * @param useCachedVersionIfAvailable If this is true, the request will only be sent if there's - * no valid cached version. Defaults to true - */ - protected createAndSendGetRequest(href$: string | Observable, useCachedVersionIfAvailable = true): void { - if (isNotEmpty(href$)) { - if (typeof href$ === 'string') { - href$ = observableOf(href$); - } - - href$.pipe( - isNotEmptyOperator(), - take(1) - ).subscribe((href: string) => { - const requestId = this.requestService.generateRequestId(); - const request = new GetRequest(requestId, href); - if (hasValue(this.responseMsToLive)) { - request.responseMsToLive = this.responseMsToLive; - } - this.requestService.send(request, useCachedVersionIfAvailable); - }); - } - } - - /** - * Return object search endpoint by given search method - * - * @param searchMethod The search method for the object - */ - protected getSearchEndpoint(searchMethod: string): Observable { - return this.halService.getEndpoint(this.linkPath).pipe( - filter((href: string) => isNotEmpty(href)), - map((href: string) => `${href}/search/${searchMethod}`)); - } - /** * Make a new FindListRequest with given search method * @@ -464,9 +216,7 @@ export abstract class DataService implements UpdateDa * Return an observable that emits response from the server */ searchBy(searchMethod: string, options: FindListOptions = {}, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable>> { - const hrefObs = this.getSearchByHref(searchMethod, options, ...linksToFollow); - - return this.findAllByHref(hrefObs, undefined, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + return this.searchData.searchBy(searchMethod, options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow) } /** @@ -548,38 +298,7 @@ export abstract class DataService implements UpdateDa * Array with additional params to combine with query string */ create(object: T, ...params: RequestParam[]): Observable> { - const requestId = this.requestService.generateRequestId(); - const endpoint$ = this.getEndpoint().pipe( - isNotEmptyOperator(), - distinctUntilChanged(), - map((endpoint: string) => this.buildHrefWithParams(endpoint, params)) - ); - - const serializedObject = new DSpaceSerializer(getClassForType(object.type)).serialize(object); - - endpoint$.pipe( - take(1) - ).subscribe((endpoint: string) => { - const request = new CreateRequest(requestId, endpoint, JSON.stringify(serializedObject)); - if (hasValue(this.responseMsToLive)) { - request.responseMsToLive = this.responseMsToLive; - } - this.requestService.send(request); - }); - - const result$ = this.rdbService.buildFromRequestUUID(requestId); - - // TODO a dataservice is not the best place to show a notification, - // this should move up to the components that use this method - result$.pipe( - takeWhile((rd: RemoteData) => rd.isLoading, true) - ).subscribe((rd: RemoteData) => { - if (rd.hasFailed) { - this.notificationsService.error('Server Error:', rd.errorMessage, new NotificationOptions(-1)); - } - }); - - return result$; + return this.createData.create(object, ...params) } /** @@ -732,16 +451,4 @@ export abstract class DataService implements UpdateDa commitUpdates(method?: RestRequestMethod) { this.requestService.commit(method); } - - /** - * Return the links to traverse from the root of the api to the - * endpoint this DataService represents - * - * e.g. if the api root links to 'foo', and the endpoint at 'foo' - * links to 'bar' the linkPath for the BarDataService would be - * 'foo/bar' - */ - getLinkPath(): string { - return this.linkPath; - } } diff --git a/src/app/core/data/update-data.service.ts b/src/app/core/data/update-data.service.ts deleted file mode 100644 index 9f707a82da9..00000000000 --- a/src/app/core/data/update-data.service.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Observable } from 'rxjs'; -import { RemoteData } from './remote-data'; -import { RestRequestMethod } from './rest-request-method'; -import { Operation } from 'fast-json-patch'; - -/** - * Represents a data service to update a given object - */ -export interface UpdateDataService { - patch(dso: T, operations: Operation[]): Observable>; - update(object: T): Observable>; - commitUpdates(method?: RestRequestMethod); -} diff --git a/src/app/core/data/version-data.service.spec.ts b/src/app/core/data/version-data.service.spec.ts index dd3f9eec945..0579b998b87 100644 --- a/src/app/core/data/version-data.service.spec.ts +++ b/src/app/core/data/version-data.service.spec.ts @@ -128,7 +128,7 @@ describe('VersionDataService test', () => { }); describe('getHistoryFromVersion', () => { - it('should proxy the call to DataService.findByHref', () => { + it('should proxy the call to UpdateDataServiceImpl.findByHref', () => { scheduler.schedule(() => service.getHistoryFromVersion(mockVersion, true, true)); scheduler.flush(); diff --git a/src/app/core/eperson/eperson-data.service.spec.ts b/src/app/core/eperson/eperson-data.service.spec.ts index c1bc3563a32..cbddf1e6c3e 100644 --- a/src/app/core/eperson/eperson-data.service.spec.ts +++ b/src/app/core/eperson/eperson-data.service.spec.ts @@ -315,7 +315,7 @@ describe('EPersonDataService', () => { service.deleteEPerson(EPersonMock).subscribe(); }); - it('should call DataService.delete with the EPerson\'s UUID', () => { + it('should call UpdateDataServiceImpl.delete with the EPerson\'s UUID', () => { expect(service.delete).toHaveBeenCalledWith(EPersonMock.id); }); }); diff --git a/src/app/core/submission/workflowitem-data.service.spec.ts b/src/app/core/submission/workflowitem-data.service.spec.ts index 3f6ec54fdad..64ffbe57180 100644 --- a/src/app/core/submission/workflowitem-data.service.spec.ts +++ b/src/app/core/submission/workflowitem-data.service.spec.ts @@ -126,7 +126,7 @@ describe('WorkflowItemDataService test', () => { }); describe('findByItem', () => { - it('should proxy the call to DataService.findByHref', () => { + it('should proxy the call to UpdateDataServiceImpl.findByHref', () => { scheduler.schedule(() => service.findByItem('1234-1234', true, true, pageInfo)); scheduler.flush(); diff --git a/src/app/core/submission/workspaceitem-data.service.spec.ts b/src/app/core/submission/workspaceitem-data.service.spec.ts index 34548c1e53f..25a849baa28 100644 --- a/src/app/core/submission/workspaceitem-data.service.spec.ts +++ b/src/app/core/submission/workspaceitem-data.service.spec.ts @@ -141,7 +141,7 @@ describe('WorkspaceitemDataService test', () => { }); describe('findByItem', () => { - it('should proxy the call to DataService.findByHref', () => { + it('should proxy the call to UpdateDataServiceImpl.findByHref', () => { scheduler.schedule(() => service.findByItem('1234-1234', true, true, pageInfo)); scheduler.flush(); const searchUrl = service.getIDHref('item', [new RequestParam('uuid', encodeURIComponent('1234-1234'))]); diff --git a/src/app/core/suggestion-notifications/suggestions-data.service.ts b/src/app/core/suggestion-notifications/suggestions-data.service.ts index 72476f6a156..945cc8b083f 100644 --- a/src/app/core/suggestion-notifications/suggestions-data.service.ts +++ b/src/app/core/suggestion-notifications/suggestions-data.service.ts @@ -11,7 +11,7 @@ import { RemoteDataBuildService } from '../cache/builders/remote-data-build.serv import { ObjectCacheService } from '../cache/object-cache.service'; import { dataService } from '../cache/builders/build-decorators'; import { RequestService } from '../data/request.service'; -import { DataService } from '../data/data.service'; +import { UpdateDataServiceImpl } from '../data/update-data-service'; import { ChangeAnalyzer } from '../data/change-analyzer'; import { DefaultChangeAnalyzer } from '../data/default-change-analyzer.service'; import { RemoteData } from '../data/remote-data'; @@ -31,13 +31,9 @@ import { SuggestionTargetDataService } from './target/suggestion-target-data.ser /* tslint:disable:max-classes-per-file */ /** - * A private DataService implementation to delegate specific methods to. + * A private UpdateDataServiceImpl implementation to delegate specific methods to. */ -export class SuggestionDataServiceImpl extends DataService { - /** - * The REST endpoint. - */ - protected linkPath = 'suggestions'; +export class SuggestionDataServiceImpl extends UpdateDataServiceImpl { /** * Initialize service variables @@ -49,6 +45,7 @@ export class SuggestionDataServiceImpl extends DataService { * @param {NotificationsService} notificationsService * @param {HttpClient} http * @param {ChangeAnalyzer} comparator + * @param responseMsToLive */ constructor( protected requestService: RequestService, @@ -58,8 +55,10 @@ export class SuggestionDataServiceImpl extends DataService { protected halService: HALEndpointService, protected notificationsService: NotificationsService, protected http: HttpClient, - protected comparator: ChangeAnalyzer) { - super(); + protected comparator: ChangeAnalyzer, + protected responseMsToLive: number, + ) { + super('suggestions', requestService, rdbService, objectCache, halService, notificationsService ,responseMsToLive); } } @@ -73,20 +72,22 @@ export class SuggestionsDataService { protected searchFindByTargetAndSourceMethod = 'findByTargetAndSource'; /** - * A private DataService implementation to delegate specific methods to. + * A private UpdateDataServiceImpl implementation to delegate specific methods to. */ private suggestionsDataService: SuggestionDataServiceImpl; /** - * A private DataService implementation to delegate specific methods to. + * A private UpdateDataServiceImpl implementation to delegate specific methods to. */ private suggestionSourcesDataService: SuggestionSourceDataService; /** - * A private DataService implementation to delegate specific methods to. + * A private UpdateDataServiceImpl implementation to delegate specific methods to. */ private suggestionTargetsDataService: SuggestionTargetDataService; + private responseMsToLive = 10 * 1000; + /** * Initialize service variables * @param {RequestService} requestService @@ -98,6 +99,7 @@ export class SuggestionsDataService { * @param {DefaultChangeAnalyzer} comparatorSuggestions * @param {DefaultChangeAnalyzer} comparatorSources * @param {DefaultChangeAnalyzer} comparatorTargets + * @param responseMsToLive */ constructor( protected requestService: RequestService, @@ -110,7 +112,7 @@ export class SuggestionsDataService { protected comparatorSources: DefaultChangeAnalyzer, protected comparatorTargets: DefaultChangeAnalyzer, ) { - this.suggestionsDataService = new SuggestionDataServiceImpl(requestService, rdbService, null, objectCache, halService, notificationsService, http, comparatorSuggestions); + this.suggestionsDataService = new SuggestionDataServiceImpl(requestService, rdbService, null, objectCache, halService, notificationsService, http, comparatorSuggestions, this.responseMsToLive); this.suggestionSourcesDataService = new SuggestionSourceDataService(requestService, rdbService, null, objectCache, halService, notificationsService, http, comparatorSources); this.suggestionTargetsDataService = new SuggestionTargetDataService(requestService, rdbService, null, objectCache, halService, notificationsService, http, comparatorTargets); } diff --git a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts index d44817be842..ad3d6680a17 100644 --- a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts +++ b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts @@ -12,7 +12,6 @@ import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject'; import { getFirstCompletedRemoteData, } from '../../core/shared/operators'; -import { UpdateDataService } from '../../core/data/update-data.service'; import { ResourceType } from '../../core/shared/resource-type'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; @@ -22,6 +21,7 @@ import { ArrayMoveChangeAnalyzer } from '../../core/data/array-move-change-analy import { DATA_SERVICE_FACTORY } from '../../core/data/base/data-service.decorator'; import { GenericConstructor } from '../../core/shared/generic-constructor'; import { HALDataService } from '../../core/data/base/hal-data-service.interface'; +import { UpdateDataService } from "../../core/data/update-data-service"; @Component({ selector: 'ds-dso-edit-metadata', diff --git a/src/app/dso-shared/dso-edit-metadata/themed-dso-edit-metadata.component.ts b/src/app/dso-shared/dso-edit-metadata/themed-dso-edit-metadata.component.ts index ba21907c99e..51eec3ac230 100644 --- a/src/app/dso-shared/dso-edit-metadata/themed-dso-edit-metadata.component.ts +++ b/src/app/dso-shared/dso-edit-metadata/themed-dso-edit-metadata.component.ts @@ -2,7 +2,7 @@ import { ThemedComponent } from '../../shared/theme-support/themed.component'; import { DsoEditMetadataComponent } from './dso-edit-metadata.component'; import { Component, Input } from '@angular/core'; import { DSpaceObject } from '../../core/shared/dspace-object.model'; -import { UpdateDataService } from '../../core/data/update-data.service'; +import { UpdateDataService } from "../../core/data/update-data-service"; @Component({ selector: 'ds-themed-dso-edit-metadata', diff --git a/src/app/menu.resolver.ts b/src/app/menu.resolver.ts index fc6eb00195c..f2a7e2dbe19 100644 --- a/src/app/menu.resolver.ts +++ b/src/app/menu.resolver.ts @@ -541,7 +541,7 @@ export class MenuResolver implements Resolve { { id: 'notifications', active: false, - visible: authorized && canSeeQA, + visible: authorized && true, model: { type: MenuItemType.TEXT, text: 'menu.section.notifications' diff --git a/src/app/notifications/notifications.module.ts b/src/app/notifications/notifications.module.ts index cd8cb99811f..00c7582b2f0 100644 --- a/src/app/notifications/notifications.module.ts +++ b/src/app/notifications/notifications.module.ts @@ -26,7 +26,7 @@ import { QualityAssuranceSourceService } from './qa/source/quality-assurance-sou import { QualityAssuranceSourceDataService } from '../core/notifications/qa/source/quality-assurance-source-data.service'; -import { SuggestionTargetsComponent } from '../suggestion-notifications/suggestion-targets/suggestion-targets.component'; +import { PublicationClaimComponent } from '../suggestion-notifications/suggestion-targets/publication-claim/publication-claim.component'; import { SuggestionActionsComponent } from '../suggestion-notifications/suggestion-actions/suggestion-actions.component'; import { SuggestionListElementComponent @@ -65,7 +65,7 @@ const COMPONENTS = [ QualityAssuranceTopicsComponent, QualityAssuranceEventsComponent, QualityAssuranceSourceComponent, - SuggestionTargetsComponent, + PublicationClaimComponent, SuggestionActionsComponent, SuggestionListElementComponent, SuggestionEvidencesComponent, diff --git a/src/app/shared/eperson-group-list/eperson-group-list.component.ts b/src/app/shared/eperson-group-list/eperson-group-list.component.ts index 7cad7a97830..1a08740a946 100644 --- a/src/app/shared/eperson-group-list/eperson-group-list.component.ts +++ b/src/app/shared/eperson-group-list/eperson-group-list.component.ts @@ -96,7 +96,7 @@ export class EpersonGroupListComponent implements OnInit, OnDestroy { private pageConfigSub: Subscription; /** - * Initialize instance variables and inject the properly DataService + * Initialize instance variables and inject the properly UpdateDataServiceImpl * * @param {DSONameService} dsoNameService * @param {Injector} parentInjector diff --git a/src/app/shared/mydspace-actions/mydspace-actions-service.factory.ts b/src/app/shared/mydspace-actions/mydspace-actions-service.factory.ts index 6408dddac6e..987ca1411e1 100644 --- a/src/app/shared/mydspace-actions/mydspace-actions-service.factory.ts +++ b/src/app/shared/mydspace-actions/mydspace-actions-service.factory.ts @@ -13,7 +13,7 @@ import { CacheableObject } from '../../core/cache/cacheable-object.model'; import { IdentifiableDataService } from '../../core/data/base/identifiable-data.service'; /** - * Class to return DataService for given ResourceType + * Class to return UpdateDataServiceImpl for given ResourceType */ export class MyDSpaceActionsServiceFactory> { public getConstructor(type: ResourceType): TService { diff --git a/src/app/shared/mydspace-actions/mydspace-actions.ts b/src/app/shared/mydspace-actions/mydspace-actions.ts index 931929ccce5..184f059bd80 100644 --- a/src/app/shared/mydspace-actions/mydspace-actions.ts +++ b/src/app/shared/mydspace-actions/mydspace-actions.ts @@ -47,7 +47,7 @@ export abstract class MyDSpaceActionsComponent(false); /** - * Instance of DataService related to mydspace object + * Instance of UpdateDataServiceImpl related to mydspace object */ protected objectDataService: TService; diff --git a/src/app/suggestion-notifications/suggestion-actions/suggestion-actions.component.html b/src/app/suggestion-notifications/suggestion-actions/suggestion-actions.component.html index 24e970a8182..2a46191deea 100644 --- a/src/app/suggestion-notifications/suggestion-actions/suggestion-actions.component.html +++ b/src/app/suggestion-notifications/suggestion-actions/suggestion-actions.component.html @@ -23,7 +23,7 @@ {{ ignoreSuggestionLabel() | translate}}

diff --git a/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.component.html b/src/app/suggestion-notifications/suggestion-targets/publication-claim/publication-claim.component.html similarity index 72% rename from src/app/suggestion-notifications/suggestion-targets/suggestion-targets.component.html rename to src/app/suggestion-notifications/suggestion-targets/publication-claim/publication-claim.component.html index 3d98082ba6e..45068cd12c8 100644 --- a/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.component.html +++ b/src/app/suggestion-notifications/suggestion-targets/publication-claim/publication-claim.component.html @@ -1,9 +1,9 @@
-

{{'reciter.suggestion.title'| translate}}

+

{{'suggestion.title'| translate}}

- + {{'reciter.suggestion.title'| transla [retainScrollPosition]="false" (paginationChange)="getSuggestionTargets()"> - +
- - + + @@ -33,9 +33,9 @@

{{'reciter.suggestion.title'| transla
diff --git a/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.component.scss b/src/app/suggestion-notifications/suggestion-targets/publication-claim/publication-claim.component.scss similarity index 100% rename from src/app/suggestion-notifications/suggestion-targets/suggestion-targets.component.scss rename to src/app/suggestion-notifications/suggestion-targets/publication-claim/publication-claim.component.scss diff --git a/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.component.ts b/src/app/suggestion-notifications/suggestion-targets/publication-claim/publication-claim.component.ts similarity index 83% rename from src/app/suggestion-notifications/suggestion-targets/suggestion-targets.component.ts rename to src/app/suggestion-notifications/suggestion-targets/publication-claim/publication-claim.component.ts index e469ac13869..aef25f40756 100644 --- a/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.component.ts +++ b/src/app/suggestion-notifications/suggestion-targets/publication-claim/publication-claim.component.ts @@ -4,23 +4,23 @@ import { Router } from '@angular/router'; import { Observable, Subscription } from 'rxjs'; import { distinctUntilChanged, take } from 'rxjs/operators'; -import { SuggestionTarget } from '../../core/suggestion-notifications/models/suggestion-target.model'; -import { hasValue } from '../../shared/empty.util'; -import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; -import { SuggestionTargetsStateService } from './suggestion-targets.state.service'; -import { getSuggestionPageRoute } from '../../suggestions-page/suggestions-page-routing-paths'; -import { SuggestionsService } from '../suggestions.service'; -import { PaginationService } from '../../core/pagination/pagination.service'; +import { SuggestionTarget } from '../../../core/suggestion-notifications/models/suggestion-target.model'; +import { hasValue } from '../../../shared/empty.util'; +import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; +import { SuggestionTargetsStateService } from '../suggestion-targets.state.service'; +import { getSuggestionPageRoute } from '../../../suggestions-page/suggestions-page-routing-paths'; +import { SuggestionsService } from '../../suggestions.service'; +import { PaginationService } from '../../../core/pagination/pagination.service'; /** * Component to display the Suggestion Target list. */ @Component({ - selector: 'ds-suggestion-target', - templateUrl: './suggestion-targets.component.html', - styleUrls: ['./suggestion-targets.component.scss'], + selector: 'ds-publication-claim', + templateUrl: './publication-claim.component.html', + styleUrls: ['./publication-claim.component.scss'], }) -export class SuggestionTargetsComponent implements OnInit { +export class PublicationClaimComponent implements OnInit { /** * The source for which to list targets diff --git a/src/app/suggestion-notifications/suggestion.service.spec.ts b/src/app/suggestion-notifications/suggestion.service.spec.ts index c7d0c7a4bf4..e6ca83d5fe3 100644 --- a/src/app/suggestion-notifications/suggestion.service.spec.ts +++ b/src/app/suggestion-notifications/suggestion.service.spec.ts @@ -156,7 +156,7 @@ describe('SuggestionsService test', () => { }); it('should delete suggestions', () => { - spyOn(service, 'notMine'); + spyOn(service, 'ignoreSuggestion'); service.ignoreSuggestionMultiple([mockSuggestionPublicationOne]); expect(service.ignoreSuggestion).toHaveBeenCalledWith(mockSuggestionPublicationOne.id); }); diff --git a/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.ts b/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.ts index 2eb5cec6dae..762f80085a8 100644 --- a/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.ts +++ b/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.ts @@ -18,7 +18,7 @@ import { combineLatest, Subject } from 'rxjs'; }) export class SuggestionsPopupComponent implements OnInit, OnDestroy { - labelPrefix = 'mydspace.'; + labelPrefix = 'notification.'; subscription; @@ -57,7 +57,7 @@ export class SuggestionsPopupComponent implements OnInit, OnDestroy { * @private */ private showNotificationForNewSuggestions(suggestionTarget: SuggestionTarget): void { - const content = this.translateService.instant(this.labelPrefix + 'notification.suggestion', + const content = this.translateService.instant(this.labelPrefix + 'suggestion', this.suggestionsService.getNotificationSuggestionInterpolation(suggestionTarget)); this.notificationsService.success('', content, {timeOut:0}, true); } diff --git a/src/app/suggestion-notifications/suggestions.service.ts b/src/app/suggestion-notifications/suggestions.service.ts index d4e8825f63e..47d4124a47e 100644 --- a/src/app/suggestion-notifications/suggestions.service.ts +++ b/src/app/suggestion-notifications/suggestions.service.ts @@ -23,7 +23,7 @@ import { NoContent } from '../core/shared/NoContent.model'; import { environment } from '../../environments/environment'; import { WorkspaceItem } from '../core/submission/models/workspaceitem.model'; import {FindListOptions} from '../core/data/find-list-options.model'; -import {SuggestionConfig} from '../../config/layout-config.interfaces'; +import {SuggestionConfig} from '../../config/suggestion-config.interfaces'; import { ResearcherProfileDataService } from '../core/profile/researcher-profile-data.service'; import { SuggestionSourceDataService @@ -229,7 +229,7 @@ export class SuggestionsService { } /** - * Perform a bulk notMine operation. + * Perform a bulk ignoreSuggestion operation. * @param suggestions the array containing the suggestions */ public ignoreSuggestionMultiple(suggestions: Suggestion[]): Observable { diff --git a/src/app/suggestions-page/suggestions-page.component.spec.ts b/src/app/suggestions-page/suggestions-page.component.spec.ts index 78cf0873628..2f6cfb7278f 100644 --- a/src/app/suggestions-page/suggestions-page.component.spec.ts +++ b/src/app/suggestions-page/suggestions-page.component.spec.ts @@ -41,7 +41,6 @@ describe('SuggestionPageComponent', () => { let scheduler: TestScheduler; const mockSuggestionsService = getMockSuggestionsService(); const mockSuggestionsTargetStateService = getMockSuggestionNotificationsStateService(); - const suggestionTargetsList: PaginatedList = buildPaginatedList(new PageInfo(), [mockSuggestionPublicationOne, mockSuggestionPublicationTwo]); const router = new RouterStub(); const routeStub = { data: observableOf({ @@ -139,7 +138,7 @@ describe('SuggestionPageComponent', () => { scheduler.schedule(() => fixture.detectChanges()); scheduler.flush(); component.ignoreSuggestion('1'); - expect(mockSuggestionsService.notMine).toHaveBeenCalledWith('1'); + expect(mockSuggestionsService.ignoreSuggestion).toHaveBeenCalledWith('1'); expect(mockSuggestionsTargetStateService.dispatchRefreshUserSuggestionsAction).toHaveBeenCalled(); expect(component.updatePage).toHaveBeenCalled(); }); @@ -150,7 +149,7 @@ describe('SuggestionPageComponent', () => { scheduler.schedule(() => fixture.detectChanges()); scheduler.flush(); component.ignoreSuggestionAllSelected(); - expect(mockSuggestionsService.notMineMultiple).toHaveBeenCalled(); + expect(mockSuggestionsService.ignoreSuggestionMultiple).toHaveBeenCalled(); expect(mockSuggestionsTargetStateService.dispatchRefreshUserSuggestionsAction).toHaveBeenCalled(); expect(component.updatePage).toHaveBeenCalled(); }); diff --git a/src/app/suggestions-page/suggestions-page.component.ts b/src/app/suggestions-page/suggestions-page.component.ts index 4883ed8406e..09051441f4a 100644 --- a/src/app/suggestions-page/suggestions-page.component.ts +++ b/src/app/suggestions-page/suggestions-page.component.ts @@ -28,6 +28,11 @@ import {redirectOn4xx} from '../core/shared/authorized.operators'; templateUrl: './suggestions-page.component.html', styleUrls: ['./suggestions-page.component.scss'], }) + +/** + * Component used to visualize one of the suggestions from the publication claim page or from the notification pop up + */ + export class SuggestionsPageComponent implements OnInit { /** @@ -139,15 +144,6 @@ export class SuggestionsPageComponent implements OnInit { this.processing$.next(false); this.suggestionsRD$.next(results); this.suggestionService.clearSuggestionRequests(); - // navigate to the mydspace if no suggestions remains - - // if (results.totalElements === 0) { - // const content = this.translateService.instant('reciter.suggestion.empty', - // this.suggestionService.getNotificationSuggestionInterpolation(this.suggestionTarget)); - // this.notificationService.success('', content, {timeOut:0}, true); - // TODO if the target is not the current use route to the suggestion target page - // this.router.navigate(['/mydspace']); - // } }); } diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 989d2ea9fbc..006fbdb5d49 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -3084,9 +3084,9 @@ "mydspace.import": "Import", - "mydspace.notification.suggestion": "We found {{count}} publications
in the {{source}} that seems to be related to your profile.
Please review the suggestions", + "notification.suggestion": "We found {{count}} publications
in the {{source}} that seems to be related to your profile.
Please review the suggestions", - "mydspace.notification.suggestion.page": "We found {{count}} {{type}} in the {{source}} that seems to be related to your profile. Please review the suggestions.", + "notification.suggestion.page": "We found {{count}} {{type}} in the {{source}} that seems to be related to your profile. Please review the suggestions.", "nav.browse.header": "All of DSpace", diff --git a/src/config/app-config.interface.ts b/src/config/app-config.interface.ts index f89623e0184..6c4b99cb0f4 100644 --- a/src/config/app-config.interface.ts +++ b/src/config/app-config.interface.ts @@ -14,7 +14,7 @@ import { AuthConfig } from './auth-config.interfaces'; import { UIServerConfig } from './ui-server-config.interface'; import { MediaViewerConfig } from './media-viewer-config.interface'; import { BrowseByConfig } from './browse-by-config.interface'; -import { SuggestionConfig } from './layout-config.interfaces'; +import { SuggestionConfig } from './suggestion-config.interfaces'; import { BundleConfig } from './bundle-config.interface'; import { ActuatorsConfig } from './actuators.config'; import { InfoConfig } from './info-config.interface'; @@ -23,7 +23,7 @@ import { HomeConfig } from './homepage-config.interface'; import { MarkdownConfig } from './markdown-config.interface'; import { FilterVocabularyConfig } from './filter-vocabulary-config'; import { DiscoverySortConfig } from './discovery-sort.config'; -import {QualityAssuranceConfig} from './quality-assurance.config'; +import { QualityAssuranceConfig } from './quality-assurance.config'; interface AppConfig extends Config { ui: UIServerConfig; diff --git a/src/config/default-app-config.ts b/src/config/default-app-config.ts index 902ab68dc3f..be9306c893c 100644 --- a/src/config/default-app-config.ts +++ b/src/config/default-app-config.ts @@ -14,7 +14,7 @@ import { ServerConfig } from './server-config.interface'; import { SubmissionConfig } from './submission-config.interface'; import { ThemeConfig } from './theme.config'; import { UIServerConfig } from './ui-server-config.interface'; -import {SuggestionConfig} from './layout-config.interfaces'; +import {SuggestionConfig} from './suggestion-config.interfaces'; import { BundleConfig } from './bundle-config.interface'; import { ActuatorsConfig } from './actuators.config'; import { InfoConfig } from './info-config.interface'; @@ -304,6 +304,8 @@ export class DefaultAppConfig implements AppConfig { // source: 'suggestionSource', // collectionId: 'collectionUUID' // } + // If not mapped the suggestion service won't be able to approve and import the related suggestion + // or load the fixed suggestions collections that can be configured here adding the source and the UUID of the collection ]; // Theme Config diff --git a/src/config/layout-config.interfaces.ts b/src/config/layout-config.interfaces.ts deleted file mode 100644 index 0b15a06aa92..00000000000 --- a/src/config/layout-config.interfaces.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { Config } from './config.interface'; - -export interface UrnConfig extends Config { - name: string; - baseUrl: string; -} - -export interface CrisRefConfig extends Config { - entityType: string; - icon: string; -} - -export interface CrisLayoutMetadataBoxConfig extends Config { - defaultMetadataLabelColStyle: string; - defaultMetadataValueColStyle: string; -} - -export interface CrisLayoutTypeConfig { - orientation: string; -} - -export interface NavbarConfig extends Config { - showCommunityCollection: boolean; -} - -export interface CrisItemPageConfig extends Config { - [entity: string]: CrisLayoutTypeConfig; - default: CrisLayoutTypeConfig; -} - - -export interface CrisLayoutConfig extends Config { - urn: UrnConfig[]; - crisRef: CrisRefConfig[]; - itemPage: CrisItemPageConfig; - metadataBox: CrisLayoutMetadataBoxConfig; -} - -export interface LayoutConfig extends Config { - navbar: NavbarConfig; -} - -export interface SuggestionConfig extends Config { - source: string; - collectionId: string; -} diff --git a/src/config/suggestion-config.interfaces.ts b/src/config/suggestion-config.interfaces.ts new file mode 100644 index 00000000000..e99ffa25f70 --- /dev/null +++ b/src/config/suggestion-config.interfaces.ts @@ -0,0 +1,6 @@ +import { Config } from "./config.interface"; + +export interface SuggestionConfig extends Config { + source: string; + collectionId: string; +} From d4bf3a519a352ef67dce884120a4c3f3efcb2289 Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Thu, 25 Jan 2024 13:22:17 +0100 Subject: [PATCH 17/44] refactor, clean up --- src/app/core/data/update-data-service.ts | 210 ++++-------------- .../suggestions-data.service.ts | 3 +- .../dso-edit-metadata.component.ts | 2 +- .../themed-dso-edit-metadata.component.ts | 2 +- src/app/menu.resolver.ts | 2 +- .../suggestion-actions.component.ts | 4 +- .../suggestion-targets.effects.ts | 4 +- .../suggestion.service.spec.ts | 8 +- .../suggestions.service.ts | 13 +- .../suggestions-page.component.spec.ts | 3 - .../suggestions-page.component.ts | 12 +- src/config/suggestion-config.interfaces.ts | 2 +- 12 files changed, 72 insertions(+), 193 deletions(-) diff --git a/src/app/core/data/update-data-service.ts b/src/app/core/data/update-data-service.ts index 994cd0ee87b..9a31067f88c 100644 --- a/src/app/core/data/update-data-service.ts +++ b/src/app/core/data/update-data-service.ts @@ -1,84 +1,85 @@ import { HttpClient } from '@angular/common/http'; import { Store } from '@ngrx/store'; import { Operation } from 'fast-json-patch'; -import { AsyncSubject, combineLatest, from as observableFrom, Observable, of as observableOf } from 'rxjs'; +import { AsyncSubject, from as observableFrom, Observable } from 'rxjs'; import { - distinctUntilChanged, - filter, find, map, mergeMap, - skipWhile, switchMap, take, - takeWhile, - tap, toArray } from 'rxjs/operators'; -import { hasValue, isNotEmpty, isNotEmptyOperator } from '../../shared/empty.util'; -import { NotificationOptions } from '../../shared/notifications/models/notification-options.model'; +import { hasValue } from '../../shared/empty.util'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; -import { getClassForType } from '../cache/builders/build-decorators'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { RequestParam } from '../cache/models/request-param.model'; import { ObjectCacheEntry } from '../cache/object-cache.reducer'; import { ObjectCacheService } from '../cache/object-cache.service'; -import { DSpaceSerializer } from '../dspace-rest/dspace.serializer'; import { HALEndpointService } from '../shared/hal-endpoint.service'; -import { getFirstCompletedRemoteData, getFirstSucceededRemoteData, getRemoteDataPayload } from '../shared/operators'; -import { URLCombiner } from '../url-combiner/url-combiner'; import { ChangeAnalyzer } from './change-analyzer'; import { PaginatedList } from './paginated-list.model'; import { RemoteData } from './remote-data'; import { - CreateRequest, DeleteByIDRequest, - DeleteRequest, - GetRequest, - PatchRequest, - PostRequest, - PutRequest + PostRequest } from './request.models'; import { RequestService } from './request.service'; import { RestRequestMethod } from './rest-request-method'; -import { GenericConstructor } from '../shared/generic-constructor'; import { NoContent } from '../shared/NoContent.model'; import { CacheableObject } from '../cache/cacheable-object.model'; import { CoreState } from '../core-state.model'; import { FindListOptions } from './find-list-options.model'; -import { BaseDataService } from "./base/base-data.service"; -import { FindAllData, FindAllDataImpl } from "./base/find-all-data"; -import { SearchData, SearchDataImpl } from "./base/search-data"; -import { CreateData, CreateDataImpl } from "./base/create-data"; +import { FindAllData, FindAllDataImpl } from './base/find-all-data'; +import { SearchData, SearchDataImpl } from './base/search-data'; +import { CreateData, CreateDataImpl } from './base/create-data'; +import { PatchData, PatchDataImpl } from './base/patch-data'; +import { IdentifiableDataService } from './base/identifiable-data.service'; +import { PutData, PutDataImpl } from './base/put-data'; +import { DeleteData, DeleteDataImpl } from './base/delete-data'; + +/** + * Interface to list the methods used by the injected service in components + */ export interface UpdateDataService { patch(dso: T, operations: Operation[]): Observable>; update(object: T): Observable>; - commitUpdates(method?: RestRequestMethod); + commitUpdates(method?: RestRequestMethod): void; } /** * Specific functionalities that not all services would need. * Goal of the class is to update remote objects, handling custom methods that don't belong to BaseDataService + * The class implements also the following common interfaces + * + * findAllData: FindAllData; + * searchData: SearchData; + * createData: CreateData; + * patchData: PatchData; + * putData: PutData; + * deleteData: DeleteData; * * Custom methods are: * - * patch - Sends a patch request to modify current object - * update - Add a new patch to the object cache, diff between given object and cache - * commitUpdates - Sends the updates to the server + * deleteOnRelated - delete all related objects to the given one + * postOnRelated - post all the related objects to the given one + * invalidate - invalidate the DSpaceObject making all requests as stale + * invalidateByHref - invalidate the href making all requests as stale */ - -export abstract class UpdateDataServiceImpl extends BaseDataService implements UpdateDataService, FindAllData, SearchData, CreateData { +export abstract class UpdateDataServiceImpl extends IdentifiableDataService implements FindAllData, SearchData, CreateData, PatchData, PutData, DeleteData { protected abstract store: Store; protected abstract http: HttpClient; - protected abstract comparator: ChangeAnalyzer; private findAllData: FindAllDataImpl; private searchData: SearchDataImpl; - private createData: CreateData; + private createData: CreateDataImpl; + private patchData: PatchDataImpl; + private putData: PutDataImpl; + private deleteData: DeleteDataImpl; constructor( @@ -88,12 +89,16 @@ export abstract class UpdateDataServiceImpl extends B protected objectCache: ObjectCacheService, protected halService: HALEndpointService, protected notificationsService: NotificationsService, + protected comparator: ChangeAnalyzer, protected responseMsToLive: number, ) { super(linkPath, requestService, rdbService, objectCache, halService, responseMsToLive); this.findAllData = new FindAllDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive); this.searchData = new SearchDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive); this.createData = new CreateDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, notificationsService ,this.responseMsToLive); + this.patchData = new PatchDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, comparator ,this.responseMsToLive, this.constructIdEndpoint); + this.putData = new PutDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive); + this.deleteData = new DeleteDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, notificationsService ,this.responseMsToLive, this.constructIdEndpoint); } @@ -107,7 +112,7 @@ export abstract class UpdateDataServiceImpl extends B * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved */ public getFindAllHref(options: FindListOptions = {}, linkPath?: string, ...linksToFollow: FollowLinkConfig[]): Observable { - return this.findAllData.getFindAllHref(options, linkPath, ...linksToFollow) + return this.findAllData.getFindAllHref(options, linkPath, ...linksToFollow); } /** @@ -120,7 +125,7 @@ export abstract class UpdateDataServiceImpl extends B * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved */ public getSearchByHref(searchMethod: string, options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig[]): Observable { - return this.searchData.getSearchByHref(searchMethod, options, ...linksToFollow) + return this.searchData.getSearchByHref(searchMethod, options, ...linksToFollow); } /** @@ -138,27 +143,7 @@ export abstract class UpdateDataServiceImpl extends B * Return an observable that emits object list */ findAll(options: FindListOptions = {}, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable>> { - return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow) - } - - /** - * Create the HREF for a specific object based on its identifier; with possible embed query params based on linksToFollow - * @param endpoint The base endpoint for the type of object - * @param resourceID The identifier for the object - * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved - */ - getIDHref(endpoint, resourceID, ...linksToFollow: FollowLinkConfig[]): string { - return this.buildHrefFromFindOptions(endpoint + '/' + resourceID, {}, [], ...linksToFollow); - } - - /** - * Create an observable for the HREF of a specific object based on its identifier - * @param resourceID The identifier for the object - * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved - */ - getIDHrefObs(resourceID: string, ...linksToFollow: FollowLinkConfig[]): Observable { - return this.getEndpoint().pipe( - map((endpoint: string) => this.getIDHref(endpoint, resourceID, ...linksToFollow))); + return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); } /** @@ -177,29 +162,6 @@ export abstract class UpdateDataServiceImpl extends B return this.findByHref(href$, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); } - /** - * An operator that will call the given function if the incoming RemoteData is stale and - * shouldReRequest is true - * - * @param shouldReRequest Whether or not to call the re-request function if the RemoteData is stale - * @param requestFn The function to call if the RemoteData is stale and shouldReRequest is - * true - */ - protected reRequestStaleRemoteData(shouldReRequest: boolean, requestFn: () => Observable>) { - return (source: Observable>): Observable> => { - if (shouldReRequest === true) { - return source.pipe( - tap((remoteData: RemoteData) => { - if (hasValue(remoteData) && remoteData.isStale) { - requestFn(); - } - }) - ); - } else { - return source; - } - }; - } /** * Make a new FindListRequest with given search method @@ -216,7 +178,7 @@ export abstract class UpdateDataServiceImpl extends B * Return an observable that emits response from the server */ searchBy(searchMethod: string, options: FindListOptions = {}, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable>> { - return this.searchData.searchBy(searchMethod, options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow) + return this.searchData.searchBy(searchMethod, options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); } /** @@ -225,30 +187,11 @@ export abstract class UpdateDataServiceImpl extends B * @param {Operation[]} operations The patch operations to be performed */ patch(object: T, operations: Operation[]): Observable> { - const requestId = this.requestService.generateRequestId(); - - const hrefObs = this.halService.getEndpoint(this.linkPath).pipe( - map((endpoint: string) => this.getIDHref(endpoint, object.uuid))); - - hrefObs.pipe( - find((href: string) => hasValue(href)), - ).subscribe((href: string) => { - const request = new PatchRequest(requestId, href, operations); - if (hasValue(this.responseMsToLive)) { - request.responseMsToLive = this.responseMsToLive; - } - this.requestService.send(request); - }); - - return this.rdbService.buildFromRequestUUID(requestId); + return this.patchData.patch(object, operations); } createPatchFromCache(object: T): Observable { - const oldVersion$ = this.findByHref(object._links.self.href, true, false); - return oldVersion$.pipe( - getFirstSucceededRemoteData(), - getRemoteDataPayload(), - map((oldVersion: T) => this.comparator.diff(oldVersion, object))); + return this.patchData.createPatchFromCache(object); } /** @@ -257,17 +200,7 @@ export abstract class UpdateDataServiceImpl extends B * @param object The object to send a put request for. */ put(object: T): Observable> { - const requestId = this.requestService.generateRequestId(); - const serializedObject = new DSpaceSerializer(object.constructor as GenericConstructor<{}>).serialize(object); - const request = new PutRequest(requestId, object._links.self.href, serializedObject); - - if (hasValue(this.responseMsToLive)) { - request.responseMsToLive = this.responseMsToLive; - } - - this.requestService.send(request); - - return this.rdbService.buildFromRequestUUID(requestId); + return this.putData.put(object); } /** @@ -276,16 +209,7 @@ export abstract class UpdateDataServiceImpl extends B * @param {DSpaceObject} object The given object */ update(object: T): Observable> { - return this.createPatchFromCache(object) - .pipe( - mergeMap((operations: Operation[]) => { - if (isNotEmpty(operations)) { - this.objectCache.addPatch(object._links.self.href, operations); - } - return this.findByHref(object._links.self.href, true, true); - } - ) - ); + return this.patchData.update(object); } /** @@ -298,7 +222,7 @@ export abstract class UpdateDataServiceImpl extends B * Array with additional params to combine with query string */ create(object: T, ...params: RequestParam[]): Observable> { - return this.createData.create(object, ...params) + return this.createData.create(object, ...params); } /** @@ -390,9 +314,7 @@ export abstract class UpdateDataServiceImpl extends B * errorMessage, timeCompleted, etc */ delete(objectId: string, copyVirtualMetadata?: string[]): Observable> { - return this.getIDHrefObs(objectId).pipe( - switchMap((href: string) => this.deleteByHref(href, copyVirtualMetadata)) - ); + return this.deleteData.delete(objectId, copyVirtualMetadata); } /** @@ -405,43 +327,7 @@ export abstract class UpdateDataServiceImpl extends B * Only emits once all request related to the DSO has been invalidated. */ deleteByHref(href: string, copyVirtualMetadata?: string[]): Observable> { - const requestId = this.requestService.generateRequestId(); - - if (copyVirtualMetadata) { - copyVirtualMetadata.forEach((id) => - href += (href.includes('?') ? '&' : '?') - + 'copyVirtualMetadata=' - + id - ); - } - - const request = new DeleteRequest(requestId, href); - if (hasValue(this.responseMsToLive)) { - request.responseMsToLive = this.responseMsToLive; - } - this.requestService.send(request); - - const response$ = this.rdbService.buildFromRequestUUID(requestId); - - const invalidated$ = new AsyncSubject(); - response$.pipe( - getFirstCompletedRemoteData(), - switchMap((rd: RemoteData) => { - if (rd.hasSucceeded) { - return this.invalidateByHref(href); - } else { - return [true]; - } - }) - ).subscribe(() => { - invalidated$.next(true); - invalidated$.complete(); - }); - - return combineLatest([response$, invalidated$]).pipe( - filter(([_, invalidated]) => invalidated), - map(([response, _]) => response), - ); + return this.deleteData.deleteByHref(href, copyVirtualMetadata); } /** @@ -449,6 +335,6 @@ export abstract class UpdateDataServiceImpl extends B * @param method The RestRequestMethod for which de server sync buffer should be committed */ commitUpdates(method?: RestRequestMethod) { - this.requestService.commit(method); + this.patchData.commitUpdates(method); } } diff --git a/src/app/core/suggestion-notifications/suggestions-data.service.ts b/src/app/core/suggestion-notifications/suggestions-data.service.ts index 945cc8b083f..2078fdb75e2 100644 --- a/src/app/core/suggestion-notifications/suggestions-data.service.ts +++ b/src/app/core/suggestion-notifications/suggestions-data.service.ts @@ -58,7 +58,7 @@ export class SuggestionDataServiceImpl extends UpdateDataServiceImpl protected comparator: ChangeAnalyzer, protected responseMsToLive: number, ) { - super('suggestions', requestService, rdbService, objectCache, halService, notificationsService ,responseMsToLive); + super('suggestions', requestService, rdbService, objectCache, halService, notificationsService, comparator ,responseMsToLive); } } @@ -99,7 +99,6 @@ export class SuggestionsDataService { * @param {DefaultChangeAnalyzer} comparatorSuggestions * @param {DefaultChangeAnalyzer} comparatorSources * @param {DefaultChangeAnalyzer} comparatorTargets - * @param responseMsToLive */ constructor( protected requestService: RequestService, diff --git a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts index ad3d6680a17..22d23e84020 100644 --- a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts +++ b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts @@ -21,7 +21,7 @@ import { ArrayMoveChangeAnalyzer } from '../../core/data/array-move-change-analy import { DATA_SERVICE_FACTORY } from '../../core/data/base/data-service.decorator'; import { GenericConstructor } from '../../core/shared/generic-constructor'; import { HALDataService } from '../../core/data/base/hal-data-service.interface'; -import { UpdateDataService } from "../../core/data/update-data-service"; +import { UpdateDataService } from '../../core/data/update-data-service'; @Component({ selector: 'ds-dso-edit-metadata', diff --git a/src/app/dso-shared/dso-edit-metadata/themed-dso-edit-metadata.component.ts b/src/app/dso-shared/dso-edit-metadata/themed-dso-edit-metadata.component.ts index 51eec3ac230..5d7ccdd87d2 100644 --- a/src/app/dso-shared/dso-edit-metadata/themed-dso-edit-metadata.component.ts +++ b/src/app/dso-shared/dso-edit-metadata/themed-dso-edit-metadata.component.ts @@ -2,7 +2,7 @@ import { ThemedComponent } from '../../shared/theme-support/themed.component'; import { DsoEditMetadataComponent } from './dso-edit-metadata.component'; import { Component, Input } from '@angular/core'; import { DSpaceObject } from '../../core/shared/dspace-object.model'; -import { UpdateDataService } from "../../core/data/update-data-service"; +import { UpdateDataService } from '../../core/data/update-data-service'; @Component({ selector: 'ds-themed-dso-edit-metadata', diff --git a/src/app/menu.resolver.ts b/src/app/menu.resolver.ts index f2a7e2dbe19..fc6eb00195c 100644 --- a/src/app/menu.resolver.ts +++ b/src/app/menu.resolver.ts @@ -541,7 +541,7 @@ export class MenuResolver implements Resolve { { id: 'notifications', active: false, - visible: authorized && true, + visible: authorized && canSeeQA, model: { type: MenuItemType.TEXT, text: 'menu.section.notifications' diff --git a/src/app/suggestion-notifications/suggestion-actions/suggestion-actions.component.ts b/src/app/suggestion-notifications/suggestion-actions/suggestion-actions.component.ts index 5a4c6ebe3f9..f6e2452738e 100644 --- a/src/app/suggestion-notifications/suggestion-actions/suggestion-actions.component.ts +++ b/src/app/suggestion-notifications/suggestion-actions/suggestion-actions.component.ts @@ -86,10 +86,10 @@ export class SuggestionActionsComponent { } ignoreSuggestionLabel(): string { - return this.isBulk ? 'reciter.suggestion.ignoreSuggestion.bulk' : 'reciter.suggestion.ignoreSuggestion' ; + return this.isBulk ? 'suggestion.ignoreSuggestion.bulk' : 'suggestion.ignoreSuggestion' ; } approveAndImportLabel(): string { - return this.isBulk ? 'reciter.suggestion.approveAndImport.bulk' : 'reciter.suggestion.approveAndImport'; + return this.isBulk ? 'suggestion.approveAndImport.bulk' : 'suggestion.approveAndImport'; } } diff --git a/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.effects.ts b/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.effects.ts index 63964b77214..7a431bf4c2c 100644 --- a/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.effects.ts +++ b/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.effects.ts @@ -55,7 +55,7 @@ export class SuggestionTargetsEffects { retrieveAllTargetsErrorAction$ = createEffect(() => this.actions$.pipe( ofType(SuggestionTargetActionTypes.RETRIEVE_TARGETS_BY_SOURCE_ERROR), tap(() => { - this.notificationsService.error(null, this.translate.get('reciter.suggestion.target.error.service.retrieve')); + this.notificationsService.error(null, this.translate.get('suggestion.target.error.service.retrieve')); }) ), { dispatch: false }); @@ -64,7 +64,7 @@ export class SuggestionTargetsEffects { */ refreshUserSuggestionsAction$ = createEffect(() => this.actions$.pipe( ofType(SuggestionTargetActionTypes.REFRESH_USER_SUGGESTIONS), - switchMap((action: RefreshUserSuggestionsAction) => { + switchMap(() => { return this.store$.select((state: any) => state.core.auth.userId) .pipe( switchMap((userId: string) => { diff --git a/src/app/suggestion-notifications/suggestion.service.spec.ts b/src/app/suggestion-notifications/suggestion.service.spec.ts index e6ca83d5fe3..ad2cb8fcc4a 100644 --- a/src/app/suggestion-notifications/suggestion.service.spec.ts +++ b/src/app/suggestion-notifications/suggestion.service.spec.ts @@ -169,18 +169,18 @@ describe('SuggestionsService test', () => { it('should get suggestion interpolation', () => { const result = service.getNotificationSuggestionInterpolation(suggestionTarget as SuggestionTarget); expect(result.count).toEqual(suggestionTarget.total); - expect(result.source).toEqual('reciter.suggestion.source.' + suggestionTarget.source); - expect(result.type).toEqual('reciter.suggestion.type.' + suggestionTarget.source); + expect(result.source).toEqual('suggestion.source.' + suggestionTarget.source); + expect(result.type).toEqual('suggestion.type.' + suggestionTarget.source); expect(result.suggestionId).toEqual(suggestionTarget.id); expect(result.displayName).toEqual(suggestionTarget.display); }); it('should translate suggestion type', () => { - expect(service.translateSuggestionType('source')).toEqual('reciter.suggestion.type.source'); + expect(service.translateSuggestionType('source')).toEqual('suggestion.type.source'); }); it('should translate suggestion source', () => { - expect(service.translateSuggestionSource('source')).toEqual('reciter.suggestion.source.source'); + expect(service.translateSuggestionSource('source')).toEqual('suggestion.source.source'); }); it('should resolve collection id', () => { diff --git a/src/app/suggestion-notifications/suggestions.service.ts b/src/app/suggestion-notifications/suggestions.service.ts index 47d4124a47e..599215d5297 100644 --- a/src/app/suggestion-notifications/suggestions.service.ts +++ b/src/app/suggestion-notifications/suggestions.service.ts @@ -51,17 +51,14 @@ export class SuggestionsService { /** * Initialize the service variables. - * @param {AuthService} authService * @param {ResearcherProfileDataService} researcherProfileService - * @param {SuggestionSourceDataService} suggestionSourceDataService * @param {SuggestionTargetDataService} suggestionTargetDataService * @param {SuggestionsDataService} suggestionsDataService + * @param translateService */ constructor( - private authService: AuthService, private researcherProfileService: ResearcherProfileDataService, private suggestionsDataService: SuggestionsDataService, - private suggestionSourceDataService: SuggestionSourceDataService, private suggestionTargetDataService: SuggestionTargetDataService, private translateService: TranslateService ) { @@ -194,7 +191,7 @@ export class SuggestionsService { return workspaceitemService.importExternalSourceEntry(suggestion.externalSourceUri, resolvedCollectionId) .pipe( getFirstSucceededRemoteDataPayload(), - catchError((error) => of(null)) + catchError(() => of(null)) ); } @@ -204,7 +201,7 @@ export class SuggestionsService { */ public ignoreSuggestion(suggestionId): Observable> { return this.deleteReviewedSuggestion(suggestionId).pipe( - catchError((error) => of(null)) + catchError(() => of(null)) ); } @@ -268,11 +265,11 @@ export class SuggestionsService { } public translateSuggestionType(source: string): string { - return 'reciter.suggestion.type.' + source; + return 'suggestion.type.' + source; } public translateSuggestionSource(source: string): string { - return 'reciter.suggestion.source.' + source; + return 'suggestion.source.' + source; } /** diff --git a/src/app/suggestions-page/suggestions-page.component.spec.ts b/src/app/suggestions-page/suggestions-page.component.spec.ts index 2f6cfb7278f..6abd28386f1 100644 --- a/src/app/suggestions-page/suggestions-page.component.spec.ts +++ b/src/app/suggestions-page/suggestions-page.component.spec.ts @@ -13,8 +13,6 @@ import { } from '../suggestion-notifications/suggestion-list-element/suggestion-list-element.component'; import { SuggestionsService } from '../suggestion-notifications/suggestions.service'; import { getMockSuggestionNotificationsStateService, getMockSuggestionsService } from '../shared/mocks/suggestion.mock'; -import { buildPaginatedList, PaginatedList } from '../core/data/paginated-list.model'; -import { Suggestion } from '../core/suggestion-notifications/models/suggestion.model'; import { mockSuggestionPublicationOne, mockSuggestionPublicationTwo } from '../shared/mocks/publication-claim.mock'; import { SuggestionEvidencesComponent } from '../suggestion-notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component'; import { ObjectKeysPipe } from '../shared/utils/object-keys-pipe'; @@ -29,7 +27,6 @@ import { getMockTranslateService } from '../shared/mocks/translate.service.mock' import { SuggestionTargetsStateService } from '../suggestion-notifications/suggestion-targets/suggestion-targets.state.service'; import { WorkspaceitemDataService } from '../core/submission/workspaceitem-data.service'; import { createSuccessfulRemoteDataObject } from '../shared/remote-data.utils'; -import { PageInfo } from '../core/shared/page-info.model'; import { TestScheduler } from 'rxjs/testing'; import { getTestScheduler } from 'jasmine-marbles'; import { PaginationServiceStub } from '../shared/testing/pagination-service.stub'; diff --git a/src/app/suggestions-page/suggestions-page.component.ts b/src/app/suggestions-page/suggestions-page.component.ts index 09051441f4a..48245b60b3b 100644 --- a/src/app/suggestions-page/suggestions-page.component.ts +++ b/src/app/suggestions-page/suggestions-page.component.ts @@ -152,7 +152,7 @@ export class SuggestionsPageComponent implements OnInit { * @suggestionId */ ignoreSuggestion(suggestionId) { - this.suggestionService.ignoreSuggestion(suggestionId).subscribe((res) => { + this.suggestionService.ignoreSuggestion(suggestionId).subscribe(() => { this.suggestionTargetsStateService.dispatchRefreshUserSuggestionsAction(); this.updatePage(); }); @@ -172,12 +172,12 @@ export class SuggestionsPageComponent implements OnInit { this.selectedSuggestions = {}; if (results.success > 0) { this.notificationService.success( - this.translateService.get('reciter.suggestion.notMine.bulk.success', + this.translateService.get('suggestion.notMine.bulk.success', {count: results.success})); } if (results.fails > 0) { this.notificationService.error( - this.translateService.get('reciter.suggestion.notMine.bulk.error', + this.translateService.get('suggestion.notMine.bulk.error', {count: results.fails})); } }); @@ -190,7 +190,7 @@ export class SuggestionsPageComponent implements OnInit { approveAndImport(event: SuggestionApproveAndImport) { this.suggestionService.approveAndImport(this.workspaceItemService, event.suggestion, event.collectionId) .subscribe((workspaceitem: WorkspaceItem) => { - const content = this.translateService.instant('reciter.suggestion.approveAndImport.success', { workspaceItemId: workspaceitem.id }); + const content = this.translateService.instant('suggestion.approveAndImport.success', { workspaceItemId: workspaceitem.id }); this.notificationService.success('', content, {timeOut:0}, true); this.suggestionTargetsStateService.dispatchRefreshUserSuggestionsAction(); this.updatePage(); @@ -212,12 +212,12 @@ export class SuggestionsPageComponent implements OnInit { this.selectedSuggestions = {}; if (results.success > 0) { this.notificationService.success( - this.translateService.get('reciter.suggestion.approveAndImport.bulk.success', + this.translateService.get('suggestion.approveAndImport.bulk.success', {count: results.success})); } if (results.fails > 0) { this.notificationService.error( - this.translateService.get('reciter.suggestion.approveAndImport.bulk.error', + this.translateService.get('suggestion.approveAndImport.bulk.error', {count: results.fails})); } }); diff --git a/src/config/suggestion-config.interfaces.ts b/src/config/suggestion-config.interfaces.ts index e99ffa25f70..afd3a38c581 100644 --- a/src/config/suggestion-config.interfaces.ts +++ b/src/config/suggestion-config.interfaces.ts @@ -1,4 +1,4 @@ -import { Config } from "./config.interface"; +import { Config } from './config.interface'; export interface SuggestionConfig extends Config { source: string; From 4cca9015a1fab16d78ad689c5024b7782a2af7ad Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Thu, 25 Jan 2024 13:23:01 +0100 Subject: [PATCH 18/44] remove unused imports --- .../suggestion-targets/suggestion-targets.effects.ts | 1 - src/app/suggestion-notifications/suggestions.service.ts | 4 ---- 2 files changed, 5 deletions(-) diff --git a/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.effects.ts b/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.effects.ts index 7a431bf4c2c..1358e6f8b54 100644 --- a/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.effects.ts +++ b/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.effects.ts @@ -9,7 +9,6 @@ import { of } from 'rxjs'; import { AddTargetAction, AddUserSuggestionsAction, - RefreshUserSuggestionsAction, RetrieveAllTargetsErrorAction, RetrieveTargetsBySourceAction, SuggestionTargetActionTypes, diff --git a/src/app/suggestion-notifications/suggestions.service.ts b/src/app/suggestion-notifications/suggestions.service.ts index 599215d5297..bf21b5ae2f4 100644 --- a/src/app/suggestion-notifications/suggestions.service.ts +++ b/src/app/suggestion-notifications/suggestions.service.ts @@ -7,7 +7,6 @@ import { SortDirection, SortOptions } from '../core/cache/models/sort-options.mo import { RemoteData } from '../core/data/remote-data'; import { PaginatedList } from '../core/data/paginated-list.model'; import { SuggestionTarget } from '../core/suggestion-notifications/models/suggestion-target.model'; -import { AuthService } from '../core/auth/auth.service'; import { hasValue, isNotEmpty } from '../shared/empty.util'; import { ResearcherProfile } from '../core/profile/model/researcher-profile.model'; import { @@ -25,9 +24,6 @@ import { WorkspaceItem } from '../core/submission/models/workspaceitem.model'; import {FindListOptions} from '../core/data/find-list-options.model'; import {SuggestionConfig} from '../../config/suggestion-config.interfaces'; import { ResearcherProfileDataService } from '../core/profile/researcher-profile-data.service'; -import { - SuggestionSourceDataService -} from '../core/suggestion-notifications/source/suggestion-source-data.service'; import { SuggestionTargetDataService } from '../core/suggestion-notifications/target/suggestion-target-data.service'; From e77343604e2288c0310c7c1565fce47e781cf11a Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Thu, 25 Jan 2024 13:50:23 +0100 Subject: [PATCH 19/44] refactor and add tests --- src/app/core/data/update-data-service.spec.ts | 144 ++++++++++++++++++ src/app/core/data/update-data-service.ts | 25 +-- .../suggestion.service.spec.ts | 15 +- 3 files changed, 147 insertions(+), 37 deletions(-) create mode 100644 src/app/core/data/update-data-service.spec.ts diff --git a/src/app/core/data/update-data-service.spec.ts b/src/app/core/data/update-data-service.spec.ts new file mode 100644 index 00000000000..6912527b918 --- /dev/null +++ b/src/app/core/data/update-data-service.spec.ts @@ -0,0 +1,144 @@ +import { of as observableOf } from 'rxjs'; +import { TestScheduler } from 'rxjs/testing'; +import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../cache/object-cache.service'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; +import { RequestService } from './request.service'; +import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; +import { HrefOnlyDataService } from './href-only-data.service'; +import { getMockHrefOnlyDataService } from '../../shared/mocks/href-only-data.service.mock'; +import { RestResponse } from '../cache/response.models'; +import { cold, getTestScheduler, hot } from 'jasmine-marbles'; +import { Item } from '../shared/item.model'; +import { Version } from '../shared/version.model'; +import { VersionHistory } from '../shared/version-history.model'; +import { RequestEntry } from './request-entry.model'; +import { testPatchDataImplementation } from './base/patch-data.spec'; +import { UpdateDataServiceImpl } from './update-data-service'; +import { testSearchDataImplementation } from './base/search-data.spec'; +import { testDeleteDataImplementation } from './base/delete-data.spec'; +import { testCreateDataImplementation } from './base/create-data.spec'; +import { testFindAllDataImplementation } from './base/find-all-data.spec'; +import { testPutDataImplementation } from './base/put-data.spec'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; + +describe('VersionDataService test', () => { + let scheduler: TestScheduler; + let service: UpdateDataServiceImpl; + let requestService: RequestService; + let rdbService: RemoteDataBuildService; + let objectCache: ObjectCacheService; + let halService: HALEndpointService; + let hrefOnlyDataService: HrefOnlyDataService; + let responseCacheEntry: RequestEntry; + + const notificationsService = {} as NotificationsService; + + const item = Object.assign(new Item(), { + id: '1234-1234', + uuid: '1234-1234', + bundles: observableOf({}), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ], + 'dc.type': [ + { + language: null, + value: 'Article' + } + ], + 'dc.contributor.author': [ + { + language: 'en_US', + value: 'Smith, Donald' + } + ], + 'dc.date.issued': [ + { + language: null, + value: '2015-06-26' + } + ] + } + }); + + const versionHistory = Object.assign(new VersionHistory(), { + id: '1', + draftVersion: true, + }); + + const mockVersion: Version = Object.assign(new Version(), { + item: createSuccessfulRemoteDataObject$(item), + versionhistory: createSuccessfulRemoteDataObject$(versionHistory), + version: 1, + }); + const mockVersionRD = createSuccessfulRemoteDataObject(mockVersion); + + const endpointURL = `https://rest.api/rest/api/versioning/versions`; + const requestUUID = '8b3c613a-5a4b-438b-9686-be1d5b4a1c5a'; + + objectCache = {} as ObjectCacheService; + const comparatorEntry = {} as any; + function initTestService() { + hrefOnlyDataService = getMockHrefOnlyDataService(); + return new UpdateDataServiceImpl( + 'testLinkPath', + requestService, + rdbService, + objectCache, + halService, + notificationsService, + comparatorEntry, + 10 * 1000 + ); + } + + beforeEach(() => { + + scheduler = getTestScheduler(); + + halService = jasmine.createSpyObj('halService', { + getEndpoint: cold('a', { a: endpointURL }) + }); + responseCacheEntry = new RequestEntry(); + responseCacheEntry.request = { href: 'https://rest.api/' } as any; + responseCacheEntry.response = new RestResponse(true, 200, 'Success'); + + requestService = jasmine.createSpyObj('requestService', { + generateRequestId: requestUUID, + send: true, + removeByHrefSubstring: {}, + getByHref: observableOf(responseCacheEntry), + getByUUID: observableOf(responseCacheEntry), + }); + rdbService = jasmine.createSpyObj('rdbService', { + buildSingle: hot('(a|)', { + a: mockVersionRD + }) + }); + + service = initTestService(); + + spyOn((service as any), 'findById').and.callThrough(); + }); + + afterEach(() => { + service = null; + }); + + describe('composition', () => { + const initService = () => new UpdateDataServiceImpl(null, null, null, null, null, null, null, null); + + testPatchDataImplementation(initService); + testSearchDataImplementation(initService); + testDeleteDataImplementation(initService); + testCreateDataImplementation(initService); + testFindAllDataImplementation(initService); + testPutDataImplementation(initService); + }); + +}); diff --git a/src/app/core/data/update-data-service.ts b/src/app/core/data/update-data-service.ts index 9a31067f88c..715b2ee413c 100644 --- a/src/app/core/data/update-data-service.ts +++ b/src/app/core/data/update-data-service.ts @@ -1,5 +1,3 @@ -import { HttpClient } from '@angular/common/http'; -import { Store } from '@ngrx/store'; import { Operation } from 'fast-json-patch'; import { AsyncSubject, from as observableFrom, Observable } from 'rxjs'; import { @@ -29,7 +27,6 @@ import { RequestService } from './request.service'; import { RestRequestMethod } from './rest-request-method'; import { NoContent } from '../shared/NoContent.model'; import { CacheableObject } from '../cache/cacheable-object.model'; -import { CoreState } from '../core-state.model'; import { FindListOptions } from './find-list-options.model'; import { FindAllData, FindAllDataImpl } from './base/find-all-data'; import { SearchData, SearchDataImpl } from './base/search-data'; @@ -70,10 +67,7 @@ export interface UpdateDataService { * invalidateByHref - invalidate the href making all requests as stale */ -export abstract class UpdateDataServiceImpl extends IdentifiableDataService implements FindAllData, SearchData, CreateData, PatchData, PutData, DeleteData { - protected abstract store: Store; - protected abstract http: HttpClient; - +export class UpdateDataServiceImpl extends IdentifiableDataService implements FindAllData, SearchData, CreateData, PatchData, PutData, DeleteData { private findAllData: FindAllDataImpl; private searchData: SearchDataImpl; private createData: CreateDataImpl; @@ -146,23 +140,6 @@ export abstract class UpdateDataServiceImpl extends I return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); } - /** - * Returns an observable of {@link RemoteData} of an object, based on its ID, with a list of - * {@link FollowLinkConfig}, to automatically resolve {@link HALLink}s of the object - * @param id ID of object we want to retrieve - * @param useCachedVersionIfAvailable If this is true, the request will only be sent if there's - * no valid cached version. Defaults to true - * @param reRequestOnStale Whether or not the request should automatically be re- - * requested after the response becomes stale - * @param linksToFollow List of {@link FollowLinkConfig} that indicate which - * {@link HALLink}s should be automatically resolved - */ - findById(id: string, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable> { - const href$ = this.getIDHrefObs(encodeURIComponent(id), ...linksToFollow); - return this.findByHref(href$, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); - } - - /** * Make a new FindListRequest with given search method * diff --git a/src/app/suggestion-notifications/suggestion.service.spec.ts b/src/app/suggestion-notifications/suggestion.service.spec.ts index ad2cb8fcc4a..acb0bb3be2e 100644 --- a/src/app/suggestion-notifications/suggestion.service.spec.ts +++ b/src/app/suggestion-notifications/suggestion.service.spec.ts @@ -1,12 +1,10 @@ import { SuggestionsService } from './suggestions.service'; -import { AuthService } from '../core/auth/auth.service'; import { ResearcherProfileDataService } from '../core/profile/researcher-profile-data.service'; import { SuggestionsDataService } from '../core/suggestion-notifications/suggestions-data.service'; -import { - SuggestionSourceDataService -} from '../core/suggestion-notifications/source/suggestion-source-data.service'; + + import { SuggestionTargetDataService } from '../core/suggestion-notifications/target/suggestion-target-data.service'; @@ -29,10 +27,8 @@ import { describe('SuggestionsService test', () => { let scheduler: TestScheduler; let service: SuggestionsService; - let authService: AuthService; let researcherProfileService: ResearcherProfileDataService; let suggestionsDataService: SuggestionsDataService; - let suggestionSourceDataService: SuggestionSourceDataService; let suggestionTargetDataService: SuggestionTargetDataService; let translateService: any = { instant: (str) => str, @@ -53,10 +49,8 @@ describe('SuggestionsService test', () => { function initTestService() { return new SuggestionsService( - authService, researcherProfileService, suggestionsDataService, - suggestionSourceDataService, suggestionTargetDataService, translateService ); @@ -65,11 +59,6 @@ describe('SuggestionsService test', () => { beforeEach(() => { scheduler = getTestScheduler(); - - suggestionSourceDataService = jasmine.createSpyObj('suggestionSourcesDataService', { - getSources: observableOf(null), - }); - researcherProfileService = jasmine.createSpyObj('researcherProfileService', { findById: createSuccessfulRemoteDataObject$(mockResercherProfile as ResearcherProfile), findRelatedItemId: observableOf('1234'), From 604d35590221847519a69f1ca646cc53cfe33e06 Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Thu, 25 Jan 2024 13:59:17 +0100 Subject: [PATCH 20/44] update labels --- .../suggestion-evidences.component.html | 6 +++--- .../suggestion-list-element.component.html | 2 +- src/app/suggestions-page/suggestions-page.component.html | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/app/suggestion-notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.html b/src/app/suggestion-notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.html index 5ad4f0a9783..e23c244eb49 100644 --- a/src/app/suggestion-notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.html +++ b/src/app/suggestion-notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.html @@ -3,9 +3,9 @@

{{'reciter.suggestion.table.name' | translate}}{{'reciter.suggestion.table.actions' | translate}}{{'suggestion.table.name' | translate}}{{'suggestion.table.actions' | translate}}
- - - + + + diff --git a/src/app/suggestion-notifications/suggestion-list-element/suggestion-list-element.component.html b/src/app/suggestion-notifications/suggestion-list-element/suggestion-list-element.component.html index 3d95aed8a3c..ef27876f2cb 100644 --- a/src/app/suggestion-notifications/suggestion-list-element/suggestion-list-element.component.html +++ b/src/app/suggestion-notifications/suggestion-list-element/suggestion-list-element.component.html @@ -11,7 +11,7 @@
-
{{'reciter.suggestion.totalScore' | translate}}
+
{{'suggestion.totalScore' | translate}}
{{ object.score }}
diff --git a/src/app/suggestions-page/suggestions-page.component.html b/src/app/suggestions-page/suggestions-page.component.html index f8b14f67286..89c676ab71a 100644 --- a/src/app/suggestions-page/suggestions-page.component.html +++ b/src/app/suggestions-page/suggestions-page.component.html @@ -6,9 +6,9 @@

{{ translateSuggestionType() | translate }} - {{'reciter.suggestion.suggestionFor' | translate}} + {{'suggestion.suggestionFor' | translate}} {{researcherName}} - {{'reciter.suggestion.from.source' | translate}} {{ translateSuggestionSource() | translate }} + {{'suggestion.from.source' | translate}} {{ translateSuggestionSource() | translate }}

@@ -33,7 +33,7 @@

  • Date: Thu, 25 Jan 2024 16:42:36 +0100 Subject: [PATCH 21/44] added german translations of feedback page translation keys --- src/assets/i18n/de.json5 | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/assets/i18n/de.json5 b/src/assets/i18n/de.json5 index c185a13432b..1f93726e05f 100644 --- a/src/assets/i18n/de.json5 +++ b/src/assets/i18n/de.json5 @@ -2193,6 +2193,44 @@ // "info.privacy.title": "Privacy Statement", "info.privacy.title": "Datenschutzerklärung", + // "info.feedback.breadcrumbs": "Feedback", + "info.feedback.breadcrumbs": "Feedback", + + // "info.feedback.head": "Feedback", + "info.feedback.head": "Feedback", + + // "info.feedback.title": "Feedback", + "info.feedback.title": "Feedback", + + // "info.feedback.info": "Thanks for sharing your feedback about the DSpace system. Your comments are appreciated!", + "info.feedback.info": "Vielen Dank für Ihre Rückmeldung. Wir werden uns in Kürze bei Ihnen melden, sofern Sie eine Rückmeldung gewünscht haben.", + + // "info.feedback.email_help": "This address will be used to follow up on your feedback.", + "info.feedback.email_help": "Sollten wir Rückfragen zu Ihrem Feedback haben, dann kontaktieren wir Sie unter dieser E-Mailadresse.", + + // "info.feedback.send": "Send Feedback", + "info.feedback.send": "Feedback senden", + + // "info.feedback.comments": "Comments", + "info.feedback.comments": "Ihr Kommentar", + + // "info.feedback.email-label": "Your Email", + "info.feedback.email-label": "Ihre E-Mailadresse", + + // "info.feedback.create.success": "Feedback Sent Successfully!", + "info.feedback.create.success": "Ihr Feedback wurde erfolgreich versendet.", + + // "info.feedback.error.email.required": "A valid email address is required", + "info.feedback.error.email.required": "Bitte geben Sie eine gültige E-Mailadresse ein!", + + // "info.feedback.error.message.required": "A comment is required", + "info.feedback.error.message.required": "Bitte geben Sie einen Kommentar ein!", + + // "info.feedback.page-label": "Page", + "info.feedback.page-label": "URL der Seite", + + // "info.feedback.page_help": "The page related to your feedback", + "info.feedback.page_help": "Dies ist die URL der Seite, auf die sich Ihr Feedback bezieht.", // "item.alerts.private": "This item is private", From e03b492dbd2a60b3512361c08f343c73392561cc Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Thu, 25 Jan 2024 16:51:25 +0100 Subject: [PATCH 22/44] minor improvement of German translation --- src/assets/i18n/de.json5 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assets/i18n/de.json5 b/src/assets/i18n/de.json5 index 1f93726e05f..6c11866891b 100644 --- a/src/assets/i18n/de.json5 +++ b/src/assets/i18n/de.json5 @@ -2203,7 +2203,7 @@ "info.feedback.title": "Feedback", // "info.feedback.info": "Thanks for sharing your feedback about the DSpace system. Your comments are appreciated!", - "info.feedback.info": "Vielen Dank für Ihre Rückmeldung. Wir werden uns in Kürze bei Ihnen melden, sofern Sie eine Rückmeldung gewünscht haben.", + "info.feedback.info": "Wir freuen uns auf Ihr Feedback. Sofern Sie eine Rückmeldung wünschen, werden wir uns in Kürze bei Ihnen melden.", // "info.feedback.email_help": "This address will be used to follow up on your feedback.", "info.feedback.email_help": "Sollten wir Rückfragen zu Ihrem Feedback haben, dann kontaktieren wir Sie unter dieser E-Mailadresse.", @@ -2218,7 +2218,7 @@ "info.feedback.email-label": "Ihre E-Mailadresse", // "info.feedback.create.success": "Feedback Sent Successfully!", - "info.feedback.create.success": "Ihr Feedback wurde erfolgreich versendet.", + "info.feedback.create.success": "Vielen Dank für Ihr Feedback! Ihr Feedback wurde erfolgreich versendet.", // "info.feedback.error.email.required": "A valid email address is required", "info.feedback.error.email.required": "Bitte geben Sie eine gültige E-Mailadresse ein!", From 80174817fd3de270cdb1d9c090c29db371b4ba87 Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Thu, 25 Jan 2024 19:32:12 +0100 Subject: [PATCH 23/44] add breadcrumbs, adapt tests, fix issue on page loading --- ...lication-claim-breadcrumb.resolver.spec.ts | 31 +++++++++++++ .../publication-claim-breadcrumb.resolver.ts | 24 ++++++++++ ...blication-claim-breadcrumb.service.spec.ts | 46 +++++++++++++++++++ .../publication-claim-breadcrumb.service.ts | 42 +++++++++++++++++ .../cache/builders/build-decorators.spec.ts | 8 +++- .../publication-claim.component.html | 2 +- .../publication-claim.component.ts | 9 +--- .../suggestions-page-routing.module.ts | 6 +-- 8 files changed, 155 insertions(+), 13 deletions(-) create mode 100644 src/app/core/breadcrumbs/publication-claim-breadcrumb.resolver.spec.ts create mode 100644 src/app/core/breadcrumbs/publication-claim-breadcrumb.resolver.ts create mode 100644 src/app/core/breadcrumbs/publication-claim-breadcrumb.service.spec.ts create mode 100644 src/app/core/breadcrumbs/publication-claim-breadcrumb.service.ts diff --git a/src/app/core/breadcrumbs/publication-claim-breadcrumb.resolver.spec.ts b/src/app/core/breadcrumbs/publication-claim-breadcrumb.resolver.spec.ts new file mode 100644 index 00000000000..b6f41424693 --- /dev/null +++ b/src/app/core/breadcrumbs/publication-claim-breadcrumb.resolver.spec.ts @@ -0,0 +1,31 @@ +import { PublicationClaimBreadcrumbResolver } from './publication-claim-breadcrumb.resolver'; + +describe('PublicationClaimBreadcrumbResolver', () => { + describe('resolve', () => { + let resolver: PublicationClaimBreadcrumbResolver; + let publicationClaimBreadcrumbService: any; + const fullPath = '/test/publication-claim/openaire:6bee076d-4f2a-4555-a475-04a267769b2a'; + const expectedKey = '6bee076d-4f2a-4555-a475-04a267769b2a'; + const expectedId = 'openaire:6bee076d-4f2a-4555-a475-04a267769b2a'; + let route; + + beforeEach(() => { + route = { + paramMap: { + get: function (param) { + return this[param]; + }, + targetId: expectedId, + } + }; + publicationClaimBreadcrumbService = {}; + resolver = new PublicationClaimBreadcrumbResolver(publicationClaimBreadcrumbService); + }); + + it('should resolve the breadcrumb config', () => { + const resolvedConfig = resolver.resolve(route as any, {url: fullPath } as any); + const expectedConfig = { provider: publicationClaimBreadcrumbService, key: expectedKey }; + expect(resolvedConfig).toEqual(expectedConfig); + }); + }); +}); diff --git a/src/app/core/breadcrumbs/publication-claim-breadcrumb.resolver.ts b/src/app/core/breadcrumbs/publication-claim-breadcrumb.resolver.ts new file mode 100644 index 00000000000..713500d6a73 --- /dev/null +++ b/src/app/core/breadcrumbs/publication-claim-breadcrumb.resolver.ts @@ -0,0 +1,24 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router'; +import {BreadcrumbConfig} from '../../breadcrumbs/breadcrumb/breadcrumb-config.model'; +import { PublicationClaimBreadcrumbService } from './publication-claim-breadcrumb.service'; + +@Injectable({ + providedIn: 'root' +}) +export class PublicationClaimBreadcrumbResolver implements Resolve> { + constructor(protected breadcrumbService: PublicationClaimBreadcrumbService) { + } + + /** + * Method that resolve Publication Claim item into a breadcrumb + * The parameter are retrieved by the url since part of the Publication Claim route config + * @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot + * @param {RouterStateSnapshot} state The current RouterStateSnapshot + * @returns BreadcrumbConfig object + */ + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): BreadcrumbConfig { + const targetId = route.paramMap.get('targetId').split(':')[1]; + return { provider: this.breadcrumbService, key: targetId }; + } +} diff --git a/src/app/core/breadcrumbs/publication-claim-breadcrumb.service.spec.ts b/src/app/core/breadcrumbs/publication-claim-breadcrumb.service.spec.ts new file mode 100644 index 00000000000..61fb1d82bf3 --- /dev/null +++ b/src/app/core/breadcrumbs/publication-claim-breadcrumb.service.spec.ts @@ -0,0 +1,46 @@ +import { TestBed, waitForAsync } from '@angular/core/testing'; +import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model'; +import { getTestScheduler } from 'jasmine-marbles'; +import { PublicationClaimBreadcrumbService } from './publication-claim-breadcrumb.service'; +import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; + +describe('PublicationClaimBreadcrumbService', () => { + let service: PublicationClaimBreadcrumbService; + let dsoNameService: any = { + getName: (str) => str + }; + let translateService: any = { + instant: (str) => str, + }; + + let dataService: any = { + findById: (str) => createSuccessfulRemoteDataObject$(str), + }; + + let exampleKey; + + const ADMIN_PUBLICATION_CLAIMS_PATH = 'admin/notifications/publication-claim'; + const ADMIN_PUBLICATION_CLAIMS_BREADCRUMB_KEY = 'admin.notifications.publicationclaim.page.title'; + + function init() { + exampleKey = '6bee076d-4f2a-4555-a475-04a267769b2a'; + } + + beforeEach(waitForAsync(() => { + init(); + TestBed.configureTestingModule({}).compileComponents(); + })); + + beforeEach(() => { + service = new PublicationClaimBreadcrumbService(dataService,dsoNameService,translateService); + }); + + describe('getBreadcrumbs', () => { + it('should return a breadcrumb based on a string', () => { + const breadcrumbs = service.getBreadcrumbs(exampleKey); + getTestScheduler().expectObservable(breadcrumbs).toBe('(a|)', { a: [new Breadcrumb(ADMIN_PUBLICATION_CLAIMS_BREADCRUMB_KEY, ADMIN_PUBLICATION_CLAIMS_PATH), + new Breadcrumb(exampleKey, undefined)] + }); + }); + }); +}); diff --git a/src/app/core/breadcrumbs/publication-claim-breadcrumb.service.ts b/src/app/core/breadcrumbs/publication-claim-breadcrumb.service.ts new file mode 100644 index 00000000000..64284ee5100 --- /dev/null +++ b/src/app/core/breadcrumbs/publication-claim-breadcrumb.service.ts @@ -0,0 +1,42 @@ +import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model'; +import { BreadcrumbsProviderService } from './breadcrumbsProviderService'; +import { Observable } from 'rxjs'; +import { Injectable } from '@angular/core'; +import { ItemDataService } from '../data/item-data.service'; +import { getFirstCompletedRemoteData } from '../shared/operators'; +import { map } from 'rxjs/operators'; +import { DSONameService } from './dso-name.service'; +import { TranslateService } from '@ngx-translate/core'; + + + +/** + * Service to calculate Publication claims breadcrumbs + */ +@Injectable({ + providedIn: 'root' +}) +export class PublicationClaimBreadcrumbService implements BreadcrumbsProviderService { + private ADMIN_PUBLICATION_CLAIMS_PATH = 'admin/notifications/publication-claim'; + private ADMIN_PUBLICATION_CLAIMS_BREADCRUMB_KEY = 'admin.notifications.publicationclaim.page.title'; + + constructor(private dataService: ItemDataService, + private dsoNameService: DSONameService, + private tranlsateService: TranslateService) { + } + + + /** + * Method to calculate the breadcrumbs + * @param key The key used to resolve the breadcrumb + */ + getBreadcrumbs(key: string): Observable { + return this.dataService.findById(key).pipe( + getFirstCompletedRemoteData(), + map((item) => { + return [new Breadcrumb(this.tranlsateService.instant(this.ADMIN_PUBLICATION_CLAIMS_BREADCRUMB_KEY), this.ADMIN_PUBLICATION_CLAIMS_PATH), + new Breadcrumb(this.dsoNameService.getName(item.payload), undefined)]; + }) + ); + } +} diff --git a/src/app/core/cache/builders/build-decorators.spec.ts b/src/app/core/cache/builders/build-decorators.spec.ts index 90d4b4fef83..e4baaa4a5a8 100644 --- a/src/app/core/cache/builders/build-decorators.spec.ts +++ b/src/app/core/cache/builders/build-decorators.spec.ts @@ -1,7 +1,7 @@ import { HALLink } from '../../shared/hal-link.model'; import { HALResource } from '../../shared/hal-resource.model'; import { ResourceType } from '../../shared/resource-type'; -import { dataService, getLinkDefinition, link } from './build-decorators'; +import { dataService, getDataServiceFor, getLinkDefinition, link } from './build-decorators'; class TestHALResource implements HALResource { _links: { @@ -51,6 +51,12 @@ describe('build decorators', () => { it(`should throw error`, () => { expect(dataService(null)).toThrow(); }); + + it(`should set properly data service for type`, () => { + const target = new TestHALResource(); + dataService(testType)(target); + expect(getDataServiceFor(testType)).toEqual(target); + }); }); }); }); diff --git a/src/app/suggestion-notifications/suggestion-targets/publication-claim/publication-claim.component.html b/src/app/suggestion-notifications/suggestion-targets/publication-claim/publication-claim.component.html index 45068cd12c8..f2ab1e5b652 100644 --- a/src/app/suggestion-notifications/suggestion-targets/publication-claim/publication-claim.component.html +++ b/src/app/suggestion-notifications/suggestion-targets/publication-claim/publication-claim.component.html @@ -31,7 +31,7 @@

    {{'suggestion.title'| translate}}

  • {{'reciter.suggestion.evidence.score' | translate}}{{'reciter.suggestion.evidence.type' | translate}}{{'reciter.suggestion.evidence.notes' | translate}}{{'suggestion.evidence.score' | translate}}{{'suggestion.evidence.type' | translate}}{{'suggestion.evidence.notes' | translate}}
    - + ({{ getSelectedSuggestionsCount() }})
    +
    {{ 'suggestion.count.missing' | translate }}
    diff --git a/src/app/suggestions-page/suggestions-page.component.ts b/src/app/suggestions-page/suggestions-page.component.ts index 48245b60b3b..d986366f1c3 100644 --- a/src/app/suggestions-page/suggestions-page.component.ts +++ b/src/app/suggestions-page/suggestions-page.component.ts @@ -172,12 +172,12 @@ export class SuggestionsPageComponent implements OnInit { this.selectedSuggestions = {}; if (results.success > 0) { this.notificationService.success( - this.translateService.get('suggestion.notMine.bulk.success', + this.translateService.get('suggestion.ignoreSuggestion.bulk.success', {count: results.success})); } if (results.fails > 0) { this.notificationService.error( - this.translateService.get('suggestion.notMine.bulk.error', + this.translateService.get('suggestion.ignoreSuggestion.bulk.error', {count: results.fails})); } }); diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 006fbdb5d49..fd4e50610c3 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -3596,7 +3596,7 @@ "suggestion.approveAndImport.bulk": "Approve & import Selected", - ".suggestion.approveAndImport.bulk.success": "{{ count }} suggestions have been imported successfully ", + "suggestion.approveAndImport.bulk.success": "{{ count }} suggestions have been imported successfully ", "suggestion.approveAndImport.bulk.error": "{{ count }} suggestions haven't been imported due to unexpected server errors", @@ -3620,6 +3620,8 @@ "suggestion.from.source": "from the ", + "suggestion.count.missing": "You have no publication claims left", + "suggestion.totalScore": "Total Score", "suggestion.type.openaire": "OpenAIRE", diff --git a/src/config/default-app-config.ts b/src/config/default-app-config.ts index be9306c893c..3b3eb00ddbf 100644 --- a/src/config/default-app-config.ts +++ b/src/config/default-app-config.ts @@ -304,8 +304,9 @@ export class DefaultAppConfig implements AppConfig { // source: 'suggestionSource', // collectionId: 'collectionUUID' // } - // If not mapped the suggestion service won't be able to approve and import the related suggestion - // or load the fixed suggestions collections that can be configured here adding the source and the UUID of the collection + // This is used as a default fallback in case there aren't collections where to import the suggestion + // If not mapped the user will be allowed to import the suggestions only in the provided options, shown clicking the button "Approve and import" + // If not mapped and no options available for import the user won't be able to import the suggestions. ]; // Theme Config From b8555f53c3125b6e9a61da116a41e43b9896a471 Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Fri, 26 Jan 2024 11:53:56 +0100 Subject: [PATCH 25/44] add commented example --- config/config.example.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/config/config.example.yml b/config/config.example.yml index 69a9ffd320f..4b9c1a27ace 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -75,7 +75,7 @@ cache: anonymousCache: # Maximum number of pages to cache. Default is zero (0) which means anonymous user cache is disabled. # As all pages are cached in server memory, increasing this value will increase memory needs. - # Individual cached pages are usually small (<100KB), so a value of max=1000 would only require ~100MB of memory. + # Individual cached pages are usually small (<100KB), so a value of max=1000 would only require ~100MB of memory. max: 0 # Amount of time after which cached pages are considered stale (in ms). After becoming stale, the cached # copy is automatically refreshed on the next request. @@ -382,7 +382,13 @@ vocabularies: vocabulary: 'srsc' enabled: true -# Default collection/community sorting order at Advanced search, Create/update community and collection when there are not a query. +# Default collection/community sorting order at Advanced search, Create/update community and collection when there are not a query. comcolSelectionSort: sortField: 'dc.title' sortDirection: 'ASC' + +# Example of fallback collection for suggestions import +# suggestion: + # - collectionId: 8f7df5ca-f9c2-47a4-81ec-8a6393d6e5af + # source: "openaire" + From 2da613bff155035ae3c384924029820e7e1c88bc Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Thu, 1 Feb 2024 11:31:26 +0100 Subject: [PATCH 26/44] clean up --- ...rvice.spec.ts => update-data.service.spec.ts} | 2 +- ...te-data-service.ts => update-data.service.ts} | 0 .../suggestions-data.service.ts | 2 +- .../dso-edit-metadata.component.ts | 2 +- .../themed-dso-edit-metadata.component.ts | 2 +- .../suggestions-notification.component.html | 2 +- .../suggestions-notification.component.ts | 2 -- .../suggestions.service.ts | 4 +++- .../suggestions-page.component.html | 1 - .../suggestions-page.component.ts | 5 ++++- src/assets/i18n/en.json5 | 16 +++++++++------- 11 files changed, 21 insertions(+), 17 deletions(-) rename src/app/core/data/{update-data-service.spec.ts => update-data.service.spec.ts} (98%) rename src/app/core/data/{update-data-service.ts => update-data.service.ts} (100%) diff --git a/src/app/core/data/update-data-service.spec.ts b/src/app/core/data/update-data.service.spec.ts similarity index 98% rename from src/app/core/data/update-data-service.spec.ts rename to src/app/core/data/update-data.service.spec.ts index 6912527b918..426fa87eb6d 100644 --- a/src/app/core/data/update-data-service.spec.ts +++ b/src/app/core/data/update-data.service.spec.ts @@ -14,7 +14,7 @@ import { Version } from '../shared/version.model'; import { VersionHistory } from '../shared/version-history.model'; import { RequestEntry } from './request-entry.model'; import { testPatchDataImplementation } from './base/patch-data.spec'; -import { UpdateDataServiceImpl } from './update-data-service'; +import { UpdateDataServiceImpl } from './update-data.service'; import { testSearchDataImplementation } from './base/search-data.spec'; import { testDeleteDataImplementation } from './base/delete-data.spec'; import { testCreateDataImplementation } from './base/create-data.spec'; diff --git a/src/app/core/data/update-data-service.ts b/src/app/core/data/update-data.service.ts similarity index 100% rename from src/app/core/data/update-data-service.ts rename to src/app/core/data/update-data.service.ts diff --git a/src/app/core/suggestion-notifications/suggestions-data.service.ts b/src/app/core/suggestion-notifications/suggestions-data.service.ts index 2078fdb75e2..8956cbd208c 100644 --- a/src/app/core/suggestion-notifications/suggestions-data.service.ts +++ b/src/app/core/suggestion-notifications/suggestions-data.service.ts @@ -11,7 +11,7 @@ import { RemoteDataBuildService } from '../cache/builders/remote-data-build.serv import { ObjectCacheService } from '../cache/object-cache.service'; import { dataService } from '../cache/builders/build-decorators'; import { RequestService } from '../data/request.service'; -import { UpdateDataServiceImpl } from '../data/update-data-service'; +import { UpdateDataServiceImpl } from '../data/update-data.service'; import { ChangeAnalyzer } from '../data/change-analyzer'; import { DefaultChangeAnalyzer } from '../data/default-change-analyzer.service'; import { RemoteData } from '../data/remote-data'; diff --git a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts index 22d23e84020..60b1dffa450 100644 --- a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts +++ b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts @@ -21,7 +21,7 @@ import { ArrayMoveChangeAnalyzer } from '../../core/data/array-move-change-analy import { DATA_SERVICE_FACTORY } from '../../core/data/base/data-service.decorator'; import { GenericConstructor } from '../../core/shared/generic-constructor'; import { HALDataService } from '../../core/data/base/hal-data-service.interface'; -import { UpdateDataService } from '../../core/data/update-data-service'; +import { UpdateDataService } from '../../core/data/update-data.service'; @Component({ selector: 'ds-dso-edit-metadata', diff --git a/src/app/dso-shared/dso-edit-metadata/themed-dso-edit-metadata.component.ts b/src/app/dso-shared/dso-edit-metadata/themed-dso-edit-metadata.component.ts index 5d7ccdd87d2..ba21907c99e 100644 --- a/src/app/dso-shared/dso-edit-metadata/themed-dso-edit-metadata.component.ts +++ b/src/app/dso-shared/dso-edit-metadata/themed-dso-edit-metadata.component.ts @@ -2,7 +2,7 @@ import { ThemedComponent } from '../../shared/theme-support/themed.component'; import { DsoEditMetadataComponent } from './dso-edit-metadata.component'; import { Component, Input } from '@angular/core'; import { DSpaceObject } from '../../core/shared/dspace-object.model'; -import { UpdateDataService } from '../../core/data/update-data-service'; +import { UpdateDataService } from '../../core/data/update-data.service'; @Component({ selector: 'ds-themed-dso-edit-metadata', diff --git a/src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.html b/src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.html index 40156b368fd..3eac8d20992 100644 --- a/src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.html +++ b/src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.html @@ -1,7 +1,7 @@
    -
    +
    diff --git a/src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.ts b/src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.ts index dfa1e187e3b..e2afe8f07ce 100644 --- a/src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.ts +++ b/src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.ts @@ -16,8 +16,6 @@ import { Observable } from 'rxjs'; }) export class SuggestionsNotificationComponent implements OnInit { - labelPrefix = 'mydspace.'; - /** * The user suggestion targets. */ diff --git a/src/app/suggestion-notifications/suggestions.service.ts b/src/app/suggestion-notifications/suggestions.service.ts index bf21b5ae2f4..565f8f94dbd 100644 --- a/src/app/suggestion-notifications/suggestions.service.ts +++ b/src/app/suggestion-notifications/suggestions.service.ts @@ -30,6 +30,7 @@ import { import { SuggestionsDataService } from '../core/suggestion-notifications/suggestions-data.service'; +import { getSuggestionPageRoute } from '../suggestions-page/suggestions-page-routing-paths'; /** * useful for multiple approvals and ignores operation @@ -256,7 +257,8 @@ export class SuggestionsService { source: this.translateService.instant(this.translateSuggestionSource(suggestionTarget.source)), type: this.translateService.instant(this.translateSuggestionType(suggestionTarget.source)), suggestionId: suggestionTarget.id, - displayName: suggestionTarget.display + displayName: suggestionTarget.display, + url: getSuggestionPageRoute(suggestionTarget.id) }; } diff --git a/src/app/suggestions-page/suggestions-page.component.html b/src/app/suggestions-page/suggestions-page.component.html index 5865b613ac0..4e367b638e8 100644 --- a/src/app/suggestions-page/suggestions-page.component.html +++ b/src/app/suggestions-page/suggestions-page.component.html @@ -5,7 +5,6 @@

    - {{ translateSuggestionType() | translate }} {{'suggestion.suggestionFor' | translate}} {{researcherName}} {{'suggestion.from.source' | translate}} {{ translateSuggestionSource() | translate }} diff --git a/src/app/suggestions-page/suggestions-page.component.ts b/src/app/suggestions-page/suggestions-page.component.ts index d986366f1c3..ec560dc3eca 100644 --- a/src/app/suggestions-page/suggestions-page.component.ts +++ b/src/app/suggestions-page/suggestions-page.component.ts @@ -22,6 +22,9 @@ import { PaginationService } from '../core/pagination/pagination.service'; import { WorkspaceItem } from '../core/submission/models/workspaceitem.model'; import {FindListOptions} from '../core/data/find-list-options.model'; import {redirectOn4xx} from '../core/shared/authorized.operators'; +import { + getWorkflowItemEditRoute +} from '../workflowitems-edit-page/workflowitems-edit-page-routing-paths'; @Component({ selector: 'ds-suggestion-page', @@ -190,7 +193,7 @@ export class SuggestionsPageComponent implements OnInit { approveAndImport(event: SuggestionApproveAndImport) { this.suggestionService.approveAndImport(this.workspaceItemService, event.suggestion, event.collectionId) .subscribe((workspaceitem: WorkspaceItem) => { - const content = this.translateService.instant('suggestion.approveAndImport.success', { workspaceItemId: workspaceitem.id }); + const content = this.translateService.instant('suggestion.approveAndImport.success', { url: getWorkflowItemEditRoute(workspaceitem.id) }); this.notificationService.success('', content, {timeOut:0}, true); this.suggestionTargetsStateService.dispatchRefreshUserSuggestionsAction(); this.updatePage(); diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index fd4e50610c3..bb82085a4a4 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1772,6 +1772,10 @@ "form.create": "Create", + "form.number-picker.decrement": "Decrement {{field}}", + + "form.number-picker.increment": "Increment {{field}}", + "form.repeatable.sort.tip": "Drop the item in the new position", "grant-deny-request-copy.deny": "Don't send copy", @@ -3084,9 +3088,7 @@ "mydspace.import": "Import", - "notification.suggestion": "We found {{count}} publications
    in the {{source}} that seems to be related to your profile.
    Please review the suggestions", - - "notification.suggestion.page": "We found {{count}} {{type}} in the {{source}} that seems to be related to your profile. Please review the suggestions.", + "notification.suggestion": "We found {{count}} publications
    in the {{source}} that seems to be related to your profile.
    Please review the suggestions", "nav.browse.header": "All of DSpace", @@ -3564,9 +3566,9 @@ "suggestion.loading": "Loading ...", - "suggestion.title": "Publication Claims", + "suggestion.title": "Publication Claim", - "suggestion.title.breadcrumbs": "Publication Claims", + "suggestion.title.breadcrumbs": "Publication Claim", "suggestion.targets.description": "Below you can see all the suggestions ", @@ -3592,7 +3594,7 @@ "suggestion.approveAndImport": "Approve & import", - "suggestion.approveAndImport.success": "The suggestion has been imported successfully. View.", + "suggestion.approveAndImport.success": "The suggestion has been imported successfully. View.", "suggestion.approveAndImport.bulk": "Approve & import Selected", @@ -3614,7 +3616,7 @@ "suggestion.hideEvidence": "Hide evidence", - "suggestion.suggestionFor": "Suggestion for", + "suggestion.suggestionFor": "Suggestions for", "suggestion.source.openaire": "OpenAIRE Graph", From 22e87a5f5a875b41e38c1ef834b9c7a9b8cea458 Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Fri, 2 Feb 2024 17:40:32 +0100 Subject: [PATCH 27/44] 111639: Added scope @Input() and made the search facets & search results use that scope --- .../shared/search/search-filter.service.ts | 1 + .../search-facet-filter-wrapper.component.ts | 9 ++++- .../search-facet-filter.component.spec.ts | 2 ++ .../search-facet-filter.component.ts | 12 +++++-- .../search-filter.component.html | 1 + .../search-filter/search-filter.component.ts | 10 +++++- .../search-hierarchy-filter.component.spec.ts | 4 ++- .../search-hierarchy-filter.component.ts | 6 ++-- .../search-range-filter.component.spec.ts | 2 ++ .../search-range-filter.component.ts | 4 ++- .../search-filters.component.html | 2 +- .../shared/search/search.component.spec.ts | 26 ++------------ src/app/shared/search/search.component.ts | 31 +++++++++++------ .../shared/search/themed-search.component.ts | 34 +++++++++++++++++-- 14 files changed, 97 insertions(+), 47 deletions(-) diff --git a/src/app/core/shared/search/search-filter.service.ts b/src/app/core/shared/search/search-filter.service.ts index 80ba200d383..bf232cb141b 100644 --- a/src/app/core/shared/search/search-filter.service.ts +++ b/src/app/core/shared/search/search-filter.service.ts @@ -27,6 +27,7 @@ const filterStateSelector = (state: SearchFiltersState) => state.searchFilter; export const FILTER_CONFIG: InjectionToken = new InjectionToken('filterConfig'); export const IN_PLACE_SEARCH: InjectionToken = new InjectionToken('inPlaceSearch'); export const REFRESH_FILTER: InjectionToken> = new InjectionToken('refreshFilters'); +export const SCOPE: InjectionToken = new InjectionToken('scope'); /** * Service that performs all actions that have to do with search filters and facets diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter-wrapper/search-facet-filter-wrapper.component.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter-wrapper/search-facet-filter-wrapper.component.ts index 0aa131d4282..f635c027b5c 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter-wrapper/search-facet-filter-wrapper.component.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter-wrapper/search-facet-filter-wrapper.component.ts @@ -4,6 +4,7 @@ import { FilterType } from '../../../models/filter-type.model'; import { SearchFilterConfig } from '../../../models/search-filter-config.model'; import { FILTER_CONFIG, + SCOPE, IN_PLACE_SEARCH, REFRESH_FILTER } from '../../../../../core/shared/search/search-filter.service'; @@ -35,6 +36,11 @@ export class SearchFacetFilterWrapperComponent implements OnInit { */ @Input() refreshFilters: BehaviorSubject; + /** + * The current scope + */ + @Input() scope: string; + /** * The constructor of the search facet filter that should be rendered, based on the filter config's type */ @@ -56,7 +62,8 @@ export class SearchFacetFilterWrapperComponent implements OnInit { providers: [ { provide: FILTER_CONFIG, useFactory: () => (this.filterConfig), deps: [] }, { provide: IN_PLACE_SEARCH, useFactory: () => (this.inPlaceSearch), deps: [] }, - { provide: REFRESH_FILTER, useFactory: () => (this.refreshFilters), deps: [] } + { provide: REFRESH_FILTER, useFactory: () => (this.refreshFilters), deps: [] }, + { provide: SCOPE, useFactory: () => (this.scope), deps: [] }, ], parent: this.injector }); diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts index 92d2e5265ba..fc348722e55 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts @@ -4,6 +4,7 @@ import { TranslateModule } from '@ngx-translate/core'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { FILTER_CONFIG, + SCOPE, IN_PLACE_SEARCH, REFRESH_FILTER, SearchFilterService @@ -99,6 +100,7 @@ describe('SearchFacetFilterComponent', () => { { provide: SEARCH_CONFIG_SERVICE, useValue: new SearchConfigurationServiceStub() }, { provide: IN_PLACE_SEARCH, useValue: false }, { provide: REFRESH_FILTER, useValue: new BehaviorSubject(false) }, + { provide: SCOPE, useValue: undefined }, { provide: SearchFilterService, useValue: { getSelectedValuesForFilter: () => observableOf(selectedValues), diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts index 2b2eb9b11a7..994b488d9c7 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts @@ -22,6 +22,7 @@ import { SearchFilterConfig } from '../../../models/search-filter-config.model'; import { SearchService } from '../../../../../core/shared/search/search.service'; import { FILTER_CONFIG, + SCOPE, IN_PLACE_SEARCH, REFRESH_FILTER, SearchFilterService @@ -104,7 +105,9 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy { @Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: SearchConfigurationService, @Inject(IN_PLACE_SEARCH) public inPlaceSearch: boolean, @Inject(FILTER_CONFIG) public filterConfig: SearchFilterConfig, - @Inject(REFRESH_FILTER) public refreshFilters: BehaviorSubject) { + @Inject(REFRESH_FILTER) public refreshFilters: BehaviorSubject, + @Inject(SCOPE) public scope: string, + ) { } /** @@ -114,8 +117,11 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy { this.currentUrl = this.router.url; this.filterValues$ = new BehaviorSubject(createPendingRemoteDataObject()); this.currentPage = this.getCurrentPage().pipe(distinctUntilChanged()); - - this.searchOptions$ = this.searchConfigService.searchOptions; + this.searchOptions$ = this.searchConfigService.searchOptions.pipe( + map((options: SearchOptions) => hasNoValue(this.scope) ? options : Object.assign({}, options, { + scope: this.scope, + })), + ); this.subs.push( this.searchOptions$.subscribe(() => this.updateFilterValueList()), this.refreshFilters.asObservable().pipe( diff --git a/src/app/shared/search/search-filters/search-filter/search-filter.component.html b/src/app/shared/search/search-filters/search-filter/search-filter.component.html index a6fb0021b7f..0eb826130d4 100644 --- a/src/app/shared/search/search-filters/search-filter/search-filter.component.html +++ b/src/app/shared/search/search-filters/search-filter/search-filter.component.html @@ -18,6 +18,7 @@
    (@slide.start)="startSlide($event)" (@slide.done)="finishSlide($event)" class="search-filter-wrapper" [ngClass]="{ 'closed' : closed, 'notab': notab }"> diff --git a/src/app/shared/search/search-filters/search-filter/search-filter.component.ts b/src/app/shared/search/search-filters/search-filter/search-filter.component.ts index d1d3bd729d4..67e8906bb5d 100644 --- a/src/app/shared/search/search-filters/search-filter/search-filter.component.ts +++ b/src/app/shared/search/search-filters/search-filter/search-filter.component.ts @@ -6,7 +6,7 @@ import { filter, map, startWith, switchMap, take } from 'rxjs/operators'; import { SearchFilterConfig } from '../../models/search-filter-config.model'; import { SearchFilterService } from '../../../../core/shared/search/search-filter.service'; import { slide } from '../../../animations/slide'; -import { isNotEmpty } from '../../../empty.util'; +import { isNotEmpty, hasValue } from '../../../empty.util'; import { SearchService } from '../../../../core/shared/search/search.service'; import { SearchConfigurationService } from '../../../../core/shared/search/search-configuration.service'; import { SEARCH_CONFIG_SERVICE } from '../../../../my-dspace-page/my-dspace-page.component'; @@ -38,6 +38,11 @@ export class SearchFilterComponent implements OnInit { */ @Input() refreshFilters: BehaviorSubject; + /** + * The current scope + */ + @Input() scope: string; + /** * True when the filter is 100% collapsed in the UI */ @@ -171,6 +176,9 @@ export class SearchFilterComponent implements OnInit { } else { return this.searchConfigService.searchOptions.pipe( switchMap((options) => { + if (hasValue(this.scope)) { + options.scope = this.scope; + } return this.searchService.getFacetValuesFor(this.filter, 1, options).pipe( filter((RD) => !RD.isLoading), map((valuesRD) => { diff --git a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts index e6c74d80478..4469a124ce6 100644 --- a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts @@ -14,6 +14,7 @@ import { CommonModule } from '@angular/common'; import { SearchService } from '../../../../../core/shared/search/search.service'; import { FILTER_CONFIG, + SCOPE, IN_PLACE_SEARCH, SearchFilterService, REFRESH_FILTER @@ -75,7 +76,8 @@ describe('SearchHierarchyFilterComponent', () => { { provide: SEARCH_CONFIG_SERVICE, useValue: new SearchConfigurationServiceStub() }, { provide: IN_PLACE_SEARCH, useValue: false }, { provide: FILTER_CONFIG, useValue: Object.assign(new SearchFilterConfig(), { name: testSearchFilter }) }, - { provide: REFRESH_FILTER, useValue: new BehaviorSubject(false)} + { provide: REFRESH_FILTER, useValue: new BehaviorSubject(false)}, + { provide: SCOPE, useValue: undefined }, ], schemas: [NO_ERRORS_SCHEMA], }).compileComponents(); diff --git a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.ts b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.ts index f9b3f2bff94..d53fa37cf4b 100644 --- a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.ts +++ b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.ts @@ -9,6 +9,7 @@ import { import { SearchService } from '../../../../../core/shared/search/search.service'; import { FILTER_CONFIG, + SCOPE, IN_PLACE_SEARCH, SearchFilterService, REFRESH_FILTER } from '../../../../../core/shared/search/search-filter.service'; @@ -49,9 +50,10 @@ export class SearchHierarchyFilterComponent extends SearchFacetFilterComponent i @Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: SearchConfigurationService, @Inject(IN_PLACE_SEARCH) public inPlaceSearch: boolean, @Inject(FILTER_CONFIG) public filterConfig: SearchFilterConfig, - @Inject(REFRESH_FILTER) public refreshFilters: BehaviorSubject + @Inject(REFRESH_FILTER) public refreshFilters: BehaviorSubject, + @Inject(SCOPE) public scope: string, ) { - super(searchService, filterService, rdbs, router, searchConfigService, inPlaceSearch, filterConfig, refreshFilters); + super(searchService, filterService, rdbs, router, searchConfigService, inPlaceSearch, filterConfig, refreshFilters, scope); } vocabularyExists$: Observable; diff --git a/src/app/shared/search/search-filters/search-filter/search-range-filter/search-range-filter.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-range-filter/search-range-filter.component.spec.ts index 3a146f50590..03f47a75698 100644 --- a/src/app/shared/search/search-filters/search-filter/search-range-filter/search-range-filter.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-range-filter/search-range-filter.component.spec.ts @@ -4,6 +4,7 @@ import { TranslateModule } from '@ngx-translate/core'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { FILTER_CONFIG, + SCOPE, IN_PLACE_SEARCH, REFRESH_FILTER, SearchFilterService @@ -105,6 +106,7 @@ describe('SearchRangeFilterComponent', () => { { provide: SEARCH_CONFIG_SERVICE, useValue: new SearchConfigurationServiceStub() }, { provide: IN_PLACE_SEARCH, useValue: false }, { provide: REFRESH_FILTER, useValue: new BehaviorSubject(false) }, + { provide: SCOPE, useValue: undefined }, { provide: SearchFilterService, useValue: { getSelectedValuesForFilter: () => selectedValues, diff --git a/src/app/shared/search/search-filters/search-filter/search-range-filter/search-range-filter.component.ts b/src/app/shared/search/search-filters/search-filter/search-range-filter/search-range-filter.component.ts index 938f67412e4..cdbf384fe98 100644 --- a/src/app/shared/search/search-filters/search-filter/search-range-filter/search-range-filter.component.ts +++ b/src/app/shared/search/search-filters/search-filter/search-range-filter/search-range-filter.component.ts @@ -9,6 +9,7 @@ import { facetLoad, SearchFacetFilterComponent } from '../search-facet-filter/se import { SearchFilterConfig } from '../../../models/search-filter-config.model'; import { FILTER_CONFIG, + SCOPE, IN_PLACE_SEARCH, REFRESH_FILTER, SearchFilterService @@ -83,8 +84,9 @@ export class SearchRangeFilterComponent extends SearchFacetFilterComponent imple @Inject(FILTER_CONFIG) public filterConfig: SearchFilterConfig, @Inject(PLATFORM_ID) private platformId: any, @Inject(REFRESH_FILTER) public refreshFilters: BehaviorSubject, + @Inject(SCOPE) public scope: string, private route: RouteService) { - super(searchService, filterService, rdbs, router, searchConfigService, inPlaceSearch, filterConfig, refreshFilters); + super(searchService, filterService, rdbs, router, searchConfigService, inPlaceSearch, filterConfig, refreshFilters, scope); } diff --git a/src/app/shared/search/search-filters/search-filters.component.html b/src/app/shared/search/search-filters/search-filters.component.html index e392cd2663e..c006d80c44f 100644 --- a/src/app/shared/search/search-filters/search-filters.component.html +++ b/src/app/shared/search/search-filters/search-filters.component.html @@ -1,7 +1,7 @@

    {{"search.filters.head" | translate}}

    - +
    {{"search.filters.reset" | translate}} diff --git a/src/app/shared/search/search.component.spec.ts b/src/app/shared/search/search.component.spec.ts index d0d9bdda86a..9d069636a94 100644 --- a/src/app/shared/search/search.component.spec.ts +++ b/src/app/shared/search/search.component.spec.ts @@ -36,8 +36,6 @@ import { getCollectionPageRoute } from '../../collection-page/collection-page-ro let comp: SearchComponent; let fixture: ComponentFixture; -let searchServiceObject: SearchService; -let searchConfigurationServiceObject: SearchConfigurationService; const store: Store = jasmine.createSpyObj('store', { /* eslint-disable no-empty,@typescript-eslint/no-empty-function */ dispatch: {}, @@ -93,7 +91,6 @@ const mockDso2 = Object.assign(new Item(), { } } }); -const sort: SortOptions = new SortOptions('score', SortDirection.DESC); const mockSearchResults: SearchObjects = Object.assign(new SearchObjects(), { page: [mockDso, mockDso2] }); @@ -106,23 +103,13 @@ const searchServiceStub = jasmine.createSpyObj('SearchService', { getSearchConfigurationFor: createSuccessfulRemoteDataObject$(searchConfig), trackSearch: {}, }) as SearchService; -const configurationParam = 'default'; const queryParam = 'test query'; const scopeParam = '7669c72a-3f2a-451f-a3b9-9210e7a4c02f'; -const fixedFilter = 'fixed filter'; const defaultSearchOptions = new PaginatedSearchOptions({ pagination }); const paginatedSearchOptions$ = new BehaviorSubject(defaultSearchOptions); -const paginatedSearchOptions = new PaginatedSearchOptions({ - configuration: configurationParam, - query: queryParam, - scope: scopeParam, - fixedFilter: fixedFilter, - pagination, - sort -}); const activatedRouteStub = { snapshot: { queryParamMap: new Map([ @@ -155,14 +142,11 @@ const filtersConfigRD = createSuccessfulRemoteDataObject([mockFilterConfig, mock const filtersConfigRD$ = observableOf(filtersConfigRD); const routeServiceStub = { - getRouteParameterValue: () => { - return observableOf(''); - }, getQueryParameterValue: () => { - return observableOf(''); + return observableOf(null); }, getQueryParamsWithPrefix: () => { - return observableOf(''); + return observableOf(null); }, setParameter: () => { return; @@ -252,16 +236,10 @@ describe('SearchComponent', () => { comp.paginationId = paginationId; spyOn((comp as any), 'getSearchOptions').and.returnValue(paginatedSearchOptions$.asObservable()); - - searchServiceObject = TestBed.inject(SearchService); - searchConfigurationServiceObject = TestBed.inject(SEARCH_CONFIG_SERVICE); - }); afterEach(() => { comp = null; - searchServiceObject = null; - searchConfigurationServiceObject = null; }); it('should init search parameters properly and call retrieveSearchResults', fakeAsync(() => { diff --git a/src/app/shared/search/search.component.ts b/src/app/shared/search/search.component.ts index 61f3a119c87..8e120940ecc 100644 --- a/src/app/shared/search/search.component.ts +++ b/src/app/shared/search/search.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, EventEmitter, Inject, Input, OnInit, Output } from '@angular/core'; +import { ChangeDetectionStrategy, Component, EventEmitter, Inject, Input, OnInit, Output, OnDestroy } from '@angular/core'; import { NavigationStart, Router } from '@angular/router'; import { BehaviorSubject, combineLatest, Observable, Subscription } from 'rxjs'; @@ -11,7 +11,7 @@ import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { pushInOut } from '../animations/push'; import { HostWindowService } from '../host-window.service'; import { SidebarService } from '../sidebar/sidebar.service'; -import { hasValue, hasValueOperator, isNotEmpty } from '../empty.util'; +import { hasValue, hasValueOperator, isEmpty, isNotEmpty } from '../empty.util'; import { RouteService } from '../../core/services/route.service'; import { SEARCH_CONFIG_SERVICE } from '../../my-dspace-page/my-dspace-page.component'; import { PaginatedSearchOptions } from './models/paginated-search-options.model'; @@ -34,7 +34,7 @@ import { CollectionElementLinkType } from '../object-collection/collection-eleme import { environment } from 'src/environments/environment'; import { SubmissionObject } from '../../core/submission/models/submission-object.model'; import { SearchFilterConfig } from './models/search-filter-config.model'; -import { WorkspaceItem } from '../..//core/submission/models/workspaceitem.model'; +import { WorkspaceItem } from '../../core/submission/models/workspaceitem.model'; import { ITEM_MODULE_PATH } from '../../item-page/item-page-routing-paths'; import { COLLECTION_MODULE_PATH } from '../../collection-page/collection-page-routing-paths'; import { COMMUNITY_MODULE_PATH } from '../../community-page/community-page-routing-paths'; @@ -50,7 +50,7 @@ import { COMMUNITY_MODULE_PATH } from '../../community-page/community-page-routi /** * This component renders a sidebar, a search input bar and the search results. */ -export class SearchComponent implements OnInit { +export class SearchComponent implements OnDestroy, OnInit { /** * The list of available configuration options @@ -166,6 +166,11 @@ export class SearchComponent implements OnInit { */ @Input() query: string; + /** + * The fallback scope when no scope is defined in the url, if this is also undefined no scope will be set + */ + @Input() scope: string; + /** * The current configuration used during the search */ @@ -179,7 +184,7 @@ export class SearchComponent implements OnInit { /** * The current sort options used */ - currentScope$: BehaviorSubject = new BehaviorSubject(''); + currentScope$: Observable; /** * The current sort options used @@ -299,6 +304,10 @@ export class SearchComponent implements OnInit { this.routeService.setParameter('fixedFilterQuery', this.fixedFilterQuery); } + this.currentScope$ = this.routeService.getQueryParameterValue('scope').pipe( + map((routeValue: string) => hasValue(routeValue) ? routeValue : this.scope), + ); + this.isSidebarCollapsed$ = this.isSidebarCollapsed(); this.searchLink = this.getSearchLink(); this.currentContext$.next(this.context); @@ -321,13 +330,13 @@ export class SearchComponent implements OnInit { ); const searchOptions$: Observable = this.getSearchOptions().pipe(distinctUntilChanged()); - this.subs.push(combineLatest([configuration$, searchSortOptions$, searchOptions$, sortOption$]).pipe( - filter(([configuration, searchSortOptions, searchOptions, sortOption]: [string, SortOptions[], PaginatedSearchOptions, SortOptions]) => { + this.subs.push(combineLatest([configuration$, searchSortOptions$, searchOptions$, sortOption$, this.currentScope$]).pipe( + filter(([configuration, searchSortOptions, searchOptions, sortOption, scope]: [string, SortOptions[], PaginatedSearchOptions, SortOptions, string]) => { // filter for search options related to instanced paginated id return searchOptions.pagination.id === this.paginationId; }), debounceTime(100) - ).subscribe(([configuration, searchSortOptions, searchOptions, sortOption]: [string, SortOptions[], PaginatedSearchOptions, SortOptions]) => { + ).subscribe(([configuration, searchSortOptions, searchOptions, sortOption, scope]: [string, SortOptions[], PaginatedSearchOptions, SortOptions, string]) => { // Build the PaginatedSearchOptions object const combinedOptions = Object.assign({}, searchOptions, { @@ -337,6 +346,9 @@ export class SearchComponent implements OnInit { if (combinedOptions.query === '') { combinedOptions.query = this.query; } + if (isEmpty(combinedOptions.scope)) { + combinedOptions.scope = scope; + } const newSearchOptions = new PaginatedSearchOptions(combinedOptions); // check if search options are changed // if so retrieve new related results otherwise skip it @@ -344,13 +356,12 @@ export class SearchComponent implements OnInit { // Initialize variables this.currentConfiguration$.next(configuration); this.currentSortOptions$.next(newSearchOptions.sort); - this.currentScope$.next(newSearchOptions.scope); this.sortOptionsList$.next(searchSortOptions); this.searchOptions$.next(newSearchOptions); this.initialized$.next(true); // retrieve results this.retrieveSearchResults(newSearchOptions); - this.retrieveFilters(searchOptions); + this.retrieveFilters(newSearchOptions); } })); diff --git a/src/app/shared/search/themed-search.component.ts b/src/app/shared/search/themed-search.component.ts index fe531e4f0f5..38df90dd8a7 100644 --- a/src/app/shared/search/themed-search.component.ts +++ b/src/app/shared/search/themed-search.component.ts @@ -15,11 +15,37 @@ import { ListableObject } from '../object-collection/shared/listable-object.mode */ @Component({ selector: 'ds-themed-search', - styleUrls: [], templateUrl: '../theme-support/themed.component.html', }) export class ThemedSearchComponent extends ThemedComponent { - protected inAndOutputNames: (keyof SearchComponent & keyof this)[] = ['configurationList', 'context', 'configuration', 'fixedFilterQuery', 'useCachedVersionIfAvailable', 'inPlaceSearch', 'linkType', 'paginationId', 'searchEnabled', 'sideBarWidth', 'searchFormPlaceholder', 'selectable', 'selectionConfig', 'showCsvExport', 'showSidebar', 'showThumbnails', 'showViewModes', 'useUniquePageId', 'viewModeList', 'showScopeSelector', 'resultFound', 'deselectObject', 'selectObject', 'trackStatistics', 'query']; + protected inAndOutputNames: (keyof SearchComponent & keyof this)[] = [ + 'configurationList', + 'context', + 'configuration', + 'fixedFilterQuery', + 'useCachedVersionIfAvailable', + 'inPlaceSearch', + 'linkType', + 'paginationId', + 'searchEnabled', + 'sideBarWidth', + 'searchFormPlaceholder', + 'selectable', + 'selectionConfig', + 'showCsvExport', + 'showSidebar', + 'showThumbnails', + 'showViewModes', + 'useUniquePageId', + 'viewModeList', + 'showScopeSelector', + 'trackStatistics', + 'query', + 'scope', + 'resultFound', + 'deselectObject', + 'selectObject', + ]; @Input() configurationList: SearchConfigurationOption[]; @@ -51,7 +77,7 @@ export class ThemedSearchComponent extends ThemedComponent { @Input() showSidebar: boolean; - @Input() showThumbnails; + @Input() showThumbnails: boolean; @Input() showViewModes: boolean; @@ -65,6 +91,8 @@ export class ThemedSearchComponent extends ThemedComponent { @Input() query: string; + @Input() scope: string; + @Output() resultFound: EventEmitter> = new EventEmitter(); @Output() deselectObject: EventEmitter = new EventEmitter(); From 93b22cba1f1b541d86f12b3bce79c8db6fd83bb9 Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Sat, 3 Feb 2024 13:39:31 +0100 Subject: [PATCH 28/44] 111639: Fixed search settings not using the scope --- .../search-settings.component.spec.ts | 41 ++----------------- .../search-settings.component.ts | 11 ++--- src/app/shared/search/search.component.ts | 5 +-- src/assets/i18n/en.json5 | 12 ++++++ 4 files changed, 21 insertions(+), 48 deletions(-) diff --git a/src/app/shared/search/search-settings/search-settings.component.spec.ts b/src/app/shared/search/search-settings/search-settings.component.spec.ts index d0b51f04b1f..bdcdb6f171f 100644 --- a/src/app/shared/search/search-settings/search-settings.component.spec.ts +++ b/src/app/shared/search/search-settings/search-settings.component.spec.ts @@ -1,4 +1,3 @@ -import { SearchService } from '../../../core/shared/search/search.service'; import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { SearchSettingsComponent } from './search-settings.component'; import { of as observableOf } from 'rxjs'; @@ -6,15 +5,11 @@ import { PaginationComponentOptions } from '../../pagination/pagination-componen import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; import { TranslateModule } from '@ngx-translate/core'; import { RouterTestingModule } from '@angular/router/testing'; -import { ActivatedRoute } from '@angular/router'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { EnumKeysPipe } from '../../utils/enum-keys-pipe'; import { By } from '@angular/platform-browser'; -import { SearchFilterService } from '../../../core/shared/search/search-filter.service'; import { VarDirective } from '../../utils/var.directive'; import { SEARCH_CONFIG_SERVICE } from '../../../my-dspace-page/my-dspace-page.component'; -import { SidebarService } from '../../sidebar/sidebar.service'; -import { SidebarServiceStub } from '../../testing/sidebar-service.stub'; import { PaginationService } from '../../../core/pagination/pagination.service'; import { PaginationServiceStub } from '../../testing/pagination-service.stub'; @@ -22,32 +17,23 @@ describe('SearchSettingsComponent', () => { let comp: SearchSettingsComponent; let fixture: ComponentFixture; - let searchServiceObject: SearchService; let pagination: PaginationComponentOptions; let sort: SortOptions; - let mockResults; - let searchServiceStub; let queryParam; let scopeParam; let paginatedSearchOptions; - let paginationService; + let paginationService: PaginationServiceStub; - let activatedRouteStub; - beforeEach(waitForAsync(() => { + beforeEach(waitForAsync(async () => { pagination = new PaginationComponentOptions(); pagination.id = 'search-results-pagination'; pagination.currentPage = 1; pagination.pageSize = 10; sort = new SortOptions('score', SortDirection.DESC); - mockResults = ['test', 'data']; - searchServiceStub = { - searchOptions: { pagination: pagination, sort: sort }, - search: () => mockResults, - }; queryParam = 'test query'; scopeParam = '7669c72a-3f2a-451f-a3b9-9210e7a4c02f'; @@ -58,30 +44,12 @@ describe('SearchSettingsComponent', () => { sort, }; - activatedRouteStub = { - queryParams: observableOf({ - query: queryParam, - scope: scopeParam, - }), - }; - paginationService = new PaginationServiceStub(pagination, sort); - TestBed.configureTestingModule({ + await TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([])], declarations: [SearchSettingsComponent, EnumKeysPipe, VarDirective], providers: [ - { provide: SearchService, useValue: searchServiceStub }, - - { provide: ActivatedRoute, useValue: activatedRouteStub }, - { - provide: SidebarService, - useValue: SidebarServiceStub, - }, - { - provide: SearchFilterService, - useValue: {}, - }, { provide: PaginationService, useValue: paginationService, @@ -111,10 +79,7 @@ describe('SearchSettingsComponent', () => { // SearchPageComponent test instance fixture.detectChanges(); - searchServiceObject = (comp as any).service; spyOn(comp, 'reloadOrder'); - spyOn(searchServiceObject, 'search').and.callThrough(); - }); it('it should show the order settings with the respective selectable options', () => { diff --git a/src/app/shared/search/search-settings/search-settings.component.ts b/src/app/shared/search/search-settings/search-settings.component.ts index 0efd38b5b28..23c9e78c3a8 100644 --- a/src/app/shared/search/search-settings/search-settings.component.ts +++ b/src/app/shared/search/search-settings/search-settings.component.ts @@ -1,7 +1,5 @@ import { Component, Inject, Input } from '@angular/core'; -import { SearchService } from '../../../core/shared/search/search.service'; import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; -import { ActivatedRoute, Router } from '@angular/router'; import { SearchConfigurationService } from '../../../core/shared/search/search-configuration.service'; import { SEARCH_CONFIG_SERVICE } from '../../../my-dspace-page/my-dspace-page.component'; import { PaginationService } from '../../../core/pagination/pagination.service'; @@ -26,11 +24,10 @@ export class SearchSettingsComponent { */ @Input() sortOptionsList: SortOptions[]; - constructor(private service: SearchService, - private route: ActivatedRoute, - private router: Router, - private paginationService: PaginationService, - @Inject(SEARCH_CONFIG_SERVICE) public searchConfigurationService: SearchConfigurationService) { + constructor( + protected paginationService: PaginationService, + @Inject(SEARCH_CONFIG_SERVICE) public searchConfigurationService: SearchConfigurationService, + ) { } /** diff --git a/src/app/shared/search/search.component.ts b/src/app/shared/search/search.component.ts index 8e120940ecc..fc07893d721 100644 --- a/src/app/shared/search/search.component.ts +++ b/src/app/shared/search/search.component.ts @@ -315,9 +315,8 @@ export class SearchComponent implements OnDestroy, OnInit { // Determinate PaginatedSearchOptions and listen to any update on it const configuration$: Observable = this.searchConfigService .getCurrentConfiguration(this.configuration).pipe(distinctUntilChanged()); - const searchSortOptions$: Observable = configuration$.pipe( - switchMap((configuration: string) => this.searchConfigService - .getConfigurationSearchConfig(configuration)), + const searchSortOptions$: Observable = combineLatest([configuration$, this.currentScope$]).pipe( + switchMap(([configuration, scope]: [string, string]) => this.searchConfigService.getConfigurationSearchConfig(configuration, scope)), map((searchConfig: SearchConfig) => this.searchConfigService.getConfigurationSortOptions(searchConfig)), distinctUntilChanged() ); diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 6c91bae4c16..19c297acd36 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -3888,6 +3888,18 @@ "sorting.lastModified.DESC": "Last modified Descending", + "sorting.person.familyName.ASC": "Surname Ascending", + + "sorting.person.familyName.DESC": "Surname Descending", + + "sorting.person.givenName.ASC": "Name Ascending", + + "sorting.person.givenName.DESC": "Name Descending", + + "sorting.person.birthDate.ASC": "Birth Date Ascending", + + "sorting.person.birthDate.DESC": "Birth Date Descending", + "statistics.title": "Statistics", "statistics.header": "Statistics for {{ scope }}", From 937687c41433073bf51a9abdbfa2aeca69909fc8 Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Mon, 5 Feb 2024 12:48:23 +0100 Subject: [PATCH 29/44] fix routing, update issue, adapt labels --- .../suggestions-notification.component.ts | 1 + .../suggestions-popup/suggestions-popup.component.ts | 4 ++-- src/app/suggestion-notifications/suggestions.service.ts | 2 +- src/app/suggestions-page/suggestions-page.component.ts | 4 ++-- .../workflowitems-edit-page-routing-paths.ts | 5 +++++ src/assets/i18n/en.json5 | 4 ++-- 6 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.ts b/src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.ts index e2afe8f07ce..e123f8f87ff 100644 --- a/src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.ts +++ b/src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.ts @@ -29,6 +29,7 @@ export class SuggestionsNotificationComponent implements OnInit { ) { } ngOnInit() { + this.suggestionTargetsStateService.dispatchRefreshUserSuggestionsAction(); this.suggestionsRD$ = this.suggestionTargetsStateService.getCurrentUserSuggestionTargets(); } diff --git a/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.ts b/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.ts index 762f80085a8..0b2176ea892 100644 --- a/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.ts +++ b/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.ts @@ -3,7 +3,7 @@ import { TranslateService } from '@ngx-translate/core'; import { SuggestionTargetsStateService } from '../suggestion-targets/suggestion-targets.state.service'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { SuggestionsService } from '../suggestions.service'; -import { takeUntil } from 'rxjs/operators'; +import { take, takeUntil } from 'rxjs/operators'; import { SuggestionTarget } from '../../core/suggestion-notifications/models/suggestion-target.model'; import { isNotEmpty } from '../../shared/empty.util'; import { combineLatest, Subject } from 'rxjs'; @@ -36,7 +36,7 @@ export class SuggestionsPopupComponent implements OnInit, OnDestroy { public initializePopup() { const notifier = new Subject(); this.subscription = combineLatest([ - this.suggestionTargetsStateService.getCurrentUserSuggestionTargets(), + this.suggestionTargetsStateService.getCurrentUserSuggestionTargets().pipe(take(2)), this.suggestionTargetsStateService.hasUserVisitedSuggestions() ]).pipe(takeUntil(notifier)).subscribe(([suggestions, visited]) => { this.suggestionTargetsStateService.dispatchRefreshUserSuggestionsAction(); diff --git a/src/app/suggestion-notifications/suggestions.service.ts b/src/app/suggestion-notifications/suggestions.service.ts index 565f8f94dbd..874659eab5f 100644 --- a/src/app/suggestion-notifications/suggestions.service.ts +++ b/src/app/suggestion-notifications/suggestions.service.ts @@ -154,7 +154,7 @@ export class SuggestionsService { * The EPerson id for which to retrieve suggestion targets */ public retrieveCurrentUserSuggestions(userUuid: string): Observable { - return this.researcherProfileService.findById(userUuid).pipe( + return this.researcherProfileService.findById(userUuid, true).pipe( getFirstSucceededRemoteDataPayload(), mergeMap((profile: ResearcherProfile) => { if (isNotEmpty(profile)) { diff --git a/src/app/suggestions-page/suggestions-page.component.ts b/src/app/suggestions-page/suggestions-page.component.ts index ec560dc3eca..20056460100 100644 --- a/src/app/suggestions-page/suggestions-page.component.ts +++ b/src/app/suggestions-page/suggestions-page.component.ts @@ -23,7 +23,7 @@ import { WorkspaceItem } from '../core/submission/models/workspaceitem.model'; import {FindListOptions} from '../core/data/find-list-options.model'; import {redirectOn4xx} from '../core/shared/authorized.operators'; import { - getWorkflowItemEditRoute + getWorkspaceItemEditRoute } from '../workflowitems-edit-page/workflowitems-edit-page-routing-paths'; @Component({ @@ -193,7 +193,7 @@ export class SuggestionsPageComponent implements OnInit { approveAndImport(event: SuggestionApproveAndImport) { this.suggestionService.approveAndImport(this.workspaceItemService, event.suggestion, event.collectionId) .subscribe((workspaceitem: WorkspaceItem) => { - const content = this.translateService.instant('suggestion.approveAndImport.success', { url: getWorkflowItemEditRoute(workspaceitem.id) }); + const content = this.translateService.instant('suggestion.approveAndImport.success', { url: getWorkspaceItemEditRoute(workspaceitem.id) }); this.notificationService.success('', content, {timeOut:0}, true); this.suggestionTargetsStateService.dispatchRefreshUserSuggestionsAction(); this.updatePage(); diff --git a/src/app/workflowitems-edit-page/workflowitems-edit-page-routing-paths.ts b/src/app/workflowitems-edit-page/workflowitems-edit-page-routing-paths.ts index 326eebe4a79..a4d4a0f2c93 100644 --- a/src/app/workflowitems-edit-page/workflowitems-edit-page-routing-paths.ts +++ b/src/app/workflowitems-edit-page/workflowitems-edit-page-routing-paths.ts @@ -28,9 +28,14 @@ export function getWorkspaceItemDeleteRoute(wsiId: string) { return new URLCombiner(getWorkspaceItemModuleRoute(), wsiId, WORKSPACE_ITEM_DELETE_PATH).toString(); } +export function getWorkspaceItemEditRoute(wsiId: string) { + return new URLCombiner(getWorkspaceItemModuleRoute(), wsiId, WORKSPACE_ITEM_EDIT_PATH).toString(); +} + export const WORKFLOW_ITEM_EDIT_PATH = 'edit'; export const WORKFLOW_ITEM_DELETE_PATH = 'delete'; export const WORKFLOW_ITEM_VIEW_PATH = 'view'; export const WORKFLOW_ITEM_SEND_BACK_PATH = 'sendback'; export const ADVANCED_WORKFLOW_PATH = 'advanced'; export const WORKSPACE_ITEM_DELETE_PATH = 'delete'; +export const WORKSPACE_ITEM_EDIT_PATH = 'edit'; diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index bb82085a4a4..1aebe0430eb 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -24,9 +24,9 @@ "404.page-not-found": "page not found", - "admin.notifications.publicationclaim.breadcrumbs": "Suggestions", + "admin.notifications.publicationclaim.breadcrumbs": "Publication Claim", - "admin.notifications.publicationclaim.page.title": "Suggestions", + "admin.notifications.publicationclaim.page.title": "Publication Claim", "error-page.description.401": "unauthorized", From 06cc944f2b64b94032e383965be1507ecd040b34 Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Mon, 5 Feb 2024 13:00:08 +0100 Subject: [PATCH 30/44] fix test --- src/app/suggestion-notifications/suggestion.service.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/suggestion-notifications/suggestion.service.spec.ts b/src/app/suggestion-notifications/suggestion.service.spec.ts index acb0bb3be2e..268eb59ddd1 100644 --- a/src/app/suggestion-notifications/suggestion.service.spec.ts +++ b/src/app/suggestion-notifications/suggestion.service.spec.ts @@ -121,7 +121,7 @@ describe('SuggestionsService test', () => { it('should retrieve current user suggestions', () => { service.retrieveCurrentUserSuggestions('1234'); - expect(researcherProfileService.findById).toHaveBeenCalledWith('1234'); + expect(researcherProfileService.findById).toHaveBeenCalledWith('1234', true); }); it('should approve and import suggestion', () => { From 044ec06cb1d47b076e75e1b0bfd51f74bf33b9cf Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Mon, 5 Feb 2024 16:53:21 +0100 Subject: [PATCH 31/44] update breadcrumb label --- .../core/breadcrumbs/publication-claim-breadcrumb.service.ts | 3 ++- src/assets/i18n/en.json5 | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/app/core/breadcrumbs/publication-claim-breadcrumb.service.ts b/src/app/core/breadcrumbs/publication-claim-breadcrumb.service.ts index 14ef7917c38..1a87fd7de60 100644 --- a/src/app/core/breadcrumbs/publication-claim-breadcrumb.service.ts +++ b/src/app/core/breadcrumbs/publication-claim-breadcrumb.service.ts @@ -38,7 +38,8 @@ export class PublicationClaimBreadcrumbService implements BreadcrumbsProviderSer map(([item, isAdmin]) => { const itemName = this.dsoNameService.getName(item.payload); return isAdmin ? [new Breadcrumb(this.tranlsateService.instant(this.ADMIN_PUBLICATION_CLAIMS_BREADCRUMB_KEY), this.ADMIN_PUBLICATION_CLAIMS_PATH), - new Breadcrumb(itemName, undefined)] : [new Breadcrumb(itemName, undefined)]; + new Breadcrumb(this.tranlsateService.instant('suggestion.suggestionFor.breadcrumb', {name: itemName}), undefined)] : + [new Breadcrumb(this.tranlsateService.instant('suggestion.suggestionFor.breadcrumb', {name: itemName}), undefined)]; }) ); } diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 1aebe0430eb..39785eed701 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -3618,6 +3618,8 @@ "suggestion.suggestionFor": "Suggestions for", + "suggestion.suggestionFor.breadcrumb": "Suggestions for {{ name }}", + "suggestion.source.openaire": "OpenAIRE Graph", "suggestion.from.source": "from the ", From 71e3d40c794a82058dc109e3f7793fa6d60fc135 Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Mon, 5 Feb 2024 17:49:49 +0100 Subject: [PATCH 32/44] fix breadcrumb test --- .../breadcrumbs/publication-claim-breadcrumb.service.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/core/breadcrumbs/publication-claim-breadcrumb.service.spec.ts b/src/app/core/breadcrumbs/publication-claim-breadcrumb.service.spec.ts index 6a2e6e54a63..11062210bb3 100644 --- a/src/app/core/breadcrumbs/publication-claim-breadcrumb.service.spec.ts +++ b/src/app/core/breadcrumbs/publication-claim-breadcrumb.service.spec.ts @@ -28,7 +28,7 @@ describe('PublicationClaimBreadcrumbService', () => { const ADMIN_PUBLICATION_CLAIMS_BREADCRUMB_KEY = 'admin.notifications.publicationclaim.page.title'; function init() { - exampleKey = '6bee076d-4f2a-4555-a475-04a267769b2a'; + exampleKey = 'suggestion.suggestionFor.breadcrumb'; } beforeEach(waitForAsync(() => { From 0ee6ee8ea1244947ed0e76b1363f4481a969a4b1 Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Fri, 9 Feb 2024 09:24:58 +0100 Subject: [PATCH 33/44] CST-5249 resolve conflicts --- src/assets/i18n/en.json5 | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index eea9c0befbc..90714201da6 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -24,10 +24,6 @@ "404.page-not-found": "page not found", - "admin.notifications.publicationclaim.breadcrumbs": "Publication Claim", - - "admin.notifications.publicationclaim.page.title": "Publication Claim", - "error-page.description.401": "unauthorized", "error-page.description.403": "forbidden", @@ -5564,4 +5560,7 @@ "vocabulary-treeview.search.form.add": "Add", + "admin.notifications.publicationclaim.breadcrumbs": "Publication Claim", + + "admin.notifications.publicationclaim.page.title": "Publication Claim" } From 5b7ca7cfa5ca44eafd6ca53cde8d33f927201abb Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Fri, 9 Feb 2024 09:32:03 +0100 Subject: [PATCH 34/44] CST-5249 fix lint --- src/assets/i18n/en.json5 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 90714201da6..97884bfb511 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -5562,5 +5562,5 @@ "admin.notifications.publicationclaim.breadcrumbs": "Publication Claim", - "admin.notifications.publicationclaim.page.title": "Publication Claim" + "admin.notifications.publicationclaim.page.title": "Publication Claim", } From 8f488220fb9734db754442d270813b09cf01fd7e Mon Sep 17 00:00:00 2001 From: Vincenzo Mecca Date: Mon, 12 Feb 2024 16:56:06 +0100 Subject: [PATCH 35/44] [#2719][CST-12825] Adds i18n missing keys --- src/assets/i18n/en.json5 | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index a3a6942909f..705e791bc69 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -2516,6 +2516,20 @@ "item.preview.oaire.fundingStream": "Funding Stream:", + "item.preview.oairecerif.identifier.url" : "URL", + + "item.preview.organization.address.addressCountry" : "Country", + + "item.preview.organization.foundingDate" : "Founding Date", + + "item.preview.organization.identifier.crossrefid" : "CrossRef ID", + + "item.preview.organization.identifier.isni" : "ISNI", + + "item.preview.organization.identifier.ror" : "ROR ID", + + "item.preview.organization.legalName" : "Legal Name", + "item.select.confirm": "Confirm selected", "item.select.empty": "No items to show", From 5a970775ae6b43142ee65c53a545824e0596a986 Mon Sep 17 00:00:00 2001 From: Vincenzo Mecca Date: Tue, 13 Feb 2024 11:16:54 +0100 Subject: [PATCH 36/44] [#2719][CST-12825] Extracts new image-page-field component with css variable --- .../item-pages/org-unit/org-unit.component.html | 10 +++++++--- .../metadata-values/metadata-values.component.html | 7 +++++-- .../metadata-values/metadata-values.component.ts | 6 +++++- src/app/item-page/item-shared.module.ts | 2 ++ .../generic/generic-item-page-field.component.ts | 2 -- .../specific-field/item-page-field.component.html | 1 - .../specific-field/item-page-field.component.ts | 2 -- src/assets/i18n/en.json5 | 2 ++ src/styles/_custom_variables.scss | 3 +++ .../dspace/styles/_theme_css_variable_overrides.scss | 2 ++ 10 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html b/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html index 92a13e96726..52df841d3b6 100644 --- a/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html +++ b/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html @@ -32,14 +32,18 @@

    - - + - + {{value}} diff --git a/src/app/item-page/field-components/metadata-values/metadata-values.component.ts b/src/app/item-page/field-components/metadata-values/metadata-values.component.ts index 2ec31159bca..0d3cafacce1 100644 --- a/src/app/item-page/field-components/metadata-values/metadata-values.component.ts +++ b/src/app/item-page/field-components/metadata-values/metadata-values.component.ts @@ -4,6 +4,7 @@ import { APP_CONFIG, AppConfig } from '../../../../config/app-config.interface'; import { BrowseDefinition } from '../../../core/shared/browse-definition.model'; import { hasValue } from '../../../shared/empty.util'; import { VALUE_LIST_BROWSE_DEFINITION } from '../../../core/shared/value-list-browse-definition.resource-type'; +import { ImageField } from '../../simple/field-components/specific-field/img/item-page-img-field.component'; /** * This component renders the configured 'values' into the ds-metadata-field-wrapper component. @@ -55,7 +56,10 @@ export class MetadataValuesComponent implements OnChanges { @Input() browseDefinition?: BrowseDefinition; - @Input() img?: string; + /** + * Optional {@code ImageField} reference that represents an image to be displayed inline. + */ + @Input() img?: ImageField; ngOnChanges(changes: SimpleChanges): void { this.renderMarkdown = !!this.appConfig.markdown.enabled && this.enableMarkdown; diff --git a/src/app/item-page/item-shared.module.ts b/src/app/item-page/item-shared.module.ts index 7a0ac436299..8b7243acde0 100644 --- a/src/app/item-page/item-shared.module.ts +++ b/src/app/item-page/item-shared.module.ts @@ -30,6 +30,7 @@ import { RelatedItemsComponent } from './simple/related-items/related-items-comp import { ThemedMetadataRepresentationListComponent } from './simple/metadata-representation-list/themed-metadata-representation-list.component'; +import { ItemPageImgFieldComponent } from './simple/field-components/specific-field/img/item-page-img-field.component'; const ENTRY_COMPONENTS = [ ItemVersionsDeleteModalComponent, @@ -46,6 +47,7 @@ const COMPONENTS = [ MetadataRepresentationListComponent, ThemedMetadataRepresentationListComponent, RelatedItemsComponent, + ItemPageImgFieldComponent, ]; @NgModule({ diff --git a/src/app/item-page/simple/field-components/specific-field/generic/generic-item-page-field.component.ts b/src/app/item-page/simple/field-components/specific-field/generic/generic-item-page-field.component.ts index 99a68745c1c..53d2f6aa20d 100644 --- a/src/app/item-page/simple/field-components/specific-field/generic/generic-item-page-field.component.ts +++ b/src/app/item-page/simple/field-components/specific-field/generic/generic-item-page-field.component.ts @@ -45,7 +45,5 @@ export class GenericItemPageFieldComponent extends ItemPageFieldComponent { */ @Input() urlRegex?: string; - @Input() img?: string; - } diff --git a/src/app/item-page/simple/field-components/specific-field/item-page-field.component.html b/src/app/item-page/simple/field-components/specific-field/item-page-field.component.html index f45d4657a46..91d40b0ad70 100644 --- a/src/app/item-page/simple/field-components/specific-field/item-page-field.component.html +++ b/src/app/item-page/simple/field-components/specific-field/item-page-field.component.html @@ -6,6 +6,5 @@ [enableMarkdown]="enableMarkdown" [urlRegex]="urlRegex" [browseDefinition]="browseDefinition|async" - [img]="img" >
    diff --git a/src/app/item-page/simple/field-components/specific-field/item-page-field.component.ts b/src/app/item-page/simple/field-components/specific-field/item-page-field.component.ts index 99e5ae7d36f..fc526dabcc5 100644 --- a/src/app/item-page/simple/field-components/specific-field/item-page-field.component.ts +++ b/src/app/item-page/simple/field-components/specific-field/item-page-field.component.ts @@ -51,8 +51,6 @@ export class ItemPageFieldComponent { */ urlRegex?: string; - img?: string; - /** * Return browse definition that matches any field used in this component if it is configured as a browse * link in dspace.cfg (webui.browse.link.) diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 705e791bc69..c9a74982554 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -2464,6 +2464,8 @@ "item.page.claim.tooltip": "Claim this item as profile", + "item.page.image.alt.ROR": "ROR logo", + "item.preview.dc.identifier.uri": "Identifier:", "item.preview.dc.contributor.author": "Authors:", diff --git a/src/styles/_custom_variables.scss b/src/styles/_custom_variables.scss index ad9a074e1b4..053c84362e8 100644 --- a/src/styles/_custom_variables.scss +++ b/src/styles/_custom_variables.scss @@ -101,4 +101,7 @@ --ds-dso-edit-lang-width: 90px; --ds-dso-edit-actions-width: 173px; --ds-dso-edit-virtual-tooltip-min-width: 300px; + + --ds-item-page-img-field-default-inline-height: 24px; + } diff --git a/src/themes/dspace/styles/_theme_css_variable_overrides.scss b/src/themes/dspace/styles/_theme_css_variable_overrides.scss index 516eff9f7e9..8512514a405 100644 --- a/src/themes/dspace/styles/_theme_css_variable_overrides.scss +++ b/src/themes/dspace/styles/_theme_css_variable_overrides.scss @@ -7,5 +7,7 @@ --ds-home-news-link-color: #{$green}; --ds-home-news-link-hover-color: #{darken($green, 15%)}; --ds-header-navbar-border-bottom-color: #{$green}; + --ds-item-page-img-field-default-inline-height: 24px; + --ds-item-page-img-field-ror-inline-height: var(--ds-item-page-img-field-default-inline-height); } From 8dc7eeb2425152c5405ff875c81a90db346f056f Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Tue, 13 Feb 2024 12:37:29 +0100 Subject: [PATCH 37/44] [CST-5249] fix suggestion refresh after ignore --- .../suggestion-data.service.spec.ts | 2 +- .../suggestion-notifications/suggestions-data.service.ts | 2 +- src/app/suggestions-page/suggestions-page.component.ts | 6 ++++-- src/assets/i18n/en.json5 | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/app/core/suggestion-notifications/suggestion-data.service.spec.ts b/src/app/core/suggestion-notifications/suggestion-data.service.spec.ts index a854514c896..c0bc97ea129 100644 --- a/src/app/core/suggestion-notifications/suggestion-data.service.spec.ts +++ b/src/app/core/suggestion-notifications/suggestion-data.service.spec.ts @@ -155,7 +155,7 @@ describe('SuggestionDataService test', () => { searchParams: [new RequestParam('target', testUserId), new RequestParam('source', testSource)] }; service.getSuggestionsByTargetAndSource(testUserId, testSource); - expect(suggestionsDataService.searchBy).toHaveBeenCalledWith('findByTargetAndSource', options, true, true); + expect(suggestionsDataService.searchBy).toHaveBeenCalledWith('findByTargetAndSource', options, false, true); }); it('should call suggestionsDataService.delete', () => { diff --git a/src/app/core/suggestion-notifications/suggestions-data.service.ts b/src/app/core/suggestion-notifications/suggestions-data.service.ts index 8956cbd208c..17b14825782 100644 --- a/src/app/core/suggestion-notifications/suggestions-data.service.ts +++ b/src/app/core/suggestion-notifications/suggestions-data.service.ts @@ -217,7 +217,7 @@ export class SuggestionsDataService { new RequestParam('source', source) ]; - return this.suggestionsDataService.searchBy(this.searchFindByTargetAndSourceMethod, options, true, true, ...linksToFollow); + return this.suggestionsDataService.searchBy(this.searchFindByTargetAndSourceMethod, options, false, true, ...linksToFollow); } /** diff --git a/src/app/suggestions-page/suggestions-page.component.ts b/src/app/suggestions-page/suggestions-page.component.ts index 20056460100..d775a1e2206 100644 --- a/src/app/suggestions-page/suggestions-page.component.ts +++ b/src/app/suggestions-page/suggestions-page.component.ts @@ -2,7 +2,7 @@ import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, Data, Router } from '@angular/router'; import { BehaviorSubject, combineLatest, Observable } from 'rxjs'; -import { distinctUntilChanged, map, switchMap, take } from 'rxjs/operators'; +import { delay, distinctUntilChanged, map, switchMap, take } from 'rxjs/operators'; import { TranslateService } from '@ngx-translate/core'; import { SortDirection, SortOptions, } from '../core/cache/models/sort-options.model'; @@ -155,7 +155,9 @@ export class SuggestionsPageComponent implements OnInit { * @suggestionId */ ignoreSuggestion(suggestionId) { - this.suggestionService.ignoreSuggestion(suggestionId).subscribe(() => { + this.suggestionService.ignoreSuggestion(suggestionId).pipe( + delay(100) + ).subscribe(() => { this.suggestionTargetsStateService.dispatchRefreshUserSuggestionsAction(); this.updatePage(); }); diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 97884bfb511..15134a01fd8 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -3120,7 +3120,7 @@ "mydspace.import": "Import", - "notification.suggestion": "We found {{count}} publications
    in the {{source}} that seems to be related to your profile.
    Please review the suggestions", + "notification.suggestion": "We found {{count}} publications in the {{source}} that seems to be related to your profile.
    Please review the suggestions", "nav.browse.header": "All of DSpace", From 5d85e511a1007a3575c03a3309811414d429a081 Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Tue, 13 Feb 2024 16:13:47 +0100 Subject: [PATCH 38/44] [CST-5249] fix tests --- .../suggestions-page/suggestions-page.component.spec.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/app/suggestions-page/suggestions-page.component.spec.ts b/src/app/suggestions-page/suggestions-page.component.spec.ts index 6abd28386f1..3e8ccfbc385 100644 --- a/src/app/suggestions-page/suggestions-page.component.spec.ts +++ b/src/app/suggestions-page/suggestions-page.component.spec.ts @@ -1,7 +1,7 @@ import { CommonModule } from '@angular/common'; import { BrowserModule } from '@angular/platform-browser'; import { NO_ERRORS_SCHEMA } from '@angular/core'; -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { of as observableOf } from 'rxjs'; @@ -129,16 +129,17 @@ describe('SuggestionPageComponent', () => { component.updatePage(); }); - it('should flag suggestion for deletion', () => { + it('should flag suggestion for deletion', fakeAsync(() => { spyOn(component, 'updatePage').and.stub(); scheduler.schedule(() => fixture.detectChanges()); scheduler.flush(); component.ignoreSuggestion('1'); + tick(101); expect(mockSuggestionsService.ignoreSuggestion).toHaveBeenCalledWith('1'); expect(mockSuggestionsTargetStateService.dispatchRefreshUserSuggestionsAction).toHaveBeenCalled(); expect(component.updatePage).toHaveBeenCalled(); - }); + })); it('should flag all suggestion for deletion', () => { spyOn(component, 'updatePage').and.stub(); From 26bfc5827891fea00d010afed26326cefc21474a Mon Sep 17 00:00:00 2001 From: Vincenzo Mecca Date: Tue, 13 Feb 2024 13:49:41 +0100 Subject: [PATCH 39/44] [#2719][CST-12825] Refactors item-page-img-field component --- .../metadata-values.component.html | 2 +- .../metadata-values.component.ts | 2 +- .../img/item-page-img-field.component.spec.ts | 84 +++++++++++++++++++ .../img/item-page-img-field.component.ts | 46 ++++++++++ .../item-page-field.component.html | 1 + .../item-page-field.component.ts | 24 ++++++ src/assets/i18n/en.json5 | 14 ++-- 7 files changed, 164 insertions(+), 9 deletions(-) create mode 100644 src/app/item-page/simple/field-components/specific-field/img/item-page-img-field.component.spec.ts create mode 100644 src/app/item-page/simple/field-components/specific-field/img/item-page-img-field.component.ts diff --git a/src/app/item-page/field-components/metadata-values/metadata-values.component.html b/src/app/item-page/field-components/metadata-values/metadata-values.component.html index 44a3db43cd8..857e82e3fc5 100644 --- a/src/app/item-page/field-components/metadata-values/metadata-values.component.html +++ b/src/app/item-page/field-components/metadata-values/metadata-values.component.html @@ -25,7 +25,7 @@ - +
    diff --git a/src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.ts b/src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.ts index e123f8f87ff..357a6ca34ef 100644 --- a/src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.ts +++ b/src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.ts @@ -1,8 +1,6 @@ import { Component, OnInit } from '@angular/core'; import { SuggestionTarget } from '../../core/suggestion-notifications/models/suggestion-target.model'; -import { TranslateService } from '@ngx-translate/core'; import { SuggestionTargetsStateService } from '../suggestion-targets/suggestion-targets.state.service'; -import { NotificationsService } from '../../shared/notifications/notifications.service'; import { SuggestionsService } from '../suggestions.service'; import { Observable } from 'rxjs'; @@ -22,9 +20,7 @@ export class SuggestionsNotificationComponent implements OnInit { suggestionsRD$: Observable; constructor( - private translateService: TranslateService, private suggestionTargetsStateService: SuggestionTargetsStateService, - private notificationsService: NotificationsService, private suggestionsService: SuggestionsService ) { } diff --git a/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.html b/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.html index 8b137891791..474dfa329e7 100644 --- a/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.html +++ b/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.html @@ -1 +1,27 @@ +
    + +
    + diff --git a/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.spec.ts b/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.spec.ts index 8a5721968bc..c8d59115d81 100644 --- a/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.spec.ts +++ b/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.spec.ts @@ -3,8 +3,6 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { SuggestionsPopupComponent } from './suggestions-popup.component'; import { TranslateModule } from '@ngx-translate/core'; import { SuggestionTargetsStateService } from '../suggestion-targets/suggestion-targets.state.service'; -import { NotificationsService } from '../../shared/notifications/notifications.service'; -import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { of as observableOf } from 'rxjs'; import { mockSuggestionTargetsObjectOne } from '../../shared/mocks/publication-claim-targets.mock'; @@ -13,7 +11,6 @@ import { SuggestionsService } from '../suggestions.service'; describe('SuggestionsPopupComponent', () => { let component: SuggestionsPopupComponent; let fixture: ComponentFixture; - let notificationsService: NotificationsService; const suggestionStateService = jasmine.createSpyObj('SuggestionTargetsStateService', { hasUserVisitedSuggestions: jasmine.createSpy('hasUserVisitedSuggestions'), @@ -35,7 +32,6 @@ describe('SuggestionsPopupComponent', () => { providers: [ { provide: SuggestionTargetsStateService, useValue: suggestionStateService }, { provide: SuggestionsService, useValue: suggestionService }, - { provide: NotificationsService, useValue: new NotificationsServiceStub() }, ], schemas: [NO_ERRORS_SCHEMA] @@ -69,12 +65,10 @@ describe('SuggestionsPopupComponent', () => { fixture = TestBed.createComponent(SuggestionsPopupComponent); component = fixture.componentInstance; - notificationsService = (component as any).notificationsService; fixture.detectChanges(); }); it('should show a notification when new publication suggestions are available', () => { - expect(notificationsService.success).toHaveBeenCalled(); expect(suggestionStateService.dispatchRefreshUserSuggestionsAction).toHaveBeenCalled(); expect(suggestionStateService.dispatchMarkUserSuggestionsAsVisitedAction).toHaveBeenCalled(); }); diff --git a/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.ts b/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.ts index 0b2176ea892..2cf3db128e6 100644 --- a/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.ts +++ b/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.ts @@ -1,12 +1,14 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; -import { TranslateService } from '@ngx-translate/core'; import { SuggestionTargetsStateService } from '../suggestion-targets/suggestion-targets.state.service'; -import { NotificationsService } from '../../shared/notifications/notifications.service'; import { SuggestionsService } from '../suggestions.service'; import { take, takeUntil } from 'rxjs/operators'; import { SuggestionTarget } from '../../core/suggestion-notifications/models/suggestion-target.model'; import { isNotEmpty } from '../../shared/empty.util'; -import { combineLatest, Subject } from 'rxjs'; +import { combineLatest, Observable, of, Subject } from 'rxjs'; +import { trigger } from '@angular/animations'; + + +import { fromTopEnter } from '../../shared/animations/fromTop'; /** * Show suggestions on a popover window, used on the homepage @@ -14,7 +16,12 @@ import { combineLatest, Subject } from 'rxjs'; @Component({ selector: 'ds-suggestions-popup', templateUrl: './suggestions-popup.component.html', - styleUrls: ['./suggestions-popup.component.scss'] + styleUrls: ['./suggestions-popup.component.scss'], + animations: [ + trigger('enterLeave', [ + fromTopEnter + ]) + ], }) export class SuggestionsPopupComponent implements OnInit, OnDestroy { @@ -22,10 +29,11 @@ export class SuggestionsPopupComponent implements OnInit, OnDestroy { subscription; + suggestionsRD$: Observable; + + constructor( - private translateService: TranslateService, private suggestionTargetsStateService: SuggestionTargetsStateService, - private notificationsService: NotificationsService, private suggestionsService: SuggestionsService ) { } @@ -42,7 +50,7 @@ export class SuggestionsPopupComponent implements OnInit, OnDestroy { this.suggestionTargetsStateService.dispatchRefreshUserSuggestionsAction(); if (isNotEmpty(suggestions)) { if (!visited) { - suggestions.forEach((suggestionTarget: SuggestionTarget) => this.showNotificationForNewSuggestions(suggestionTarget)); + this.suggestionsRD$ = of(suggestions); this.suggestionTargetsStateService.dispatchMarkUserSuggestionsAsVisitedAction(); notifier.next(null); notifier.complete(); @@ -51,21 +59,24 @@ export class SuggestionsPopupComponent implements OnInit, OnDestroy { }); } - /** - * Show a notification to user for a new suggestions detected - * @param suggestionTarget - * @private - */ - private showNotificationForNewSuggestions(suggestionTarget: SuggestionTarget): void { - const content = this.translateService.instant(this.labelPrefix + 'suggestion', - this.suggestionsService.getNotificationSuggestionInterpolation(suggestionTarget)); - this.notificationsService.success('', content, {timeOut:0}, true); - } - ngOnDestroy() { if (this.subscription) { this.subscription.unsubscribe(); } } + /** + * Interpolated params to build the notification suggestions notification. + * @param suggestionTarget + */ + public getNotificationSuggestionInterpolation(suggestionTarget: SuggestionTarget): any { + return this.suggestionsService.getNotificationSuggestionInterpolation(suggestionTarget); + } + + /** + * Hide popup from view + */ + public removePopup() { + this.suggestionsRD$ = null; + } } diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 15134a01fd8..05b3964a17f 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -3120,7 +3120,11 @@ "mydspace.import": "Import", - "notification.suggestion": "We found {{count}} publications in the {{source}} that seems to be related to your profile.
    Please review the suggestions", + "notification.suggestion": "We found {{count}} publications in the {{source}} that seems to be related to your profile.
    ", + + "notification.suggestion.review": "review the suggestions", + + "notification.suggestion.please": "Please", "nav.browse.header": "All of DSpace", From 6380abc759eb09997e0e6fe236bbb904c1425afb Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Fri, 16 Feb 2024 13:10:38 +0100 Subject: [PATCH 43/44] Fix merge conflicts --- ...publication-claim-page-resolver.service.ts | 12 - ...s-publication-claim-page.component.spec.ts | 25 +- .../admin-notifications-routing.module.ts | 51 ++- .../admin-notifications.module.ts | 12 +- src/app/admin/admin-routing-paths.ts | 5 + src/app/admin/admin-routing.module.ts | 7 +- src/app/core/core.module.ts | 4 +- .../submission/workspaceitem-data.service.ts | 13 - .../metadata-values.component.ts | 11 + src/app/menu.resolver.ts | 82 +++-- .../notifications/notifications-effects.ts | 2 +- src/app/notifications/notifications.module.ts | 36 +- .../notifications/notifications.reducer.ts | 2 +- .../suggestion-actions.component.ts | 9 +- .../suggestion-evidences.component.ts | 8 +- .../suggestion-list-element.component.ts | 12 +- .../publication-claim.component.ts | 11 +- .../suggestion-targets.actions.ts | 8 +- .../suggestion-targets.effects.ts | 12 +- .../suggestion-targets.reducer.ts | 7 +- .../suggestion-targets.state.service.ts | 28 +- .../notifications/suggestion.service.spec.ts | 13 +- .../suggestions-notification.component.ts | 8 +- .../suggestions-popup.component.ts | 2 +- src/app/notifications/suggestions.service.ts | 71 +--- .../notifications-pages-routing.module.ts | 6 +- ...uggestion-targets-page-resolver.service.ts | 15 +- ...ons-suggestion-targets-page.component.html | 2 +- ...-suggestion-targets-page.component.spec.ts | 24 +- .../mocks/publication-claim-targets.mock.ts | 2 +- .../shared/mocks/publication-claim.mock.ts | 5 +- src/app/suggestion-notifications/selectors.ts | 10 +- .../suggestions-page.component.spec.ts | 17 +- .../suggestions-page.component.ts | 10 +- .../suggestions-page.module.ts | 4 +- .../suggestions-page.resolver.ts | 7 +- src/assets/i18n/en.json5 | 328 ++++++++++++++++++ src/environments/environment.test.ts | 2 - 38 files changed, 537 insertions(+), 346 deletions(-) diff --git a/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page-resolver.service.ts b/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page-resolver.service.ts index d7cbf846e4c..f524cd56c20 100644 --- a/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page-resolver.service.ts +++ b/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page-resolver.service.ts @@ -4,11 +4,7 @@ import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/r /** * Interface for the route parameters. */ -<<<<<<<< HEAD:src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page-resolver.service.ts export interface NotificationsSuggestionTargetsPageParams { -======== -export interface AdminNotificationsPublicationClaimPageParams { ->>>>>>>> main:src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page-resolver.service.ts pageId?: string; pageSize?: number; currentPage?: number; @@ -18,11 +14,7 @@ export interface AdminNotificationsPublicationClaimPageParams { * This class represents a resolver that retrieve the route data before the route is activated. */ @Injectable() -<<<<<<<< HEAD:src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page-resolver.service.ts export class NotificationsSuggestionTargetsPageResolver implements Resolve { -======== -export class AdminNotificationsPublicationClaimPageResolver implements Resolve { ->>>>>>>> main:src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page-resolver.service.ts /** * Method for resolving the parameters in the current route. @@ -30,11 +22,7 @@ export class AdminNotificationsPublicationClaimPageResolver implements Resolve>>>>>>> main:src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page-resolver.service.ts return { pageId: route.queryParams.pageId, pageSize: parseInt(route.queryParams.pageSize, 10), diff --git a/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.spec.ts b/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.spec.ts index 6061bda0634..cec8ddc00b8 100644 --- a/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.spec.ts +++ b/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.spec.ts @@ -1,23 +1,15 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -<<<<<<<< HEAD:src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.spec.ts -import { NotificationsSuggestionTargetsPageComponent } from './notifications-suggestion-targets-page.component'; -======== -import { AdminNotificationsPublicationClaimPageComponent } from './admin-notifications-publication-claim-page.component'; ->>>>>>>> main:src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.spec.ts import { NO_ERRORS_SCHEMA } from '@angular/core'; import { CommonModule } from '@angular/common'; import { TranslateModule } from '@ngx-translate/core'; +import { + NotificationsSuggestionTargetsPageComponent +} from '../../../quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component'; -<<<<<<<< HEAD:src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.spec.ts describe('NotificationsSuggestionTargetsPageComponent', () => { let component: NotificationsSuggestionTargetsPageComponent; let fixture: ComponentFixture; -======== -describe('AdminNotificationsPublicationClaimPageComponent', () => { - let component: AdminNotificationsPublicationClaimPageComponent; - let fixture: ComponentFixture; ->>>>>>>> main:src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.spec.ts beforeEach(async(() => { TestBed.configureTestingModule({ @@ -26,17 +18,10 @@ describe('AdminNotificationsPublicationClaimPageComponent', () => { TranslateModule.forRoot() ], declarations: [ -<<<<<<<< HEAD:src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.spec.ts NotificationsSuggestionTargetsPageComponent ], providers: [ NotificationsSuggestionTargetsPageComponent -======== - AdminNotificationsPublicationClaimPageComponent - ], - providers: [ - AdminNotificationsPublicationClaimPageComponent ->>>>>>>> main:src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.spec.ts ], schemas: [NO_ERRORS_SCHEMA] }) @@ -44,11 +29,7 @@ describe('AdminNotificationsPublicationClaimPageComponent', () => { })); beforeEach(() => { -<<<<<<<< HEAD:src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.spec.ts fixture = TestBed.createComponent(NotificationsSuggestionTargetsPageComponent); -======== - fixture = TestBed.createComponent(AdminNotificationsPublicationClaimPageComponent); ->>>>>>>> main:src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.spec.ts component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/src/app/admin/admin-notifications/admin-notifications-routing.module.ts b/src/app/admin/admin-notifications/admin-notifications-routing.module.ts index 07a98aa080d..755f2e784ba 100644 --- a/src/app/admin/admin-notifications/admin-notifications-routing.module.ts +++ b/src/app/admin/admin-notifications/admin-notifications-routing.module.ts @@ -6,19 +6,34 @@ import { I18nBreadcrumbResolver } from '../../core/breadcrumbs/i18n-breadcrumb.r import { I18nBreadcrumbsService } from '../../core/breadcrumbs/i18n-breadcrumbs.service'; import { PUBLICATION_CLAIMS_PATH } from './admin-notifications-routing-paths'; import { AdminNotificationsPublicationClaimPageComponent } from './admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component'; -import { AdminNotificationsPublicationClaimPageResolver } from './admin-notifications-publication-claim-page/admin-notifications-publication-claim-page-resolver.service'; import { QUALITY_ASSURANCE_EDIT_PATH } from './admin-notifications-routing-paths'; -import { AdminQualityAssuranceTopicsPageComponent } from './admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component'; -import { AdminQualityAssuranceEventsPageComponent } from './admin-quality-assurance-events-page/admin-quality-assurance-events-page.component'; -import { AdminQualityAssuranceTopicsPageResolver } from './admin-quality-assurance-topics-page/admin-quality-assurance-topics-page-resolver.service'; -import { AdminQualityAssuranceEventsPageResolver } from './admin-quality-assurance-events-page/admin-quality-assurance-events-page.resolver'; -import { AdminQualityAssuranceSourcePageComponent } from './admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component'; -import { AdminQualityAssuranceSourcePageResolver } from './admin-quality-assurance-source-page-component/admin-quality-assurance-source-page-resolver.service'; import { QualityAssuranceBreadcrumbResolver } from '../../core/breadcrumbs/quality-assurance-breadcrumb.resolver'; import { QualityAssuranceBreadcrumbService } from '../../core/breadcrumbs/quality-assurance-breadcrumb.service'; +import { + AdminNotificationsPublicationClaimPageResolver +} from '../../quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page-resolver.service'; +import { + QualityAssuranceTopicsPageComponent +} from '../../quality-assurance-notifications-pages/quality-assurance-topics-page/quality-assurance-topics-page.component'; +import { + QualityAssuranceTopicsPageResolver +} from '../../quality-assurance-notifications-pages/quality-assurance-topics-page/quality-assurance-topics-page-resolver.service'; import { SourceDataResolver -} from './admin-quality-assurance-source-page-component/admin-quality-assurance-source-data.resolver'; +} from '../../quality-assurance-notifications-pages/quality-assurance-source-page-component/quality-assurance-source-data.resolver'; +import { + QualityAssuranceEventsPageResolver +} from '../../quality-assurance-notifications-pages/quality-assurance-events-page/quality-assurance-events-page.resolver'; +import { + QualityAssuranceEventsPageComponent +} from '../../quality-assurance-notifications-pages/quality-assurance-events-page/quality-assurance-events-page.component'; +import { + QualityAssuranceSourcePageResolver +} from '../../quality-assurance-notifications-pages/quality-assurance-source-page-component/quality-assurance-source-page-resolver.service'; +import { + QualityAssuranceSourcePageComponent +} from '../../quality-assurance-notifications-pages/quality-assurance-source-page-component/quality-assurance-source-page.component'; + @NgModule({ imports: [ @@ -41,11 +56,11 @@ import { { canActivate: [ AuthenticatedGuard ], path: `${QUALITY_ASSURANCE_EDIT_PATH}/:sourceId`, - component: AdminQualityAssuranceTopicsPageComponent, + component: QualityAssuranceTopicsPageComponent, pathMatch: 'full', resolve: { breadcrumb: QualityAssuranceBreadcrumbResolver, - openaireQualityAssuranceTopicsParams: AdminQualityAssuranceTopicsPageResolver + openaireQualityAssuranceTopicsParams: QualityAssuranceTopicsPageResolver }, data: { title: 'admin.quality-assurance.page.title', @@ -56,11 +71,11 @@ import { { canActivate: [ AuthenticatedGuard ], path: `${QUALITY_ASSURANCE_EDIT_PATH}`, - component: AdminQualityAssuranceSourcePageComponent, + component: QualityAssuranceSourcePageComponent, pathMatch: 'full', resolve: { breadcrumb: I18nBreadcrumbResolver, - openaireQualityAssuranceSourceParams: AdminQualityAssuranceSourcePageResolver, + openaireQualityAssuranceSourceParams: QualityAssuranceSourcePageResolver, sourceData: SourceDataResolver }, data: { @@ -72,11 +87,11 @@ import { { canActivate: [ AuthenticatedGuard ], path: `${QUALITY_ASSURANCE_EDIT_PATH}/:sourceId/:topicId`, - component: AdminQualityAssuranceEventsPageComponent, + component: QualityAssuranceEventsPageComponent, pathMatch: 'full', resolve: { breadcrumb: QualityAssuranceBreadcrumbResolver, - openaireQualityAssuranceEventsParams: AdminQualityAssuranceEventsPageResolver + openaireQualityAssuranceEventsParams: QualityAssuranceEventsPageResolver }, data: { title: 'admin.notifications.event.page.title', @@ -91,10 +106,10 @@ import { I18nBreadcrumbsService, AdminNotificationsPublicationClaimPageResolver, SourceDataResolver, - AdminQualityAssuranceSourcePageResolver, - AdminQualityAssuranceTopicsPageResolver, - AdminQualityAssuranceEventsPageResolver, - AdminQualityAssuranceSourcePageResolver, + QualityAssuranceSourcePageResolver, + QualityAssuranceTopicsPageResolver, + QualityAssuranceEventsPageResolver, + QualityAssuranceSourcePageResolver, QualityAssuranceBreadcrumbResolver, QualityAssuranceBreadcrumbService ] diff --git a/src/app/admin/admin-notifications/admin-notifications.module.ts b/src/app/admin/admin-notifications/admin-notifications.module.ts index d9efb4c2886..ea670d222c0 100644 --- a/src/app/admin/admin-notifications/admin-notifications.module.ts +++ b/src/app/admin/admin-notifications/admin-notifications.module.ts @@ -4,11 +4,14 @@ import { CoreModule } from '../../core/core.module'; import { SharedModule } from '../../shared/shared.module'; import { AdminNotificationsRoutingModule } from './admin-notifications-routing.module'; import { AdminNotificationsPublicationClaimPageComponent } from './admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component'; -import { AdminQualityAssuranceTopicsPageComponent } from './admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component'; -import { AdminQualityAssuranceEventsPageComponent } from './admin-quality-assurance-events-page/admin-quality-assurance-events-page.component'; -import { AdminQualityAssuranceSourcePageComponent } from './admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component'; import { NotificationsModule } from '../../notifications/notifications.module'; + + + + + + @NgModule({ imports: [ CommonModule, @@ -19,9 +22,6 @@ import { NotificationsModule } from '../../notifications/notifications.module'; ], declarations: [ AdminNotificationsPublicationClaimPageComponent, - AdminQualityAssuranceTopicsPageComponent, - AdminQualityAssuranceEventsPageComponent, - AdminQualityAssuranceSourcePageComponent ], entryComponents: [] }) diff --git a/src/app/admin/admin-routing-paths.ts b/src/app/admin/admin-routing-paths.ts index 064e28f594a..508d352c50d 100644 --- a/src/app/admin/admin-routing-paths.ts +++ b/src/app/admin/admin-routing-paths.ts @@ -18,3 +18,8 @@ export function getLdnServicesModuleRoute() { export function getNotificatioQualityAssuranceRoute() { return new URLCombiner(`/${NOTIFICATIONS_MODULE_PATH}`, getQualityAssuranceEditRoute()).toString(); } + + +export function getNotificationsModuleRoute() { + return new URLCombiner(getAdminModuleRoute(), NOTIFICATIONS_MODULE_PATH).toString(); +} diff --git a/src/app/admin/admin-routing.module.ts b/src/app/admin/admin-routing.module.ts index b590df69ca2..23350e40430 100644 --- a/src/app/admin/admin-routing.module.ts +++ b/src/app/admin/admin-routing.module.ts @@ -6,12 +6,17 @@ 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 { LDN_PATH, REGISTRIES_MODULE_PATH } from './admin-routing-paths'; +import { LDN_PATH, NOTIFICATIONS_MODULE_PATH, REGISTRIES_MODULE_PATH } from './admin-routing-paths'; import { BatchImportPageComponent } from './admin-import-batch-page/batch-import-page.component'; @NgModule({ imports: [ RouterModule.forChild([ + { + path: NOTIFICATIONS_MODULE_PATH, + loadChildren: () => import('./admin-notifications/admin-notifications.module') + .then((m) => m.AdminNotificationsModule), + }, { path: REGISTRIES_MODULE_PATH, loadChildren: () => import('./admin-registries/admin-registries.module') diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index 5df1908642a..dd8419634f7 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -185,8 +185,6 @@ import { FlatBrowseDefinition } from './shared/flat-browse-definition.model'; import { ValueListBrowseDefinition } from './shared/value-list-browse-definition.model'; import { NonHierarchicalBrowseDefinition } from './shared/non-hierarchical-browse-definition'; import { BulkAccessConditionOptions } from './config/models/bulk-access-condition-options.model'; -import { SuggestionTarget } from './notifications/reciter-suggestions/models/suggestion-target.model'; -import { SuggestionSource } from './notifications/reciter-suggestions/models/suggestion-source.model'; 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 { LdnItemfiltersService } from '../admin/admin-ldn-services/ldn-services-data/ldn-itemfilters-data.service'; @@ -197,6 +195,8 @@ import { import { SubmissionCoarNotifyConfig } from '../submission/sections/section-coar-notify/submission-coar-notify.config'; import { NotifyRequestsStatus } from '../item-page/simple/notify-requests-status/notify-requests-status.model'; import { NotifyRequestsStatusDataService } from './data/notify-services-status-data.service'; +import { SuggestionTarget } from './notifications/models/suggestion-target.model'; +import { SuggestionSource } from './notifications/models/suggestion-source.model'; /** diff --git a/src/app/core/submission/workspaceitem-data.service.ts b/src/app/core/submission/workspaceitem-data.service.ts index 91a9115c52a..38810d8fd6f 100644 --- a/src/app/core/submission/workspaceitem-data.service.ts +++ b/src/app/core/submission/workspaceitem-data.service.ts @@ -110,19 +110,6 @@ export class WorkspaceitemDataService extends IdentifiableDataService> { - return this.deleteData.deleteByHref(href, copyVirtualMetadata); - } - /** * Make a new FindListRequest with given search method * diff --git a/src/app/item-page/field-components/metadata-values/metadata-values.component.ts b/src/app/item-page/field-components/metadata-values/metadata-values.component.ts index 29c20c6e2ac..34dd8cf351a 100644 --- a/src/app/item-page/field-components/metadata-values/metadata-values.component.ts +++ b/src/app/item-page/field-components/metadata-values/metadata-values.component.ts @@ -5,6 +5,7 @@ import { BrowseDefinition } from '../../../core/shared/browse-definition.model'; import { hasValue } from '../../../shared/empty.util'; import { VALUE_LIST_BROWSE_DEFINITION } from '../../../core/shared/value-list-browse-definition.resource-type'; import { ImageField } from '../../simple/field-components/specific-field/item-page-field.component'; +import { environment } from '../../../../environments/environment'; /** * This component renders the configured 'values' into the ds-metadata-field-wrapper component. @@ -96,4 +97,14 @@ export class MetadataValuesComponent implements OnChanges { } return queryParams; } + + + /** + * Checks if the given link value is an internal link. + * @param linkValue - The link value to check. + * @returns True if the link value starts with the base URL defined in the environment configuration, false otherwise. + */ + hasInternalLink(linkValue: string): boolean { + return linkValue.startsWith(environment.ui.baseUrl); + } } diff --git a/src/app/menu.resolver.ts b/src/app/menu.resolver.ts index 75e72470c64..52a9617865e 100644 --- a/src/app/menu.resolver.ts +++ b/src/app/menu.resolver.ts @@ -47,7 +47,7 @@ import { import { ExportBatchSelectorComponent } from './shared/dso-selector/modal-wrappers/export-batch-selector/export-batch-selector.component'; -import { NOTIFICATIONS_RECITER_SUGGESTION_PATH } from './quality-assurance-notifications-pages/notifications-pages-routing-paths'; +import { PUBLICATION_CLAIMS_PATH } from './admin/admin-notifications/admin-notifications-routing-paths'; /** * Creates all of the app's menus @@ -171,7 +171,8 @@ export class MenuResolver implements Resolve { this.authorizationService.isAuthorized(FeatureID.AdministratorOf), this.authorizationService.isAuthorized(FeatureID.CanSubmit), this.authorizationService.isAuthorized(FeatureID.CanEditItem), - ]).subscribe(([isCollectionAdmin, isCommunityAdmin, isSiteAdmin, canSubmit, canEditItem]) => { + this.authorizationService.isAuthorized(FeatureID.CanSeeQA) + ]).subscribe(([isCollectionAdmin, isCommunityAdmin, isSiteAdmin, canSubmit, canEditItem, canSeeQa]) => { const newSubMenuList = [ { id: 'new_community', @@ -387,6 +388,41 @@ export class MenuResolver implements Resolve { icon: 'heartbeat', index: 11 }, + /* Notifications */ + { + id: 'notifications', + active: false, + visible: canSeeQa || isSiteAdmin, + model: { + type: MenuItemType.TEXT, + text: 'menu.section.notifications' + } as TextMenuItemModel, + icon: 'bell', + index: 4 + }, + { + id: 'notifications_quality-assurance', + parentID: 'notifications', + active: false, + visible: canSeeQa, + model: { + type: MenuItemType.LINK, + text: 'menu.section.quality-assurance', + link: '/notifications/quality-assurance' + } as LinkMenuItemModel, + }, + { + id: 'notifications_publication-claim', + parentID: 'notifications', + active: false, + visible: isSiteAdmin, + model: { + type: MenuItemType.LINK, + text: 'menu.section.notifications_publication-claim', + link: '/admin/notifications/' + PUBLICATION_CLAIMS_PATH + } as LinkMenuItemModel, + }, + /* Admin Search */ ]; menuList.forEach((menuSection) => this.menuService.addSection(MenuID.ADMIN, Object.assign(menuSection, { shouldPersistOnRouteChange: true @@ -556,47 +592,9 @@ export class MenuResolver implements Resolve { * Create menu sections dependent on whether or not the current user is a site administrator */ createSiteAdministratorMenuSections() { - combineLatest([ - this.authorizationService.isAuthorized(FeatureID.AdministratorOf), - this.authorizationService.isAuthorized(FeatureID.CanSeeQA) - ]) - .subscribe(([authorized, canSeeQA]) => { + this.authorizationService.isAuthorized(FeatureID.AdministratorOf) + .subscribe((authorized) => { const menuList = [ - /* Notifications */ - { - id: 'notifications', - active: false, - visible: authorized && canSeeQA, - model: { - type: MenuItemType.TEXT, - text: 'menu.section.notifications' - } as TextMenuItemModel, - icon: 'bell', - index: 4 - }, - { - id: 'notifications_quality-assurance', - parentID: 'notifications', - active: false, - visible: authorized, - model: { - type: MenuItemType.LINK, - text: 'menu.section.quality-assurance', - link: '/notifications/quality-assurance' - } as LinkMenuItemModel, - }, - { - id: 'notifications_reciter', - parentID: 'notifications', - active: false, - visible: authorized, - model: { - type: MenuItemType.LINK, - text: 'menu.section.notifications_reciter', - link: '/notifications/' + NOTIFICATIONS_RECITER_SUGGESTION_PATH - } as LinkMenuItemModel, - }, - /* Admin Search */ { id: 'admin_search', active: false, diff --git a/src/app/notifications/notifications-effects.ts b/src/app/notifications/notifications-effects.ts index a73fd04fc0e..9c446cb66ad 100644 --- a/src/app/notifications/notifications-effects.ts +++ b/src/app/notifications/notifications-effects.ts @@ -1,6 +1,6 @@ import { QualityAssuranceSourceEffects } from './qa/source/quality-assurance-source.effects'; import { QualityAssuranceTopicsEffects } from './qa/topics/quality-assurance-topics.effects'; -import { SuggestionTargetsEffects } from '../suggestion-notifications/suggestion-targets/suggestion-targets.effects'; +import { SuggestionTargetsEffects } from './suggestion-targets/suggestion-targets.effects'; export const notificationsEffects = [ QualityAssuranceTopicsEffects, diff --git a/src/app/notifications/notifications.module.ts b/src/app/notifications/notifications.module.ts index 00c7582b2f0..0ecd491a192 100644 --- a/src/app/notifications/notifications.module.ts +++ b/src/app/notifications/notifications.module.ts @@ -26,29 +26,23 @@ import { QualityAssuranceSourceService } from './qa/source/quality-assurance-sou import { QualityAssuranceSourceDataService } from '../core/notifications/qa/source/quality-assurance-source-data.service'; -import { PublicationClaimComponent } from '../suggestion-notifications/suggestion-targets/publication-claim/publication-claim.component'; -import { SuggestionActionsComponent } from '../suggestion-notifications/suggestion-actions/suggestion-actions.component'; -import { - SuggestionListElementComponent -} from '../suggestion-notifications/suggestion-list-element/suggestion-list-element.component'; + +import { SuggestionsPopupComponent } from './suggestions-popup/suggestions-popup.component'; +import { SuggestionSourceDataService } from '../core/notifications/source/suggestion-source-data.service'; +import { SuggestionTargetDataService } from '../core/notifications/target/suggestion-target-data.service'; +import { SuggestionsDataService } from '../core/notifications/suggestions-data.service'; +import { PublicationClaimComponent } from '../notifications/suggestion-targets/publication-claim/publication-claim.component'; + +import { SuggestionsNotificationComponent } from './suggestions-notification/suggestions-notification.component'; +import { SuggestionsService } from './suggestions.service'; +import { SuggestionTargetsStateService } from './suggestion-targets/suggestion-targets.state.service'; +import { SuggestionActionsComponent } from './suggestion-actions/suggestion-actions.component'; +import { SuggestionListElementComponent } from './suggestion-list-element/suggestion-list-element.component'; import { SuggestionEvidencesComponent -} from '../suggestion-notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component'; -import { SuggestionsPopupComponent } from '../suggestion-notifications/suggestions-popup/suggestions-popup.component'; -import { - SuggestionsNotificationComponent -} from '../suggestion-notifications/suggestions-notification/suggestions-notification.component'; -import { SuggestionsService } from '../suggestion-notifications/suggestions.service'; -import { SuggestionsDataService } from '../core/suggestion-notifications/suggestions-data.service'; -import { - SuggestionSourceDataService -} from '../core/suggestion-notifications/source/suggestion-source-data.service'; -import { - SuggestionTargetDataService -} from '../core/suggestion-notifications/target/suggestion-target-data.service'; -import { - SuggestionTargetsStateService -} from '../suggestion-notifications/suggestion-targets/suggestion-targets.state.service'; +} from './suggestion-list-element/suggestion-evidences/suggestion-evidences.component'; + + const MODULES = [ diff --git a/src/app/notifications/notifications.reducer.ts b/src/app/notifications/notifications.reducer.ts index cced6755fa9..665c5d73929 100644 --- a/src/app/notifications/notifications.reducer.ts +++ b/src/app/notifications/notifications.reducer.ts @@ -1,7 +1,7 @@ import { ActionReducerMap, createFeatureSelector } from '@ngrx/store'; import { qualityAssuranceSourceReducer, QualityAssuranceSourceState } from './qa/source/quality-assurance-source.reducer'; import { qualityAssuranceTopicsReducer, QualityAssuranceTopicState, } from './qa/topics/quality-assurance-topics.reducer'; -import { SuggestionTargetsReducer, SuggestionTargetState } from '../suggestion-notifications/suggestion-targets/suggestion-targets.reducer'; +import { SuggestionTargetsReducer, SuggestionTargetState } from './suggestion-targets/suggestion-targets.reducer'; /** * The OpenAIRE State diff --git a/src/app/notifications/suggestion-actions/suggestion-actions.component.ts b/src/app/notifications/suggestion-actions/suggestion-actions.component.ts index 6af1e2c67ad..5f1443794ca 100644 --- a/src/app/notifications/suggestion-actions/suggestion-actions.component.ts +++ b/src/app/notifications/suggestion-actions/suggestion-actions.component.ts @@ -1,15 +1,12 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; import { ItemType } from '../../core/shared/item-relationships/item-type.model'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; -<<<<<<<< HEAD:src/app/notifications/reciter-suggestions/suggestion-actions/suggestion-actions.component.ts -import { Suggestion } from '../../../core/notifications/reciter-suggestions/models/suggestion.model'; -======== -import { Suggestion } from '../../core/suggestion-notifications/models/suggestion.model'; ->>>>>>>> main:src/app/notifications/suggestion-actions/suggestion-actions.component.ts -import { SuggestionApproveAndImport } from '../suggestion-list-element/suggestion-list-element.component'; + import { Collection } from '../../core/shared/collection.model'; import { take } from 'rxjs/operators'; import { CreateItemParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component'; +import { Suggestion } from '../../core/notifications/models/suggestion.model'; +import { SuggestionApproveAndImport } from '../suggestion-list-element/suggestion-list-element.component'; /** * Show and trigger the actions to submit for a suggestion diff --git a/src/app/notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.ts b/src/app/notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.ts index 2346c862577..d58f8d39c18 100644 --- a/src/app/notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.ts +++ b/src/app/notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.ts @@ -1,11 +1,7 @@ import { Component, Input } from '@angular/core'; -<<<<<<<< HEAD:src/app/notifications/reciter-suggestions/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.ts -import { fadeIn } from '../../../../shared/animations/fade'; -import { SuggestionEvidences } from '../../../../core/notifications/reciter-suggestions/models/suggestion.model'; -======== import { fadeIn } from '../../../shared/animations/fade'; -import { SuggestionEvidences } from '../../../core/suggestion-notifications/models/suggestion.model'; ->>>>>>>> main:src/app/notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.ts +import { SuggestionEvidences } from '../../../core/notifications/models/suggestion.model'; + /** * Show suggestion evidences such as score (authorScore, dateScore) diff --git a/src/app/notifications/suggestion-list-element/suggestion-list-element.component.ts b/src/app/notifications/suggestion-list-element/suggestion-list-element.component.ts index 76d1314417c..bc5db3d1bfb 100644 --- a/src/app/notifications/suggestion-list-element/suggestion-list-element.component.ts +++ b/src/app/notifications/suggestion-list-element/suggestion-list-element.component.ts @@ -1,18 +1,12 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; - -<<<<<<<< HEAD:src/app/notifications/reciter-suggestions/suggestion-list-element/suggestion-list-element.component.ts -import { fadeIn } from '../../../shared/animations/fade'; -import { Suggestion } from '../../../core/notifications/reciter-suggestions/models/suggestion.model'; -import { Item } from '../../../core/shared/item.model'; -import { isNotEmpty } from '../../../shared/empty.util'; -======== +import { Suggestion } from 'src/app/core/notifications/models/suggestion.model'; import { fadeIn } from '../../shared/animations/fade'; -import { Suggestion } from '../../core/suggestion-notifications/models/suggestion.model'; import { Item } from '../../core/shared/item.model'; import { isNotEmpty } from '../../shared/empty.util'; ->>>>>>>> main:src/app/notifications/suggestion-list-element/suggestion-list-element.component.ts + + /** * A simple interface to unite a specific suggestion and the id of the chosen collection diff --git a/src/app/notifications/suggestion-targets/publication-claim/publication-claim.component.ts b/src/app/notifications/suggestion-targets/publication-claim/publication-claim.component.ts index b9474911bc7..1b6d70cba4e 100644 --- a/src/app/notifications/suggestion-targets/publication-claim/publication-claim.component.ts +++ b/src/app/notifications/suggestion-targets/publication-claim/publication-claim.component.ts @@ -4,17 +4,14 @@ import { Router } from '@angular/router'; import { Observable, Subscription } from 'rxjs'; import { distinctUntilChanged, take } from 'rxjs/operators'; -<<<<<<<< HEAD:src/app/notifications/reciter-suggestions/suggestion-targets/suggestion-targets.component.ts -import { SuggestionTarget } from '../../../core/notifications/reciter-suggestions/models/suggestion-target.model'; -======== -import { SuggestionTarget } from '../../../core/suggestion-notifications/models/suggestion-target.model'; ->>>>>>>> main:src/app/notifications/suggestion-targets/publication-claim/publication-claim.component.ts + import { hasValue } from '../../../shared/empty.util'; import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; -import { SuggestionTargetsStateService } from '../suggestion-targets.state.service'; import { getSuggestionPageRoute } from '../../../suggestions-page/suggestions-page-routing-paths'; -import { SuggestionsService } from '../../suggestions.service'; import { PaginationService } from '../../../core/pagination/pagination.service'; +import { SuggestionTarget } from '../../../core/notifications/models/suggestion-target.model'; +import { SuggestionTargetsStateService } from '../suggestion-targets.state.service'; +import { SuggestionsService } from '../../suggestions.service'; /** * Component to display the Suggestion Target list. diff --git a/src/app/notifications/suggestion-targets/suggestion-targets.actions.ts b/src/app/notifications/suggestion-targets/suggestion-targets.actions.ts index fe631f65dad..281e07d99e1 100644 --- a/src/app/notifications/suggestion-targets/suggestion-targets.actions.ts +++ b/src/app/notifications/suggestion-targets/suggestion-targets.actions.ts @@ -1,12 +1,8 @@ /* eslint-disable max-classes-per-file */ import { Action } from '@ngrx/store'; -<<<<<<<< HEAD:src/app/notifications/reciter-suggestions/suggestion-targets/suggestion-targets.actions.ts -import { type } from '../../../shared/ngrx/type'; -import { SuggestionTarget } from '../../../core/notifications/reciter-suggestions/models/suggestion-target.model'; -======== import { type } from '../../shared/ngrx/type'; -import { SuggestionTarget } from '../../core/suggestion-notifications/models/suggestion-target.model'; ->>>>>>>> main:src/app/notifications/suggestion-targets/suggestion-targets.actions.ts +import { SuggestionTarget } from '../../core/notifications/models/suggestion-target.model'; + /** * For each action type in an action group, make a simple diff --git a/src/app/notifications/suggestion-targets/suggestion-targets.effects.ts b/src/app/notifications/suggestion-targets/suggestion-targets.effects.ts index 257501dee94..f8be925d8ba 100644 --- a/src/app/notifications/suggestion-targets/suggestion-targets.effects.ts +++ b/src/app/notifications/suggestion-targets/suggestion-targets.effects.ts @@ -15,13 +15,9 @@ import { } from './suggestion-targets.actions'; import { PaginatedList } from '../../core/data/paginated-list.model'; import { SuggestionsService } from '../suggestions.service'; -<<<<<<<< HEAD:src/app/notifications/reciter-suggestions/suggestion-targets/suggestion-targets.effects.ts -import { NotificationsService } from '../../../shared/notifications/notifications.service'; -import { SuggestionTarget } from '../../../core/notifications/reciter-suggestions/models/suggestion-target.model'; -======== +import { SuggestionTarget } from '../../core/notifications/models/suggestion-target.model'; import { NotificationsService } from '../../shared/notifications/notifications.service'; -import { SuggestionTarget } from '../../core/suggestion-notifications/models/suggestion-target.model'; ->>>>>>>> main:src/app/notifications/suggestion-targets/suggestion-targets.effects.ts + /** * Provides effect methods for the Suggestion Targets actions. @@ -80,12 +76,8 @@ export class SuggestionTargetsEffects { }), catchError((errors) => of(errors)) ); -<<<<<<<< HEAD:src/app/notifications/reciter-suggestions/suggestion-targets/suggestion-targets.effects.ts - })), { dispatch: false }); -======== })) ); ->>>>>>>> main:src/app/notifications/suggestion-targets/suggestion-targets.effects.ts /** * Initialize the effect class variables. diff --git a/src/app/notifications/suggestion-targets/suggestion-targets.reducer.ts b/src/app/notifications/suggestion-targets/suggestion-targets.reducer.ts index 05f7ac73519..6ba29303b34 100644 --- a/src/app/notifications/suggestion-targets/suggestion-targets.reducer.ts +++ b/src/app/notifications/suggestion-targets/suggestion-targets.reducer.ts @@ -1,9 +1,6 @@ +import { SuggestionTarget } from '../../core/notifications/models/suggestion-target.model'; import { SuggestionTargetActionTypes, SuggestionTargetsActions } from './suggestion-targets.actions'; -<<<<<<<< HEAD:src/app/notifications/reciter-suggestions/suggestion-targets/suggestion-targets.reducer.ts -import { SuggestionTarget } from '../../../core/notifications/reciter-suggestions/models/suggestion-target.model'; -======== -import { SuggestionTarget } from '../../core/suggestion-notifications/models/suggestion-target.model'; ->>>>>>>> main:src/app/notifications/suggestion-targets/suggestion-targets.reducer.ts + /** * The interface representing the OpenAIRE suggestion targets state. diff --git a/src/app/notifications/suggestion-targets/suggestion-targets.state.service.ts b/src/app/notifications/suggestion-targets/suggestion-targets.state.service.ts index 56668812a36..1ca01b10f29 100644 --- a/src/app/notifications/suggestion-targets/suggestion-targets.state.service.ts +++ b/src/app/notifications/suggestion-targets/suggestion-targets.state.service.ts @@ -4,31 +4,23 @@ import { select, Store } from '@ngrx/store'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; -import { - getCurrentUserSuggestionTargetsSelector, - getCurrentUserSuggestionTargetsVisitedSelector, - getSuggestionTargetCurrentPageSelector, - getSuggestionTargetTotalsSelector, - isSuggestionTargetLoadedSelector, - isReciterSuggestionTargetProcessingSelector, - suggestionTargetObjectSelector -} from '../selectors'; -<<<<<<<< HEAD:src/app/notifications/reciter-suggestions/suggestion-targets/suggestion-targets.state.service.ts -import { SuggestionTarget } from '../../../core/notifications/reciter-suggestions/models/suggestion-target.model'; -======== -import { SuggestionTarget } from '../../core/suggestion-notifications/models/suggestion-target.model'; ->>>>>>>> main:src/app/notifications/suggestion-targets/suggestion-targets.state.service.ts + import { ClearSuggestionTargetsAction, MarkUserSuggestionsAsVisitedAction, RefreshUserSuggestionsAction, RetrieveTargetsBySourceAction } from './suggestion-targets.actions'; -<<<<<<<< HEAD:src/app/notifications/reciter-suggestions/suggestion-targets/suggestion-targets.state.service.ts -import { SuggestionNotificationsState } from '../../notifications.reducer'; -======== import { SuggestionNotificationsState } from '../../notifications/notifications.reducer'; ->>>>>>>> main:src/app/notifications/suggestion-targets/suggestion-targets.state.service.ts +import { SuggestionTarget } from '../../core/notifications/models/suggestion-target.model'; +import { + getCurrentUserSuggestionTargetsSelector, getCurrentUserSuggestionTargetsVisitedSelector, + getSuggestionTargetCurrentPageSelector, + getSuggestionTargetTotalsSelector, + isReciterSuggestionTargetProcessingSelector, + isSuggestionTargetLoadedSelector, + suggestionTargetObjectSelector +} from '../../suggestion-notifications/selectors'; /** * The service handling the Suggestion targets State. diff --git a/src/app/notifications/suggestion.service.spec.ts b/src/app/notifications/suggestion.service.spec.ts index 268eb59ddd1..082c7c3f04e 100644 --- a/src/app/notifications/suggestion.service.spec.ts +++ b/src/app/notifications/suggestion.service.spec.ts @@ -1,13 +1,6 @@ import { SuggestionsService } from './suggestions.service'; import { ResearcherProfileDataService } from '../core/profile/researcher-profile-data.service'; -import { - SuggestionsDataService -} from '../core/suggestion-notifications/suggestions-data.service'; - -import { - SuggestionTargetDataService -} from '../core/suggestion-notifications/target/suggestion-target-data.service'; import { TestScheduler } from 'rxjs/testing'; import { getTestScheduler } from 'jasmine-marbles'; import { of as observableOf } from 'rxjs'; @@ -18,11 +11,11 @@ import { createSuccessfulRemoteDataObject$ } from '../shared/remote-data.utils'; import { WorkspaceitemDataService } from '../core/submission/workspaceitem-data.service'; import { mockSuggestionPublicationOne } from '../shared/mocks/publication-claim.mock'; import { ResourceType } from '../core/shared/resource-type'; +import { SuggestionsDataService } from '../core/notifications/suggestions-data.service'; +import { SuggestionTargetDataService } from '../core/notifications/target/suggestion-target-data.service'; +import { SuggestionTarget } from '../core/notifications/models/suggestion-target.model'; -import { - SuggestionTarget -} from '../core/suggestion-notifications/models/suggestion-target.model'; describe('SuggestionsService test', () => { let scheduler: TestScheduler; diff --git a/src/app/notifications/suggestions-notification/suggestions-notification.component.ts b/src/app/notifications/suggestions-notification/suggestions-notification.component.ts index 3d0e233ad75..107da67fce8 100644 --- a/src/app/notifications/suggestions-notification/suggestions-notification.component.ts +++ b/src/app/notifications/suggestions-notification/suggestions-notification.component.ts @@ -1,13 +1,9 @@ import { Component, OnInit } from '@angular/core'; -<<<<<<<< HEAD:src/app/notifications/reciter-suggestions/suggestions-notification/suggestions-notification.component.ts -import { SuggestionTarget } from '../../../core/notifications/reciter-suggestions/models/suggestion-target.model'; -import { TranslateService } from '@ngx-translate/core'; -======== -import { SuggestionTarget } from '../../core/suggestion-notifications/models/suggestion-target.model'; ->>>>>>>> main:src/app/notifications/suggestions-notification/suggestions-notification.component.ts + import { SuggestionTargetsStateService } from '../suggestion-targets/suggestion-targets.state.service'; import { SuggestionsService } from '../suggestions.service'; import { Observable } from 'rxjs'; +import { SuggestionTarget } from '../../core/notifications/models/suggestion-target.model'; /** * Show suggestions notification, used on myDSpace and Profile pages diff --git a/src/app/notifications/suggestions-popup/suggestions-popup.component.ts b/src/app/notifications/suggestions-popup/suggestions-popup.component.ts index 2cf3db128e6..1921c4fe93d 100644 --- a/src/app/notifications/suggestions-popup/suggestions-popup.component.ts +++ b/src/app/notifications/suggestions-popup/suggestions-popup.component.ts @@ -2,13 +2,13 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; import { SuggestionTargetsStateService } from '../suggestion-targets/suggestion-targets.state.service'; import { SuggestionsService } from '../suggestions.service'; import { take, takeUntil } from 'rxjs/operators'; -import { SuggestionTarget } from '../../core/suggestion-notifications/models/suggestion-target.model'; import { isNotEmpty } from '../../shared/empty.util'; import { combineLatest, Observable, of, Subject } from 'rxjs'; import { trigger } from '@angular/animations'; import { fromTopEnter } from '../../shared/animations/fromTop'; +import { SuggestionTarget } from '../../core/notifications/models/suggestion-target.model'; /** * Show suggestions on a popover window, used on the homepage diff --git a/src/app/notifications/suggestions.service.ts b/src/app/notifications/suggestions.service.ts index b1b03915f75..e2b32b38ec3 100644 --- a/src/app/notifications/suggestions.service.ts +++ b/src/app/notifications/suggestions.service.ts @@ -1,68 +1,27 @@ import { Injectable } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; import { of, forkJoin, Observable } from 'rxjs'; import { catchError, map, mergeMap, take } from 'rxjs/operators'; - -<<<<<<<< HEAD:src/app/notifications/reciter-suggestions/suggestions.service.ts -import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; -import { RemoteData } from '../../core/data/remote-data'; -import { PaginatedList } from '../../core/data/paginated-list.model'; -import { SuggestionTarget } from '../../core/notifications/reciter-suggestions/models/suggestion-target.model'; -import { AuthService } from '../../core/auth/auth.service'; -import { hasValue, isNotEmpty } from '../../shared/empty.util'; -import { ResearcherProfile } from '../../core/profile/model/researcher-profile.model'; -======== import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model'; -import { RemoteData } from '../core/data/remote-data'; +import { FindListOptions } from '../core/data/find-list-options.model'; import { PaginatedList } from '../core/data/paginated-list.model'; -import { SuggestionTarget } from '../core/suggestion-notifications/models/suggestion-target.model'; -import { hasValue, isNotEmpty } from '../shared/empty.util'; -import { ResearcherProfile } from '../core/profile/model/researcher-profile.model'; ->>>>>>>> main:src/app/notifications/suggestions.service.ts -import { - getAllSucceededRemoteDataPayload, - getFinishedRemoteData, - getFirstSucceededRemoteDataPayload, - getFirstSucceededRemoteListPayload -<<<<<<<< HEAD:src/app/notifications/reciter-suggestions/suggestions.service.ts -} from '../../core/shared/operators'; -import { Suggestion } from '../../core/notifications/reciter-suggestions/models/suggestion.model'; -import { WorkspaceitemDataService } from '../../core/submission/workspaceitem-data.service'; -import { TranslateService } from '@ngx-translate/core'; -import { NoContent } from '../../core/shared/NoContent.model'; -import { environment } from '../../../environments/environment'; -import { WorkspaceItem } from '../../core/submission/models/workspaceitem.model'; -import {FindListOptions} from '../../core/data/find-list-options.model'; -import {SuggestionConfig} from '../../../config/layout-config.interfaces'; -import { ResearcherProfileDataService } from '../../core/profile/researcher-profile-data.service'; -import { - SuggestionSourceDataService -} from '../../core/notifications/reciter-suggestions/source/suggestion-source-data.service'; -import { - SuggestionTargetDataService -} from '../../core/notifications/reciter-suggestions/target/suggestion-target-data.service'; -import { - SuggestionsDataService -} from '../../core/notifications/reciter-suggestions/suggestions-data.service'; -======== -} from '../core/shared/operators'; -import { Suggestion } from '../core/suggestion-notifications/models/suggestion.model'; -import { WorkspaceitemDataService } from '../core/submission/workspaceitem-data.service'; -import { TranslateService } from '@ngx-translate/core'; +import { RemoteData } from '../core/data/remote-data'; +import { SuggestionTarget } from '../core/notifications/models/suggestion-target.model'; +import { SuggestionsDataService } from '../core/notifications/suggestions-data.service'; +import { SuggestionTargetDataService } from '../core/notifications/target/suggestion-target-data.service'; +import { ResearcherProfileDataService } from '../core/profile/researcher-profile-data.service'; import { NoContent } from '../core/shared/NoContent.model'; +import { getFirstSucceededRemoteListPayload, getFirstSucceededRemoteDataPayload, getAllSucceededRemoteDataPayload, getFinishedRemoteData } from '../core/shared/operators'; +import { getSuggestionPageRoute } from '../suggestions-page/suggestions-page-routing-paths'; import { environment } from '../../environments/environment'; +import { SuggestionConfig } from '../../config/suggestion-config.interfaces'; +import { Suggestion } from '../core/notifications/models/suggestion.model'; +import { ResearcherProfile } from '../core/profile/model/researcher-profile.model'; +import { hasValue, isNotEmpty } from '../shared/empty.util'; +import { WorkspaceitemDataService } from '../core/submission/workspaceitem-data.service'; import { WorkspaceItem } from '../core/submission/models/workspaceitem.model'; -import {FindListOptions} from '../core/data/find-list-options.model'; -import {SuggestionConfig} from '../../config/suggestion-config.interfaces'; -import { ResearcherProfileDataService } from '../core/profile/researcher-profile-data.service'; -import { - SuggestionTargetDataService -} from '../core/suggestion-notifications/target/suggestion-target-data.service'; -import { - SuggestionsDataService -} from '../core/suggestion-notifications/suggestions-data.service'; -import { getSuggestionPageRoute } from '../suggestions-page/suggestions-page-routing-paths'; ->>>>>>>> main:src/app/notifications/suggestions.service.ts + /** * useful for multiple approvals and ignores operation diff --git a/src/app/quality-assurance-notifications-pages/notifications-pages-routing.module.ts b/src/app/quality-assurance-notifications-pages/notifications-pages-routing.module.ts index c64ae6381ac..c57b22a028b 100644 --- a/src/app/quality-assurance-notifications-pages/notifications-pages-routing.module.ts +++ b/src/app/quality-assurance-notifications-pages/notifications-pages-routing.module.ts @@ -6,7 +6,7 @@ import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.reso import { I18nBreadcrumbsService } from '../core/breadcrumbs/i18n-breadcrumbs.service'; import { NOTIFICATIONS_RECITER_SUGGESTION_PATH } from './notifications-pages-routing-paths'; import { NotificationsSuggestionTargetsPageComponent } from './notifications-suggestion-targets-page/notifications-suggestion-targets-page.component'; -import { NotificationsSuggestionTargetsPageResolver } from './notifications-suggestion-targets-page/notifications-suggestion-targets-page-resolver.service'; +import { AdminNotificationsPublicationClaimPageResolver } from './notifications-suggestion-targets-page/notifications-suggestion-targets-page-resolver.service'; import { QUALITY_ASSURANCE_EDIT_PATH } from './notifications-pages-routing-paths'; import { QualityAssuranceTopicsPageComponent } from './quality-assurance-topics-page/quality-assurance-topics-page.component'; import { QualityAssuranceEventsPageComponent } from './quality-assurance-events-page/quality-assurance-events-page.component'; @@ -30,7 +30,7 @@ import { pathMatch: 'full', resolve: { breadcrumb: I18nBreadcrumbResolver, - reciterSuggestionTargetParams: NotificationsSuggestionTargetsPageResolver + reciterSuggestionTargetParams: AdminNotificationsPublicationClaimPageResolver }, data: { title: 'admin.notifications.recitersuggestion.page.title', @@ -104,7 +104,7 @@ import { providers: [ I18nBreadcrumbResolver, I18nBreadcrumbsService, - NotificationsSuggestionTargetsPageResolver, + AdminNotificationsPublicationClaimPageResolver, SourceDataResolver, QualityAssuranceSourcePageResolver, QualityAssuranceTopicsPageResolver, diff --git a/src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page-resolver.service.ts b/src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page-resolver.service.ts index d7cbf846e4c..783387281e1 100644 --- a/src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page-resolver.service.ts +++ b/src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page-resolver.service.ts @@ -4,11 +4,8 @@ import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/r /** * Interface for the route parameters. */ -<<<<<<<< HEAD:src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page-resolver.service.ts -export interface NotificationsSuggestionTargetsPageParams { -======== + export interface AdminNotificationsPublicationClaimPageParams { ->>>>>>>> main:src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page-resolver.service.ts pageId?: string; pageSize?: number; currentPage?: number; @@ -18,11 +15,8 @@ export interface AdminNotificationsPublicationClaimPageParams { * This class represents a resolver that retrieve the route data before the route is activated. */ @Injectable() -<<<<<<<< HEAD:src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page-resolver.service.ts -export class NotificationsSuggestionTargetsPageResolver implements Resolve { -======== + export class AdminNotificationsPublicationClaimPageResolver implements Resolve { ->>>>>>>> main:src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page-resolver.service.ts /** * Method for resolving the parameters in the current route. @@ -30,11 +24,8 @@ export class AdminNotificationsPublicationClaimPageResolver implements Resolve>>>>>>> main:src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page-resolver.service.ts return { pageId: route.queryParams.pageId, pageSize: parseInt(route.queryParams.pageSize, 10), diff --git a/src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.html b/src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.html index 5d06a1a6bdd..11db25fa7bf 100644 --- a/src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.html +++ b/src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.html @@ -1 +1 @@ - + diff --git a/src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.spec.ts b/src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.spec.ts index 6061bda0634..bbca7f8d393 100644 --- a/src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.spec.ts +++ b/src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.spec.ts @@ -1,23 +1,16 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -<<<<<<<< HEAD:src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.spec.ts import { NotificationsSuggestionTargetsPageComponent } from './notifications-suggestion-targets-page.component'; -======== -import { AdminNotificationsPublicationClaimPageComponent } from './admin-notifications-publication-claim-page.component'; ->>>>>>>> main:src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.spec.ts import { NO_ERRORS_SCHEMA } from '@angular/core'; import { CommonModule } from '@angular/common'; import { TranslateModule } from '@ngx-translate/core'; +import { + AdminNotificationsPublicationClaimPageComponent +} from '../../admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component'; -<<<<<<<< HEAD:src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.spec.ts describe('NotificationsSuggestionTargetsPageComponent', () => { let component: NotificationsSuggestionTargetsPageComponent; let fixture: ComponentFixture; -======== -describe('AdminNotificationsPublicationClaimPageComponent', () => { - let component: AdminNotificationsPublicationClaimPageComponent; - let fixture: ComponentFixture; ->>>>>>>> main:src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.spec.ts beforeEach(async(() => { TestBed.configureTestingModule({ @@ -26,17 +19,10 @@ describe('AdminNotificationsPublicationClaimPageComponent', () => { TranslateModule.forRoot() ], declarations: [ -<<<<<<<< HEAD:src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.spec.ts NotificationsSuggestionTargetsPageComponent ], - providers: [ - NotificationsSuggestionTargetsPageComponent -======== - AdminNotificationsPublicationClaimPageComponent - ], providers: [ AdminNotificationsPublicationClaimPageComponent ->>>>>>>> main:src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.spec.ts ], schemas: [NO_ERRORS_SCHEMA] }) @@ -44,11 +30,7 @@ describe('AdminNotificationsPublicationClaimPageComponent', () => { })); beforeEach(() => { -<<<<<<<< HEAD:src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.spec.ts fixture = TestBed.createComponent(NotificationsSuggestionTargetsPageComponent); -======== - fixture = TestBed.createComponent(AdminNotificationsPublicationClaimPageComponent); ->>>>>>>> main:src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.spec.ts component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/src/app/shared/mocks/publication-claim-targets.mock.ts b/src/app/shared/mocks/publication-claim-targets.mock.ts index 1d7688c1e3d..932a98bee55 100644 --- a/src/app/shared/mocks/publication-claim-targets.mock.ts +++ b/src/app/shared/mocks/publication-claim-targets.mock.ts @@ -1,5 +1,5 @@ import { ResourceType } from '../../core/shared/resource-type'; -import { SuggestionTarget } from '../../core/suggestion-notifications/models/suggestion-target.model'; +import { SuggestionTarget } from '../../core/notifications/models/suggestion-target.model'; // REST Mock --------------------------------------------------------------------- // ------------------------------------------------------------------------------- diff --git a/src/app/shared/mocks/publication-claim.mock.ts b/src/app/shared/mocks/publication-claim.mock.ts index 143b54d8dd7..02364347f4c 100644 --- a/src/app/shared/mocks/publication-claim.mock.ts +++ b/src/app/shared/mocks/publication-claim.mock.ts @@ -2,8 +2,9 @@ // REST Mock --------------------------------------------------------------------- // ------------------------------------------------------------------------------- -import { Suggestion } from '../../core/suggestion-notifications/models/suggestion.model'; -import { SUGGESTION } from '../../core/suggestion-notifications/models/suggestion-objects.resource-type'; + +import { Suggestion } from '../../core/notifications/models/suggestion.model'; +import { SUGGESTION } from '../../core/notifications/models/suggestion-objects.resource-type'; export const mockSuggestionPublicationOne: Suggestion = { id: '24694773', diff --git a/src/app/suggestion-notifications/selectors.ts b/src/app/suggestion-notifications/selectors.ts index 45d56a67935..1dd0df11a74 100644 --- a/src/app/suggestion-notifications/selectors.ts +++ b/src/app/suggestion-notifications/selectors.ts @@ -1,13 +1,9 @@ import {createFeatureSelector, createSelector, MemoizedSelector} from '@ngrx/store'; -<<<<<<<< HEAD:src/app/notifications/reciter-suggestions/selectors.ts -import { suggestionNotificationsSelector, SuggestionNotificationsState } from '../notifications.reducer'; -import { SuggestionTarget } from '../../core/notifications/reciter-suggestions/models/suggestion-target.model'; -======== import { suggestionNotificationsSelector, SuggestionNotificationsState } from '../notifications/notifications.reducer'; -import { SuggestionTarget } from '../core/suggestion-notifications/models/suggestion-target.model'; ->>>>>>>> main:src/app/suggestion-notifications/selectors.ts -import { SuggestionTargetState } from './suggestion-targets/suggestion-targets.reducer'; + import {subStateSelector} from '../submission/selectors'; +import { SuggestionTargetState } from '../notifications/suggestion-targets/suggestion-targets.reducer'; +import { SuggestionTarget } from '../core/notifications/models/suggestion-target.model'; /** * Returns the Reciter Suggestion Target state. diff --git a/src/app/suggestions-page/suggestions-page.component.spec.ts b/src/app/suggestions-page/suggestions-page.component.spec.ts index 98535297a29..7cdeaddc788 100644 --- a/src/app/suggestions-page/suggestions-page.component.spec.ts +++ b/src/app/suggestions-page/suggestions-page.component.spec.ts @@ -7,14 +7,9 @@ import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { of as observableOf } from 'rxjs'; import { SuggestionsPageComponent } from './suggestions-page.component'; -import { - SuggestionApproveAndImport, - SuggestionListElementComponent -} from '../suggestion-notifications/suggestion-list-element/suggestion-list-element.component'; -import { SuggestionsService } from '../suggestion-notifications/suggestions.service'; + import { getMockSuggestionNotificationsStateService, getMockSuggestionsService } from '../shared/mocks/suggestion.mock'; import { mockSuggestionPublicationOne, mockSuggestionPublicationTwo } from '../shared/mocks/publication-claim.mock'; -import { SuggestionEvidencesComponent } from '../suggestion-notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component'; import { ObjectKeysPipe } from '../shared/utils/object-keys-pipe'; import { VarDirective } from '../shared/utils/var.directive'; import { ActivatedRoute, Router } from '@angular/router'; @@ -24,13 +19,21 @@ import { AuthService } from '../core/auth/auth.service'; import { NotificationsService } from '../shared/notifications/notifications.service'; import { NotificationsServiceStub } from '../shared/testing/notifications-service.stub'; import { getMockTranslateService } from '../shared/mocks/translate.service.mock'; -import { SuggestionTargetsStateService } from '../suggestion-notifications/suggestion-targets/suggestion-targets.state.service'; import { WorkspaceitemDataService } from '../core/submission/workspaceitem-data.service'; import { createSuccessfulRemoteDataObject } from '../shared/remote-data.utils'; import { TestScheduler } from 'rxjs/testing'; import { getTestScheduler } from 'jasmine-marbles'; import { PaginationServiceStub } from '../shared/testing/pagination-service.stub'; import { PaginationService } from '../core/pagination/pagination.service'; +import { + SuggestionEvidencesComponent +} from '../notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component'; +import { + SuggestionApproveAndImport, + SuggestionListElementComponent +} from '../notifications/suggestion-list-element/suggestion-list-element.component'; +import { SuggestionsService } from '../notifications/suggestions.service'; +import { SuggestionTargetsStateService } from '../notifications/suggestion-targets/suggestion-targets.state.service'; describe('SuggestionPageComponent', () => { let component: SuggestionsPageComponent; diff --git a/src/app/suggestions-page/suggestions-page.component.ts b/src/app/suggestions-page/suggestions-page.component.ts index fdbf131e592..e4305cc2266 100644 --- a/src/app/suggestions-page/suggestions-page.component.ts +++ b/src/app/suggestions-page/suggestions-page.component.ts @@ -9,14 +9,9 @@ import { SortDirection, SortOptions, } from '../core/cache/models/sort-options.m import { PaginatedList } from '../core/data/paginated-list.model'; import { RemoteData } from '../core/data/remote-data'; import { getFirstSucceededRemoteDataPayload } from '../core/shared/operators'; -import { SuggestionBulkResult, SuggestionsService } from '../suggestion-notifications/suggestions.service'; import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model'; -import { Suggestion } from '../core/suggestion-notifications/models/suggestion.model'; -import { SuggestionTarget } from '../core/suggestion-notifications/models/suggestion-target.model'; import { AuthService } from '../core/auth/auth.service'; -import { SuggestionApproveAndImport } from '../suggestion-notifications/suggestion-list-element/suggestion-list-element.component'; import { NotificationsService } from '../shared/notifications/notifications.service'; -import { SuggestionTargetsStateService } from '../suggestion-notifications/suggestion-targets/suggestion-targets.state.service'; import { WorkspaceitemDataService } from '../core/submission/workspaceitem-data.service'; import { PaginationService } from '../core/pagination/pagination.service'; import { WorkspaceItem } from '../core/submission/models/workspaceitem.model'; @@ -25,6 +20,11 @@ import {redirectOn4xx} from '../core/shared/authorized.operators'; import { getWorkspaceItemEditRoute } from '../workflowitems-edit-page/workflowitems-edit-page-routing-paths'; +import { Suggestion } from '../core/notifications/models/suggestion.model'; +import { SuggestionTarget } from '../core/notifications/models/suggestion-target.model'; +import { SuggestionBulkResult, SuggestionsService } from '../notifications/suggestions.service'; +import { SuggestionTargetsStateService } from '../notifications/suggestion-targets/suggestion-targets.state.service'; +import { SuggestionApproveAndImport } from '../notifications/suggestion-list-element/suggestion-list-element.component'; @Component({ selector: 'ds-suggestion-page', diff --git a/src/app/suggestions-page/suggestions-page.module.ts b/src/app/suggestions-page/suggestions-page.module.ts index e25e483e39a..90fbdbcf705 100644 --- a/src/app/suggestions-page/suggestions-page.module.ts +++ b/src/app/suggestions-page/suggestions-page.module.ts @@ -4,9 +4,9 @@ import { CommonModule } from '@angular/common'; import { SuggestionsPageComponent } from './suggestions-page.component'; import { SharedModule } from '../shared/shared.module'; import { SuggestionsPageRoutingModule } from './suggestions-page-routing.module'; -import { SuggestionsService } from '../suggestion-notifications/suggestions.service'; -import { SuggestionsDataService } from '../core/suggestion-notifications/suggestions-data.service'; import { NotificationsModule } from '../notifications/notifications.module'; +import { SuggestionsDataService } from '../core/notifications/suggestions-data.service'; +import { SuggestionsService } from '../notifications/suggestions.service'; @NgModule({ declarations: [SuggestionsPageComponent], diff --git a/src/app/suggestions-page/suggestions-page.resolver.ts b/src/app/suggestions-page/suggestions-page.resolver.ts index dde5b847f5d..a2074d38bfb 100644 --- a/src/app/suggestions-page/suggestions-page.resolver.ts +++ b/src/app/suggestions-page/suggestions-page.resolver.ts @@ -6,10 +6,9 @@ import { find } from 'rxjs/operators'; import { RemoteData } from '../core/data/remote-data'; import { hasValue } from '../shared/empty.util'; -import { SuggestionTarget } from '../core/suggestion-notifications/models/suggestion-target.model'; -import { - SuggestionTargetDataService -} from '../core/suggestion-notifications/target/suggestion-target-data.service'; +import { SuggestionTarget } from '../core/notifications/models/suggestion-target.model'; +import { SuggestionTargetDataService } from '../core/notifications/target/suggestion-target-data.service'; + /** * This class represents a resolver that requests a specific collection before the route is activated diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index e20a724158a..89c53543ab5 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -5639,4 +5639,332 @@ "admin.notifications.publicationclaim.breadcrumbs": "Publication Claim", "admin.notifications.publicationclaim.page.title": "Publication Claim", + + "coar-notify-support.title": "COAR Notify Protocol", + + "coar-notify-support-title.content": "Here, we fully support the COAR Notify protocol, which is designed to enhance the communication between repositories. To learn more about the COAR Notify protocol, you can visit their official website here.", + + "coar-notify-support.ldn-inbox.title": "LDN InBox", + + "coar-notify-support.ldn-inbox.content": "For your convenience, our LDN (Linked Data Notifications) InBox is easily accessible at {ldnInboxUrl}. The LDN InBox enables seamless communication and data exchange, ensuring efficient and effective collaboration.", + + "coar-notify-support.message-moderation.title": "Message Moderation", + + "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", + "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-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-edit-registered-service.title": "Edit Service", + "ldn-create-service.title": "Create service", + "service.overview.create.modal": "Create Service", + "service.overview.create.body": "Please confirm the creation of this service.", + "ldn-service-status": "Status", + "service.confirm.create": "Create", + "service.refuse.create": "Cancel", + "ldn-register-new-service.title": "Register a new service", + "ldn-new-service.form.label.submit": "Save", + "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.ip-range": "Service IP range", + "ldn-new-service.form.label.score": "Level of trust", + "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.lowerIp": "IPv4 range lower bound", + "ldn-new-service.form.placeholder.upperIp": "IPv4 range upper bound", + "ldn-new-service.form.placeholder.ldnUrl": "Please specify the URL of the LDN Inbox", + "ldn-new-service.form.placeholder.score": "Please enter a value between 0 and 1. Use the “.” as decimal separator", + "ldn-service.form.label.placeholder.default-select": "Select a pattern", + + "ldn-service.form.pattern.ack-accept.label": "Acknowledge and Accept", + "ldn-service.form.pattern.ack-accept.description": "This pattern is used to acknowledge and accept a request (offer). It implies an intention to act on the request.", + "ldn-service.form.pattern.ack-accept.category": "Acknowledgements", + + "ldn-service.form.pattern.ack-reject.label": "Acknowledge and Reject", + "ldn-service.form.pattern.ack-reject.description": "This pattern is used to acknowledge and reject a request (offer). It signifies no further action regarding the request.", + "ldn-service.form.pattern.ack-reject.category": "Acknowledgements", + + "ldn-service.form.pattern.ack-tentative-accept.label": "Acknowledge and Tentatively Accept", + "ldn-service.form.pattern.ack-tentative-accept.description": "This pattern is used to acknowledge and tentatively accept a request (offer). It implies an intention to act, which may change.", + "ldn-service.form.pattern.ack-tentative-accept.category": "Acknowledgements", + + "ldn-service.form.pattern.ack-tentative-reject.label": "Acknowledge and Tentatively Reject", + "ldn-service.form.pattern.ack-tentative-reject.description": "This pattern is used to acknowledge and tentatively reject a request (offer). It signifies no further action, subject to change.", + "ldn-service.form.pattern.ack-tentative-reject.category": "Acknowledgements", + + "ldn-service.form.pattern.announce-endorsement.label": "Announce Endorsement", + "ldn-service.form.pattern.announce-endorsement.description": "This pattern is used to announce the existence of an endorsement, referencing the endorsed resource.", + "ldn-service.form.pattern.announce-endorsement.category": "Announcements", + + "ldn-service.form.pattern.announce-ingest.label": "Announce Ingest", + "ldn-service.form.pattern.announce-ingest.description": "This pattern is used to announce that a resource has been ingested.", + "ldn-service.form.pattern.announce-ingest.category": "Announcements", + + "ldn-service.form.pattern.announce-relationship.label": "Announce Relationship", + "ldn-service.form.pattern.announce-relationship.description": "This pattern is used to announce a relationship between two resources.", + "ldn-service.form.pattern.announce-relationship.category": "Announcements", + + "ldn-service.form.pattern.announce-review.label": "Announce Review", + "ldn-service.form.pattern.announce-review.description": "This pattern is used to announce the existence of a review, referencing the reviewed resource.", + "ldn-service.form.pattern.announce-review.category": "Announcements", + + "ldn-service.form.pattern.announce-service-result.label": "Announce Service Result", + "ldn-service.form.pattern.announce-service-result.description": "This pattern is used to announce the existence of a 'service result', referencing the relevant resource.", + "ldn-service.form.pattern.announce-service-result.category": "Announcements", + + "ldn-service.form.pattern.request-endorsement.label": "Request Endorsement", + "ldn-service.form.pattern.request-endorsement.description": "This pattern is used to request endorsement of a resource owned by the origin system.", + "ldn-service.form.pattern.request-endorsement.category": "Requests", + + "ldn-service.form.pattern.request-ingest.label": "Request Ingest", + "ldn-service.form.pattern.request-ingest.description": "This pattern is used to request that the target system ingest a resource.", + "ldn-service.form.pattern.request-ingest.category": "Requests", + + "ldn-service.form.pattern.request-review.label": "Request Review", + "ldn-service.form.pattern.request-review.description": "This pattern is used to request a review of a resource owned by the origin system.", + "ldn-service.form.pattern.request-review.category": "Requests", + + "ldn-service.form.pattern.undo-offer.label": "Undo Offer", + "ldn-service.form.pattern.undo-offer.description": "This pattern is used to undo (retract) an offer previously made.", + "ldn-service.form.pattern.undo-offer.category": "Undo", + + "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.ipRange": "Please enter a valid IP range", + "ldn-new-service.form.hint.ipRange": "Please enter a valid IpV4 in both range bounds (note: for single IP, please enter the same value in both fields)", + "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.inboundPattern": "Inbound 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.edit.body": "Do you confirm the changes?", + "service.overview.edit.modal": "Edit Service", + "service.detail.update": "Confirm", + "service.detail.return": "Cancel", + "service.overview.reset-form.body": "Are you sure you want to discard the changes and leave?", + "service.overview.reset-form.modal": "Discard Changes", + "service.overview.reset-form.reset-confirm": "Discard", + "admin.registries.services-formats.modify.success.head": "Successful Edit", + "admin.registries.services-formats.modify.success.content": "The service has been edited", + "admin.registries.services-formats.modify.failure.head": "Failed Edit", + "admin.registries.services-formats.modify.failure.content": "The service has not been edited", + "ldn-service-notification.created.success.title": "Successful Create", + "ldn-service-notification.created.success.body": "The service has been created", + "ldn-service-notification.created.failure.title": "Failed Create", + "ldn-service-notification.created.failure.body": "The service has not been created", + "ldn-service-notification.created.warning.title": "Please select at least one Inbound Pattern", + "ldn-enable-service.notification.success.title": "Successful status updated", + "ldn-enable-service.notification.success.content": "The service status has been updated", + "ldn-service-delete.notification.success.title": "Successful Deletion", + "ldn-service-delete.notification.success.content": "The service has been deleted", + "ldn-service-delete.notification.error.title": "Failed Deletion", + "ldn-service-delete.notification.error.content": "The service has not been deleted", + "service.overview.reset-form.reset-return": "Cancel", + "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.submit": "Save", + "ldn-edit-service.breadcrumbs": "Edit Service", + "ldn-service.control-constaint-select-none": "Select none", + + "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", + + "info.coar-notify-support.title": "Notify Support", + + "info.coar-notify.breadcrumbs": "Notify Support", + + "submission.sections.notify.info": "The selected service is compatible with the item according to its current status. {{ service.name }}: {{ service.description }}", + + "item.qa-event-notification.check.notification-info": "There are {{num}} pending review to check", + + "item.qa-event-notification-info.check.button": "Check", + + "mydspace.qa-event-notification.check.notification-info": "There are {{num}} pending review to check", + + "mydspace.qa-event-notification-info.check.button": "Check", + + "item.page.endorsed-by": "Endorsement", + + "item.page.is-reviewed-by": "Review", + + "item.page.is-supplemented-by": "Dataset", + + "item.page.endorsment": "Endorsment", + + "item.page.review": "Review", + + "item.page.dataset": "Dataset", + "menu.section.icon.ldn_services": "LDN Services overview", + "menu.section.services": "LDN Services", + + "menu.section.services_new": "LDN Service", + + "mydspace.import": "Import", + + "mydspace.notification.suggestion": "We found {{count}} publications
    in the {{source}} that seems to be related to your profile.
    Please review the suggestions", + + "mydspace.notification.suggestion.page": "We found {{count}} {{type}} in the {{source}} that seems to be related to your profile. Please review the suggestions.", + + "quality-assurance.topics.description-with-target": "Below you can see all the topics received from the subscriptions to {{source}} in regards to the", + "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.event.table.event.message.serviceUrl": "Service URL:", + + "quality-assurance.event.table.event.message.link": "Link:", + + "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", + + "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", + + "reciter.suggestion.loading": "Loading ...", + + "reciter.suggestion.title": "Suggestions", + + "reciter.suggestion.targets.description": "Below you can see all the suggestions ", + + "reciter.suggestion.targets": "Current Suggestions", + + "reciter.suggestion.table.name": "Researcher Name", + + "reciter.suggestion.table.actions": "Actions", + + "reciter.suggestion.button.review": "Review {{ total }} suggestion(s)", + + "reciter.suggestion.noTargets": "No target found.", + + "reciter.suggestion.target.error.service.retrieve": "An error occurred while loading the Suggestion targets", + + "reciter.suggestion.evidence.type": "Type", + + "reciter.suggestion.evidence.score": "Score", + + "reciter.suggestion.evidence.notes": "Notes", + + "reciter.suggestion.approveAndImport": "Approve & import", + + "reciter.suggestion.approveAndImport.success": "The suggestion has been imported successfully. View.", + + "reciter.suggestion.approveAndImport.bulk": "Approve & import Selected", + + "reciter.suggestion.approveAndImport.bulk.success": "{{ count }} suggestions have been imported successfully ", + + "reciter.suggestion.approveAndImport.bulk.error": "{{ count }} suggestions haven't been imported due to unexpected server errors", + + "reciter.suggestion.notMine": "Not mine", + + "reciter.suggestion.notMine.success": "The suggestion has been discarded", + + "reciter.suggestion.notMine.bulk": "Not mine Selected", + + "reciter.suggestion.notMine.bulk.success": "{{ count }} suggestions have been discarded ", + + "reciter.suggestion.notMine.bulk.error": "{{ count }} suggestions haven't been discarded due to unexpected server errors", + + "reciter.suggestion.seeEvidence": "See evidence", + + "reciter.suggestion.hideEvidence": "Hide evidence", + + "reciter.suggestion.suggestionFor": "Suggestion for", + + "reciter.suggestion.source.oaire": "OpenAIRE Graph", + + "reciter.suggestion.from.source": "from the ", + + "reciter.suggestion.totalScore": "Total Score", + + "reciter.suggestion.type.oaire": "OpenAIRE", + + "submission.sections.submit.progressbar.coarnotify": "COAR Notify", + + "submission.section.section-coar-notify.control.request-review.label": "You can request a review to one of the following services", + + "submission.section.section-coar-notify.control.request-endorsement.label": "You can request an Endorsement to one of the following overlay journals", + + "submission.section.section-coar-notify.control.request-ingest.label": "You can request to ingest a copy of your submission to one of the following services", + + "submission.section.section-coar-notify.dropdown.no-data": "No data available", + + "submission.section.section-coar-notify.dropdown.select-none": "Select none", + + "submission.section.section-coar-notify.small.notification": "Select a service for {{ pattern }} of this item", + + "submission.section.section-coar-notify.selection.description": "Selected service's description:", + + "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.", + + "request-status-alert-box.accepted": "The requested {{ offerType }} for {{ serviceName }} has been taken in charge.", + + "request-status-alert-box.rejected": "The requested {{ offerType }} for {{ serviceName }} has been rejected.", + + "request-status-alert-box.requested": "The requested {{ offerType }} for {{ serviceName }} is pending.", } diff --git a/src/environments/environment.test.ts b/src/environments/environment.test.ts index 76b3d901386..3908dd71dd2 100644 --- a/src/environments/environment.test.ts +++ b/src/environments/environment.test.ts @@ -324,6 +324,4 @@ export const environment: BuildConfig = { enabled: true } ], - - suggestion: [] }; From 251729e8696b6e97a4b565d1709e20cac1b190f8 Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Fri, 16 Feb 2024 15:18:42 +0100 Subject: [PATCH 44/44] fix empty result js error --- .../notify-requests-status.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.ts b/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.ts index a04ed96363e..18061ee292c 100644 --- a/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.ts +++ b/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.ts @@ -56,7 +56,7 @@ export class NotifyRequestsStatusComponent implements OnInit { */ private groupDataByStatus(notifyRequestsStatus: NotifyRequestsStatus) { const statusMap: Map = new Map(); - notifyRequestsStatus.notifyStatus.forEach( + notifyRequestsStatus.notifyStatus?.forEach( (notifyStatus: NotifyStatuses) => { const status = notifyStatus.status;