diff --git a/cypress/integration/search-page.spec.ts b/cypress/integration/search-page.spec.ts index a2bfbe6a5b..859c765d2e 100644 --- a/cypress/integration/search-page.spec.ts +++ b/cypress/integration/search-page.spec.ts @@ -53,7 +53,7 @@ describe('Search Page', () => { // Click to display grid view // TODO: These buttons should likely have an easier way to uniquely select - cy.get('#search-sidebar-content > ds-view-mode-switch > .btn-group > [href="/search?spc.sf=score&spc.sd=DESC&view=grid"] > .fas').click(); + cy.get('#search-sidebar-content > ds-view-mode-switch > .btn-group > [href="/search?view=grid"] > .fas').click(); // tag must be loaded cy.get('ds-search-page').should('exist'); diff --git a/src/app/access-control/access-control.module.ts b/src/app/access-control/access-control.module.ts index 0e872458bd..891238bbed 100644 --- a/src/app/access-control/access-control.module.ts +++ b/src/app/access-control/access-control.module.ts @@ -9,13 +9,15 @@ import { GroupFormComponent } from './group-registry/group-form/group-form.compo import { MembersListComponent } from './group-registry/group-form/members-list/members-list.component'; import { SubgroupsListComponent } from './group-registry/group-form/subgroup-list/subgroups-list.component'; import { GroupsRegistryComponent } from './group-registry/groups-registry.component'; +import { FormModule } from '../shared/form/form.module'; @NgModule({ imports: [ CommonModule, SharedModule, RouterModule, - AccessControlRoutingModule + AccessControlRoutingModule, + FormModule ], declarations: [ EPeopleRegistryComponent, diff --git a/src/app/admin/admin-registries/admin-registries.module.ts b/src/app/admin/admin-registries/admin-registries.module.ts index 5c82bb2ec9..65f7b61419 100644 --- a/src/app/admin/admin-registries/admin-registries.module.ts +++ b/src/app/admin/admin-registries/admin-registries.module.ts @@ -8,6 +8,7 @@ import { SharedModule } from '../../shared/shared.module'; import { MetadataSchemaFormComponent } from './metadata-registry/metadata-schema-form/metadata-schema-form.component'; import { MetadataFieldFormComponent } from './metadata-schema/metadata-field-form/metadata-field-form.component'; import { BitstreamFormatsModule } from './bitstream-formats/bitstream-formats.module'; +import { FormModule } from '../../shared/form/form.module'; @NgModule({ imports: [ @@ -15,7 +16,8 @@ import { BitstreamFormatsModule } from './bitstream-formats/bitstream-formats.mo SharedModule, RouterModule, BitstreamFormatsModule, - AdminRegistriesRoutingModule + AdminRegistriesRoutingModule, + FormModule ], declarations: [ MetadataRegistryComponent, diff --git a/src/app/admin/admin-registries/bitstream-formats/bitstream-formats.module.ts b/src/app/admin/admin-registries/bitstream-formats/bitstream-formats.module.ts index 1667a07c0b..afbe35a1f6 100644 --- a/src/app/admin/admin-registries/bitstream-formats/bitstream-formats.module.ts +++ b/src/app/admin/admin-registries/bitstream-formats/bitstream-formats.module.ts @@ -7,13 +7,15 @@ import { FormatFormComponent } from './format-form/format-form.component'; import { EditBitstreamFormatComponent } from './edit-bitstream-format/edit-bitstream-format.component'; import { BitstreamFormatsRoutingModule } from './bitstream-formats-routing.module'; import { AddBitstreamFormatComponent } from './add-bitstream-format/add-bitstream-format.component'; +import { FormModule } from '../../../shared/form/form.module'; @NgModule({ imports: [ CommonModule, SharedModule, RouterModule, - BitstreamFormatsRoutingModule + BitstreamFormatsRoutingModule, + FormModule ], declarations: [ BitstreamFormatsComponent, diff --git a/src/app/admin/admin-search-page/admin-search.module.ts b/src/app/admin/admin-search-page/admin-search.module.ts index ecf8d8a2d2..353d6dd498 100644 --- a/src/app/admin/admin-search-page/admin-search.module.ts +++ b/src/app/admin/admin-search-page/admin-search.module.ts @@ -10,6 +10,7 @@ import { CollectionAdminSearchResultGridElementComponent } from './admin-search- import { ItemAdminSearchResultActionsComponent } from './admin-search-results/item-admin-search-result-actions.component'; import { JournalEntitiesModule } from '../../entity-groups/journal-entities/journal-entities.module'; import { ResearchEntitiesModule } from '../../entity-groups/research-entities/research-entities.module'; +import { SearchModule } from '../../shared/search/search.module'; const ENTRY_COMPONENTS = [ // put only entry components that use custom decorator @@ -24,6 +25,7 @@ const ENTRY_COMPONENTS = [ @NgModule({ imports: [ + SearchModule, SharedModule.withEntryComponents(), JournalEntitiesModule.withEntryComponents(), ResearchEntitiesModule.withEntryComponents() diff --git a/src/app/admin/admin-workflow-page/admin-workflow.module.ts b/src/app/admin/admin-workflow-page/admin-workflow.module.ts index 02e5e01023..85e8f00a46 100644 --- a/src/app/admin/admin-workflow-page/admin-workflow.module.ts +++ b/src/app/admin/admin-workflow-page/admin-workflow.module.ts @@ -5,6 +5,7 @@ import { WorkflowItemSearchResultAdminWorkflowGridElementComponent } from './adm import { WorkflowItemAdminWorkflowActionsComponent } from './admin-workflow-search-results/workflow-item-admin-workflow-actions.component'; import { WorkflowItemSearchResultAdminWorkflowListElementComponent } from './admin-workflow-search-results/admin-workflow-search-result-list-element/workflow-item/workflow-item-search-result-admin-workflow-list-element.component'; import { AdminWorkflowPageComponent } from './admin-workflow-page.component'; +import { SearchModule } from '../../shared/search/search.module'; const ENTRY_COMPONENTS = [ // put only entry components that use custom decorator @@ -14,6 +15,7 @@ const ENTRY_COMPONENTS = [ @NgModule({ imports: [ + SearchModule, SharedModule.withEntryComponents() ], declarations: [ diff --git a/src/app/admin/admin.module.ts b/src/app/admin/admin.module.ts index 6c756dd851..b28a0cf89e 100644 --- a/src/app/admin/admin.module.ts +++ b/src/app/admin/admin.module.ts @@ -24,7 +24,7 @@ const ENTRY_COMPONENTS = [ AccessControlModule, AdminSearchModule.withEntryComponents(), AdminWorkflowModuleModule.withEntryComponents(), - SharedModule, + SharedModule ], declarations: [ AdminCurationTasksComponent, diff --git a/src/app/bitstream-page/bitstream-page.module.ts b/src/app/bitstream-page/bitstream-page.module.ts index 80e5ad14e3..d168a06db2 100644 --- a/src/app/bitstream-page/bitstream-page.module.ts +++ b/src/app/bitstream-page/bitstream-page.module.ts @@ -4,6 +4,8 @@ import { SharedModule } from '../shared/shared.module'; import { EditBitstreamPageComponent } from './edit-bitstream-page/edit-bitstream-page.component'; import { BitstreamPageRoutingModule } from './bitstream-page-routing.module'; import { BitstreamAuthorizationsComponent } from './bitstream-authorizations/bitstream-authorizations.component'; +import { FormModule } from '../shared/form/form.module'; +import { ResourcePoliciesModule } from '../shared/resource-policies/resource-policies.module'; /** * This module handles all components that are necessary for Bitstream related pages @@ -12,7 +14,9 @@ import { BitstreamAuthorizationsComponent } from './bitstream-authorizations/bit imports: [ CommonModule, SharedModule, - BitstreamPageRoutingModule + BitstreamPageRoutingModule, + FormModule, + ResourcePoliciesModule ], declarations: [ BitstreamAuthorizationsComponent, diff --git a/src/app/browse-by/browse-by.module.ts b/src/app/browse-by/browse-by.module.ts index cd44e52b81..e1dfaacea5 100644 --- a/src/app/browse-by/browse-by.module.ts +++ b/src/app/browse-by/browse-by.module.ts @@ -6,6 +6,7 @@ import { BrowseByMetadataPageComponent } from './browse-by-metadata-page/browse- import { BrowseByDatePageComponent } from './browse-by-date-page/browse-by-date-page.component'; import { BrowseBySwitcherComponent } from './browse-by-switcher/browse-by-switcher.component'; import { ThemedBrowseBySwitcherComponent } from './browse-by-switcher/themed-browse-by-switcher.component'; +import { ComcolModule } from '../shared/comcol/comcol.module'; const ENTRY_COMPONENTS = [ // put only entry components that use custom decorator @@ -17,6 +18,7 @@ const ENTRY_COMPONENTS = [ @NgModule({ imports: [ CommonModule, + ComcolModule, SharedModule ], declarations: [ diff --git a/src/app/collection-page/collection-form/collection-form.component.ts b/src/app/collection-page/collection-form/collection-form.component.ts index 7835ccc8e5..bb84153835 100644 --- a/src/app/collection-page/collection-form/collection-form.component.ts +++ b/src/app/collection-page/collection-form/collection-form.component.ts @@ -10,7 +10,7 @@ import { } from '@ng-dynamic-forms/core'; import { Collection } from '../../core/shared/collection.model'; -import { ComColFormComponent } from '../../shared/comcol-forms/comcol-form/comcol-form.component'; +import { ComColFormComponent } from '../../shared/comcol/comcol-forms/comcol-form/comcol-form.component'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { CommunityDataService } from '../../core/data/community-data.service'; import { AuthService } from '../../core/auth/auth.service'; @@ -28,8 +28,8 @@ import { NONE_ENTITY_TYPE } from '../../core/shared/item-relationships/item-type */ @Component({ selector: 'ds-collection-form', - styleUrls: ['../../shared/comcol-forms/comcol-form/comcol-form.component.scss'], - templateUrl: '../../shared/comcol-forms/comcol-form/comcol-form.component.html' + styleUrls: ['../../shared/comcol/comcol-forms/comcol-form/comcol-form.component.scss'], + templateUrl: '../../shared/comcol/comcol-forms/comcol-form/comcol-form.component.html' }) export class CollectionFormComponent extends ComColFormComponent implements OnInit { /** diff --git a/src/app/collection-page/collection-form/collection-form.module.ts b/src/app/collection-page/collection-form/collection-form.module.ts index a9ff5f3ea9..ddf18f0586 100644 --- a/src/app/collection-page/collection-form/collection-form.module.ts +++ b/src/app/collection-page/collection-form/collection-form.module.ts @@ -2,9 +2,13 @@ import { NgModule } from '@angular/core'; import { CollectionFormComponent } from './collection-form.component'; import { SharedModule } from '../../shared/shared.module'; +import { ComcolModule } from '../../shared/comcol/comcol.module'; +import { FormModule } from '../../shared/form/form.module'; @NgModule({ imports: [ + ComcolModule, + FormModule, SharedModule ], declarations: [ diff --git a/src/app/collection-page/collection-item-mapper/collection-item-mapper.component.spec.ts b/src/app/collection-page/collection-item-mapper/collection-item-mapper.component.spec.ts index 0dfd013449..e8d8d3eb11 100644 --- a/src/app/collection-page/collection-item-mapper/collection-item-mapper.component.spec.ts +++ b/src/app/collection-page/collection-item-mapper/collection-item-mapper.component.spec.ts @@ -33,7 +33,7 @@ import { ErrorComponent } from '../../shared/error/error.component'; import { LoadingComponent } from '../../shared/loading/loading.component'; import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service'; import { SearchService } from '../../core/shared/search/search.service'; -import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; +import { PaginatedSearchOptions } from '../../shared/search/models/paginated-search-options.model'; import { createFailedRemoteDataObject$, createSuccessfulRemoteDataObject, diff --git a/src/app/collection-page/collection-item-mapper/collection-item-mapper.component.ts b/src/app/collection-page/collection-item-mapper/collection-item-mapper.component.ts index 9a93457436..3172616efc 100644 --- a/src/app/collection-page/collection-item-mapper/collection-item-mapper.component.ts +++ b/src/app/collection-page/collection-item-mapper/collection-item-mapper.component.ts @@ -9,10 +9,11 @@ import { Collection } from '../../core/shared/collection.model'; import { PaginatedList } from '../../core/data/paginated-list.model'; import { map, startWith, switchMap, take } from 'rxjs/operators'; import { - getRemoteDataPayload, - getFirstSucceededRemoteData, - toDSpaceObjectListRD, - getFirstCompletedRemoteData, getAllSucceededRemoteData + getAllSucceededRemoteData, + getFirstCompletedRemoteData, + getFirstSucceededRemoteData, + getRemoteDataPayload, + toDSpaceObjectListRD } from '../../core/shared/operators'; import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { DSpaceObjectType } from '../../core/shared/dspace-object-type.model'; @@ -24,7 +25,7 @@ import { CollectionDataService } from '../../core/data/collection-data.service'; import { isNotEmpty } from '../../shared/empty.util'; import { SEARCH_CONFIG_SERVICE } from '../../my-dspace-page/my-dspace-page.component'; import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service'; -import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; +import { PaginatedSearchOptions } from '../../shared/search/models/paginated-search-options.model'; import { SearchService } from '../../core/shared/search/search.service'; import { followLink } from '../../shared/utils/follow-link-config.model'; import { NoContent } from '../../core/shared/NoContent.model'; diff --git a/src/app/collection-page/collection-page.component.ts b/src/app/collection-page/collection-page.component.ts index 62d072c249..be602f8458 100644 --- a/src/app/collection-page/collection-page.component.ts +++ b/src/app/collection-page/collection-page.component.ts @@ -1,13 +1,8 @@ import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; -import { - BehaviorSubject, - combineLatest as observableCombineLatest, - Observable, - Subject -} from 'rxjs'; +import { BehaviorSubject, combineLatest as observableCombineLatest, Observable, Subject } from 'rxjs'; import { filter, map, mergeMap, startWith, switchMap, take } from 'rxjs/operators'; -import { PaginatedSearchOptions } from '../shared/search/paginated-search-options.model'; +import { PaginatedSearchOptions } from '../shared/search/models/paginated-search-options.model'; import { SearchService } from '../core/shared/search/search.service'; import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model'; import { CollectionDataService } from '../core/data/collection-data.service'; diff --git a/src/app/collection-page/collection-page.module.ts b/src/app/collection-page/collection-page.module.ts index a13731ed23..3652823200 100644 --- a/src/app/collection-page/collection-page.module.ts +++ b/src/app/collection-page/collection-page.module.ts @@ -14,6 +14,7 @@ import { SearchService } from '../core/shared/search/search.service'; import { StatisticsModule } from '../statistics/statistics.module'; import { CollectionFormModule } from './collection-form/collection-form.module'; import { ThemedCollectionPageComponent } from './themed-collection-page.component'; +import { ComcolModule } from '../shared/comcol/comcol.module'; @NgModule({ imports: [ @@ -22,7 +23,8 @@ import { ThemedCollectionPageComponent } from './themed-collection-page.componen CollectionPageRoutingModule, StatisticsModule.forRoot(), EditItemPageModule, - CollectionFormModule + CollectionFormModule, + ComcolModule ], declarations: [ CollectionPageComponent, diff --git a/src/app/collection-page/create-collection-page/create-collection-page.component.ts b/src/app/collection-page/create-collection-page/create-collection-page.component.ts index a38739c407..a938b37ce1 100644 --- a/src/app/collection-page/create-collection-page/create-collection-page.component.ts +++ b/src/app/collection-page/create-collection-page/create-collection-page.component.ts @@ -2,12 +2,12 @@ import { Component } from '@angular/core'; import { CommunityDataService } from '../../core/data/community-data.service'; import { RouteService } from '../../core/services/route.service'; import { Router } from '@angular/router'; -import { CreateComColPageComponent } from '../../shared/comcol-forms/create-comcol-page/create-comcol-page.component'; +import { CreateComColPageComponent } from '../../shared/comcol/comcol-forms/create-comcol-page/create-comcol-page.component'; import { Collection } from '../../core/shared/collection.model'; import { CollectionDataService } from '../../core/data/collection-data.service'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; -import {RequestService} from '../../core/data/request.service'; +import { RequestService } from '../../core/data/request.service'; /** * Component that represents the page where a user can create a new Collection diff --git a/src/app/collection-page/delete-collection-page/delete-collection-page.component.ts b/src/app/collection-page/delete-collection-page/delete-collection-page.component.ts index 8daba0abfc..3e30373070 100644 --- a/src/app/collection-page/delete-collection-page/delete-collection-page.component.ts +++ b/src/app/collection-page/delete-collection-page/delete-collection-page.component.ts @@ -1,11 +1,11 @@ import { Component } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; -import { DeleteComColPageComponent } from '../../shared/comcol-forms/delete-comcol-page/delete-comcol-page.component'; +import { DeleteComColPageComponent } from '../../shared/comcol/comcol-forms/delete-comcol-page/delete-comcol-page.component'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { CollectionDataService } from '../../core/data/collection-data.service'; import { Collection } from '../../core/shared/collection.model'; import { TranslateService } from '@ngx-translate/core'; -import {RequestService} from '../../core/data/request.service'; +import { RequestService } from '../../core/data/request.service'; /** * Component that represents the page where a user can delete an existing Collection diff --git a/src/app/collection-page/edit-collection-page/collection-metadata/collection-metadata.component.ts b/src/app/collection-page/edit-collection-page/collection-metadata/collection-metadata.component.ts index 8cb10775ac..cfaad3767e 100644 --- a/src/app/collection-page/edit-collection-page/collection-metadata/collection-metadata.component.ts +++ b/src/app/collection-page/edit-collection-page/collection-metadata/collection-metadata.component.ts @@ -1,5 +1,5 @@ import { Component } from '@angular/core'; -import { ComcolMetadataComponent } from '../../../shared/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component'; +import { ComcolMetadataComponent } from '../../../shared/comcol/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component'; import { Collection } from '../../../core/shared/collection.model'; import { CollectionDataService } from '../../../core/data/collection-data.service'; import { ActivatedRoute, Router } from '@angular/router'; diff --git a/src/app/collection-page/edit-collection-page/collection-roles/collection-roles.component.spec.ts b/src/app/collection-page/edit-collection-page/collection-roles/collection-roles.component.spec.ts index 401065a661..985290a592 100644 --- a/src/app/collection-page/edit-collection-page/collection-roles/collection-roles.component.spec.ts +++ b/src/app/collection-page/edit-collection-page/collection-roles/collection-roles.component.spec.ts @@ -12,6 +12,7 @@ import { RequestService } from '../../../core/data/request.service'; import { RouterTestingModule } from '@angular/router/testing'; import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { ComcolModule } from '../../../shared/comcol/comcol.module'; describe('CollectionRolesComponent', () => { @@ -65,6 +66,7 @@ describe('CollectionRolesComponent', () => { TestBed.configureTestingModule({ imports: [ + ComcolModule, SharedModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), diff --git a/src/app/collection-page/edit-collection-page/edit-collection-page.component.ts b/src/app/collection-page/edit-collection-page/edit-collection-page.component.ts index aff1995a14..62fbb3ee3d 100644 --- a/src/app/collection-page/edit-collection-page/edit-collection-page.component.ts +++ b/src/app/collection-page/edit-collection-page/edit-collection-page.component.ts @@ -1,6 +1,6 @@ import { Component } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; -import { EditComColPageComponent } from '../../shared/comcol-forms/edit-comcol-page/edit-comcol-page.component'; +import { EditComColPageComponent } from '../../shared/comcol/comcol-forms/edit-comcol-page/edit-comcol-page.component'; import { Collection } from '../../core/shared/collection.model'; import { getCollectionPageRoute } from '../collection-page-routing-paths'; @@ -9,7 +9,7 @@ import { getCollectionPageRoute } from '../collection-page-routing-paths'; */ @Component({ selector: 'ds-edit-collection', - templateUrl: '../../shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.html' + templateUrl: '../../shared/comcol/comcol-forms/edit-comcol-page/edit-comcol-page.component.html' }) export class EditCollectionPageComponent extends EditComColPageComponent { type = 'collection'; diff --git a/src/app/collection-page/edit-collection-page/edit-collection-page.module.ts b/src/app/collection-page/edit-collection-page/edit-collection-page.module.ts index 0b09542fa0..45612be41a 100644 --- a/src/app/collection-page/edit-collection-page/edit-collection-page.module.ts +++ b/src/app/collection-page/edit-collection-page/edit-collection-page.module.ts @@ -10,6 +10,9 @@ import { CollectionSourceComponent } from './collection-source/collection-source import { CollectionAuthorizationsComponent } from './collection-authorizations/collection-authorizations.component'; import { CollectionFormModule } from '../collection-form/collection-form.module'; import { CollectionSourceControlsComponent } from './collection-source/collection-source-controls/collection-source-controls.component'; +import { ResourcePoliciesModule } from '../../shared/resource-policies/resource-policies.module'; +import { FormModule } from '../../shared/form/form.module'; +import { ComcolModule } from '../../shared/comcol/comcol.module'; /** * Module that contains all components related to the Edit Collection page administrator functionality @@ -19,7 +22,10 @@ import { CollectionSourceControlsComponent } from './collection-source/collectio CommonModule, SharedModule, EditCollectionPageRoutingModule, - CollectionFormModule + CollectionFormModule, + ResourcePoliciesModule, + FormModule, + ComcolModule ], declarations: [ EditCollectionPageComponent, diff --git a/src/app/community-page/community-form/community-form.component.ts b/src/app/community-page/community-form/community-form.component.ts index 59480e8f68..a3730fd418 100644 --- a/src/app/community-page/community-form/community-form.component.ts +++ b/src/app/community-page/community-form/community-form.component.ts @@ -6,7 +6,7 @@ import { DynamicTextAreaModel } from '@ng-dynamic-forms/core'; import { Community } from '../../core/shared/community.model'; -import { ComColFormComponent } from '../../shared/comcol-forms/comcol-form/comcol-form.component'; +import { ComColFormComponent } from '../../shared/comcol/comcol-forms/comcol-form/comcol-form.component'; import { TranslateService } from '@ngx-translate/core'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { CommunityDataService } from '../../core/data/community-data.service'; @@ -19,8 +19,8 @@ import { ObjectCacheService } from '../../core/cache/object-cache.service'; */ @Component({ selector: 'ds-community-form', - styleUrls: ['../../shared/comcol-forms/comcol-form/comcol-form.component.scss'], - templateUrl: '../../shared/comcol-forms/comcol-form/comcol-form.component.html' + styleUrls: ['../../shared/comcol/comcol-forms/comcol-form/comcol-form.component.scss'], + templateUrl: '../../shared/comcol/comcol-forms/comcol-form/comcol-form.component.html' }) export class CommunityFormComponent extends ComColFormComponent { /** diff --git a/src/app/community-page/community-form/community-form.module.ts b/src/app/community-page/community-form/community-form.module.ts index 36dbea5c0d..925d218973 100644 --- a/src/app/community-page/community-form/community-form.module.ts +++ b/src/app/community-page/community-form/community-form.module.ts @@ -2,9 +2,13 @@ import { NgModule } from '@angular/core'; import { CommunityFormComponent } from './community-form.component'; import { SharedModule } from '../../shared/shared.module'; +import { ComcolModule } from '../../shared/comcol/comcol.module'; +import { FormModule } from '../../shared/form/form.module'; @NgModule({ imports: [ + ComcolModule, + FormModule, SharedModule ], declarations: [ diff --git a/src/app/community-page/community-page.module.ts b/src/app/community-page/community-page.module.ts index 3ae75f166c..724b762e90 100644 --- a/src/app/community-page/community-page.module.ts +++ b/src/app/community-page/community-page.module.ts @@ -12,6 +12,7 @@ import { DeleteCommunityPageComponent } from './delete-community-page/delete-com import { StatisticsModule } from '../statistics/statistics.module'; import { CommunityFormModule } from './community-form/community-form.module'; import { ThemedCommunityPageComponent } from './themed-community-page.component'; +import { ComcolModule } from '../shared/comcol/comcol.module'; const DECLARATIONS = [CommunityPageComponent, ThemedCommunityPageComponent, @@ -26,7 +27,8 @@ const DECLARATIONS = [CommunityPageComponent, SharedModule, CommunityPageRoutingModule, StatisticsModule.forRoot(), - CommunityFormModule + CommunityFormModule, + ComcolModule ], declarations: [ ...DECLARATIONS diff --git a/src/app/community-page/create-community-page/create-community-page.component.ts b/src/app/community-page/create-community-page/create-community-page.component.ts index be3385b92f..b332fad100 100644 --- a/src/app/community-page/create-community-page/create-community-page.component.ts +++ b/src/app/community-page/create-community-page/create-community-page.component.ts @@ -3,7 +3,7 @@ import { Community } from '../../core/shared/community.model'; import { CommunityDataService } from '../../core/data/community-data.service'; import { RouteService } from '../../core/services/route.service'; import { Router } from '@angular/router'; -import { CreateComColPageComponent } from '../../shared/comcol-forms/create-comcol-page/create-comcol-page.component'; +import { CreateComColPageComponent } from '../../shared/comcol/comcol-forms/create-comcol-page/create-comcol-page.component'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; import { RequestService } from '../../core/data/request.service'; diff --git a/src/app/community-page/delete-community-page/delete-community-page.component.ts b/src/app/community-page/delete-community-page/delete-community-page.component.ts index ec51076bbc..0cccc503e1 100644 --- a/src/app/community-page/delete-community-page/delete-community-page.component.ts +++ b/src/app/community-page/delete-community-page/delete-community-page.component.ts @@ -2,10 +2,10 @@ import { Component } from '@angular/core'; import { Community } from '../../core/shared/community.model'; import { CommunityDataService } from '../../core/data/community-data.service'; import { ActivatedRoute, Router } from '@angular/router'; -import { DeleteComColPageComponent } from '../../shared/comcol-forms/delete-comcol-page/delete-comcol-page.component'; +import { DeleteComColPageComponent } from '../../shared/comcol/comcol-forms/delete-comcol-page/delete-comcol-page.component'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; -import {RequestService} from '../../core/data/request.service'; +import { RequestService } from '../../core/data/request.service'; /** * Component that represents the page where a user can delete an existing Community diff --git a/src/app/community-page/edit-community-page/community-metadata/community-metadata.component.ts b/src/app/community-page/edit-community-page/community-metadata/community-metadata.component.ts index c4bb88289f..a2dbfa6eb6 100644 --- a/src/app/community-page/edit-community-page/community-metadata/community-metadata.component.ts +++ b/src/app/community-page/edit-community-page/community-metadata/community-metadata.component.ts @@ -1,5 +1,5 @@ import { Component } from '@angular/core'; -import { ComcolMetadataComponent } from '../../../shared/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component'; +import { ComcolMetadataComponent } from '../../../shared/comcol/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component'; import { ActivatedRoute, Router } from '@angular/router'; import { Community } from '../../../core/shared/community.model'; import { CommunityDataService } from '../../../core/data/community-data.service'; diff --git a/src/app/community-page/edit-community-page/community-roles/community-roles.component.spec.ts b/src/app/community-page/edit-community-page/community-roles/community-roles.component.spec.ts index b61705126c..d1188df02d 100644 --- a/src/app/community-page/edit-community-page/community-roles/community-roles.component.spec.ts +++ b/src/app/community-page/edit-community-page/community-roles/community-roles.component.spec.ts @@ -12,6 +12,7 @@ import { SharedModule } from '../../../shared/shared.module'; import { RouterTestingModule } from '@angular/router/testing'; import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { ComcolModule } from '../../../shared/comcol/comcol.module'; describe('CommunityRolesComponent', () => { @@ -50,6 +51,7 @@ describe('CommunityRolesComponent', () => { TestBed.configureTestingModule({ imports: [ + ComcolModule, SharedModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), diff --git a/src/app/community-page/edit-community-page/edit-community-page.component.ts b/src/app/community-page/edit-community-page/edit-community-page.component.ts index 836384ab84..54a6ee4944 100644 --- a/src/app/community-page/edit-community-page/edit-community-page.component.ts +++ b/src/app/community-page/edit-community-page/edit-community-page.component.ts @@ -1,7 +1,7 @@ import { Component } from '@angular/core'; import { Community } from '../../core/shared/community.model'; import { ActivatedRoute, Router } from '@angular/router'; -import { EditComColPageComponent } from '../../shared/comcol-forms/edit-comcol-page/edit-comcol-page.component'; +import { EditComColPageComponent } from '../../shared/comcol/comcol-forms/edit-comcol-page/edit-comcol-page.component'; import { getCommunityPageRoute } from '../community-page-routing-paths'; /** @@ -9,7 +9,7 @@ import { getCommunityPageRoute } from '../community-page-routing-paths'; */ @Component({ selector: 'ds-edit-community', - templateUrl: '../../shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.html' + templateUrl: '../../shared/comcol/comcol-forms/edit-comcol-page/edit-comcol-page.component.html' }) export class EditCommunityPageComponent extends EditComColPageComponent { type = 'community'; diff --git a/src/app/community-page/edit-community-page/edit-community-page.module.ts b/src/app/community-page/edit-community-page/edit-community-page.module.ts index 3f7511f700..2b0fc73f2a 100644 --- a/src/app/community-page/edit-community-page/edit-community-page.module.ts +++ b/src/app/community-page/edit-community-page/edit-community-page.module.ts @@ -8,6 +8,8 @@ import { CommunityMetadataComponent } from './community-metadata/community-metad import { CommunityRolesComponent } from './community-roles/community-roles.component'; import { CommunityAuthorizationsComponent } from './community-authorizations/community-authorizations.component'; import { CommunityFormModule } from '../community-form/community-form.module'; +import { ResourcePoliciesModule } from '../../shared/resource-policies/resource-policies.module'; +import { ComcolModule } from '../../shared/comcol/comcol.module'; /** * Module that contains all components related to the Edit Community page administrator functionality @@ -17,7 +19,9 @@ import { CommunityFormModule } from '../community-form/community-form.module'; CommonModule, SharedModule, EditCommunityPageRoutingModule, - CommunityFormModule + CommunityFormModule, + ComcolModule, + ResourcePoliciesModule ], declarations: [ EditCommunityPageComponent, diff --git a/src/app/core/data/bundle-data.service.ts b/src/app/core/data/bundle-data.service.ts index bff21d2c8d..3c885c0afd 100644 --- a/src/app/core/data/bundle-data.service.ts +++ b/src/app/core/data/bundle-data.service.ts @@ -20,7 +20,7 @@ import { PaginatedList } from './paginated-list.model'; import { RemoteData } from './remote-data'; import { FindListOptions, GetRequest } from './request.models'; import { RequestService } from './request.service'; -import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; +import { PaginatedSearchOptions } from '../../shared/search/models/paginated-search-options.model'; import { Bitstream } from '../shared/bitstream.model'; import { RequestEntryState } from './request.reducer'; diff --git a/src/app/core/data/external-source.service.ts b/src/app/core/data/external-source.service.ts index a3a0a532ec..d2fc9e6d96 100644 --- a/src/app/core/data/external-source.service.ts +++ b/src/app/core/data/external-source.service.ts @@ -12,7 +12,7 @@ import { HttpClient } from '@angular/common/http'; import { FindListOptions } from './request.models'; import { Observable } from 'rxjs'; import { distinctUntilChanged, map, switchMap, take } from 'rxjs/operators'; -import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; +import { PaginatedSearchOptions } from '../../shared/search/models/paginated-search-options.model'; import { hasValue, isNotEmptyOperator } from '../../shared/empty.util'; import { RemoteData } from './remote-data'; import { PaginatedList } from './paginated-list.model'; diff --git a/src/app/core/data/facet-config-response-parsing.service.ts b/src/app/core/data/facet-config-response-parsing.service.ts index fc543c9072..8c24bd61d9 100644 --- a/src/app/core/data/facet-config-response-parsing.service.ts +++ b/src/app/core/data/facet-config-response-parsing.service.ts @@ -1,11 +1,11 @@ import { Injectable } from '@angular/core'; -import { SearchFilterConfig } from '../../shared/search/search-filter-config.model'; +import { SearchFilterConfig } from '../../shared/search/models/search-filter-config.model'; import { ParsedResponse } from '../cache/response.models'; import { RawRestResponse } from '../dspace-rest/raw-rest-response.model'; import { DSpaceSerializer } from '../dspace-rest/dspace.serializer'; import { RestRequest } from './request.models'; import { DspaceRestResponseParsingService } from './dspace-rest-response-parsing.service'; -import { FacetConfigResponse } from '../../shared/search/facet-config-response.model'; +import { FacetConfigResponse } from '../../shared/search/models/facet-config-response.model'; @Injectable() export class FacetConfigResponseParsingService extends DspaceRestResponseParsingService { diff --git a/src/app/core/data/facet-value-response-parsing.service.ts b/src/app/core/data/facet-value-response-parsing.service.ts index 6b9e832685..12a2d4ba8c 100644 --- a/src/app/core/data/facet-value-response-parsing.service.ts +++ b/src/app/core/data/facet-value-response-parsing.service.ts @@ -1,10 +1,10 @@ import { Injectable } from '@angular/core'; -import { FacetValue } from '../../shared/search/facet-value.model'; +import { FacetValue } from '../../shared/search/models/facet-value.model'; import { ParsedResponse } from '../cache/response.models'; import { RawRestResponse } from '../dspace-rest/raw-rest-response.model'; import { DSpaceSerializer } from '../dspace-rest/dspace.serializer'; import { RestRequest } from './request.models'; -import { FacetValues } from '../../shared/search/facet-values.model'; +import { FacetValues } from '../../shared/search/models/facet-values.model'; import { DspaceRestResponseParsingService } from './dspace-rest-response-parsing.service'; @Injectable() diff --git a/src/app/core/data/item-data.service.ts b/src/app/core/data/item-data.service.ts index c31b6b3c97..a8d380124e 100644 --- a/src/app/core/data/item-data.service.ts +++ b/src/app/core/data/item-data.service.ts @@ -25,7 +25,7 @@ import { PaginatedList } from './paginated-list.model'; import { RemoteData } from './remote-data'; import { DeleteRequest, FindListOptions, GetRequest, PostRequest, PutRequest, RestRequest } from './request.models'; import { RequestService } from './request.service'; -import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; +import { PaginatedSearchOptions } from '../../shared/search/models/paginated-search-options.model'; import { Bundle } from '../shared/bundle.model'; import { MetadataMap } from '../shared/metadata.models'; import { BundleDataService } from './bundle-data.service'; diff --git a/src/app/core/data/lookup-relation.service.spec.ts b/src/app/core/data/lookup-relation.service.spec.ts index 876336bfa9..c9e523f796 100644 --- a/src/app/core/data/lookup-relation.service.spec.ts +++ b/src/app/core/data/lookup-relation.service.spec.ts @@ -5,9 +5,9 @@ import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.util import { createPaginatedList } from '../../shared/testing/utils.test'; import { buildPaginatedList } from './paginated-list.model'; import { PageInfo } from '../shared/page-info.model'; -import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; +import { PaginatedSearchOptions } from '../../shared/search/models/paginated-search-options.model'; import { RelationshipOptions } from '../../shared/form/builder/models/relationship-options.model'; -import { SearchResult } from '../../shared/search/search-result.model'; +import { SearchResult } from '../../shared/search/models/search-result.model'; import { Item } from '../shared/item.model'; import { skip, take } from 'rxjs/operators'; import { ExternalSource } from '../shared/external-source.model'; diff --git a/src/app/core/data/lookup-relation.service.ts b/src/app/core/data/lookup-relation.service.ts index 7ecf3a19cc..7808a24e92 100644 --- a/src/app/core/data/lookup-relation.service.ts +++ b/src/app/core/data/lookup-relation.service.ts @@ -1,11 +1,11 @@ import { ExternalSourceService } from './external-source.service'; import { SearchService } from '../shared/search/search.service'; import { concat, distinctUntilChanged, map, multicast, startWith, take, takeWhile } from 'rxjs/operators'; -import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; +import { PaginatedSearchOptions } from '../../shared/search/models/paginated-search-options.model'; import { Observable, ReplaySubject } from 'rxjs'; import { RemoteData } from './remote-data'; import { PaginatedList } from './paginated-list.model'; -import { SearchResult } from '../../shared/search/search-result.model'; +import { SearchResult } from '../../shared/search/models/search-result.model'; import { DSpaceObject } from '../shared/dspace-object.model'; import { RelationshipOptions } from '../../shared/form/builder/models/relationship-options.model'; import { Item } from '../shared/item.model'; diff --git a/src/app/core/data/mydspace-response-parsing.service.ts b/src/app/core/data/mydspace-response-parsing.service.ts index f71eaeb811..e111aca9dd 100644 --- a/src/app/core/data/mydspace-response-parsing.service.ts +++ b/src/app/core/data/mydspace-response-parsing.service.ts @@ -4,7 +4,7 @@ import { DSpaceSerializer } from '../dspace-rest/dspace.serializer'; import { RestRequest } from './request.models'; import { RawRestResponse } from '../dspace-rest/raw-rest-response.model'; import { hasValue } from '../../shared/empty.util'; -import { SearchObjects } from '../../shared/search/search-objects.model'; +import { SearchObjects } from '../../shared/search/models/search-objects.model'; import { MetadataMap, MetadataValue } from '../shared/metadata.models'; import { DspaceRestResponseParsingService } from './dspace-rest-response-parsing.service'; diff --git a/src/app/core/data/search-response-parsing.service.ts b/src/app/core/data/search-response-parsing.service.ts index be2fbe90fc..814a2f8d1f 100644 --- a/src/app/core/data/search-response-parsing.service.ts +++ b/src/app/core/data/search-response-parsing.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; import { hasValue } from '../../shared/empty.util'; -import { SearchObjects } from '../../shared/search/search-objects.model'; +import { SearchObjects } from '../../shared/search/models/search-objects.model'; import { ParsedResponse } from '../cache/response.models'; import { RawRestResponse } from '../dspace-rest/raw-rest-response.model'; import { DSpaceSerializer } from '../dspace-rest/dspace.serializer'; diff --git a/src/app/core/data/version-history-data.service.ts b/src/app/core/data/version-history-data.service.ts index 4268516e6b..9aa4f055ff 100644 --- a/src/app/core/data/version-history-data.service.ts +++ b/src/app/core/data/version-history-data.service.ts @@ -12,7 +12,7 @@ import { HttpClient, HttpHeaders } from '@angular/common/http'; import { DefaultChangeAnalyzer } from './default-change-analyzer.service'; import { FindListOptions, PostRequest, RestRequest } from './request.models'; import { Observable, of } from 'rxjs'; -import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; +import { PaginatedSearchOptions } from '../../shared/search/models/paginated-search-options.model'; import { RemoteData } from './remote-data'; import { PaginatedList } from './paginated-list.model'; import { Version } from '../shared/version.model'; diff --git a/src/app/core/shared/operators.ts b/src/app/core/shared/operators.ts index 3be04447ab..ea2a0283eb 100644 --- a/src/app/core/shared/operators.ts +++ b/src/app/core/shared/operators.ts @@ -13,7 +13,7 @@ import { withLatestFrom } from 'rxjs/operators'; import { hasNoValue, hasValue, hasValueOperator, isNotEmpty } from '../../shared/empty.util'; -import { SearchResult } from '../../shared/search/search-result.model'; +import { SearchResult } from '../../shared/search/models/search-result.model'; import { PaginatedList } from '../data/paginated-list.model'; import { RemoteData } from '../data/remote-data'; import { RestRequest } from '../data/request.models'; diff --git a/src/app/core/shared/search/search-configuration.service.spec.ts b/src/app/core/shared/search/search-configuration.service.spec.ts index 805ecd0486..96f9ac5018 100644 --- a/src/app/core/shared/search/search-configuration.service.spec.ts +++ b/src/app/core/shared/search/search-configuration.service.spec.ts @@ -2,8 +2,8 @@ import { SearchConfigurationService } from './search-configuration.service'; import { ActivatedRouteStub } from '../../../shared/testing/active-router.stub'; import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; import { SortDirection, SortOptions } from '../../cache/models/sort-options.model'; -import { PaginatedSearchOptions } from '../../../shared/search/paginated-search-options.model'; -import { SearchFilter } from '../../../shared/search/search-filter.model'; +import { PaginatedSearchOptions } from '../../../shared/search/models/paginated-search-options.model'; +import { SearchFilter } from '../../../shared/search/models/search-filter.model'; import { of as observableOf } from 'rxjs'; import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; diff --git a/src/app/core/shared/search/search-configuration.service.ts b/src/app/core/shared/search/search-configuration.service.ts index 8c37fbc8f5..81df63f6b3 100644 --- a/src/app/core/shared/search/search-configuration.service.ts +++ b/src/app/core/shared/search/search-configuration.service.ts @@ -3,30 +3,25 @@ import { ActivatedRoute, Params } from '@angular/router'; import { BehaviorSubject, - combineLatest, combineLatest as observableCombineLatest, merge as observableMerge, Observable, Subscription } from 'rxjs'; -import { distinctUntilChanged, filter, map, startWith, switchMap, take } from 'rxjs/operators'; +import { filter, map, startWith } from 'rxjs/operators'; import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; -import { SearchOptions } from '../../../shared/search/search-options.model'; -import { PaginatedSearchOptions } from '../../../shared/search/paginated-search-options.model'; -import { SearchFilter } from '../../../shared/search/search-filter.model'; +import { SearchOptions } from '../../../shared/search/models/search-options.model'; +import { PaginatedSearchOptions } from '../../../shared/search/models/paginated-search-options.model'; +import { SearchFilter } from '../../../shared/search/models/search-filter.model'; import { RemoteData } from '../../data/remote-data'; import { DSpaceObjectType } from '../dspace-object-type.model'; import { SortDirection, SortOptions } from '../../cache/models/sort-options.model'; import { RouteService } from '../../services/route.service'; -import { - getAllSucceededRemoteDataPayload, - getFirstSucceededRemoteData -} from '../operators'; +import { getAllSucceededRemoteDataPayload, getFirstSucceededRemoteData } from '../operators'; import { hasNoValue, hasValue, isNotEmpty, isNotEmptyOperator } from '../../../shared/empty.util'; import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; -import { SearchConfig } from './search-filters/search-config.model'; +import { SearchConfig, SortConfig } from './search-filters/search-config.model'; import { SearchService } from './search.service'; -import { of } from 'rxjs'; import { PaginationService } from '../../pagination/pagination.service'; /** @@ -35,7 +30,21 @@ import { PaginationService } from '../../pagination/pagination.service'; @Injectable() export class SearchConfigurationService implements OnDestroy { + /** + * Default pagination id + */ public paginationID = 'spc'; + + /** + * Emits the current search options + */ + public searchOptions: BehaviorSubject; + + /** + * Emits the current search options including pagination and sort + */ + public paginatedSearchOptions: BehaviorSubject; + /** * Default pagination settings */ @@ -45,16 +54,6 @@ export class SearchConfigurationService implements OnDestroy { currentPage: 1 }); - /** - * Default sort settings - */ - protected defaultSort = new SortOptions('score', SortDirection.DESC); - - /** - * Default configuration parameter setting - */ - protected defaultConfiguration; - /** * Default scope setting */ @@ -71,23 +70,14 @@ export class SearchConfigurationService implements OnDestroy { protected _defaults: Observable>; /** - * Emits the current search options + * A map of subscriptions to unsubscribe from on destroy */ - public searchOptions: BehaviorSubject; - - /** - * Emits the current search options including pagination and sort - */ - public paginatedSearchOptions: BehaviorSubject; - - /** - * List of subscriptions to unsubscribe from on destroy - */ - protected subs: Subscription[] = []; + protected subs: Map = new Map(null); /** * Initialize the search options * @param {RouteService} routeService + * @param {PaginationService} paginationService * @param {ActivatedRoute} route */ constructor(protected routeService: RouteService, @@ -98,29 +88,28 @@ export class SearchConfigurationService implements OnDestroy { } /** - * Initialize the search options + * Default values for the Search Options */ - protected initDefaults() { - this.defaults - .pipe(getFirstSucceededRemoteData()) - .subscribe((defRD: RemoteData) => { - const defs = defRD.payload; - this.paginatedSearchOptions = new BehaviorSubject(defs); - this.searchOptions = new BehaviorSubject(defs); - this.subs.push(this.subscribeToSearchOptions(defs)); - this.subs.push(this.subscribeToPaginatedSearchOptions(defs.pagination.id, defs)); - } - ); + get defaults(): Observable> { + if (hasNoValue(this._defaults)) { + const options = new PaginatedSearchOptions({ + pagination: this.defaultPagination, + scope: this.defaultScope, + query: this.defaultQuery + }); + this._defaults = createSuccessfulRemoteDataObject$(options, new Date().getTime()); + } + return this._defaults; } /** * @returns {Observable} Emits the current configuration string */ getCurrentConfiguration(defaultConfiguration: string) { - return observableCombineLatest( + return observableCombineLatest([ this.routeService.getQueryParameterValue('configuration').pipe(startWith(undefined)), this.routeService.getRouteParameterValue('configuration').pipe(startWith(undefined)) - ).pipe( + ]).pipe( map(([queryConfig, routeConfig]) => { return queryConfig || routeConfig || defaultConfiguration; }) @@ -208,59 +197,82 @@ export class SearchConfigurationService implements OnDestroy { } /** - * Creates an observable of SearchConfig every time the configuration$ stream emits. - * @param configuration$ - * @param service + * Creates an observable of SearchConfig every time the configuration stream emits. + * @param configuration The search configuration + * @param service The search service to use + * @param scope The search scope if exists */ - getConfigurationSearchConfigObservable(configuration$: Observable, service: SearchService): Observable { - return configuration$.pipe( - distinctUntilChanged(), - switchMap((configuration) => service.getSearchConfigurationFor(null, configuration)), - getAllSucceededRemoteDataPayload()); + getConfigurationSearchConfig(configuration: string, service: SearchService, scope?: string): Observable { + return service.getSearchConfigurationFor(scope, configuration).pipe( + getAllSucceededRemoteDataPayload() + ); } /** - * Every time searchConfig change (after a configuration change) it update the navigation with the default sort option - * and emit the new paginateSearchOptions value. - * @param configuration$ - * @param service + * Return the SortOptions list available for the given SearchConfig + * @param searchConfig The SearchConfig object */ - initializeSortOptionsFromConfiguration(searchConfig$: Observable) { - const subscription = searchConfig$.pipe(switchMap((searchConfig) => combineLatest([ - of(searchConfig), - this.paginatedSearchOptions.pipe(take(1)) - ]))).subscribe(([searchConfig, searchOptions]) => { - const field = searchConfig.sortOptions[0].name; - const direction = searchConfig.sortOptions[0].sortOrder.toLowerCase() === SortDirection.ASC.toLowerCase() ? SortDirection.ASC : SortDirection.DESC; - const updateValue = Object.assign(new PaginatedSearchOptions({}), searchOptions, { - sort: new SortOptions(field, direction) - }); - this.paginationService.updateRoute(this.paginationID, - { - sortDirection: updateValue.sort.direction, - sortField: updateValue.sort.field, - }); - this.paginatedSearchOptions.next(updateValue); - }); - this.subs.push(subscription); - } - - /** - * Creates an observable of available SortOptions[] every time the searchConfig$ stream emits. - * @param searchConfig$ - * @param service - */ - getConfigurationSortOptionsObservable(searchConfig$: Observable): Observable { - return searchConfig$.pipe(map((searchConfig) => { - const sortOptions = []; - searchConfig.sortOptions.forEach(sortOption => { - sortOptions.push(new SortOptions(sortOption.name, SortDirection.ASC)); - sortOptions.push(new SortOptions(sortOption.name, SortDirection.DESC)); - }); - return sortOptions; + getConfigurationSortOptions(searchConfig: SearchConfig): SortOptions[] { + return searchConfig.sortOptions.map((entry: SortConfig) => ({ + field: entry.name, + direction: entry.sortOrder.toLowerCase() === SortDirection.ASC.toLowerCase() ? SortDirection.ASC : SortDirection.DESC })); } + setPaginationId(paginationId): void { + if (isNotEmpty(paginationId)) { + const currentValue: PaginatedSearchOptions = this.paginatedSearchOptions.getValue(); + const updatedValue: PaginatedSearchOptions = Object.assign(new PaginatedSearchOptions({}), currentValue, { + pagination: Object.assign({}, currentValue.pagination, { + id: paginationId + }) + }); + // unsubscribe from subscription related to old pagination id + this.unsubscribeFromSearchOptions(this.paginationID); + + // change to the new pagination id + this.paginationID = paginationId; + this.paginatedSearchOptions.next(updatedValue); + this.setSearchSubscription(this.paginationID, this.paginatedSearchOptions.value); + } + } + + /** + * Make sure to unsubscribe from all existing subscription to prevent memory leaks + */ + ngOnDestroy(): void { + this.subs + .forEach((subs: Subscription[]) => subs + .filter((sub) => hasValue(sub)) + .forEach((sub) => sub.unsubscribe()) + ); + + this.subs = new Map(null); + } + + /** + * Initialize the search options + */ + protected initDefaults() { + this.defaults + .pipe(getFirstSucceededRemoteData()) + .subscribe((defRD: RemoteData) => { + const defs = defRD.payload; + this.paginatedSearchOptions = new BehaviorSubject(defs); + this.searchOptions = new BehaviorSubject(defs); + this.setSearchSubscription(this.paginationID, defs); + }); + } + + private setSearchSubscription(paginationID: string, defaults: PaginatedSearchOptions) { + this.unsubscribeFromSearchOptions(paginationID); + const subs = [ + this.subscribeToSearchOptions(defaults), + this.subscribeToPaginatedSearchOptions(paginationID || defaults.pagination.id, defaults) + ]; + this.subs.set(this.paginationID, subs); + } + /** * Sets up a subscription to all necessary parameters to make sure the searchOptions emits a new value every time they update * @param {SearchOptions} defaults Default values for when no parameters are available @@ -283,14 +295,15 @@ export class SearchConfigurationService implements OnDestroy { /** * Sets up a subscription to all necessary parameters to make sure the paginatedSearchOptions emits a new value every time they update + * @param {string} paginationId The pagination ID * @param {PaginatedSearchOptions} defaults Default values for when no parameters are available * @returns {Subscription} The subscription to unsubscribe from */ private subscribeToPaginatedSearchOptions(paginationId: string, defaults: PaginatedSearchOptions): Subscription { return observableMerge( + this.getConfigurationPart(defaults.configuration), this.getPaginationPart(paginationId, defaults.pagination), this.getSortPart(paginationId, defaults.sort), - this.getConfigurationPart(defaults.configuration), this.getScopePart(defaults.scope), this.getQueryPart(defaults.query), this.getDSOTypePart(), @@ -304,30 +317,16 @@ export class SearchConfigurationService implements OnDestroy { } /** - * Default values for the Search Options + * Unsubscribe from all subscriptions related to the given paginationID + * @param paginationId The pagination id */ - get defaults(): Observable> { - if (hasNoValue(this._defaults)) { - const options = new PaginatedSearchOptions({ - pagination: this.defaultPagination, - configuration: this.defaultConfiguration, - sort: this.defaultSort, - scope: this.defaultScope, - query: this.defaultQuery - }); - this._defaults = createSuccessfulRemoteDataObject$(options, new Date().getTime()); + private unsubscribeFromSearchOptions(paginationId: string): void { + if (this.subs.has(this.paginationID)) { + this.subs.get(this.paginationID) + .filter((sub) => hasValue(sub)) + .forEach((sub) => sub.unsubscribe()); + this.subs.delete(paginationId); } - return this._defaults; - } - - /** - * Make sure to unsubscribe from all existing subscription to prevent memory leaks - */ - ngOnDestroy(): void { - this.subs.forEach((sub) => { - sub.unsubscribe(); - }); - this.subs = []; } /** diff --git a/src/app/core/shared/search/search-filter.service.spec.ts b/src/app/core/shared/search/search-filter.service.spec.ts index 045b2b17c9..a42bf8e5f6 100644 --- a/src/app/core/shared/search/search-filter.service.spec.ts +++ b/src/app/core/shared/search/search-filter.service.spec.ts @@ -10,8 +10,8 @@ import { SearchFilterToggleAction } from '../../../shared/search/search-filters/search-filter/search-filter.actions'; import { SearchFiltersState } from '../../../shared/search/search-filters/search-filter/search-filter.reducer'; -import { SearchFilterConfig } from '../../../shared/search/search-filter-config.model'; -import { FilterType } from '../../../shared/search/filter-type.model'; +import { SearchFilterConfig } from '../../../shared/search/models/search-filter-config.model'; +import { FilterType } from '../../../shared/search/models/filter-type.model'; import { ActivatedRouteStub } from '../../../shared/testing/active-router.stub'; import { of as observableOf } from 'rxjs'; import { SortDirection, SortOptions } from '../../cache/models/sort-options.model'; diff --git a/src/app/core/shared/search/search-filter.service.ts b/src/app/core/shared/search/search-filter.service.ts index 84d7268abb..00125e31f5 100644 --- a/src/app/core/shared/search/search-filter.service.ts +++ b/src/app/core/shared/search/search-filter.service.ts @@ -16,7 +16,7 @@ import { SearchFilterToggleAction } from '../../../shared/search/search-filters/search-filter/search-filter.actions'; import { hasValue, isNotEmpty, } from '../../../shared/empty.util'; -import { SearchFilterConfig } from '../../../shared/search/search-filter-config.model'; +import { SearchFilterConfig } from '../../../shared/search/models/search-filter-config.model'; import { SortDirection, SortOptions } from '../../cache/models/sort-options.model'; import { RouteService } from '../../services/route.service'; import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; diff --git a/src/app/core/shared/search/search-filters/search-config.model.ts b/src/app/core/shared/search/search-filters/search-config.model.ts index 725761fe7b..e789de0f80 100644 --- a/src/app/core/shared/search/search-filters/search-config.model.ts +++ b/src/app/core/shared/search/search-filters/search-config.model.ts @@ -29,7 +29,7 @@ export class SearchConfig implements CacheableObject { * The configured sort options. */ @autoserialize - sortOptions: SortOption[]; + sortOptions: SortConfig[]; /** * The object type. @@ -63,7 +63,7 @@ export interface FilterConfig { /** * Interface to model sort option's configuration. */ -export interface SortOption { +export interface SortConfig { name: string; sortOrder: string; } diff --git a/src/app/core/shared/search/search.service.spec.ts b/src/app/core/shared/search/search.service.spec.ts index 00f10230c3..f9b768655e 100644 --- a/src/app/core/shared/search/search.service.spec.ts +++ b/src/app/core/shared/search/search.service.spec.ts @@ -9,7 +9,7 @@ import { ActivatedRouteStub } from '../../../shared/testing/active-router.stub'; import { RouterStub } from '../../../shared/testing/router.stub'; import { HALEndpointService } from '../hal-endpoint.service'; import { combineLatest as observableCombineLatest, Observable, of as observableOf } from 'rxjs'; -import { PaginatedSearchOptions } from '../../../shared/search/paginated-search-options.model'; +import { PaginatedSearchOptions } from '../../../shared/search/models/paginated-search-options.model'; import { RemoteData } from '../../data/remote-data'; import { RequestEntry } from '../../data/request.reducer'; import { getMockRequestService } from '../../../shared/mocks/request.service.mock'; @@ -21,11 +21,8 @@ import { RouteService } from '../../services/route.service'; import { routeServiceStub } from '../../../shared/testing/route-service.stub'; import { RemoteDataBuildService } from '../../cache/builders/remote-data-build.service'; import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; -import { SearchObjects } from '../../../shared/search/search-objects.model'; +import { SearchObjects } from '../../../shared/search/models/search-objects.model'; import { PaginationService } from '../../pagination/pagination.service'; -import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; -import { SortDirection, SortOptions } from '../../cache/models/sort-options.model'; -import { FindListOptions } from '../../data/request.models'; import { SearchConfigurationService } from './search-configuration.service'; import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; diff --git a/src/app/core/shared/search/search.service.ts b/src/app/core/shared/search/search.service.ts index 91916a35ac..f70416594d 100644 --- a/src/app/core/shared/search/search.service.ts +++ b/src/app/core/shared/search/search.service.ts @@ -14,24 +14,24 @@ import { GenericConstructor } from '../generic-constructor'; import { HALEndpointService } from '../hal-endpoint.service'; import { URLCombiner } from '../../url-combiner/url-combiner'; import { hasValue, hasValueOperator, isNotEmpty } from '../../../shared/empty.util'; -import { SearchOptions } from '../../../shared/search/search-options.model'; -import { SearchFilterConfig } from '../../../shared/search/search-filter-config.model'; +import { SearchOptions } from '../../../shared/search/models/search-options.model'; +import { SearchFilterConfig } from '../../../shared/search/models/search-filter-config.model'; import { SearchResponseParsingService } from '../../data/search-response-parsing.service'; -import { SearchObjects } from '../../../shared/search/search-objects.model'; +import { SearchObjects } from '../../../shared/search/models/search-objects.model'; import { FacetValueResponseParsingService } from '../../data/facet-value-response-parsing.service'; import { FacetConfigResponseParsingService } from '../../data/facet-config-response-parsing.service'; -import { PaginatedSearchOptions } from '../../../shared/search/paginated-search-options.model'; +import { PaginatedSearchOptions } from '../../../shared/search/models/paginated-search-options.model'; import { CommunityDataService } from '../../data/community-data.service'; import { ViewMode } from '../view-mode.model'; import { DSpaceObjectDataService } from '../../data/dspace-object-data.service'; import { RemoteDataBuildService } from '../../cache/builders/remote-data-build.service'; import { getFirstCompletedRemoteData, getRemoteDataPayload } from '../operators'; import { RouteService } from '../../services/route.service'; -import { SearchResult } from '../../../shared/search/search-result.model'; +import { SearchResult } from '../../../shared/search/models/search-result.model'; import { ListableObject } from '../../../shared/object-collection/shared/listable-object.model'; import { getSearchResultFor } from '../../../shared/search/search-result-element-decorator'; -import { FacetConfigResponse } from '../../../shared/search/facet-config-response.model'; -import { FacetValues } from '../../../shared/search/facet-values.model'; +import { FacetConfigResponse } from '../../../shared/search/models/facet-config-response.model'; +import { FacetValues } from '../../../shared/search/models/facet-values.model'; import { SearchConfig } from './search-filters/search-config.model'; import { PaginationService } from '../../pagination/pagination.service'; import { SearchConfigurationService } from './search-configuration.service'; @@ -407,6 +407,7 @@ export class SearchService implements OnDestroy { /** * Changes the current view mode in the current URL * @param {ViewMode} viewMode Mode to switch to + * @param {string[]} searchLinkParts */ setViewMode(viewMode: ViewMode, searchLinkParts?: string[]) { this.paginationService.getCurrentPagination(this.searchConfigurationService.paginationID, new PaginationComponentOptions()).pipe(take(1)) diff --git a/src/app/core/shared/view-mode.model.ts b/src/app/core/shared/view-mode.model.ts index c2f076a5e5..a27cb6954b 100644 --- a/src/app/core/shared/view-mode.model.ts +++ b/src/app/core/shared/view-mode.model.ts @@ -3,8 +3,8 @@ */ export enum ViewMode { - ListElement = 'listElement', - GridElement = 'gridElement', - DetailedListElement = 'detailedListElement', - StandalonePage = 'standalonePage', + ListElement = 'list', + GridElement = 'grid', + DetailedListElement = 'detailed', + StandalonePage = 'standalone', } diff --git a/src/app/entity-groups/journal-entities/journal-entities.module.ts b/src/app/entity-groups/journal-entities/journal-entities.module.ts index dc88490eac..3bf861e10d 100644 --- a/src/app/entity-groups/journal-entities/journal-entities.module.ts +++ b/src/app/entity-groups/journal-entities/journal-entities.module.ts @@ -19,6 +19,7 @@ import { JournalVolumeSearchResultGridElementComponent } from './item-grid-eleme import { JournalVolumeSidebarSearchListElementComponent } from './item-list-elements/sidebar-search-list-elements/journal-volume/journal-volume-sidebar-search-list-element.component'; import { JournalIssueSidebarSearchListElementComponent } from './item-list-elements/sidebar-search-list-elements/journal-issue/journal-issue-sidebar-search-list-element.component'; import { JournalSidebarSearchListElementComponent } from './item-list-elements/sidebar-search-list-elements/journal/journal-sidebar-search-list-element.component'; +import { ItemSharedModule } from '../../item-page/item-shared.module'; const ENTRY_COMPONENTS = [ // put only entry components that use custom decorator @@ -45,6 +46,7 @@ const ENTRY_COMPONENTS = [ @NgModule({ imports: [ CommonModule, + ItemSharedModule, SharedModule ], declarations: [ diff --git a/src/app/entity-groups/research-entities/research-entities.module.ts b/src/app/entity-groups/research-entities/research-entities.module.ts index c9d6c2d5b6..721a22be08 100644 --- a/src/app/entity-groups/research-entities/research-entities.module.ts +++ b/src/app/entity-groups/research-entities/research-entities.module.ts @@ -1,5 +1,6 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; +import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'; import { SharedModule } from '../../shared/shared.module'; import { OrgUnitComponent } from './item-pages/org-unit/org-unit.component'; import { PersonComponent } from './item-pages/person/person.component'; @@ -27,6 +28,7 @@ import { ExternalSourceEntryListSubmissionElementComponent } from './submission/ import { OrgUnitSidebarSearchListElementComponent } from './item-list-elements/sidebar-search-list-elements/org-unit/org-unit-sidebar-search-list-element.component'; import { PersonSidebarSearchListElementComponent } from './item-list-elements/sidebar-search-list-elements/person/person-sidebar-search-list-element.component'; import { ProjectSidebarSearchListElementComponent } from './item-list-elements/sidebar-search-list-elements/project/project-sidebar-search-list-element.component'; +import { ItemSharedModule } from '../../item-page/item-shared.module'; const ENTRY_COMPONENTS = [ // put only entry components that use custom decorator @@ -65,7 +67,9 @@ const COMPONENTS = [ @NgModule({ imports: [ CommonModule, - SharedModule + ItemSharedModule, + SharedModule, + NgbTooltipModule ], declarations: [ ...COMPONENTS, @@ -79,7 +83,7 @@ export class ResearchEntitiesModule { static withEntryComponents() { return { ngModule: ResearchEntitiesModule, - providers: ENTRY_COMPONENTS.map((component) => ({provide: component})) + providers: ENTRY_COMPONENTS.map((component) => ({ provide: component })) }; } } diff --git a/src/app/item-page/edit-item-page/edit-item-page.module.ts b/src/app/item-page/edit-item-page/edit-item-page.module.ts index 11b1d585ba..97901bd7c8 100644 --- a/src/app/item-page/edit-item-page/edit-item-page.module.ts +++ b/src/app/item-page/edit-item-page/edit-item-page.module.ts @@ -1,5 +1,8 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; + +import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'; + import { SharedModule } from '../../shared/shared.module'; import { EditItemPageRoutingModule } from './edit-item-page.routing.module'; import { EditItemPageComponent } from './edit-item-page.component'; @@ -31,6 +34,8 @@ import { VirtualMetadataComponent } from './virtual-metadata/virtual-metadata.co import { ItemVersionHistoryComponent } from './item-version-history/item-version-history.component'; import { ItemAuthorizationsComponent } from './item-authorizations/item-authorizations.component'; import { ObjectValuesPipe } from '../../shared/utils/object-values-pipe'; +import { ResourcePoliciesModule } from '../../shared/resource-policies/resource-policies.module'; + /** * Module that contains all components related to the Edit Item page administrator functionality @@ -39,9 +44,11 @@ import { ObjectValuesPipe } from '../../shared/utils/object-values-pipe'; imports: [ CommonModule, SharedModule, + NgbTooltipModule, EditItemPageRoutingModule, SearchPageModule, - DragDropModule + DragDropModule, + ResourcePoliciesModule ], declarations: [ EditItemPageComponent, diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts index d66c5d060d..42e40b8f6d 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts @@ -15,14 +15,11 @@ import { getFirstSucceededRemoteData, getRemoteDataPayload } from '../../../core import { RemoteData } from '../../../core/data/remote-data'; import { PaginatedList } from '../../../core/data/paginated-list.model'; import { Bundle } from '../../../core/shared/bundle.model'; -import { - FieldUpdate, - FieldUpdates -} from '../../../core/data/object-updates/object-updates.reducer'; +import { FieldUpdate, FieldUpdates } from '../../../core/data/object-updates/object-updates.reducer'; import { Bitstream } from '../../../core/shared/bitstream.model'; import { FieldChangeType } from '../../../core/data/object-updates/object-updates.actions'; import { BundleDataService } from '../../../core/data/bundle-data.service'; -import { PaginatedSearchOptions } from '../../../shared/search/paginated-search-options.model'; +import { PaginatedSearchOptions } from '../../../shared/search/models/paginated-search-options.model'; import { ResponsiveColumnSizes } from '../../../shared/responsive-table-sizes/responsive-column-sizes'; import { ResponsiveTableSizes } from '../../../shared/responsive-table-sizes/responsive-table-sizes'; import { NoContent } from '../../../core/shared/NoContent.model'; diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.ts index f3f00abf92..2c81a4e2cb 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.ts @@ -5,7 +5,7 @@ import { Bitstream } from '../../../../../core/shared/bitstream.model'; import { ObjectUpdatesService } from '../../../../../core/data/object-updates/object-updates.service'; import { BundleDataService } from '../../../../../core/data/bundle-data.service'; import { switchMap } from 'rxjs/operators'; -import { PaginatedSearchOptions } from '../../../../../shared/search/paginated-search-options.model'; +import { PaginatedSearchOptions } from '../../../../../shared/search/models/paginated-search-options.model'; import { ResponsiveTableSizes } from '../../../../../shared/responsive-table-sizes/responsive-table-sizes'; import { followLink } from '../../../../../shared/utils/follow-link-config.model'; import { ObjectValuesPipe } from '../../../../../shared/utils/object-values-pipe'; diff --git a/src/app/item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.spec.ts b/src/app/item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.spec.ts index b5473fa02d..c073f2d63e 100644 --- a/src/app/item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.spec.ts +++ b/src/app/item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.spec.ts @@ -1,6 +1,6 @@ import { CommonModule } from '@angular/common'; import { EventEmitter } from '@angular/core'; -import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { FormsModule } from '@angular/forms'; import { By } from '@angular/platform-browser'; import { ActivatedRoute, Router } from '@angular/router'; @@ -25,7 +25,7 @@ import { ObjectSelectService } from '../../../shared/object-select/object-select import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; import { PaginationComponent } from '../../../shared/pagination/pagination.component'; import { SearchFormComponent } from '../../../shared/search-form/search-form.component'; -import { PaginatedSearchOptions } from '../../../shared/search/paginated-search-options.model'; +import { PaginatedSearchOptions } from '../../../shared/search/models/paginated-search-options.model'; import { HostWindowServiceStub } from '../../../shared/testing/host-window-service.stub'; import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub'; import { ObjectSelectServiceStub } from '../../../shared/testing/object-select-service.stub'; diff --git a/src/app/item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.ts b/src/app/item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.ts index a7dc8dc1e5..a71fe5b385 100644 --- a/src/app/item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.ts +++ b/src/app/item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.ts @@ -9,11 +9,12 @@ import { PaginatedList } from '../../../core/data/paginated-list.model'; import { Collection } from '../../../core/shared/collection.model'; import { Item } from '../../../core/shared/item.model'; import { + getAllSucceededRemoteData, + getFirstCompletedRemoteData, + getFirstSucceededRemoteData, getFirstSucceededRemoteDataPayload, getRemoteDataPayload, - getFirstSucceededRemoteData, - toDSpaceObjectListRD, - getAllSucceededRemoteData, getFirstCompletedRemoteData + toDSpaceObjectListRD } from '../../../core/shared/operators'; import { ActivatedRoute, Router } from '@angular/router'; import { filter, map, startWith, switchMap, take } from 'rxjs/operators'; @@ -22,7 +23,7 @@ import { TranslateService } from '@ngx-translate/core'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; import { DSpaceObjectType } from '../../../core/shared/dspace-object-type.model'; import { hasValue, isNotEmpty } from '../../../shared/empty.util'; -import { PaginatedSearchOptions } from '../../../shared/search/paginated-search-options.model'; +import { PaginatedSearchOptions } from '../../../shared/search/models/paginated-search-options.model'; import { SearchConfigurationService } from '../../../core/shared/search/search-configuration.service'; import { SearchService } from '../../../core/shared/search/search.service'; import { NoContent } from '../../../core/shared/NoContent.model'; diff --git a/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.ts b/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.ts index fe7ff0aacf..c7dd6799d7 100644 --- a/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.ts +++ b/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.ts @@ -3,7 +3,13 @@ import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { LinkService } from '../../../../core/cache/builders/link.service'; import { FieldChangeType } from '../../../../core/data/object-updates/object-updates.actions'; import { ObjectUpdatesService } from '../../../../core/data/object-updates/object-updates.service'; -import { combineLatest as observableCombineLatest, from as observableFrom, BehaviorSubject, Observable, Subscription } from 'rxjs'; +import { + BehaviorSubject, + combineLatest as observableCombineLatest, + from as observableFrom, + Observable, + Subscription +} from 'rxjs'; import { FieldUpdate, FieldUpdates, @@ -25,7 +31,7 @@ import { ItemType } from '../../../../core/shared/item-relationships/item-type.m import { DsDynamicLookupRelationModalComponent } from '../../../../shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component'; import { RelationshipOptions } from '../../../../shared/form/builder/models/relationship-options.model'; import { SelectableListService } from '../../../../shared/object-list/selectable-list/selectable-list.service'; -import { SearchResult } from '../../../../shared/search/search-result.model'; +import { SearchResult } from '../../../../shared/search/models/search-result.model'; import { followLink } from '../../../../shared/utils/follow-link-config.model'; import { PaginatedList } from '../../../../core/data/paginated-list.model'; import { RemoteData } from '../../../../core/data/remote-data'; diff --git a/src/app/item-page/item-shared.module.ts b/src/app/item-page/item-shared.module.ts new file mode 100644 index 0000000000..b191b6c4b3 --- /dev/null +++ b/src/app/item-page/item-shared.module.ts @@ -0,0 +1,36 @@ +import { RelatedEntitiesSearchComponent } from './simple/related-entities/related-entities-search/related-entities-search.component'; +import { NgModule } from '@angular/core'; +import { CommonModule } 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'; + +const COMPONENTS = [ + RelatedEntitiesSearchComponent, + TabbedRelatedEntitiesSearchComponent +]; + +@NgModule({ + declarations: [ + ...COMPONENTS + ], + imports: [ + CommonModule, + SearchModule, + SharedModule, + TranslateModule + ], + exports: [ + ...COMPONENTS + ], + providers: [ + { + provide: DYNAMIC_FORM_CONTROL_MAP_FN, + useValue: dsDynamicFormControlMapFn + } + ] +}) +export class ItemSharedModule { } diff --git a/src/app/item-page/simple/related-entities/related-entities-search/related-entities-search.component.html b/src/app/item-page/simple/related-entities/related-entities-search/related-entities-search.component.html index 75f3b7aaad..2a08efeb2c 100644 --- a/src/app/item-page/simple/related-entities/related-entities-search/related-entities-search.component.html +++ b/src/app/item-page/simple/related-entities/related-entities-search/related-entities-search.component.html @@ -1,7 +1,6 @@ diff --git a/src/app/item-page/simple/related-entities/related-entities-search/related-entities-search.component.spec.ts b/src/app/item-page/simple/related-entities/related-entities-search/related-entities-search.component.spec.ts index a75a0feae2..a9fd11b9ee 100644 --- a/src/app/item-page/simple/related-entities/related-entities-search/related-entities-search.component.spec.ts +++ b/src/app/item-page/simple/related-entities/related-entities-search/related-entities-search.component.spec.ts @@ -38,10 +38,4 @@ describe('RelatedEntitiesSearchComponent', () => { expect(comp.fixedFilter).toEqual(mockFilter); }); - it('should create a configuration$', () => { - comp.configuration$.subscribe((configuration) => { - expect(configuration).toEqual(mockConfiguration); - }); - }); - }); diff --git a/src/app/item-page/simple/related-entities/related-entities-search/related-entities-search.component.ts b/src/app/item-page/simple/related-entities/related-entities-search/related-entities-search.component.ts index 46c02a613a..a3f76c12d7 100644 --- a/src/app/item-page/simple/related-entities/related-entities-search/related-entities-search.component.ts +++ b/src/app/item-page/simple/related-entities/related-entities-search/related-entities-search.component.ts @@ -1,5 +1,4 @@ import { Component, Input, OnInit } from '@angular/core'; -import { Observable, of } from 'rxjs'; import { Item } from '../../../../core/shared/item.model'; import { isNotEmpty } from '../../../../shared/empty.util'; import { getFilterByRelation } from '../../../../shared/utils/relation-query.utils'; @@ -10,7 +9,7 @@ import { getFilterByRelation } from '../../../../shared/utils/relation-query.uti }) /** * A component to show related items as search results. - * Related items can be facetted, or queried using an + * Related items can be faceted, or queried using an * optional search box. */ export class RelatedEntitiesSearchComponent implements OnInit { @@ -44,15 +43,11 @@ export class RelatedEntitiesSearchComponent implements OnInit { @Input() sideBarWidth = 4; fixedFilter: string; - configuration$: Observable; ngOnInit(): void { if (isNotEmpty(this.relationType) && isNotEmpty(this.item)) { this.fixedFilter = getFilterByRelation(this.relationType, this.item.id); } - if (isNotEmpty(this.configuration)) { - this.configuration$ = of(this.configuration); - } } } diff --git a/src/app/my-dspace-page/my-dspace-configuration.service.spec.ts b/src/app/my-dspace-page/my-dspace-configuration.service.spec.ts index fa278da967..dc971bc3af 100644 --- a/src/app/my-dspace-page/my-dspace-configuration.service.spec.ts +++ b/src/app/my-dspace-page/my-dspace-configuration.service.spec.ts @@ -1,16 +1,16 @@ import { of as observableOf } from 'rxjs'; import { MyDSpaceConfigurationService } from './my-dspace-configuration.service'; -import { PaginatedSearchOptions } from '../shared/search/paginated-search-options.model'; +import { PaginatedSearchOptions } from '../shared/search/models/paginated-search-options.model'; import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model'; import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model'; -import { SearchFilter } from '../shared/search/search-filter.model'; +import { SearchFilter } from '../shared/search/models/search-filter.model'; import { ActivatedRouteStub } from '../shared/testing/active-router.stub'; import { RoleServiceMock } from '../shared/mocks/role-service.mock'; import { cold, hot } from 'jasmine-marbles'; import { MyDSpaceConfigurationValueType } from './my-dspace-configuration-value-type'; import { PaginationServiceStub } from '../shared/testing/pagination-service.stub'; -import { PaginationService } from '../core/pagination/pagination.service'; +import { Context } from '../core/shared/context.model'; describe('MyDSpaceConfigurationService', () => { let service: MyDSpaceConfigurationService; @@ -242,11 +242,13 @@ describe('MyDSpaceConfigurationService', () => { b: [ { value: MyDSpaceConfigurationValueType.Workspace, - label: `mydspace.show.${MyDSpaceConfigurationValueType.Workspace}` + label: `mydspace.show.${MyDSpaceConfigurationValueType.Workspace}`, + context: Context.Workspace }, { value: MyDSpaceConfigurationValueType.Workflow, - label: `mydspace.show.${MyDSpaceConfigurationValueType.Workflow}` + label: `mydspace.show.${MyDSpaceConfigurationValueType.Workflow}`, + context: Context.Workflow } ] })); diff --git a/src/app/my-dspace-page/my-dspace-configuration.service.ts b/src/app/my-dspace-page/my-dspace-configuration.service.ts index 82f76eb776..7dde8eff77 100644 --- a/src/app/my-dspace-page/my-dspace-configuration.service.ts +++ b/src/app/my-dspace-page/my-dspace-configuration.service.ts @@ -12,6 +12,13 @@ import { PaginationComponentOptions } from '../shared/pagination/pagination-comp import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model'; import { RouteService } from '../core/services/route.service'; import { PaginationService } from '../core/pagination/pagination.service'; +import { Context } from '../core/shared/context.model'; + +export const MyDSpaceConfigurationToContextMap = new Map([ + [MyDSpaceConfigurationValueType.Workspace, Context.Workspace], + [MyDSpaceConfigurationValueType.Workflow, Context.Workflow] +]); + /** * Service that performs all actions that have to do with the current mydspace configuration @@ -110,7 +117,8 @@ export class MyDSpaceConfigurationService extends SearchConfigurationService { availableConfigurationTypes.forEach((type) => { const value = type; const label = `mydspace.show.${value}`; - configurationOptions.push({ value, label }); + const context = MyDSpaceConfigurationToContextMap.get(type); + configurationOptions.push({ value, label, context }); }); return configurationOptions; }) diff --git a/src/app/my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts b/src/app/my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts index 580afd8ad4..127d266138 100644 --- a/src/app/my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts +++ b/src/app/my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts @@ -13,7 +13,7 @@ import { UploaderOptions } from '../../shared/uploader/uploader-options.model'; import { HALEndpointService } from '../../core/shared/hal-endpoint.service'; import { NotificationType } from '../../shared/notifications/models/notification-type'; import { hasValue } from '../../shared/empty.util'; -import { SearchResult } from '../../shared/search/search-result.model'; +import { SearchResult } from '../../shared/search/models/search-result.model'; import { CollectionSelectorComponent } from '../collection-selector/collection-selector.component'; import { UploaderComponent } from '../../shared/uploader/uploader.component'; import { UploaderError } from '../../shared/uploader/uploader-error.model'; diff --git a/src/app/my-dspace-page/my-dspace-page.component.html b/src/app/my-dspace-page/my-dspace-page.component.html index 5a15abcc08..45cade0804 100644 --- a/src/app/my-dspace-page/my-dspace-page.component.html +++ b/src/app/my-dspace-page/my-dspace-page.component.html @@ -1,56 +1,10 @@
-
- -
- - - -
-
- - -
-
- - -
- -
-
-
-
-
+ + diff --git a/src/app/my-dspace-page/my-dspace-page.component.scss b/src/app/my-dspace-page/my-dspace-page.component.scss index b35b2ba709..b9b3e5d2f6 100644 --- a/src/app/my-dspace-page/my-dspace-page.component.scss +++ b/src/app/my-dspace-page/my-dspace-page.component.scss @@ -1 +1 @@ -@import '../search-page/search.component.scss'; +@import '../shared/search/search.component'; diff --git a/src/app/my-dspace-page/my-dspace-page.component.spec.ts b/src/app/my-dspace-page/my-dspace-page.component.spec.ts index b4b75b42a0..34bf20d462 100644 --- a/src/app/my-dspace-page/my-dspace-page.component.spec.ts +++ b/src/app/my-dspace-page/my-dspace-page.component.spec.ts @@ -1,213 +1,88 @@ -import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { ActivatedRoute } from '@angular/router'; -import { By } from '@angular/platform-browser'; import { NgbCollapseModule } from '@ng-bootstrap/ng-bootstrap'; -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, fakeAsync, flush, TestBed, waitForAsync } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; -import { Store } from '@ngrx/store'; +import { of as observableOf } from 'rxjs'; import { TranslateModule } from '@ngx-translate/core'; import { cold } from 'jasmine-marbles'; -import { of as observableOf } from 'rxjs'; -import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model'; -import { CommunityDataService } from '../core/data/community-data.service'; -import { HostWindowService } from '../shared/host-window.service'; -import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model'; import { MyDSpacePageComponent, SEARCH_CONFIG_SERVICE } from './my-dspace-page.component'; -import { RouteService } from '../core/services/route.service'; -import { routeServiceStub } from '../shared/testing/route-service.stub'; -import { SearchConfigurationServiceStub } from '../shared/testing/search-configuration-service.stub'; import { SearchService } from '../core/shared/search/search.service'; -import { SearchConfigurationService } from '../core/shared/search/search-configuration.service'; -import { PaginatedSearchOptions } from '../shared/search/paginated-search-options.model'; -import { SidebarService } from '../shared/sidebar/sidebar.service'; -import { SearchFilterService } from '../core/shared/search/search-filter.service'; -import { RoleDirective } from '../shared/roles/role.directive'; -import { RoleService } from '../core/roles/role.service'; -import { RoleServiceMock } from '../shared/mocks/role-service.mock'; -import { createSuccessfulRemoteDataObject$ } from '../shared/remote-data.utils'; -import { SidebarServiceStub } from '../shared/testing/sidebar-service.stub'; +import { MyDSpaceConfigurationService } from './my-dspace-configuration.service'; +import { MyDSpaceConfigurationValueType } from './my-dspace-configuration-value-type'; +import { Context } from '../core/shared/context.model'; +import SpyObj = jasmine.SpyObj; describe('MyDSpacePageComponent', () => { let comp: MyDSpacePageComponent; let fixture: ComponentFixture; - let searchServiceObject: SearchService; - let searchConfigurationServiceObject: SearchConfigurationService; - const store: Store = jasmine.createSpyObj('store', { - /* tslint:disable:no-empty */ - dispatch: {}, - /* tslint:enable:no-empty */ - select: observableOf(true) + + const searchServiceStub: SpyObj = jasmine.createSpyObj('SearchService', { + setServiceOptions: jasmine.createSpy('setServiceOptions') }); - const pagination: PaginationComponentOptions = new PaginationComponentOptions(); - pagination.id = 'mydspace-results-pagination'; - pagination.currentPage = 1; - pagination.pageSize = 10; - const sortOption = { name: 'score', sortOrder: 'DESC', metadata: null }; - const sort: SortOptions = new SortOptions('score', SortDirection.DESC); - const mockResults = createSuccessfulRemoteDataObject$(['test', 'data']); - const searchServiceStub = jasmine.createSpyObj('SearchService', { - search: mockResults, - getEndpoint: observableOf('discover/search/objects'), - getSearchLink: '/mydspace', - getScopes: observableOf(['test-scope']), - setServiceOptions: {}, - getSearchConfigurationFor: createSuccessfulRemoteDataObject$({ sortOptions: [sortOption]}) + + const myDSpaceConfigurationServiceStub: SpyObj = jasmine.createSpyObj('MyDSpaceConfigurationService', { + getAvailableConfigurationOptions: jasmine.createSpy('getAvailableConfigurationOptions') }); - const configurationParam = 'default'; - const queryParam = 'test query'; - const scopeParam = '7669c72a-3f2a-451f-a3b9-9210e7a4c02f'; - const paginatedSearchOptions = new PaginatedSearchOptions({ - configuration: configurationParam, - query: queryParam, - scope: scopeParam, - pagination, - sort - }); - const activatedRouteStub = { - snapshot: { - queryParamMap: new Map([ - ['query', queryParam], - ['scope', scopeParam] - ]) + + const configurationList = [ + { + value: MyDSpaceConfigurationValueType.Workspace, + label: `mydspace.show.${MyDSpaceConfigurationValueType.Workspace}`, + context: Context.Workspace }, - queryParams: observableOf({ - query: queryParam, - scope: scopeParam - }) - }; + { + value: MyDSpaceConfigurationValueType.Workflow, + label: `mydspace.show.${MyDSpaceConfigurationValueType.Workflow}`, + context: Context.Workflow + } + ]; beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), NoopAnimationsModule, NgbCollapseModule], - declarations: [MyDSpacePageComponent, RoleDirective], + declarations: [MyDSpacePageComponent], providers: [ { provide: SearchService, useValue: searchServiceStub }, - { - provide: CommunityDataService, - useValue: jasmine.createSpyObj('communityService', ['findById', 'findAll']) - }, - { provide: ActivatedRoute, useValue: activatedRouteStub }, - { provide: RouteService, useValue: routeServiceStub }, - { - provide: Store, useValue: store - }, - { - provide: HostWindowService, useValue: jasmine.createSpyObj('hostWindowService', - { - isXs: observableOf(true), - isSm: observableOf(false), - isXsOrSm: observableOf(true) - }) - }, - { - provide: SidebarService, - useValue: SidebarServiceStub - }, - { - provide: SearchFilterService, - useValue: {} - }, { - provide: SEARCH_CONFIG_SERVICE, - useValue: new SearchConfigurationServiceStub() - }, - { - provide: RoleService, - useValue: new RoleServiceMock() - }, + { provide: MyDSpaceConfigurationService, useValue: myDSpaceConfigurationServiceStub }, ], schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(MyDSpacePageComponent, { - set: { changeDetection: ChangeDetectionStrategy.Default } + set: { + providers: [ + { + provide: SEARCH_CONFIG_SERVICE, + useValue: myDSpaceConfigurationServiceStub + } + ] + } }).compileComponents(); })); beforeEach(() => { fixture = TestBed.createComponent(MyDSpacePageComponent); comp = fixture.componentInstance; // SearchPageComponent test instance + myDSpaceConfigurationServiceStub.getAvailableConfigurationOptions.and.returnValue(observableOf(configurationList)); + fixture.detectChanges(); - searchServiceObject = (comp as any).service; - searchConfigurationServiceObject = (comp as any).searchConfigService; + }); afterEach(() => { comp = null; - searchServiceObject = null; - searchConfigurationServiceObject = null; }); - it('should get the scope and query from the route parameters', () => { + it('should init properly context and configuration', fakeAsync(() => { - searchConfigurationServiceObject.paginatedSearchOptions.next(paginatedSearchOptions); - expect(comp.searchOptions$).toBeObservable(cold('b', { - b: paginatedSearchOptions + expect(comp.configurationList$).toBeObservable(cold('(a|)', { + a: configurationList })); - }); + flush(); + expect(comp.configuration).toBe(MyDSpaceConfigurationValueType.Workspace); + expect(comp.context).toBe(Context.Workspace); + })); - describe('when the open sidebar button is clicked in mobile view', () => { - - beforeEach(() => { - spyOn(comp, 'openSidebar'); - const openSidebarButton = fixture.debugElement.query(By.css('.open-sidebar')); - openSidebarButton.triggerEventHandler('click', null); - }); - - it('should trigger the openSidebar function', () => { - expect(comp.openSidebar).toHaveBeenCalled(); - }); - - }); - - describe('when sidebarCollapsed is true in mobile view', () => { - let menu: HTMLElement; - - beforeEach(() => { - menu = fixture.debugElement.query(By.css('#search-sidebar-sm')).nativeElement; - comp.isSidebarCollapsed = () => observableOf(true); - fixture.detectChanges(); - }); - - it('should close the sidebar', () => { - expect(menu.classList).not.toContain('active'); - }); - - }); - - describe('when sidebarCollapsed is false in mobile view', () => { - let menu: HTMLElement; - - beforeEach(() => { - menu = fixture.debugElement.query(By.css('#search-sidebar-sm')).nativeElement; - comp.isSidebarCollapsed = () => observableOf(false); - fixture.detectChanges(); - }); - - it('should open the menu', () => { - expect(menu.classList).toContain('active'); - }); - - }); - - describe('when stable', () => { - - beforeEach(() => { - fixture.detectChanges(); - }); - - it('should have initialized the sortOptions$ observable', (done) => { - - comp.sortOptions$.subscribe((sortOptions) => { - - expect(sortOptions.length).toEqual(2); - expect(sortOptions[0]).toEqual(new SortOptions('score', SortDirection.ASC)); - expect(sortOptions[1]).toEqual(new SortOptions('score', SortDirection.DESC)); - done(); - }); - - }); - - }); }); diff --git a/src/app/my-dspace-page/my-dspace-page.component.ts b/src/app/my-dspace-page/my-dspace-page.component.ts index 89a4023be8..c5176ef29e 100644 --- a/src/app/my-dspace-page/my-dspace-page.component.ts +++ b/src/app/my-dspace-page/my-dspace-page.component.ts @@ -1,36 +1,16 @@ -import { - ChangeDetectionStrategy, - Component, - Inject, - InjectionToken, - Input, - OnInit -} from '@angular/core'; +import { ChangeDetectionStrategy, Component, Inject, InjectionToken, OnInit } from '@angular/core'; -import { BehaviorSubject, Observable, Subject, Subscription } from 'rxjs'; -import { map, switchMap, tap } from 'rxjs/operators'; - -import { PaginatedList } from '../core/data/paginated-list.model'; -import { RemoteData } from '../core/data/remote-data'; -import { DSpaceObject } from '../core/shared/dspace-object.model'; -import { pushInOut } from '../shared/animations/push'; -import { HostWindowService } from '../shared/host-window.service'; -import { PaginatedSearchOptions } from '../shared/search/paginated-search-options.model'; +import { Observable } from 'rxjs'; +import { take } from 'rxjs/operators'; import { SearchService } from '../core/shared/search/search.service'; -import { SidebarService } from '../shared/sidebar/sidebar.service'; -import { hasValue } from '../shared/empty.util'; -import { getFirstCompletedRemoteData } from '../core/shared/operators'; import { MyDSpaceResponseParsingService } from '../core/data/mydspace-response-parsing.service'; import { SearchConfigurationOption } from '../shared/search/search-switch-configuration/search-configuration-option.model'; -import { RoleType } from '../core/roles/role-types'; import { SearchConfigurationService } from '../core/shared/search/search-configuration.service'; import { MyDSpaceConfigurationService } from './my-dspace-configuration.service'; import { ViewMode } from '../core/shared/view-mode.model'; import { MyDSpaceRequest } from '../core/data/request.models'; -import { SearchResult } from '../shared/search/search-result.model'; import { Context } from '../core/shared/context.model'; -import { SortOptions } from '../core/cache/models/sort-options.model'; -import { SearchObjects } from '../shared/search/search-objects.model'; +import { RoleType } from '../core/roles/role-types'; export const MYDSPACE_ROUTE = '/mydspace'; export const SEARCH_CONFIG_SERVICE: InjectionToken = new InjectionToken('searchConfigurationService'); @@ -43,7 +23,6 @@ export const SEARCH_CONFIG_SERVICE: InjectionToken = styleUrls: ['./my-dspace-page.component.scss'], templateUrl: './my-dspace-page.component.html', changeDetection: ChangeDetectionStrategy.OnPush, - animations: [pushInOut], providers: [ { provide: SEARCH_CONFIG_SERVICE, @@ -53,40 +32,20 @@ export const SEARCH_CONFIG_SERVICE: InjectionToken = }) export class MyDSpacePageComponent implements OnInit { - /** - * True when the search component should show results on the current page - */ - @Input() inPlaceSearch = true; - /** * The list of available configuration options */ configurationList$: Observable; /** - * The current search results + * The start context to use in the search: workspace or workflow */ - resultsRD$: BehaviorSubject>>> = new BehaviorSubject(null); + context: Context; /** - * The current paginated search options + * The start configuration to use in the search: workspace or workflow */ - searchOptions$: Observable; - - /** - * The current available sort options - */ - sortOptions$: Observable; - - /** - * Emits true if were on a small screen - */ - isXsOrSm$: Observable; - - /** - * Subscription to unsubscribe from - */ - sub: Subscription; + configuration: string; /** * Variable for enumeration RoleType @@ -98,21 +57,8 @@ export class MyDSpacePageComponent implements OnInit { */ viewModeList = [ViewMode.ListElement, ViewMode.DetailedListElement]; - /** - * The current context of this page: workspace or workflow - */ - context$: Observable; - - /** - * Emit an event every time search sidebars must refresh their contents. - */ - refreshFilters: Subject = new Subject(); - constructor(private service: SearchService, - private sidebarService: SidebarService, - private windowService: HostWindowService, @Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: MyDSpaceConfigurationService) { - this.isXsOrSm$ = this.windowService.isXsOrSm(); this.service.setServiceOptions(MyDSpaceResponseParsingService, MyDSpaceRequest); } @@ -130,77 +76,12 @@ export class MyDSpacePageComponent implements OnInit { */ ngOnInit(): void { this.configurationList$ = this.searchConfigService.getAvailableConfigurationOptions(); - this.searchOptions$ = this.searchConfigService.paginatedSearchOptions; - this.sub = this.searchOptions$.pipe( - tap(() => this.resultsRD$.next(null)), - switchMap((options: PaginatedSearchOptions) => this.service.search(options).pipe(getFirstCompletedRemoteData()))) - .subscribe((results: RemoteData>) => { - this.resultsRD$.next(results); - }); - this.context$ = this.searchConfigService.getCurrentConfiguration('workspace') - .pipe( - map((configuration: string) => { - if (configuration === 'workspace') { - return Context.Workspace; - } else { - return Context.Workflow; - } - }) - ); - - const configuration$ = this.searchConfigService.getCurrentConfiguration('workspace'); - const searchConfig$ = this.searchConfigService.getConfigurationSearchConfigObservable(configuration$, this.service); - - this.sortOptions$ = this.searchConfigService.getConfigurationSortOptionsObservable(searchConfig$); - this.searchConfigService.initializeSortOptionsFromConfiguration(searchConfig$); + this.configurationList$.pipe(take(1)).subscribe((configurationList: SearchConfigurationOption[]) => { + this.configuration = configurationList[0].value; + this.context = configurationList[0].context; + }); } - /** - * Handle the contentChange event from within the my dspace content. - * Notify search sidebars to refresh their content. - */ - onResultsContentChange() { - this.refreshFilters.next(); - } - - /** - * Set the sidebar to a collapsed state - */ - public closeSidebar(): void { - this.sidebarService.collapse(); - } - - /** - * Set the sidebar to an expanded state - */ - public openSidebar(): void { - this.sidebarService.expand(); - } - - /** - * Check if the sidebar is collapsed - * @returns {Observable} emits true if the sidebar is currently collapsed, false if it is expanded - */ - public isSidebarCollapsed(): Observable { - return this.sidebarService.isCollapsed; - } - - /** - * @returns {string} The base path to the search page - */ - public getSearchLink(): string { - return this.service.getSearchLink(); - } - - /** - * Unsubscribe from the subscription - */ - ngOnDestroy(): void { - if (hasValue(this.sub)) { - this.sub.unsubscribe(); - } - this.refreshFilters.complete(); - } } diff --git a/src/app/my-dspace-page/my-dspace-page.module.ts b/src/app/my-dspace-page/my-dspace-page.module.ts index a5a18effbc..2ccddd87f7 100644 --- a/src/app/my-dspace-page/my-dspace-page.module.ts +++ b/src/app/my-dspace-page/my-dspace-page.module.ts @@ -5,7 +5,6 @@ import { SharedModule } from '../shared/shared.module'; import { MyDspacePageRoutingModule } from './my-dspace-page-routing.module'; import { MyDSpacePageComponent } from './my-dspace-page.component'; -import { MyDSpaceResultsComponent } from './my-dspace-results/my-dspace-results.component'; import { MyDSpaceNewSubmissionComponent } from './my-dspace-new-submission/my-dspace-new-submission.component'; import { MyDSpaceGuard } from './my-dspace.guard'; import { MyDSpaceConfigurationService } from './my-dspace-configuration.service'; @@ -14,11 +13,11 @@ import { MyDspaceSearchModule } from './my-dspace-search.module'; import { MyDSpaceNewSubmissionDropdownComponent } from './my-dspace-new-submission/my-dspace-new-submission-dropdown/my-dspace-new-submission-dropdown.component'; import { MyDSpaceNewExternalDropdownComponent } from './my-dspace-new-submission/my-dspace-new-external-dropdown/my-dspace-new-external-dropdown.component'; import { ThemedMyDSpacePageComponent } from './themed-my-dspace-page.component'; +import { SearchModule } from '../shared/search/search.module'; const DECLARATIONS = [ MyDSpacePageComponent, ThemedMyDSpacePageComponent, - MyDSpaceResultsComponent, MyDSpaceNewSubmissionComponent, CollectionSelectorComponent, MyDSpaceNewSubmissionDropdownComponent, @@ -29,6 +28,7 @@ const DECLARATIONS = [ imports: [ CommonModule, SharedModule, + SearchModule, MyDspacePageRoutingModule, MyDspaceSearchModule.withEntryComponents() ], diff --git a/src/app/my-dspace-page/my-dspace-results/my-dspace-results.component.html b/src/app/my-dspace-page/my-dspace-results/my-dspace-results.component.html deleted file mode 100644 index 67b13cc49c..0000000000 --- a/src/app/my-dspace-page/my-dspace-results/my-dspace-results.component.html +++ /dev/null @@ -1,14 +0,0 @@ -
- - -
- - -

{{'mydspace.results.no-results' | translate}}

diff --git a/src/app/my-dspace-page/my-dspace-results/my-dspace-results.component.spec.ts b/src/app/my-dspace-page/my-dspace-results/my-dspace-results.component.spec.ts deleted file mode 100644 index 5b069f4ddb..0000000000 --- a/src/app/my-dspace-page/my-dspace-results/my-dspace-results.component.spec.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { NO_ERRORS_SCHEMA } from '@angular/core'; - -import { TranslateModule } from '@ngx-translate/core'; -import { QueryParamsDirectiveStub } from '../../shared/testing/query-params-directive.stub'; -import { MyDSpaceResultsComponent } from './my-dspace-results.component'; - -describe('MyDSpaceResultsComponent', () => { - let comp: MyDSpaceResultsComponent; - let fixture: ComponentFixture; - - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - imports: [TranslateModule.forRoot(), NoopAnimationsModule], - declarations: [ - MyDSpaceResultsComponent, - QueryParamsDirectiveStub], - schemas: [NO_ERRORS_SCHEMA] - }).compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(MyDSpaceResultsComponent); - comp = fixture.componentInstance; // MyDSpaceResultsComponent test instance - }); - - it('should display results when results are not empty', () => { - (comp as any).searchResults = { hasSucceeded: true, isLoading: false, payload: { page: { length: 2 } } }; - (comp as any).searchConfig = {}; - fixture.detectChanges(); - expect(fixture.debugElement.query(By.css('ds-viewable-collection'))).not.toBeNull(); - }); - - it('should not display link when results are not empty', () => { - (comp as any).searchResults = { hasSucceeded: true, isLoading: false, payload: { page: { length: 2 } } }; - (comp as any).searchConfig = {}; - fixture.detectChanges(); - expect(fixture.debugElement.query(By.css('a'))).toBeNull(); - }); - - it('should display error message if error is 500', () => { - (comp as any).searchResults = { hasFailed: true, statusCode: 500 }; - fixture.detectChanges(); - expect(comp.showError()).toBeTrue(); - expect(comp.errorMessageLabel()).toBe('error.search-results'); - expect(fixture.debugElement.query(By.css('ds-error'))).not.toBeNull(); - }); - - it('should display error message if error is 422', () => { - (comp as any).searchResults = { hasFailed: true, statusCode: 422 }; - fixture.detectChanges(); - expect(comp.showError()).toBeTrue(); - expect(comp.errorMessageLabel()).toBe('error.invalid-search-query'); - expect(fixture.debugElement.query(By.css('ds-error'))).not.toBeNull(); - }); - - it('should display a message if search result is empty', () => { - (comp as any).searchResults = { payload: { page: { length: 0 } } }; - (comp as any).searchConfig = { query: 'foobar' }; - fixture.detectChanges(); - - const linkDes = fixture.debugElement.queryAll(By.css('text-muted')); - - expect(linkDes).toBeDefined(); - }); -}); diff --git a/src/app/my-dspace-page/my-dspace-results/my-dspace-results.component.ts b/src/app/my-dspace-page/my-dspace-results/my-dspace-results.component.ts deleted file mode 100644 index 77f27e9d42..0000000000 --- a/src/app/my-dspace-page/my-dspace-results/my-dspace-results.component.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { Component, EventEmitter, Input, Output } from '@angular/core'; -import { RemoteData } from '../../core/data/remote-data'; -import { DSpaceObject } from '../../core/shared/dspace-object.model'; -import { fadeIn, fadeInOut } from '../../shared/animations/fade'; -import { PaginatedList } from '../../core/data/paginated-list.model'; -import { ViewMode } from '../../core/shared/view-mode.model'; -import { isEmpty } from '../../shared/empty.util'; -import { Context } from '../../core/shared/context.model'; -import { SearchResult } from '../../shared/search/search-result.model'; -import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; - -/** - * Component that represents all results for mydspace page - */ -@Component({ - selector: 'ds-my-dspace-results', - templateUrl: './my-dspace-results.component.html', - animations: [ - fadeIn, - fadeInOut - ] -}) -export class MyDSpaceResultsComponent { - - /** - * The actual search result objects - */ - @Input() searchResults: RemoteData>>; - - /** - * The current configuration of the search - */ - @Input() searchConfig: PaginatedSearchOptions; - - /** - * The current view mode for the search results - */ - @Input() viewMode: ViewMode; - - /** - * The current context for the search results - */ - @Input() context: Context; - - /** - * Emit when one of the results has changed. - */ - @Output() contentChange = new EventEmitter(); - - /** - * A boolean representing if search results entry are separated by a line - */ - hasBorder = true; - - /** - * Check if mydspace search results are loading - */ - isLoading() { - return !this.searchResults || isEmpty(this.searchResults) || this.searchResults.isLoading; - } - - showError(): boolean { - return this.searchResults?.hasFailed && (!this.searchResults?.errorMessage || this.searchResults?.statusCode !== 400); - } - - errorMessageLabel(): string { - return (this.searchResults?.statusCode === 422) ? 'error.invalid-search-query' : 'error.search-results'; - } -} diff --git a/src/app/profile-page/profile-page.module.ts b/src/app/profile-page/profile-page.module.ts index 0b2274f2d4..dc9595140b 100644 --- a/src/app/profile-page/profile-page.module.ts +++ b/src/app/profile-page/profile-page.module.ts @@ -6,12 +6,14 @@ import { ProfilePageComponent } from './profile-page.component'; import { ProfilePageMetadataFormComponent } from './profile-page-metadata-form/profile-page-metadata-form.component'; import { ProfilePageSecurityFormComponent } from './profile-page-security-form/profile-page-security-form.component'; import { ThemedProfilePageComponent } from './themed-profile-page.component'; +import { FormModule } from '../shared/form/form.module'; @NgModule({ imports: [ ProfilePageRoutingModule, CommonModule, - SharedModule + SharedModule, + FormModule ], exports: [ ProfilePageSecurityFormComponent, diff --git a/src/app/search-navbar/search-navbar.component.spec.ts b/src/app/search-navbar/search-navbar.component.spec.ts index ba08c7ca75..fbdcdc951c 100644 --- a/src/app/search-navbar/search-navbar.component.spec.ts +++ b/src/app/search-navbar/search-navbar.component.spec.ts @@ -2,18 +2,14 @@ import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angul import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { By } from '@angular/platform-browser'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { Router } from '@angular/router'; +import { NavigationExtras, Router } from '@angular/router'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { SearchService } from '../core/shared/search/search.service'; import { TranslateLoaderMock } from '../shared/mocks/translate-loader.mock'; import { SearchNavbarComponent } from './search-navbar.component'; -import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model'; -import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model'; -import { of as observableOf } from 'rxjs'; -import { PaginationService } from '../core/pagination/pagination.service'; -import { SearchConfigurationService } from '../core/shared/search/search-configuration.service'; import { PaginationServiceStub } from '../shared/testing/pagination-service.stub'; +import { RouterTestingModule } from '@angular/router/testing'; describe('SearchNavbarComponent', () => { let component: SearchNavbarComponent; @@ -41,6 +37,7 @@ describe('SearchNavbarComponent', () => { FormsModule, ReactiveFormsModule, BrowserAnimationsModule, + RouterTestingModule, TranslateModule.forRoot({ loader: { provide: TranslateLoader, @@ -49,10 +46,7 @@ describe('SearchNavbarComponent', () => { })], declarations: [SearchNavbarComponent], providers: [ - { provide: SearchService, useValue: mockSearchService }, - { provide: PaginationService, useValue: paginationService }, - { provide: Router, useValue: routerStub }, - { provide: SearchConfigurationService, useValue: {paginationID: 'page-id'} } + { provide: SearchService, useValue: mockSearchService } ] }) .compileComponents(); @@ -61,8 +55,8 @@ describe('SearchNavbarComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(SearchNavbarComponent); component = fixture.componentInstance; + router = TestBed.inject(Router); fixture.detectChanges(); - router = (component as any).router; }); it('should create', () => { @@ -73,7 +67,7 @@ describe('SearchNavbarComponent', () => { beforeEach(fakeAsync(() => { spyOn(component, 'expand').and.callThrough(); spyOn(component, 'onSubmit').and.callThrough(); - spyOn(router, 'navigate').and.callThrough(); + spyOn(router, 'navigate'); const searchIcon = fixture.debugElement.query(By.css('#search-navbar-container form .submit-icon')); searchIcon.triggerEventHandler('click', { preventDefault: () => {/**/ @@ -99,8 +93,9 @@ describe('SearchNavbarComponent', () => { fixture.detectChanges(); })); it('to search page with empty query', () => { + const extras: NavigationExtras = {queryParams: { query: '' }, queryParamsHandling: 'merge'}; expect(component.onSubmit).toHaveBeenCalledWith({ query: '' }); - expect(paginationService.updateRouteWithUrl).toHaveBeenCalled(); + expect(router.navigate).toHaveBeenCalledWith(['search'], extras); }); }); }); @@ -123,8 +118,10 @@ describe('SearchNavbarComponent', () => { fixture.detectChanges(); })); it('to search page with query', async () => { + const extras: NavigationExtras = { queryParams: { query: 'test' }, queryParamsHandling: 'merge'}; expect(component.onSubmit).toHaveBeenCalledWith({ query: 'test' }); - expect(paginationService.updateRouteWithUrl).toHaveBeenCalled(); + + expect(router.navigate).toHaveBeenCalledWith(['search'], extras); }); }); }); diff --git a/src/app/search-navbar/search-navbar.component.ts b/src/app/search-navbar/search-navbar.component.ts index 1e509a180b..ccdaa27861 100644 --- a/src/app/search-navbar/search-navbar.component.ts +++ b/src/app/search-navbar/search-navbar.component.ts @@ -3,8 +3,6 @@ import { FormBuilder } from '@angular/forms'; import { Router } from '@angular/router'; import { SearchService } from '../core/shared/search/search.service'; import { expandSearchInput } from '../shared/animations/slide'; -import { PaginationService } from '../core/pagination/pagination.service'; -import { SearchConfigurationService } from '../core/shared/search/search-configuration.service'; /** * The search box in the header that expands on focus and collapses on focus out @@ -26,9 +24,7 @@ export class SearchNavbarComponent { // Search input field @ViewChild('searchInput') searchField: ElementRef; - constructor(private formBuilder: FormBuilder, private router: Router, private searchService: SearchService, - private paginationService: PaginationService, - private searchConfig: SearchConfigurationService) { + constructor(private formBuilder: FormBuilder, private router: Router, private searchService: SearchService) { this.searchForm = this.formBuilder.group(({ query: '', })); @@ -65,8 +61,13 @@ export class SearchNavbarComponent { */ onSubmit(data: any) { this.collapse(); - const linkToNavigateTo = this.searchService.getSearchLink().split('/'); + const queryParams = Object.assign({}, data); + const linkToNavigateTo = [this.searchService.getSearchLink().replace('/', '')]; this.searchForm.reset(); - this.paginationService.updateRouteWithUrl(this.searchConfig.paginationID, linkToNavigateTo, {page: 1}, data); + + this.router.navigate(linkToNavigateTo, { + queryParams: queryParams, + queryParamsHandling: 'merge' + }); } } diff --git a/src/app/search-page/configuration-search-page.component.spec.ts b/src/app/search-page/configuration-search-page.component.spec.ts index 5ca593981f..4468aad9c4 100644 --- a/src/app/search-page/configuration-search-page.component.spec.ts +++ b/src/app/search-page/configuration-search-page.component.spec.ts @@ -1,5 +1,5 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; -import { configureSearchComponentTestingModule } from './search.component.spec'; +import { configureSearchComponentTestingModule } from '../shared/search/search.component.spec'; import { ConfigurationSearchPageComponent } from './configuration-search-page.component'; import { SearchConfigurationService } from '../core/shared/search/search-configuration.service'; import { Component, ViewChild } from '@angular/core'; diff --git a/src/app/search-page/configuration-search-page.component.ts b/src/app/search-page/configuration-search-page.component.ts index df25febde7..8ccafb3bf6 100644 --- a/src/app/search-page/configuration-search-page.component.ts +++ b/src/app/search-page/configuration-search-page.component.ts @@ -1,17 +1,10 @@ import { HostWindowService } from '../shared/host-window.service'; import { SidebarService } from '../shared/sidebar/sidebar.service'; -import { SearchComponent } from './search.component'; -import { - ChangeDetectionStrategy, - Component, - Inject, - Input, - OnInit -} from '@angular/core'; +import { SearchComponent } from '../shared/search/search.component'; +import { ChangeDetectionStrategy, Component, Inject } from '@angular/core'; import { pushInOut } from '../shared/animations/push'; import { SEARCH_CONFIG_SERVICE } from '../my-dspace-page/my-dspace-page.component'; import { SearchConfigurationService } from '../core/shared/search/search-configuration.service'; -import { hasValue } from '../shared/empty.util'; import { RouteService } from '../core/services/route.service'; import { SearchService } from '../core/shared/search/search.service'; import { Router } from '@angular/router'; @@ -21,8 +14,8 @@ import { Router } from '@angular/router'; */ @Component({ selector: 'ds-configuration-search-page', - styleUrls: ['./search.component.scss'], - templateUrl: './search.component.html', + styleUrls: ['../shared/search/search.component.scss'], + templateUrl: '../shared/search/search.component.html', changeDetection: ChangeDetectionStrategy.OnPush, animations: [pushInOut], providers: [ @@ -33,18 +26,7 @@ import { Router } from '@angular/router'; ] }) -export class ConfigurationSearchPageComponent extends SearchComponent implements OnInit { - /** - * The configuration to use for the search options - * If empty, the configuration will be determined by the route parameter called 'configuration' - */ - @Input() configuration: string; - - /** - * The actual query for the fixed filter. - * If empty, the query will be determined by the route parameter called 'filter' - */ - @Input() fixedFilterQuery: string; +export class ConfigurationSearchPageComponent extends SearchComponent { constructor(protected service: SearchService, protected sidebarService: SidebarService, @@ -55,20 +37,4 @@ export class ConfigurationSearchPageComponent extends SearchComponent implements super(service, sidebarService, windowService, searchConfigService, routeService, router); } - /** - * Listening to changes in the paginated search options - * If something changes, update the search results - * - * Listen to changes in the scope - * If something changes, update the list of scopes for the dropdown - */ - ngOnInit(): void { - super.ngOnInit(); - if (hasValue(this.configuration)) { - this.routeService.setParameter('configuration', this.configuration); - } - if (hasValue(this.fixedFilterQuery)) { - this.routeService.setParameter('fixedFilterQuery', this.fixedFilterQuery); - } - } } diff --git a/src/app/search-page/search-page.component.ts b/src/app/search-page/search-page.component.ts index 393af37c27..38647b779b 100644 --- a/src/app/search-page/search-page.component.ts +++ b/src/app/search-page/search-page.component.ts @@ -1,8 +1,16 @@ import { Component } from '@angular/core'; +import { SEARCH_CONFIG_SERVICE } from '../my-dspace-page/my-dspace-page.component'; +import { SearchConfigurationService } from '../core/shared/search/search-configuration.service'; @Component({ selector: 'ds-search-page', templateUrl: './search-page.component.html', + providers: [ + { + provide: SEARCH_CONFIG_SERVICE, + useClass: SearchConfigurationService + } + ] }) /** * This component represents the whole search page diff --git a/src/app/search-page/search-page.module.ts b/src/app/search-page/search-page.module.ts index 0cf6164f8a..758eca15c0 100644 --- a/src/app/search-page/search-page.module.ts +++ b/src/app/search-page/search-page.module.ts @@ -2,7 +2,6 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { CoreModule } from '../core/core.module'; import { SharedModule } from '../shared/shared.module'; -import { SearchComponent } from './search.component'; import { SidebarService } from '../shared/sidebar/sidebar.service'; import { ConfigurationSearchPageGuard } from './configuration-search-page.guard'; import { SearchTrackerComponent } from './search-tracker.component'; @@ -14,10 +13,10 @@ import { SearchConfigurationService } from '../core/shared/search/search-configu import { JournalEntitiesModule } from '../entity-groups/journal-entities/journal-entities.module'; import { ResearchEntitiesModule } from '../entity-groups/research-entities/research-entities.module'; import { ThemedSearchPageComponent } from './themed-search-page.component'; +import { SearchModule } from '../shared/search/search.module'; const components = [ SearchPageComponent, - SearchComponent, SearchTrackerComponent, ThemedSearchPageComponent ]; @@ -25,6 +24,7 @@ const components = [ @NgModule({ imports: [ CommonModule, + SearchModule, SharedModule.withEntryComponents(), CoreModule.forRoot(), StatisticsModule.forRoot(), diff --git a/src/app/search-page/search-tracker.component.ts b/src/app/search-page/search-tracker.component.ts index e7f59a2f23..f766e6f669 100644 --- a/src/app/search-page/search-tracker.component.ts +++ b/src/app/search-page/search-tracker.component.ts @@ -1,15 +1,15 @@ import { Component, Inject, OnInit } from '@angular/core'; import { Angulartics2 } from 'angulartics2'; import { map, switchMap } from 'rxjs/operators'; -import { SearchComponent } from './search.component'; +import { SearchComponent } from '../shared/search/search.component'; import { SidebarService } from '../shared/sidebar/sidebar.service'; import { HostWindowService } from '../shared/host-window.service'; import { SEARCH_CONFIG_SERVICE } from '../my-dspace-page/my-dspace-page.component'; import { RouteService } from '../core/services/route.service'; import { SearchConfigurationService } from '../core/shared/search/search-configuration.service'; import { SearchService } from '../core/shared/search/search.service'; -import { PaginatedSearchOptions } from '../shared/search/paginated-search-options.model'; -import { SearchObjects } from '../shared/search/search-objects.model'; +import { PaginatedSearchOptions } from '../shared/search/models/paginated-search-options.model'; +import { SearchObjects } from '../shared/search/models/search-objects.model'; import { Router } from '@angular/router'; import { RemoteData } from '../core/data/remote-data'; import { DSpaceObject } from '../core/shared/dspace-object.model'; diff --git a/src/app/search-page/search.component.html b/src/app/search-page/search.component.html deleted file mode 100644 index 3489cccdfb..0000000000 --- a/src/app/search-page/search.component.html +++ /dev/null @@ -1,59 +0,0 @@ -
-
-
- -
-
-
- -
-
- -
-
-
- - -
- -
-
-
- - - - - - - - - - -
-
- -
-
-
diff --git a/src/app/search-page/search.component.spec.ts b/src/app/search-page/search.component.spec.ts deleted file mode 100644 index 445f4614d3..0000000000 --- a/src/app/search-page/search.component.spec.ts +++ /dev/null @@ -1,206 +0,0 @@ -import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; - -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; -import { RouterTestingModule } from '@angular/router/testing'; -import { Store } from '@ngrx/store'; -import { TranslateModule } from '@ngx-translate/core'; -import { cold, hot } from 'jasmine-marbles'; -import { of as observableOf } from 'rxjs'; -import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model'; -import { CommunityDataService } from '../core/data/community-data.service'; -import { HostWindowService } from '../shared/host-window.service'; -import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model'; -import { SearchComponent } from './search.component'; -import { SearchService } from '../core/shared/search/search.service'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { ActivatedRoute } from '@angular/router'; -import { By } from '@angular/platform-browser'; -import { NgbCollapseModule } from '@ng-bootstrap/ng-bootstrap'; -import { SidebarService } from '../shared/sidebar/sidebar.service'; -import { SearchFilterService } from '../core/shared/search/search-filter.service'; -import { SearchConfigurationService } from '../core/shared/search/search-configuration.service'; -import { SEARCH_CONFIG_SERVICE } from '../my-dspace-page/my-dspace-page.component'; -import { RouteService } from '../core/services/route.service'; -import { SearchConfigurationServiceStub } from '../shared/testing/search-configuration-service.stub'; -import { createSuccessfulRemoteDataObject$ } from '../shared/remote-data.utils'; -import { PaginatedSearchOptions } from '../shared/search/paginated-search-options.model'; -import { SidebarServiceStub } from '../shared/testing/sidebar-service.stub'; - -let comp: SearchComponent; -let fixture: ComponentFixture; -let searchServiceObject: SearchService; -let searchConfigurationServiceObject: SearchConfigurationService; -const store: Store = jasmine.createSpyObj('store', { - /* tslint:disable:no-empty */ - dispatch: {}, - /* tslint:enable:no-empty */ - select: observableOf(true) -}); -const pagination: PaginationComponentOptions = new PaginationComponentOptions(); -pagination.id = 'search-results-pagination'; -pagination.currentPage = 1; -pagination.pageSize = 10; -const sortOption = { name: 'score', sortOrder: 'DESC', metadata: null }; -const sort: SortOptions = new SortOptions('score', SortDirection.DESC); -const mockResults = createSuccessfulRemoteDataObject$(['test', 'data']); -const searchServiceStub = jasmine.createSpyObj('SearchService', { - search: mockResults, - getSearchLink: '/search', - getScopes: observableOf(['test-scope']), - getSearchConfigurationFor: createSuccessfulRemoteDataObject$({ sortOptions: [sortOption]}) -}); -const configurationParam = 'default'; -const queryParam = 'test query'; -const scopeParam = '7669c72a-3f2a-451f-a3b9-9210e7a4c02f'; -const fixedFilter = 'fixed filter'; -const paginatedSearchOptions = new PaginatedSearchOptions({ - configuration: configurationParam, - query: queryParam, - scope: scopeParam, - fixedFilter: fixedFilter, - pagination, - sort -}); -const activatedRouteStub = { - snapshot: { - queryParamMap: new Map([ - ['query', queryParam], - ['scope', scopeParam] - ]) - }, - queryParams: observableOf({ - query: queryParam, - scope: scopeParam - }) -}; - -const routeServiceStub = { - getRouteParameterValue: () => { - return observableOf(''); - }, - getQueryParameterValue: () => { - return observableOf(''); - }, - getQueryParamsWithPrefix: () => { - return observableOf(''); - } -}; - -export function configureSearchComponentTestingModule(compType, additionalDeclarations: any[] = []) { - TestBed.configureTestingModule({ - imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), NoopAnimationsModule, NgbCollapseModule], - declarations: [compType, ...additionalDeclarations], - providers: [ - { provide: SearchService, useValue: searchServiceStub }, - { - provide: CommunityDataService, - useValue: jasmine.createSpyObj('communityService', ['findById', 'findAll']) - }, - { provide: ActivatedRoute, useValue: activatedRouteStub }, - { provide: RouteService, useValue: routeServiceStub }, - { - provide: Store, useValue: store - }, - { - provide: HostWindowService, useValue: jasmine.createSpyObj('hostWindowService', - { - isXs: observableOf(true), - isSm: observableOf(false), - isXsOrSm: observableOf(true) - }) - }, - { - provide: SidebarService, - useValue: SidebarServiceStub - }, - { - provide: SearchFilterService, - useValue: {} - }, - { - provide: SearchConfigurationService, - useValue: { - paginatedSearchOptions: hot('a', { - a: paginatedSearchOptions - }), - getCurrentScope: (a) => observableOf('test-id'), - /* tslint:disable:no-empty */ - updateFixedFilter: (newFilter) => { - } - /* tslint:enable:no-empty */ - } - }, - { - provide: SEARCH_CONFIG_SERVICE, - useValue: new SearchConfigurationServiceStub() - }, - ], - schemas: [NO_ERRORS_SCHEMA] - }).overrideComponent(compType, { - set: { changeDetection: ChangeDetectionStrategy.Default } - }).compileComponents(); -} - -describe('SearchComponent', () => { - beforeEach(waitForAsync(() => { - configureSearchComponentTestingModule(SearchComponent); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(SearchComponent); - comp = fixture.componentInstance; // SearchComponent test instance - comp.inPlaceSearch = false; - fixture.detectChanges(); - searchServiceObject = (comp as any).service; - searchConfigurationServiceObject = (comp as any).searchConfigService; - }); - - afterEach(() => { - comp = null; - searchServiceObject = null; - searchConfigurationServiceObject = null; - }); - - it('should get the scope and query from the route parameters', () => { - - searchConfigurationServiceObject.paginatedSearchOptions.next(paginatedSearchOptions); - expect(comp.searchOptions$).toBeObservable(cold('b', { - b: paginatedSearchOptions - })); - - }); - - describe('when the open sidebar button is clicked in mobile view', () => { - - beforeEach(() => { - spyOn(comp, 'openSidebar'); - const openSidebarButton = fixture.debugElement.query(By.css('.open-sidebar')); - openSidebarButton.triggerEventHandler('click', null); - }); - - it('should trigger the openSidebar function', () => { - expect(comp.openSidebar).toHaveBeenCalled(); - }); - - }); - - describe('when stable', () => { - - beforeEach(() => { - fixture.detectChanges(); - }); - - it('should have initialized the sortOptions$ observable', (done) => { - - comp.sortOptions$.subscribe((sortOptions) => { - - expect(sortOptions.length).toEqual(2); - expect(sortOptions[0]).toEqual(new SortOptions('score', SortDirection.ASC)); - expect(sortOptions[1]).toEqual(new SortOptions('score', SortDirection.DESC)); - done(); - }); - - }); - - }); -}); diff --git a/src/app/search-page/search.component.ts b/src/app/search-page/search.component.ts deleted file mode 100644 index 2972175bdf..0000000000 --- a/src/app/search-page/search.component.ts +++ /dev/null @@ -1,195 +0,0 @@ -import { ChangeDetectionStrategy, Component, Inject, Input, OnInit } from '@angular/core'; -import { BehaviorSubject, Observable, Subscription } from 'rxjs'; -import { startWith, switchMap } from 'rxjs/operators'; -import { PaginatedList } from '../core/data/paginated-list.model'; -import { RemoteData } from '../core/data/remote-data'; -import { DSpaceObject } from '../core/shared/dspace-object.model'; -import { pushInOut } from '../shared/animations/push'; -import { HostWindowService } from '../shared/host-window.service'; -import { SidebarService } from '../shared/sidebar/sidebar.service'; -import { hasValue, isEmpty } from '../shared/empty.util'; -import { getFirstCompletedRemoteData } from '../core/shared/operators'; -import { RouteService } from '../core/services/route.service'; -import { SEARCH_CONFIG_SERVICE } from '../my-dspace-page/my-dspace-page.component'; -import { PaginatedSearchOptions } from '../shared/search/paginated-search-options.model'; -import { SearchResult } from '../shared/search/search-result.model'; -import { SearchConfigurationService } from '../core/shared/search/search-configuration.service'; -import { SearchService } from '../core/shared/search/search.service'; -import { currentPath } from '../shared/utils/route.utils'; -import { Router } from '@angular/router'; -import { Context } from '../core/shared/context.model'; -import { SortOptions } from '../core/cache/models/sort-options.model'; -import { followLink } from '../shared/utils/follow-link-config.model'; -import { Item } from '../core/shared/item.model'; - -@Component({ - selector: 'ds-search', - styleUrls: ['./search.component.scss'], - templateUrl: './search.component.html', - changeDetection: ChangeDetectionStrategy.OnPush, - animations: [pushInOut], - providers: [ - { - provide: SEARCH_CONFIG_SERVICE, - useClass: SearchConfigurationService - } - ] -}) - -/** - * This component renders a sidebar, a search input bar and the search results. - */ -export class SearchComponent implements OnInit { - /** - * The current search results - */ - resultsRD$: BehaviorSubject>>> = new BehaviorSubject(null); - - /** - * The current paginated search options - */ - searchOptions$: Observable; - - /** - * The current available sort options - */ - sortOptions$: Observable; - - /** - * Emits true if were on a small screen - */ - isXsOrSm$: Observable; - - /** - * Subscription to unsubscribe from - */ - sub: Subscription; - - /** - * True when the search component should show results on the current page - */ - @Input() inPlaceSearch = true; - - /** - * Whether or not the search bar should be visible - */ - @Input() - searchEnabled = true; - - /** - * The width of the sidebar (bootstrap columns) - */ - @Input() - sideBarWidth = 3; - - /** - * The currently applied configuration (determines title of search) - */ - @Input() - configuration$: Observable; - - /** - * The current context - */ - @Input() - context: Context; - - /** - * Link to the search page - */ - searchLink: string; - - /** - * Observable for whether or not the sidebar is currently collapsed - */ - isSidebarCollapsed$: Observable; - - constructor(protected service: SearchService, - protected sidebarService: SidebarService, - protected windowService: HostWindowService, - @Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: SearchConfigurationService, - protected routeService: RouteService, - protected router: Router) { - this.isXsOrSm$ = this.windowService.isXsOrSm(); - } - - /** - * Listening to changes in the paginated search options - * If something changes, update the search results - * - * Listen to changes in the scope - * If something changes, update the list of scopes for the dropdown - */ - ngOnInit(): void { - this.isSidebarCollapsed$ = this.isSidebarCollapsed(); - this.searchLink = this.getSearchLink(); - this.searchOptions$ = this.getSearchOptions(); - this.sub = this.searchOptions$.pipe( - switchMap((options) => this.service.search( - options, undefined, false, true, followLink('thumbnail', { isOptional: true }) - ).pipe(getFirstCompletedRemoteData(), startWith(undefined)) - ) - ).subscribe((results) => { - this.resultsRD$.next(results); - }); - - if (isEmpty(this.configuration$)) { - this.configuration$ = this.searchConfigService.getCurrentConfiguration('default'); - } - - const searchConfig$ = this.searchConfigService.getConfigurationSearchConfigObservable(this.configuration$, this.service); - - this.sortOptions$ = this.searchConfigService.getConfigurationSortOptionsObservable(searchConfig$); - this.searchConfigService.initializeSortOptionsFromConfiguration(searchConfig$); - - } - - /** - * Get the current paginated search options - * @returns {Observable} - */ - protected getSearchOptions(): Observable { - return this.searchConfigService.paginatedSearchOptions; - } - - /** - * Set the sidebar to a collapsed state - */ - public closeSidebar(): void { - this.sidebarService.collapse(); - } - - /** - * Set the sidebar to an expanded state - */ - public openSidebar(): void { - this.sidebarService.expand(); - } - - /** - * Check if the sidebar is collapsed - * @returns {Observable} emits true if the sidebar is currently collapsed, false if it is expanded - */ - private isSidebarCollapsed(): Observable { - return this.sidebarService.isCollapsed; - } - - /** - * @returns {string} The base path to the search page, or the current page when inPlaceSearch is true - */ - private getSearchLink(): string { - if (this.inPlaceSearch) { - return currentPath(this.router); - } - return this.service.getSearchLink(); - } - - /** - * Unsubscribe from the subscription - */ - ngOnDestroy(): void { - if (hasValue(this.sub)) { - this.sub.unsubscribe(); - } - } -} diff --git a/src/app/search-page/themed-configuration-search-page.component.ts b/src/app/search-page/themed-configuration-search-page.component.ts index 1419d18a88..e4d6e93402 100644 --- a/src/app/search-page/themed-configuration-search-page.component.ts +++ b/src/app/search-page/themed-configuration-search-page.component.ts @@ -55,7 +55,7 @@ export class ThemedConfigurationSearchPageComponent extends ThemedComponent { let comp: ComColFormComponent; diff --git a/src/app/shared/comcol-forms/comcol-form/comcol-form.component.ts b/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.ts similarity index 85% rename from src/app/shared/comcol-forms/comcol-form/comcol-form.component.ts rename to src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.ts index ef7a5e55e8..c3ba9dcaee 100644 --- a/src/app/shared/comcol-forms/comcol-form/comcol-form.component.ts +++ b/src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.ts @@ -1,39 +1,27 @@ -import { - Component, - EventEmitter, - Input, - OnDestroy, - OnInit, - Output, - ViewChild -} from '@angular/core'; +import { Component, EventEmitter, Input, OnDestroy, OnInit, Output, ViewChild } from '@angular/core'; import { FormGroup } from '@angular/forms'; -import { - DynamicFormControlModel, - DynamicFormService, - DynamicInputModel -} from '@ng-dynamic-forms/core'; +import { DynamicFormControlModel, DynamicFormService, DynamicInputModel } from '@ng-dynamic-forms/core'; import { TranslateService } from '@ngx-translate/core'; import { FileUploader } from 'ng2-file-upload'; import { BehaviorSubject, combineLatest as observableCombineLatest, Subscription } from 'rxjs'; -import { AuthService } from '../../../core/auth/auth.service'; -import { ObjectCacheService } from '../../../core/cache/object-cache.service'; -import { ComColDataService } from '../../../core/data/comcol-data.service'; -import { RemoteData } from '../../../core/data/remote-data'; -import { RequestService } from '../../../core/data/request.service'; -import { RestRequestMethod } from '../../../core/data/rest-request-method'; -import { Bitstream } from '../../../core/shared/bitstream.model'; -import { Collection } from '../../../core/shared/collection.model'; -import { Community } from '../../../core/shared/community.model'; -import { MetadataMap, MetadataValue } from '../../../core/shared/metadata.models'; -import { ResourceType } from '../../../core/shared/resource-type'; -import { hasValue, isNotEmpty } from '../../empty.util'; -import { NotificationsService } from '../../notifications/notifications.service'; -import { UploaderOptions } from '../../uploader/uploader-options.model'; -import { UploaderComponent } from '../../uploader/uploader.component'; +import { AuthService } from '../../../../core/auth/auth.service'; +import { ObjectCacheService } from '../../../../core/cache/object-cache.service'; +import { ComColDataService } from '../../../../core/data/comcol-data.service'; +import { RemoteData } from '../../../../core/data/remote-data'; +import { RequestService } from '../../../../core/data/request.service'; +import { RestRequestMethod } from '../../../../core/data/rest-request-method'; +import { Bitstream } from '../../../../core/shared/bitstream.model'; +import { Collection } from '../../../../core/shared/collection.model'; +import { Community } from '../../../../core/shared/community.model'; +import { MetadataMap, MetadataValue } from '../../../../core/shared/metadata.models'; +import { ResourceType } from '../../../../core/shared/resource-type'; +import { hasValue, isNotEmpty } from '../../../empty.util'; +import { NotificationsService } from '../../../notifications/notifications.service'; +import { UploaderOptions } from '../../../uploader/uploader-options.model'; +import { UploaderComponent } from '../../../uploader/uploader.component'; import { Operation } from 'fast-json-patch'; -import { NoContent } from '../../../core/shared/NoContent.model'; -import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; +import { NoContent } from '../../../../core/shared/NoContent.model'; +import { getFirstCompletedRemoteData } from '../../../../core/shared/operators'; /** * A form for creating and editing Communities or Collections diff --git a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts b/src/app/shared/comcol/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts similarity index 90% rename from src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts rename to src/app/shared/comcol/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts index 05c3e50e4b..0104de83ca 100644 --- a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts +++ b/src/app/shared/comcol/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts @@ -1,20 +1,20 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; -import { CommunityDataService } from '../../../core/data/community-data.service'; -import { RouteService } from '../../../core/services/route.service'; +import { CommunityDataService } from '../../../../core/data/community-data.service'; +import { RouteService } from '../../../../core/services/route.service'; import { Router } from '@angular/router'; import { TranslateModule } from '@ngx-translate/core'; import { of as observableOf } from 'rxjs'; -import { Community } from '../../../core/shared/community.model'; -import { SharedModule } from '../../shared.module'; +import { Community } from '../../../../core/shared/community.model'; +import { SharedModule } from '../../../shared.module'; import { CommonModule } from '@angular/common'; import { RouterTestingModule } from '@angular/router/testing'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { CreateComColPageComponent } from './create-comcol-page.component'; -import { createFailedRemoteDataObject$, createSuccessfulRemoteDataObject$ } from '../../remote-data.utils'; -import { ComColDataService } from '../../../core/data/comcol-data.service'; -import { NotificationsService } from '../../notifications/notifications.service'; -import { NotificationsServiceStub } from '../../testing/notifications-service.stub'; -import { RequestService } from '../../../core/data/request.service'; +import { createFailedRemoteDataObject$, createSuccessfulRemoteDataObject$ } from '../../../remote-data.utils'; +import { ComColDataService } from '../../../../core/data/comcol-data.service'; +import { NotificationsService } from '../../../notifications/notifications.service'; +import { NotificationsServiceStub } from '../../../testing/notifications-service.stub'; +import { RequestService } from '../../../../core/data/request.service'; import { getTestScheduler } from 'jasmine-marbles'; describe('CreateComColPageComponent', () => { diff --git a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts b/src/app/shared/comcol/comcol-forms/create-comcol-page/create-comcol-page.component.ts similarity index 77% rename from src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts rename to src/app/shared/comcol/comcol-forms/create-comcol-page/create-comcol-page.component.ts index b1be5ae9be..2db9fcc20c 100644 --- a/src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts +++ b/src/app/shared/comcol/comcol-forms/create-comcol-page/create-comcol-page.component.ts @@ -3,18 +3,18 @@ import { Router } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; import { Observable } from 'rxjs'; import { mergeMap, take } from 'rxjs/operators'; -import { ComColDataService } from '../../../core/data/comcol-data.service'; -import { CommunityDataService } from '../../../core/data/community-data.service'; -import { RemoteData } from '../../../core/data/remote-data'; -import { RouteService } from '../../../core/services/route.service'; -import { Community } from '../../../core/shared/community.model'; -import { getFirstSucceededRemoteDataPayload, } from '../../../core/shared/operators'; -import { ResourceType } from '../../../core/shared/resource-type'; -import { hasValue, isNotEmpty, isNotUndefined } from '../../empty.util'; -import { NotificationsService } from '../../notifications/notifications.service'; -import { RequestParam } from '../../../core/cache/models/request-param.model'; -import { RequestService } from '../../../core/data/request.service'; -import { Collection } from '../../../core/shared/collection.model'; +import { ComColDataService } from '../../../../core/data/comcol-data.service'; +import { CommunityDataService } from '../../../../core/data/community-data.service'; +import { RemoteData } from '../../../../core/data/remote-data'; +import { RouteService } from '../../../../core/services/route.service'; +import { Community } from '../../../../core/shared/community.model'; +import { getFirstSucceededRemoteDataPayload, } from '../../../../core/shared/operators'; +import { ResourceType } from '../../../../core/shared/resource-type'; +import { hasValue, isNotEmpty, isNotUndefined } from '../../../empty.util'; +import { NotificationsService } from '../../../notifications/notifications.service'; +import { RequestParam } from '../../../../core/cache/models/request-param.model'; +import { RequestService } from '../../../../core/data/request.service'; +import { Collection } from '../../../../core/shared/collection.model'; /** * Component representing the create page for communities and collections diff --git a/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.spec.ts b/src/app/shared/comcol/comcol-forms/delete-comcol-page/delete-comcol-page.component.spec.ts similarity index 91% rename from src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.spec.ts rename to src/app/shared/comcol/comcol-forms/delete-comcol-page/delete-comcol-page.component.spec.ts index 6eaf102808..6aab79c5d4 100644 --- a/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.spec.ts +++ b/src/app/shared/comcol/comcol-forms/delete-comcol-page/delete-comcol-page.component.spec.ts @@ -1,20 +1,20 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; -import { CommunityDataService } from '../../../core/data/community-data.service'; +import { CommunityDataService } from '../../../../core/data/community-data.service'; import { ActivatedRoute, Router } from '@angular/router'; import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { of as observableOf } from 'rxjs'; -import { Community } from '../../../core/shared/community.model'; -import { SharedModule } from '../../shared.module'; +import { Community } from '../../../../core/shared/community.model'; +import { SharedModule } from '../../../shared.module'; import { CommonModule } from '@angular/common'; import { RouterTestingModule } from '@angular/router/testing'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { DeleteComColPageComponent } from './delete-comcol-page.component'; -import { NotificationsService } from '../../notifications/notifications.service'; -import { NotificationsServiceStub } from '../../testing/notifications-service.stub'; -import { RequestService } from '../../../core/data/request.service'; +import { NotificationsService } from '../../../notifications/notifications.service'; +import { NotificationsServiceStub } from '../../../testing/notifications-service.stub'; +import { RequestService } from '../../../../core/data/request.service'; import { getTestScheduler } from 'jasmine-marbles'; -import { ComColDataService } from '../../../core/data/comcol-data.service'; -import { createFailedRemoteDataObject$, createNoContentRemoteDataObject$ } from '../../remote-data.utils'; +import { ComColDataService } from '../../../../core/data/comcol-data.service'; +import { createFailedRemoteDataObject$, createNoContentRemoteDataObject$ } from '../../../remote-data.utils'; describe('DeleteComColPageComponent', () => { let comp: DeleteComColPageComponent; diff --git a/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.ts b/src/app/shared/comcol/comcol-forms/delete-comcol-page/delete-comcol-page.component.ts similarity index 80% rename from src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.ts rename to src/app/shared/comcol/comcol-forms/delete-comcol-page/delete-comcol-page.component.ts index 8579becc83..f781b71f3f 100644 --- a/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.ts +++ b/src/app/shared/comcol/comcol-forms/delete-comcol-page/delete-comcol-page.component.ts @@ -1,16 +1,16 @@ import { Component, OnInit } from '@angular/core'; import { BehaviorSubject, Observable } from 'rxjs'; import { ActivatedRoute, Router } from '@angular/router'; -import { RemoteData } from '../../../core/data/remote-data'; +import { RemoteData } from '../../../../core/data/remote-data'; import { first, map } from 'rxjs/operators'; -import { NotificationsService } from '../../notifications/notifications.service'; +import { NotificationsService } from '../../../notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; -import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; -import { NoContent } from '../../../core/shared/NoContent.model'; -import { RequestService } from '../../../core/data/request.service'; -import { ComColDataService } from '../../../core/data/comcol-data.service'; -import { Community } from '../../../core/shared/community.model'; -import { Collection } from '../../../core/shared/collection.model'; +import { getFirstCompletedRemoteData } from '../../../../core/shared/operators'; +import { NoContent } from '../../../../core/shared/NoContent.model'; +import { RequestService } from '../../../../core/data/request.service'; +import { ComColDataService } from '../../../../core/data/comcol-data.service'; +import { Community } from '../../../../core/shared/community.model'; +import { Collection } from '../../../../core/shared/collection.model'; /** * Component representing the delete page for communities and collections diff --git a/src/app/shared/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.spec.ts b/src/app/shared/comcol/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.spec.ts similarity index 92% rename from src/app/shared/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.spec.ts rename to src/app/shared/comcol/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.spec.ts index 9c8d616383..6588d9cbac 100644 --- a/src/app/shared/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.spec.ts +++ b/src/app/shared/comcol/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.spec.ts @@ -5,16 +5,16 @@ import { ActivatedRoute, Router } from '@angular/router'; import { RouterTestingModule } from '@angular/router/testing'; import { TranslateModule } from '@ngx-translate/core'; import { of as observableOf } from 'rxjs'; -import { ComColDataService } from '../../../../core/data/comcol-data.service'; -import { Community } from '../../../../core/shared/community.model'; -import { NotificationsService } from '../../../notifications/notifications.service'; -import { SharedModule } from '../../../shared.module'; -import { NotificationsServiceStub } from '../../../testing/notifications-service.stub'; +import { ComColDataService } from '../../../../../core/data/comcol-data.service'; +import { Community } from '../../../../../core/shared/community.model'; +import { NotificationsService } from '../../../../notifications/notifications.service'; +import { SharedModule } from '../../../../shared.module'; +import { NotificationsServiceStub } from '../../../../testing/notifications-service.stub'; import { createFailedRemoteDataObject$, createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ -} from '../../../remote-data.utils'; +} from '../../../../remote-data.utils'; import { ComcolMetadataComponent } from './comcol-metadata.component'; describe('ComColMetadataComponent', () => { diff --git a/src/app/shared/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.ts b/src/app/shared/comcol/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.ts similarity index 79% rename from src/app/shared/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.ts rename to src/app/shared/comcol/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.ts index cc68ad4970..5bd51ea650 100644 --- a/src/app/shared/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.ts +++ b/src/app/shared/comcol/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.ts @@ -1,17 +1,17 @@ import { Component, OnInit } from '@angular/core'; -import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; +import { DSpaceObject } from '../../../../../core/shared/dspace-object.model'; import { Observable } from 'rxjs'; -import { RemoteData } from '../../../../core/data/remote-data'; +import { RemoteData } from '../../../../../core/data/remote-data'; import { ActivatedRoute, Router } from '@angular/router'; import { first, map, take } from 'rxjs/operators'; -import { getFirstSucceededRemoteData, getFirstCompletedRemoteData } from '../../../../core/shared/operators'; -import { hasValue, isEmpty } from '../../../empty.util'; -import { ResourceType } from '../../../../core/shared/resource-type'; -import { ComColDataService } from '../../../../core/data/comcol-data.service'; -import { NotificationsService } from '../../../notifications/notifications.service'; +import { getFirstCompletedRemoteData, getFirstSucceededRemoteData } from '../../../../../core/shared/operators'; +import { hasValue, isEmpty } from '../../../../empty.util'; +import { ResourceType } from '../../../../../core/shared/resource-type'; +import { ComColDataService } from '../../../../../core/data/comcol-data.service'; +import { NotificationsService } from '../../../../notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; -import { Community } from '../../../../core/shared/community.model'; -import { Collection } from '../../../../core/shared/collection.model'; +import { Community } from '../../../../../core/shared/community.model'; +import { Collection } from '../../../../../core/shared/collection.model'; @Component({ selector: 'ds-comcol-metadata', diff --git a/src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.html b/src/app/shared/comcol/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.html similarity index 100% rename from src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.html rename to src/app/shared/comcol/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.html diff --git a/src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.scss b/src/app/shared/comcol/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.scss similarity index 100% rename from src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.scss rename to src/app/shared/comcol/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.scss diff --git a/src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.spec.ts b/src/app/shared/comcol/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.spec.ts similarity index 94% rename from src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.spec.ts rename to src/app/shared/comcol/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.spec.ts index cc5b64b9b5..175abe48e4 100644 --- a/src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.spec.ts +++ b/src/app/shared/comcol/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.spec.ts @@ -1,15 +1,15 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { ComcolRoleComponent } from './comcol-role.component'; -import { GroupDataService } from '../../../../core/eperson/group-data.service'; +import { GroupDataService } from '../../../../../core/eperson/group-data.service'; import { By } from '@angular/platform-browser'; -import { SharedModule } from '../../../shared.module'; import { TranslateModule } from '@ngx-translate/core'; import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'; -import { RequestService } from '../../../../core/data/request.service'; +import { RequestService } from '../../../../../core/data/request.service'; import { of as observableOf } from 'rxjs'; import { RouterTestingModule } from '@angular/router/testing'; -import { createFailedRemoteDataObject$, createSuccessfulRemoteDataObject$ } from '../../../remote-data.utils'; +import { createFailedRemoteDataObject$, createSuccessfulRemoteDataObject$ } from '../../../../remote-data.utils'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { ComcolModule } from '../../../comcol.module'; describe('ComcolRoleComponent', () => { @@ -32,7 +32,7 @@ describe('ComcolRoleComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [ - SharedModule, + ComcolModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NoopAnimationsModule diff --git a/src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.ts b/src/app/shared/comcol/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.ts similarity index 82% rename from src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.ts rename to src/app/shared/comcol/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.ts index 4eb364a3cc..7ed88fae1c 100644 --- a/src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.ts +++ b/src/app/shared/comcol/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.ts @@ -1,17 +1,17 @@ import { Component, Input, OnInit } from '@angular/core'; -import { Group } from '../../../../core/eperson/models/group.model'; -import { Community } from '../../../../core/shared/community.model'; +import { Group } from '../../../../../core/eperson/models/group.model'; +import { Community } from '../../../../../core/shared/community.model'; import { BehaviorSubject, Observable } from 'rxjs'; -import { GroupDataService } from '../../../../core/eperson/group-data.service'; -import { Collection } from '../../../../core/shared/collection.model'; +import { GroupDataService } from '../../../../../core/eperson/group-data.service'; +import { Collection } from '../../../../../core/shared/collection.model'; import { filter, map, switchMap } from 'rxjs/operators'; -import { getAllCompletedRemoteData, getFirstCompletedRemoteData } from '../../../../core/shared/operators'; -import { RequestService } from '../../../../core/data/request.service'; -import { RemoteData } from '../../../../core/data/remote-data'; -import { HALLink } from '../../../../core/shared/hal-link.model'; -import { getGroupEditRoute } from '../../../../access-control/access-control-routing-paths'; -import { hasNoValue, hasValue } from '../../../empty.util'; -import { NoContent } from '../../../../core/shared/NoContent.model'; +import { getAllCompletedRemoteData, getFirstCompletedRemoteData } from '../../../../../core/shared/operators'; +import { RequestService } from '../../../../../core/data/request.service'; +import { RemoteData } from '../../../../../core/data/remote-data'; +import { HALLink } from '../../../../../core/shared/hal-link.model'; +import { getGroupEditRoute } from '../../../../../access-control/access-control-routing-paths'; +import { hasNoValue, hasValue } from '../../../../empty.util'; +import { NoContent } from '../../../../../core/shared/NoContent.model'; /** * Component for managing a community or collection role. diff --git a/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.html b/src/app/shared/comcol/comcol-forms/edit-comcol-page/edit-comcol-page.component.html similarity index 100% rename from src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.html rename to src/app/shared/comcol/comcol-forms/edit-comcol-page/edit-comcol-page.component.html diff --git a/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.spec.ts b/src/app/shared/comcol/comcol-forms/edit-comcol-page/edit-comcol-page.component.spec.ts similarity index 91% rename from src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.spec.ts rename to src/app/shared/comcol/comcol-forms/edit-comcol-page/edit-comcol-page.component.spec.ts index d13958bb79..d3d936c9f7 100644 --- a/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.spec.ts +++ b/src/app/shared/comcol/comcol-forms/edit-comcol-page/edit-comcol-page.component.spec.ts @@ -2,12 +2,12 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { ActivatedRoute, Router } from '@angular/router'; import { TranslateModule } from '@ngx-translate/core'; import { of as observableOf } from 'rxjs'; -import { Community } from '../../../core/shared/community.model'; -import { SharedModule } from '../../shared.module'; +import { Community } from '../../../../core/shared/community.model'; +import { SharedModule } from '../../../shared.module'; import { CommonModule } from '@angular/common'; import { RouterTestingModule } from '@angular/router/testing'; import { NO_ERRORS_SCHEMA } from '@angular/core'; -import { DSpaceObject } from '../../../core/shared/dspace-object.model'; +import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; import { EditComColPageComponent } from './edit-comcol-page.component'; describe('EditComColPageComponent', () => { diff --git a/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.ts b/src/app/shared/comcol/comcol-forms/edit-comcol-page/edit-comcol-page.component.ts similarity index 90% rename from src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.ts rename to src/app/shared/comcol/comcol-forms/edit-comcol-page/edit-comcol-page.component.ts index 793065096f..48eb9aec96 100644 --- a/src/app/shared/comcol-forms/edit-comcol-page/edit-comcol-page.component.ts +++ b/src/app/shared/comcol/comcol-forms/edit-comcol-page/edit-comcol-page.component.ts @@ -4,9 +4,9 @@ import { Observable } from 'rxjs'; import { first, map } from 'rxjs/operators'; import { ActivatedRoute, Router } from '@angular/router'; -import { RemoteData } from '../../../core/data/remote-data'; -import { isNotEmpty } from '../../empty.util'; -import { DSpaceObject } from '../../../core/shared/dspace-object.model'; +import { RemoteData } from '../../../../core/data/remote-data'; +import { isNotEmpty } from '../../../empty.util'; +import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; /** * Component representing the edit page for communities and collections diff --git a/src/app/shared/comcol-page-browse-by/comcol-page-browse-by.component.html b/src/app/shared/comcol/comcol-page-browse-by/comcol-page-browse-by.component.html similarity index 100% rename from src/app/shared/comcol-page-browse-by/comcol-page-browse-by.component.html rename to src/app/shared/comcol/comcol-page-browse-by/comcol-page-browse-by.component.html diff --git a/src/app/shared/comcol-page-browse-by/comcol-page-browse-by.component.scss b/src/app/shared/comcol/comcol-page-browse-by/comcol-page-browse-by.component.scss similarity index 100% rename from src/app/shared/comcol-page-browse-by/comcol-page-browse-by.component.scss rename to src/app/shared/comcol/comcol-page-browse-by/comcol-page-browse-by.component.scss diff --git a/src/app/shared/comcol-page-browse-by/comcol-page-browse-by.component.ts b/src/app/shared/comcol/comcol-page-browse-by/comcol-page-browse-by.component.ts similarity index 81% rename from src/app/shared/comcol-page-browse-by/comcol-page-browse-by.component.ts rename to src/app/shared/comcol/comcol-page-browse-by/comcol-page-browse-by.component.ts index 08f7ec67ee..0527d283f0 100644 --- a/src/app/shared/comcol-page-browse-by/comcol-page-browse-by.component.ts +++ b/src/app/shared/comcol/comcol-page-browse-by/comcol-page-browse-by.component.ts @@ -2,13 +2,13 @@ import { Component, Input, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { ActivatedRoute, Params, Router } from '@angular/router'; -import { getCommunityPageRoute } from '../../community-page/community-page-routing-paths'; -import { getCollectionPageRoute } from '../../collection-page/collection-page-routing-paths'; -import { getFirstCompletedRemoteData } from '../../core/shared/operators'; -import { PaginatedList } from '../../core/data/paginated-list.model'; -import { BrowseDefinition } from '../../core/shared/browse-definition.model'; -import { RemoteData } from '../../core/data/remote-data'; -import { BrowseService } from '../../core/browse/browse.service'; +import { getCommunityPageRoute } from '../../../community-page/community-page-routing-paths'; +import { getCollectionPageRoute } from '../../../collection-page/collection-page-routing-paths'; +import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; +import { PaginatedList } from '../../../core/data/paginated-list.model'; +import { BrowseDefinition } from '../../../core/shared/browse-definition.model'; +import { RemoteData } from '../../../core/data/remote-data'; +import { BrowseService } from '../../../core/browse/browse.service'; export interface ComColPageNavOption { id: string; diff --git a/src/app/shared/comcol-page-content/comcol-page-content.component.html b/src/app/shared/comcol/comcol-page-content/comcol-page-content.component.html similarity index 100% rename from src/app/shared/comcol-page-content/comcol-page-content.component.html rename to src/app/shared/comcol/comcol-page-content/comcol-page-content.component.html diff --git a/src/app/shared/comcol-page-content/comcol-page-content.component.scss b/src/app/shared/comcol/comcol-page-content/comcol-page-content.component.scss similarity index 100% rename from src/app/shared/comcol-page-content/comcol-page-content.component.scss rename to src/app/shared/comcol/comcol-page-content/comcol-page-content.component.scss diff --git a/src/app/shared/comcol-page-content/comcol-page-content.component.ts b/src/app/shared/comcol/comcol-page-content/comcol-page-content.component.ts similarity index 100% rename from src/app/shared/comcol-page-content/comcol-page-content.component.ts rename to src/app/shared/comcol/comcol-page-content/comcol-page-content.component.ts diff --git a/src/app/shared/comcol-page-handle/comcol-page-handle.component.html b/src/app/shared/comcol/comcol-page-handle/comcol-page-handle.component.html similarity index 100% rename from src/app/shared/comcol-page-handle/comcol-page-handle.component.html rename to src/app/shared/comcol/comcol-page-handle/comcol-page-handle.component.html diff --git a/src/app/shared/comcol-page-handle/comcol-page-handle.component.scss b/src/app/shared/comcol/comcol-page-handle/comcol-page-handle.component.scss similarity index 100% rename from src/app/shared/comcol-page-handle/comcol-page-handle.component.scss rename to src/app/shared/comcol/comcol-page-handle/comcol-page-handle.component.scss diff --git a/src/app/shared/comcol-page-handle/comcol-page-handle.component.spec.ts b/src/app/shared/comcol/comcol-page-handle/comcol-page-handle.component.spec.ts similarity index 100% rename from src/app/shared/comcol-page-handle/comcol-page-handle.component.spec.ts rename to src/app/shared/comcol/comcol-page-handle/comcol-page-handle.component.spec.ts diff --git a/src/app/shared/comcol-page-handle/comcol-page-handle.component.ts b/src/app/shared/comcol/comcol-page-handle/comcol-page-handle.component.ts similarity index 100% rename from src/app/shared/comcol-page-handle/comcol-page-handle.component.ts rename to src/app/shared/comcol/comcol-page-handle/comcol-page-handle.component.ts diff --git a/src/app/shared/comcol-page-header/comcol-page-header.component.html b/src/app/shared/comcol/comcol-page-header/comcol-page-header.component.html similarity index 100% rename from src/app/shared/comcol-page-header/comcol-page-header.component.html rename to src/app/shared/comcol/comcol-page-header/comcol-page-header.component.html diff --git a/src/app/shared/comcol-page-header/comcol-page-header.component.scss b/src/app/shared/comcol/comcol-page-header/comcol-page-header.component.scss similarity index 100% rename from src/app/shared/comcol-page-header/comcol-page-header.component.scss rename to src/app/shared/comcol/comcol-page-header/comcol-page-header.component.scss diff --git a/src/app/shared/comcol-page-header/comcol-page-header.component.ts b/src/app/shared/comcol/comcol-page-header/comcol-page-header.component.ts similarity index 100% rename from src/app/shared/comcol-page-header/comcol-page-header.component.ts rename to src/app/shared/comcol/comcol-page-header/comcol-page-header.component.ts diff --git a/src/app/shared/comcol-page-logo/comcol-page-logo.component.html b/src/app/shared/comcol/comcol-page-logo/comcol-page-logo.component.html similarity index 100% rename from src/app/shared/comcol-page-logo/comcol-page-logo.component.html rename to src/app/shared/comcol/comcol-page-logo/comcol-page-logo.component.html diff --git a/src/app/shared/comcol-page-logo/comcol-page-logo.component.scss b/src/app/shared/comcol/comcol-page-logo/comcol-page-logo.component.scss similarity index 100% rename from src/app/shared/comcol-page-logo/comcol-page-logo.component.scss rename to src/app/shared/comcol/comcol-page-logo/comcol-page-logo.component.scss diff --git a/src/app/shared/comcol-page-logo/comcol-page-logo.component.ts b/src/app/shared/comcol/comcol-page-logo/comcol-page-logo.component.ts similarity index 95% rename from src/app/shared/comcol-page-logo/comcol-page-logo.component.ts rename to src/app/shared/comcol/comcol-page-logo/comcol-page-logo.component.ts index f3c2d4e80d..a9761bfd5f 100644 --- a/src/app/shared/comcol-page-logo/comcol-page-logo.component.ts +++ b/src/app/shared/comcol/comcol-page-logo/comcol-page-logo.component.ts @@ -1,6 +1,6 @@ import { Component, Input } from '@angular/core'; -import { Bitstream } from '../../core/shared/bitstream.model'; +import { Bitstream } from '../../../core/shared/bitstream.model'; @Component({ selector: 'ds-comcol-page-logo', diff --git a/src/app/shared/comcol/comcol.module.ts b/src/app/shared/comcol/comcol.module.ts new file mode 100644 index 0000000000..664f14a098 --- /dev/null +++ b/src/app/shared/comcol/comcol.module.ts @@ -0,0 +1,42 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ComcolPageContentComponent } from './comcol-page-content/comcol-page-content.component'; +import { ComcolPageHandleComponent } from './comcol-page-handle/comcol-page-handle.component'; +import { ComcolPageHeaderComponent } from './comcol-page-header/comcol-page-header.component'; +import { ComcolPageLogoComponent } from './comcol-page-logo/comcol-page-logo.component'; +import { ComColFormComponent } from './comcol-forms/comcol-form/comcol-form.component'; +import { CreateComColPageComponent } from './comcol-forms/create-comcol-page/create-comcol-page.component'; +import { EditComColPageComponent } from './comcol-forms/edit-comcol-page/edit-comcol-page.component'; +import { DeleteComColPageComponent } from './comcol-forms/delete-comcol-page/delete-comcol-page.component'; +import { ComcolPageBrowseByComponent } from './comcol-page-browse-by/comcol-page-browse-by.component'; +import { ComcolRoleComponent } from './comcol-forms/edit-comcol-page/comcol-role/comcol-role.component'; +import { SharedModule } from '../shared.module'; +import { FormModule } from '../form/form.module'; + +const COMPONENTS = [ + ComcolPageContentComponent, + ComcolPageHandleComponent, + ComcolPageHeaderComponent, + ComcolPageLogoComponent, + ComColFormComponent, + CreateComColPageComponent, + EditComColPageComponent, + DeleteComColPageComponent, + ComcolPageBrowseByComponent, + ComcolRoleComponent, +]; + +@NgModule({ + declarations: [ + ...COMPONENTS + ], + imports: [ + CommonModule, + FormModule, + SharedModule + ], + exports: [ + ...COMPONENTS + ] +}) +export class ComcolModule { } diff --git a/src/app/shared/dso-selector/dso-selector/authorized-collection-selector/authorized-collection-selector.component.ts b/src/app/shared/dso-selector/dso-selector/authorized-collection-selector/authorized-collection-selector.component.ts index b6aa0b3413..176d131566 100644 --- a/src/app/shared/dso-selector/dso-selector/authorized-collection-selector/authorized-collection-selector.component.ts +++ b/src/app/shared/dso-selector/dso-selector/authorized-collection-selector/authorized-collection-selector.component.ts @@ -6,7 +6,7 @@ import { Observable } from 'rxjs'; import { getFirstCompletedRemoteData } from '../../../../core/shared/operators'; import { map } from 'rxjs/operators'; import { CollectionSearchResult } from '../../../object-collection/shared/collection-search-result.model'; -import { SearchResult } from '../../../search/search-result.model'; +import { SearchResult } from '../../../search/models/search-result.model'; import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; import { buildPaginatedList, PaginatedList } from '../../../../core/data/paginated-list.model'; import { followLink } from '../../../utils/follow-link-config.model'; diff --git a/src/app/shared/dso-selector/dso-selector/dso-selector.component.spec.ts b/src/app/shared/dso-selector/dso-selector/dso-selector.component.spec.ts index 2565b36f7d..7c28859388 100644 --- a/src/app/shared/dso-selector/dso-selector/dso-selector.component.spec.ts +++ b/src/app/shared/dso-selector/dso-selector/dso-selector.component.spec.ts @@ -7,7 +7,7 @@ import { DSpaceObjectType } from '../../../core/shared/dspace-object-type.model' import { ItemSearchResult } from '../../object-collection/shared/item-search-result.model'; import { Item } from '../../../core/shared/item.model'; import { createFailedRemoteDataObject$, createSuccessfulRemoteDataObject$ } from '../../remote-data.utils'; -import { PaginatedSearchOptions } from '../../search/paginated-search-options.model'; +import { PaginatedSearchOptions } from '../../search/models/paginated-search-options.model'; import { hasValue } from '../../empty.util'; import { createPaginatedList } from '../../testing/utils.test'; import { NotificationsService } from '../../notifications/notifications.service'; diff --git a/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts b/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts index ebd9f24b61..82ad095cd4 100644 --- a/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts +++ b/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts @@ -22,15 +22,15 @@ import { debounceTime, map, startWith, switchMap, tap } from 'rxjs/operators'; import { SearchService } from '../../../core/shared/search/search.service'; import { CollectionElementLinkType } from '../../object-collection/collection-element-link.type'; -import { PaginatedSearchOptions } from '../../search/paginated-search-options.model'; +import { PaginatedSearchOptions } from '../../search/models/paginated-search-options.model'; import { DSpaceObjectType } from '../../../core/shared/dspace-object-type.model'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { ViewMode } from '../../../core/shared/view-mode.model'; import { Context } from '../../../core/shared/context.model'; import { getFirstCompletedRemoteData, getFirstSucceededRemoteDataPayload } from '../../../core/shared/operators'; import { hasNoValue, hasValue, isEmpty, isNotEmpty } from '../../empty.util'; -import { PaginatedList, buildPaginatedList } from '../../../core/data/paginated-list.model'; -import { SearchResult } from '../../search/search-result.model'; +import { buildPaginatedList, PaginatedList } from '../../../core/data/paginated-list.model'; +import { SearchResult } from '../../search/models/search-result.model'; import { RemoteData } from '../../../core/data/remote-data'; import { NotificationsService } from '../../notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts index 7adb9a837b..eb448a7d24 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts @@ -81,7 +81,7 @@ import { DYNAMIC_FORM_CONTROL_TYPE_CUSTOM_SWITCH } from './models/custom-switch/ import { CustomSwitchComponent } from './models/custom-switch/custom-switch.component'; import { find, map, startWith, switchMap, take } from 'rxjs/operators'; import { combineLatest as observableCombineLatest, Observable, Subscription } from 'rxjs'; -import { SearchResult } from '../../../search/search-result.model'; +import { SearchResult } from '../../../search/models/search-result.model'; import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { RelationshipService } from '../../../../core/data/relationship.service'; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.html index 058b3142c3..f95cd98c65 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.html @@ -26,6 +26,7 @@ [toRemove]="toRemove" (selectObject)="select($event)" (deselectObject)="deselect($event)" + (resultFound)="setTotalInternals($event.pageInfo.totalElements)" class="d-block pt-3"> @@ -81,7 +82,7 @@  {{"item.edit.metadata.discard-button" | translate}} - - -
- - - - -
- - + {{ ('submission.sections.describe.relationship-lookup.search-tab.loading' | translate) }} + + +
+ + + +
- - - + - + + + diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component.spec.ts index f2e7efeaa5..72c026e42e 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component.spec.ts @@ -4,26 +4,23 @@ import { DsDynamicLookupRelationSearchTabComponent } from './dynamic-lookup-rela import { SearchService } from '../../../../../../core/shared/search/search.service'; import { SelectableListService } from '../../../../../object-list/selectable-list/selectable-list.service'; import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service'; -import { RouteService } from '../../../../../../core/services/route.service'; import { RouterTestingModule } from '@angular/router/testing'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { VarDirective } from '../../../../../utils/var.directive'; import { RelationshipOptions } from '../../../models/relationship-options.model'; import { of as observableOf } from 'rxjs'; -import { PaginatedSearchOptions } from '../../../../../search/paginated-search-options.model'; +import { PaginatedSearchOptions } from '../../../../../search/models/paginated-search-options.model'; import { createSuccessfulRemoteDataObject$ } from '../../../../../remote-data.utils'; import { buildPaginatedList } from '../../../../../../core/data/paginated-list.model'; import { ItemSearchResult } from '../../../../../object-collection/shared/item-search-result.model'; import { Item } from '../../../../../../core/shared/item.model'; -import { ActivatedRoute } from '@angular/router'; import { LookupRelationService } from '../../../../../../core/data/lookup-relation.service'; import { PaginationService } from '../../../../../../core/pagination/pagination.service'; import { PaginationServiceStub } from '../../../../../testing/pagination-service.stub'; import { RelationshipService } from '../../../../../../core/data/relationship.service'; import { relatedRelationships } from '../../../../../testing/related-relationships.mock'; -import { RelationshipTypeService } from '../../../../../../core/data/relationship-type.service'; import { RelationshipType } from '../../../../../../core/shared/item-relationships/relationship-type.model'; - +import { SearchObjects } from '../../../../../search/models/search-objects.model'; describe('DsDynamicLookupRelationSearchTabComponent', () => { @@ -43,6 +40,7 @@ describe('DsDynamicLookupRelationSearchTabComponent', () => { let selection$; let results; + let searchResult; let selectableListService; let lookupRelationService; const relationshipService = jasmine.createSpyObj('searchByItemsAndType',{ @@ -81,6 +79,9 @@ describe('DsDynamicLookupRelationSearchTabComponent', () => { selection$ = observableOf([searchResult1, searchResult2]); results = buildPaginatedList(undefined, [searchResult1, searchResult2, searchResult3]); + searchResult = Object.assign(new SearchObjects(), { + page: [searchResult1, searchResult2, searchResult3] + }); selectableListService = jasmine.createSpyObj('selectableListService', ['deselect', 'select', 'deselectAll']); lookupRelationService = jasmine.createSpyObj('lookupRelationService', { getLocalResults: createSuccessfulRemoteDataObject$(results) @@ -103,14 +104,6 @@ describe('DsDynamicLookupRelationSearchTabComponent', () => { paginatedSearchOptions: observableOf(pSearchOptions) } }, - { - provide: RouteService, useValue: { - setParameter: () => { - // do nothing - } - } - }, - { provide: ActivatedRoute, useValue: { snapshot: { queryParams: {} } } }, { provide: LookupRelationService, useValue: lookupRelationService }, { provide: PaginationService, useValue: new PaginationServiceStub() }, { provide: RelationshipService, useValue: relationshipService } @@ -188,6 +181,7 @@ describe('DsDynamicLookupRelationSearchTabComponent', () => { describe('check searchByItemsAndType', () => { it('should call relationshipService.searchByItemsAndType', () => { + component.onResultFound(searchResult); expect(relationshipService.searchByItemsAndType).toHaveBeenCalled(); }); }); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component.ts index 96af591540..f70f073743 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component.ts @@ -2,20 +2,17 @@ import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angu import { SEARCH_CONFIG_SERVICE } from '../../../../../../my-dspace-page/my-dspace-page.component'; import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service'; import { Item } from '../../../../../../core/shared/item.model'; -import { SearchResult } from '../../../../../search/search-result.model'; +import { SearchResult } from '../../../../../search/models/search-result.model'; import { PaginatedList } from '../../../../../../core/data/paginated-list.model'; -import { RemoteData } from '../../../../../../core/data/remote-data'; import { Observable } from 'rxjs'; import { RelationshipOptions } from '../../../models/relationship-options.model'; import { PaginationComponentOptions } from '../../../../../pagination/pagination-component-options.model'; import { ListableObject } from '../../../../../object-collection/shared/listable-object.model'; import { SearchService } from '../../../../../../core/shared/search/search.service'; -import { ActivatedRoute, Router } from '@angular/router'; import { SelectableListService } from '../../../../../object-list/selectable-list/selectable-list.service'; import { hasValue } from '../../../../../empty.util'; -import { map, mapTo, startWith, switchMap, take, tap } from 'rxjs/operators'; +import { map, mapTo, switchMap, take, tap } from 'rxjs/operators'; import { getFirstSucceededRemoteData, getRemoteDataPayload } from '../../../../../../core/shared/operators'; -import { RouteService } from '../../../../../../core/services/route.service'; import { CollectionElementLinkType } from '../../../../../object-collection/collection-element-link.type'; import { Context } from '../../../../../../core/shared/context.model'; import { LookupRelationService } from '../../../../../../core/data/lookup-relation.service'; @@ -24,6 +21,9 @@ import { RelationshipService } from '../../../../../../core/data/relationship.se import { RelationshipType } from '../../../../../../core/shared/item-relationships/relationship-type.model'; import { Relationship } from '../../../../../../core/shared/item-relationships/relationship.model'; +import { SearchObjects } from '../../../../../search/models/search-objects.model'; +import { DSpaceObject } from '../../../../../../core/shared/dspace-object.model'; +import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject'; @Component({ @@ -107,7 +107,7 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest /** * Search results */ - resultsRD$: Observable>>>; + resultsRD$: BehaviorSubject> = new BehaviorSubject>(null); /** * Are all results selected? @@ -142,13 +142,15 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest */ linkTypes = CollectionElementLinkType; + /** + * Emits an event with the current search result entries + */ + @Output() resultFound: EventEmitter> = new EventEmitter>(); + constructor( private searchService: SearchService, - private router: Router, - private route: ActivatedRoute, private selectableListService: SelectableListService, public searchConfigService: SearchConfigurationService, - private routeService: RouteService, public lookupRelationService: LookupRelationService, private relationshipService: RelationshipService, private paginationService: PaginationService @@ -160,21 +162,6 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest */ ngOnInit(): void { this.resetRoute(); - this.routeService.setParameter('fixedFilterQuery', this.relationship.filter); - this.routeService.setParameter('configuration', this.relationship.searchConfiguration); - this.resultsRD$ = this.searchConfigService.paginatedSearchOptions.pipe( - switchMap((options) => this.lookupRelationService.getLocalResults(this.relationship, options).pipe( - tap( res => { - if ( !!res && res.hasSucceeded && this.isEditRelationship ) { - const idOfItems = res.payload.page.map( itemSearchResult => { - return itemSearchResult.indexableObject.uuid; - }); - this.setSelectedIds(idOfItems,res.payload.page); - } - }), - startWith(undefined), - )) - ); } /** @@ -188,7 +175,7 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest * Selects a page in the store * @param page The page to select */ - selectPage(page: SearchResult[]) { + selectPage(page: SearchResult[]) { this.selection$ .pipe(take(1)) .subscribe((selection: SearchResult[]) => { @@ -202,7 +189,7 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest * Deselects a page in the store * @param page the page to deselect */ - deselectPage(page: SearchResult[]) { + deselectPage(page: SearchResult[]) { this.allSelected = false; this.selection$ .pipe(take(1)) @@ -247,7 +234,7 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest * @param idOfItems the uuid of items that are being checked * @param resultListOfItems the list of results of the items */ - setSelectedIds(idOfItems, resultListOfItems) { + setSelectedIds(idOfItems: string[], resultListOfItems: SearchResult[]) { let relationType = this.relationshipType.rightwardType; if ( this.isLeft ) { relationType = this.relationshipType.leftwardType; @@ -267,7 +254,7 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest } const uuid = arrUrl[ arrUrl.length - 1 ]; - return this.getRelatedItem(uuid,resultListOfItems); + return this.getRelatedItem(uuid, resultListOfItems); }); selectableObject = selectableObject.filter( (selObject) => { @@ -287,11 +274,11 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest this.allSelected = false; this.selection$ .pipe(take(1)) - .subscribe((selection: SearchResult[]) => this.deselectObject.emit(...selection)); + .subscribe((selection: SearchResult[]) => this.deselectObject.emit(...selection)); this.selectableListService.deselectAll(this.listId); } - getRelatedItem(uuid: string, resultList: SearchResult[]) { + getRelatedItem(uuid: string, resultList: SearchResult[]) { return resultList.find( (resultItem) => { return resultItem.indexableObject.uuid === uuid; }); @@ -306,4 +293,15 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest this.subscription.unsubscribe(); } } + + onResultFound($event: SearchObjects) { + this.resultsRD$.next($event); + this.resultFound.emit($event); + if (this.isEditRelationship ) { + const idOfItems = $event.page.map( itemSearchResult => { + return itemSearchResult.indexableObject.uuid; + }); + this.setSelectedIds(idOfItems, $event.page); + } + } } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/selection-tab/dynamic-lookup-relation-selection-tab.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/selection-tab/dynamic-lookup-relation-selection-tab.component.spec.ts index dbe46609a6..472a719b27 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/selection-tab/dynamic-lookup-relation-selection-tab.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/selection-tab/dynamic-lookup-relation-selection-tab.component.spec.ts @@ -4,7 +4,7 @@ import { SearchConfigurationService } from '../../../../../../core/shared/search import { NO_ERRORS_SCHEMA } from '@angular/core'; import { VarDirective } from '../../../../../utils/var.directive'; import { Observable, of as observableOf } from 'rxjs'; -import { PaginatedSearchOptions } from '../../../../../search/paginated-search-options.model'; +import { PaginatedSearchOptions } from '../../../../../search/models/paginated-search-options.model'; import { ItemSearchResult } from '../../../../../object-collection/shared/item-search-result.model'; import { Item } from '../../../../../../core/shared/item.model'; import { DsDynamicLookupRelationSelectionTabComponent } from './dynamic-lookup-relation-selection-tab.component'; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/selection-tab/dynamic-lookup-relation-selection-tab.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/selection-tab/dynamic-lookup-relation-selection-tab.component.ts index 9ba0ee2413..a78bf8896c 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/selection-tab/dynamic-lookup-relation-selection-tab.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/selection-tab/dynamic-lookup-relation-selection-tab.component.ts @@ -8,7 +8,7 @@ import { map, switchMap, take } from 'rxjs/operators'; import { PaginationComponentOptions } from '../../../../../pagination/pagination-component-options.model'; import { buildPaginatedList, PaginatedList } from '../../../../../../core/data/paginated-list.model'; import { Router } from '@angular/router'; -import { PaginatedSearchOptions } from '../../../../../search/paginated-search-options.model'; +import { PaginatedSearchOptions } from '../../../../../search/models/paginated-search-options.model'; import { PageInfo } from '../../../../../../core/shared/page-info.model'; import { Context } from '../../../../../../core/shared/context.model'; import { createSuccessfulRemoteDataObject } from '../../../../../remote-data.utils'; diff --git a/src/app/shared/form/form.module.ts b/src/app/shared/form/form.module.ts new file mode 100644 index 0000000000..62ab5bd647 --- /dev/null +++ b/src/app/shared/form/form.module.ts @@ -0,0 +1,82 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormComponent } from './form.component'; +import { DsDynamicFormComponent } from './builder/ds-dynamic-form-ui/ds-dynamic-form.component'; +import { + DsDynamicFormControlContainerComponent, + dsDynamicFormControlMapFn +} from './builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component'; +import { DsDynamicListComponent } from './builder/ds-dynamic-form-ui/models/list/dynamic-list.component'; +import { DsDynamicLookupComponent } from './builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component'; +import { DsDynamicDisabledComponent } from './builder/ds-dynamic-form-ui/models/disabled/dynamic-disabled.component'; +import { DsDynamicLookupRelationModalComponent } from './builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component'; +import { DsDynamicScrollableDropdownComponent } from './builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component'; +import { DsDynamicTagComponent } from './builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component'; +import { DsDynamicOneboxComponent } from './builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component'; +import { DsDynamicRelationGroupComponent } from './builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.components'; +import { DsDatePickerComponent } from './builder/ds-dynamic-form-ui/models/date-picker/date-picker.component'; +import { DsDynamicFormGroupComponent } from './builder/ds-dynamic-form-ui/models/form-group/dynamic-form-group.component'; +import { DsDynamicFormArrayComponent } from './builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component'; +import { DsDatePickerInlineComponent } from './builder/ds-dynamic-form-ui/models/date-picker-inline/dynamic-date-picker-inline.component'; +import { DsDynamicLookupRelationSearchTabComponent } from './builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component'; +import { DsDynamicLookupRelationSelectionTabComponent } from './builder/ds-dynamic-form-ui/relation-lookup-modal/selection-tab/dynamic-lookup-relation-selection-tab.component'; +import { DsDynamicLookupRelationExternalSourceTabComponent } from './builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component'; +import { SharedModule } from '../shared.module'; +import { TranslateModule } from '@ngx-translate/core'; +import { SearchModule } from '../search/search.module'; +import { DYNAMIC_FORM_CONTROL_MAP_FN, DynamicFormsCoreModule } from '@ng-dynamic-forms/core'; +import { ExistingMetadataListElementComponent } from './builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component'; +import { ExistingRelationListElementComponent } from './builder/ds-dynamic-form-ui/existing-relation-list-element/existing-relation-list-element.component'; +import { ExternalSourceEntryImportModalComponent } from './builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component'; +import { CustomSwitchComponent } from './builder/ds-dynamic-form-ui/models/custom-switch/custom-switch.component'; +import { DynamicFormsNGBootstrapUIModule } from '@ng-dynamic-forms/ui-ng-bootstrap'; + +const COMPONENTS = [ + CustomSwitchComponent, + DsDynamicFormComponent, + DsDynamicFormControlContainerComponent, + DsDynamicListComponent, + DsDynamicLookupComponent, + DsDynamicLookupRelationSearchTabComponent, + DsDynamicLookupRelationSelectionTabComponent, + DsDynamicLookupRelationExternalSourceTabComponent, + DsDynamicDisabledComponent, + DsDynamicLookupRelationModalComponent, + DsDynamicScrollableDropdownComponent, + DsDynamicTagComponent, + DsDynamicOneboxComponent, + DsDynamicRelationGroupComponent, + DsDatePickerComponent, + DsDynamicFormGroupComponent, + DsDynamicFormArrayComponent, + DsDatePickerInlineComponent, + ExistingMetadataListElementComponent, + ExistingRelationListElementComponent, + ExternalSourceEntryImportModalComponent, + FormComponent +]; + +@NgModule({ + declarations: [ + ...COMPONENTS + ], + imports: [ + CommonModule, + DynamicFormsCoreModule, + DynamicFormsNGBootstrapUIModule, + SearchModule, + SharedModule, + TranslateModule + ], + exports: [ + ...COMPONENTS + ], + providers: [ + { + provide: DYNAMIC_FORM_CONTROL_MAP_FN, + useValue: dsDynamicFormControlMapFn + } + ] +}) +export class FormModule { +} diff --git a/src/app/shared/item/item-versions/item-versions.component.ts b/src/app/shared/item/item-versions/item-versions.component.ts index 6796dfd1ad..2457cf76c4 100644 --- a/src/app/shared/item/item-versions/item-versions.component.ts +++ b/src/app/shared/item/item-versions/item-versions.component.ts @@ -22,7 +22,7 @@ import { map, mergeMap, startWith, switchMap, take, tap } from 'rxjs/operators'; import { PaginatedList } from '../../../core/data/paginated-list.model'; import { PaginationComponentOptions } from '../../pagination/pagination-component-options.model'; import { VersionHistoryDataService } from '../../../core/data/version-history-data.service'; -import { PaginatedSearchOptions } from '../../search/paginated-search-options.model'; +import { PaginatedSearchOptions } from '../../search/models/paginated-search-options.model'; import { AlertType } from '../../alert/aletr-type'; import { followLink } from '../../utils/follow-link-config.model'; import { hasValue, hasValueOperator } from '../../empty.util'; diff --git a/src/app/shared/object-collection/object-collection.component.ts b/src/app/shared/object-collection/object-collection.component.ts index 52881f5eaf..29fdb37ea1 100644 --- a/src/app/shared/object-collection/object-collection.component.ts +++ b/src/app/shared/object-collection/object-collection.component.ts @@ -2,14 +2,14 @@ import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } fro import { ActivatedRoute, Router } from '@angular/router'; import { Observable } from 'rxjs'; -import { filter, map, startWith } from 'rxjs/operators'; +import { distinctUntilChanged, map } from 'rxjs/operators'; import { RemoteData } from '../../core/data/remote-data'; import { PageInfo } from '../../core/shared/page-info.model'; import { PaginationComponentOptions } from '../pagination/pagination-component-options.model'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { ListableObject } from './shared/listable-object.model'; -import { isNotEmpty } from '../empty.util'; +import { isEmpty } from '../empty.util'; import { ViewMode } from '../../core/shared/view-mode.model'; import { CollectionElementLinkType } from './collection-element-link.type'; import { PaginatedList } from '../../core/data/paginated-list.model'; @@ -136,9 +136,8 @@ export class ObjectCollectionComponent implements OnInit { this.currentMode$ = this.route .queryParams .pipe( - filter((params) => isNotEmpty(params.view)), - map((params) => params.view), - startWith(ViewMode.ListElement) + map((params) => isEmpty(params?.view) ? ViewMode.ListElement : params.view), + distinctUntilChanged() ); } diff --git a/src/app/shared/object-collection/shared/claimed-approved-task-search-result.model.ts b/src/app/shared/object-collection/shared/claimed-approved-task-search-result.model.ts index 7cacd87048..71b885d249 100644 --- a/src/app/shared/object-collection/shared/claimed-approved-task-search-result.model.ts +++ b/src/app/shared/object-collection/shared/claimed-approved-task-search-result.model.ts @@ -1,5 +1,5 @@ import { ClaimedTask } from '../../../core/tasks/models/claimed-task-object.model'; -import { SearchResult } from '../../search/search-result.model'; +import { SearchResult } from '../../search/models/search-result.model'; /** * Represents a search result object of an Approved ClaimedTask object diff --git a/src/app/shared/object-collection/shared/claimed-declined-task-search-result.model.ts b/src/app/shared/object-collection/shared/claimed-declined-task-search-result.model.ts index ff775be909..eaf63bf6dd 100644 --- a/src/app/shared/object-collection/shared/claimed-declined-task-search-result.model.ts +++ b/src/app/shared/object-collection/shared/claimed-declined-task-search-result.model.ts @@ -1,5 +1,5 @@ import { ClaimedTask } from '../../../core/tasks/models/claimed-task-object.model'; -import { SearchResult } from '../../search/search-result.model'; +import { SearchResult } from '../../search/models/search-result.model'; /** * Represents a search result object of a Declined ClaimedTask object diff --git a/src/app/shared/object-collection/shared/claimed-task-search-result.model.ts b/src/app/shared/object-collection/shared/claimed-task-search-result.model.ts index 1148ea1526..f8d0752245 100644 --- a/src/app/shared/object-collection/shared/claimed-task-search-result.model.ts +++ b/src/app/shared/object-collection/shared/claimed-task-search-result.model.ts @@ -1,5 +1,5 @@ import { ClaimedTask } from '../../../core/tasks/models/claimed-task-object.model'; -import { SearchResult } from '../../search/search-result.model'; +import { SearchResult } from '../../search/models/search-result.model'; import { searchResultFor } from '../../search/search-result-element-decorator'; /** diff --git a/src/app/shared/object-collection/shared/collection-search-result.model.ts b/src/app/shared/object-collection/shared/collection-search-result.model.ts index 3b32197533..615ef0809c 100644 --- a/src/app/shared/object-collection/shared/collection-search-result.model.ts +++ b/src/app/shared/object-collection/shared/collection-search-result.model.ts @@ -1,4 +1,4 @@ -import { SearchResult } from '../../search/search-result.model'; +import { SearchResult } from '../../search/models/search-result.model'; import { Collection } from '../../../core/shared/collection.model'; import { searchResultFor } from '../../search/search-result-element-decorator'; diff --git a/src/app/shared/object-collection/shared/community-search-result.model.ts b/src/app/shared/object-collection/shared/community-search-result.model.ts index 9ce936b5d8..e80dfdaecf 100644 --- a/src/app/shared/object-collection/shared/community-search-result.model.ts +++ b/src/app/shared/object-collection/shared/community-search-result.model.ts @@ -1,5 +1,5 @@ import { Community } from '../../../core/shared/community.model'; -import { SearchResult } from '../../search/search-result.model'; +import { SearchResult } from '../../search/models/search-result.model'; import { searchResultFor } from '../../search/search-result-element-decorator'; @searchResultFor(Community) diff --git a/src/app/shared/object-collection/shared/item-search-result.model.ts b/src/app/shared/object-collection/shared/item-search-result.model.ts index 4e445f0c88..66f3eb1513 100644 --- a/src/app/shared/object-collection/shared/item-search-result.model.ts +++ b/src/app/shared/object-collection/shared/item-search-result.model.ts @@ -1,4 +1,4 @@ -import { SearchResult } from '../../search/search-result.model'; +import { SearchResult } from '../../search/models/search-result.model'; import { Item } from '../../../core/shared/item.model'; import { inheritEquatable } from '../../../core/utilities/equals.decorators'; import { GenericConstructor } from '../../../core/shared/generic-constructor'; diff --git a/src/app/shared/object-collection/shared/pool-task-search-result.model.ts b/src/app/shared/object-collection/shared/pool-task-search-result.model.ts index 3cff48ba51..9ee74bcd4b 100644 --- a/src/app/shared/object-collection/shared/pool-task-search-result.model.ts +++ b/src/app/shared/object-collection/shared/pool-task-search-result.model.ts @@ -1,5 +1,5 @@ import { PoolTask } from '../../../core/tasks/models/pool-task-object.model'; -import { SearchResult } from '../../search/search-result.model'; +import { SearchResult } from '../../search/models/search-result.model'; import { searchResultFor } from '../../search/search-result-element-decorator'; /** diff --git a/src/app/shared/object-collection/shared/workflow-item-search-result.model.ts b/src/app/shared/object-collection/shared/workflow-item-search-result.model.ts index 107b66cbee..8611f8678a 100644 --- a/src/app/shared/object-collection/shared/workflow-item-search-result.model.ts +++ b/src/app/shared/object-collection/shared/workflow-item-search-result.model.ts @@ -1,5 +1,5 @@ import { WorkflowItem } from '../../../core/submission/models/workflowitem.model'; -import { SearchResult } from '../../search/search-result.model'; +import { SearchResult } from '../../search/models/search-result.model'; import { searchResultFor } from '../../search/search-result-element-decorator'; /** diff --git a/src/app/shared/object-collection/shared/workspace-item-search-result.model.ts b/src/app/shared/object-collection/shared/workspace-item-search-result.model.ts index aa1d4988d4..fddd5dc203 100644 --- a/src/app/shared/object-collection/shared/workspace-item-search-result.model.ts +++ b/src/app/shared/object-collection/shared/workspace-item-search-result.model.ts @@ -1,6 +1,6 @@ import { WorkspaceItem } from '../../../core/submission/models/workspaceitem.model'; import { searchResultFor } from '../../search/search-result-element-decorator'; -import { SearchResult } from '../../search/search-result.model'; +import { SearchResult } from '../../search/models/search-result.model'; /** * Represents a search result object of a WorkspaceItem object diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview-field/item-detail-preview-field.component.ts b/src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview-field/item-detail-preview-field.component.ts index 5c880133bc..5faf02eac0 100644 --- a/src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview-field/item-detail-preview-field.component.ts +++ b/src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview-field/item-detail-preview-field.component.ts @@ -2,7 +2,7 @@ import { Component, Input } from '@angular/core'; import { Metadata } from '../../../../../core/shared/metadata.utils'; import { Item } from '../../../../../core/shared/item.model'; -import { SearchResult } from '../../../../search/search-result.model'; +import { SearchResult } from '../../../../search/models/search-result.model'; /** * This component show values for the given item metadata diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview.component.ts b/src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview.component.ts index 92c1afcb59..778e455004 100644 --- a/src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview.component.ts +++ b/src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview.component.ts @@ -11,7 +11,7 @@ import { fadeInOut } from '../../../animations/fade'; import { Bitstream } from '../../../../core/shared/bitstream.model'; import { FileService } from '../../../../core/shared/file.service'; import { HALEndpointService } from '../../../../core/shared/hal-endpoint.service'; -import { SearchResult } from '../../../search/search-result.model'; +import { SearchResult } from '../../../search/models/search-result.model'; /** * This component show metadata for the given item object in the detail view. diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/search-result-detail-element.component.ts b/src/app/shared/object-detail/my-dspace-result-detail-element/search-result-detail-element.component.ts index e56576a08b..5b0bd2c39b 100644 --- a/src/app/shared/object-detail/my-dspace-result-detail-element/search-result-detail-element.component.ts +++ b/src/app/shared/object-detail/my-dspace-result-detail-element/search-result-detail-element.component.ts @@ -4,7 +4,7 @@ import { AbstractListableElementComponent } from '../../object-collection/shared import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { Metadata } from '../../../core/shared/metadata.utils'; import { hasValue } from '../../empty.util'; -import { SearchResult } from '../../search/search-result.model'; +import { SearchResult } from '../../search/models/search-result.model'; /** * Component representing Search Results with ViewMode.DetailedElement diff --git a/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts b/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts index da1f0ea11b..6e72eaa942 100644 --- a/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts +++ b/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; -import { SearchResult } from '../../search/search-result.model'; +import { SearchResult } from '../../search/models/search-result.model'; import { BitstreamDataService } from '../../../core/data/bitstream-data.service'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { Metadata } from '../../../core/shared/metadata.utils'; diff --git a/src/app/shared/object-list/my-dspace-result-list-element/item-list-preview/item-list-preview.component.ts b/src/app/shared/object-list/my-dspace-result-list-element/item-list-preview/item-list-preview.component.ts index 6d9f325757..840960d51f 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/item-list-preview/item-list-preview.component.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/item-list-preview/item-list-preview.component.ts @@ -3,7 +3,7 @@ import { Component, Input } from '@angular/core'; import { Item } from '../../../../core/shared/item.model'; import { fadeInOut } from '../../../animations/fade'; import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; -import { SearchResult } from '../../../search/search-result.model'; +import { SearchResult } from '../../../search/models/search-result.model'; /** * This component show metadata for the given item object in the list view. diff --git a/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts b/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts index afd0363e7a..b85fb0a39f 100644 --- a/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts +++ b/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; -import { SearchResult } from '../../search/search-result.model'; +import { SearchResult } from '../../search/models/search-result.model'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { hasValue } from '../../empty.util'; import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; diff --git a/src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.spec.ts b/src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.spec.ts index 31ad68ec63..e6bd15df1b 100644 --- a/src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.spec.ts +++ b/src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.spec.ts @@ -3,7 +3,7 @@ import { VarDirective } from '../../utils/var.directive'; import { RouterTestingModule } from '@angular/router/testing'; import { TranslateModule } from '@ngx-translate/core'; import { NO_ERRORS_SCHEMA } from '@angular/core'; -import { SearchResult } from '../../search/search-result.model'; +import { SearchResult } from '../../search/models/search-result.model'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { TruncatableService } from '../../truncatable/truncatable.service'; import { LinkService } from '../../../core/cache/builders/link.service'; diff --git a/src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.ts b/src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.ts index 693d6a9665..91f3ba6d88 100644 --- a/src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.ts +++ b/src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.ts @@ -1,4 +1,4 @@ -import { SearchResult } from '../../search/search-result.model'; +import { SearchResult } from '../../search/models/search-result.model'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { SearchResultListElementComponent } from '../search-result-list-element/search-result-list-element.component'; import { Component } from '@angular/core'; diff --git a/src/app/shared/page-size-selector/page-size-selector.component.ts b/src/app/shared/page-size-selector/page-size-selector.component.ts index ddfe1ca4d9..0dce32a4ba 100644 --- a/src/app/shared/page-size-selector/page-size-selector.component.ts +++ b/src/app/shared/page-size-selector/page-size-selector.component.ts @@ -4,7 +4,7 @@ import { Observable } from 'rxjs'; import { ActivatedRoute, Router } from '@angular/router'; import { SEARCH_CONFIG_SERVICE } from '../../my-dspace-page/my-dspace-page.component'; import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service'; -import { PaginatedSearchOptions } from '../search/paginated-search-options.model'; +import { PaginatedSearchOptions } from '../search/models/paginated-search-options.model'; import { map, take } from 'rxjs/operators'; import { PaginationService } from '../../core/pagination/pagination.service'; diff --git a/src/app/shared/resource-policies/resource-policies.module.ts b/src/app/shared/resource-policies/resource-policies.module.ts new file mode 100644 index 0000000000..6eeaddce36 --- /dev/null +++ b/src/app/shared/resource-policies/resource-policies.module.ts @@ -0,0 +1,52 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; + +import { TranslateModule } from '@ngx-translate/core'; + +import { ResourcePoliciesComponent } from './resource-policies.component'; +import { ResourcePolicyFormComponent } from './form/resource-policy-form.component'; +import { ResourcePolicyEditComponent } from './edit/resource-policy-edit.component'; +import { ResourcePolicyCreateComponent } from './create/resource-policy-create.component'; +import { FormModule } from '../form/form.module'; +import { ResourcePolicyResolver } from './resolvers/resource-policy.resolver'; +import { ResourcePolicyTargetResolver } from './resolvers/resource-policy-target.resolver'; +import { EpersonGroupListComponent } from './form/eperson-group-list/eperson-group-list.component'; +import { GroupSearchBoxComponent } from './form/eperson-group-list/group-search-box/group-search-box.component'; +import { EpersonSearchBoxComponent } from './form/eperson-group-list/eperson-search-box/eperson-search-box.component'; +import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { SharedModule } from '../shared.module'; + +const COMPONENTS = [ + ResourcePoliciesComponent, + ResourcePolicyFormComponent, + ResourcePolicyEditComponent, + ResourcePolicyCreateComponent, + EpersonGroupListComponent, + EpersonSearchBoxComponent, + GroupSearchBoxComponent +]; + +const PROVIDERS = [ + ResourcePolicyResolver, + ResourcePolicyTargetResolver +]; + +@NgModule({ + declarations: [ + ...COMPONENTS + ], + imports: [ + NgbModule, + CommonModule, + FormModule, + TranslateModule, + SharedModule + ], + providers: [ + ...PROVIDERS + ], + exports: [ + ...COMPONENTS + ] +}) +export class ResourcePoliciesModule { } diff --git a/src/app/shared/search-form/search-form.component.ts b/src/app/shared/search-form/search-form.component.ts index cb9b43dbd1..caf6a91046 100644 --- a/src/app/shared/search-form/search-form.component.ts +++ b/src/app/shared/search-form/search-form.component.ts @@ -116,14 +116,11 @@ export class SearchFormComponent implements OnInit { */ updateSearch(data: any) { const queryParams = Object.assign({}, data); - const pageParam = this.paginationService.getPageParam(this.searchConfig.paginationID); - queryParams[pageParam] = 1; this.router.navigate(this.getSearchLinkParts(), { queryParams: queryParams, queryParamsHandling: 'merge' }); - this.paginationService.updateRouteWithUrl(this.searchConfig.paginationID, this.getSearchLinkParts(), { page: 1 }, data); } /** diff --git a/src/app/shared/search/facet-config-response.model.ts b/src/app/shared/search/models/facet-config-response.model.ts similarity index 62% rename from src/app/shared/search/facet-config-response.model.ts rename to src/app/shared/search/models/facet-config-response.model.ts index 74190d35ba..74e6f10d62 100644 --- a/src/app/shared/search/facet-config-response.model.ts +++ b/src/app/shared/search/models/facet-config-response.model.ts @@ -1,10 +1,10 @@ -import { CacheableObject } from '../../core/cache/object-cache.reducer'; -import { typedObject } from '../../core/cache/builders/build-decorators'; -import { FACET_CONFIG_RESPONSE } from './facet-config-response.resouce-type'; -import { excludeFromEquals } from '../../core/utilities/equals.decorators'; +import { CacheableObject } from '../../../core/cache/object-cache.reducer'; +import { typedObject } from '../../../core/cache/builders/build-decorators'; +import { FACET_CONFIG_RESPONSE } from './types/facet-config-response.resouce-type'; +import { excludeFromEquals } from '../../../core/utilities/equals.decorators'; import { SearchFilterConfig } from './search-filter-config.model'; import { deserialize } from 'cerialize'; -import { HALLink } from '../../core/shared/hal-link.model'; +import { HALLink } from '../../../core/shared/hal-link.model'; /** * The response from the discover/facets endpoint diff --git a/src/app/shared/search/facet-value.model.ts b/src/app/shared/search/models/facet-value.model.ts similarity index 84% rename from src/app/shared/search/facet-value.model.ts rename to src/app/shared/search/models/facet-value.model.ts index 935190743d..6c1d353480 100644 --- a/src/app/shared/search/facet-value.model.ts +++ b/src/app/shared/search/models/facet-value.model.ts @@ -1,6 +1,6 @@ import { autoserialize, autoserializeAs, deserialize } from 'cerialize'; -import { HALLink } from '../../core/shared/hal-link.model'; -import { HALResource } from '../../core/shared/hal-resource.model'; +import { HALLink } from '../../../core/shared/hal-link.model'; +import { HALResource } from '../../../core/shared/hal-resource.model'; /** * Class representing possible values for a certain filter diff --git a/src/app/shared/search/facet-values.model.ts b/src/app/shared/search/models/facet-values.model.ts similarity index 72% rename from src/app/shared/search/facet-values.model.ts rename to src/app/shared/search/models/facet-values.model.ts index 31b1f560fb..09bef25876 100644 --- a/src/app/shared/search/facet-values.model.ts +++ b/src/app/shared/search/models/facet-values.model.ts @@ -1,11 +1,11 @@ -import { typedObject } from '../../core/cache/builders/build-decorators'; -import { excludeFromEquals } from '../../core/utilities/equals.decorators'; -import { FACET_VALUES } from './facet-values.resource-type'; +import { typedObject } from '../../../core/cache/builders/build-decorators'; +import { excludeFromEquals } from '../../../core/utilities/equals.decorators'; +import { FACET_VALUES } from './types/facet-values.resource-type'; import { FacetValue } from './facet-value.model'; import { SearchQueryResponse } from './search-query-response.model'; -import { autoserializeAs, autoserialize, inheritSerialization } from 'cerialize'; +import { autoserialize, autoserializeAs, inheritSerialization } from 'cerialize'; import { FilterType } from './filter-type.model'; -import { PaginatedList } from '../../core/data/paginated-list.model'; +import { PaginatedList } from '../../../core/data/paginated-list.model'; @typedObject @inheritSerialization(PaginatedList) diff --git a/src/app/shared/search/filter-type.model.ts b/src/app/shared/search/models/filter-type.model.ts similarity index 100% rename from src/app/shared/search/filter-type.model.ts rename to src/app/shared/search/models/filter-type.model.ts diff --git a/src/app/shared/search/paginated-search-options.model.spec.ts b/src/app/shared/search/models/paginated-search-options.model.spec.ts similarity index 87% rename from src/app/shared/search/paginated-search-options.model.spec.ts rename to src/app/shared/search/models/paginated-search-options.model.spec.ts index 9881cc1149..7afee06abf 100644 --- a/src/app/shared/search/paginated-search-options.model.spec.ts +++ b/src/app/shared/search/models/paginated-search-options.model.spec.ts @@ -1,7 +1,7 @@ -import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; -import { PaginationComponentOptions } from '../pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; +import { PaginationComponentOptions } from '../../pagination/pagination-component-options.model'; import { PaginatedSearchOptions } from './paginated-search-options.model'; -import { DSpaceObjectType } from '../../core/shared/dspace-object-type.model'; +import { DSpaceObjectType } from '../../../core/shared/dspace-object-type.model'; import { SearchFilter } from './search-filter.model'; describe('PaginatedSearchOptions', () => { diff --git a/src/app/shared/search/paginated-search-options.model.ts b/src/app/shared/search/models/paginated-search-options.model.ts similarity index 82% rename from src/app/shared/search/paginated-search-options.model.ts rename to src/app/shared/search/models/paginated-search-options.model.ts index 950b207c3a..925a7a3a7e 100644 --- a/src/app/shared/search/paginated-search-options.model.ts +++ b/src/app/shared/search/models/paginated-search-options.model.ts @@ -1,9 +1,9 @@ -import { SortOptions } from '../../core/cache/models/sort-options.model'; -import { PaginationComponentOptions } from '../pagination/pagination-component-options.model'; -import { isNotEmpty } from '../empty.util'; +import { SortOptions } from '../../../core/cache/models/sort-options.model'; +import { PaginationComponentOptions } from '../../pagination/pagination-component-options.model'; +import { isNotEmpty } from '../../empty.util'; import { SearchOptions } from './search-options.model'; import { SearchFilter } from './search-filter.model'; -import { DSpaceObjectType } from '../../core/shared/dspace-object-type.model'; +import { DSpaceObjectType } from '../../../core/shared/dspace-object-type.model'; /** * This model class represents all parameters needed to request information about a certain page of a search request, in a certain order diff --git a/src/app/shared/search/search-filter-config.model.ts b/src/app/shared/search/models/search-filter-config.model.ts similarity index 78% rename from src/app/shared/search/search-filter-config.model.ts rename to src/app/shared/search/models/search-filter-config.model.ts index 1a0be94d2b..129259985a 100644 --- a/src/app/shared/search/search-filter-config.model.ts +++ b/src/app/shared/search/models/search-filter-config.model.ts @@ -1,14 +1,14 @@ import { FilterType } from './filter-type.model'; import { autoserialize, autoserializeAs, deserialize } from 'cerialize'; -import { HALLink } from '../../core/shared/hal-link.model'; -import { typedObject } from '../../core/cache/builders/build-decorators'; -import { CacheableObject } from '../../core/cache/object-cache.reducer'; -import { excludeFromEquals } from '../../core/utilities/equals.decorators'; -import { SEARCH_FILTER_CONFIG } from './search-filter-config.resource-type'; +import { HALLink } from '../../../core/shared/hal-link.model'; +import { typedObject } from '../../../core/cache/builders/build-decorators'; +import { CacheableObject } from '../../../core/cache/object-cache.reducer'; +import { excludeFromEquals } from '../../../core/utilities/equals.decorators'; +import { SEARCH_FILTER_CONFIG } from './types/search-filter-config.resource-type'; - /** - * The configuration for a search filter - */ +/** + * The configuration for a search filter + */ @typedObject export class SearchFilterConfig implements CacheableObject { static type = SEARCH_FILTER_CONFIG; diff --git a/src/app/shared/search/search-filter.model.ts b/src/app/shared/search/models/search-filter.model.ts similarity index 100% rename from src/app/shared/search/search-filter.model.ts rename to src/app/shared/search/models/search-filter.model.ts diff --git a/src/app/shared/search/search-objects.model.ts b/src/app/shared/search/models/search-objects.model.ts similarity index 68% rename from src/app/shared/search/search-objects.model.ts rename to src/app/shared/search/models/search-objects.model.ts index 9974dc64ec..2afbab372b 100644 --- a/src/app/shared/search/search-objects.model.ts +++ b/src/app/shared/search/models/search-objects.model.ts @@ -1,10 +1,10 @@ import { autoserializeAs, inheritSerialization } from 'cerialize'; -import { DSpaceObject } from '../../core/shared/dspace-object.model'; +import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { SearchResult } from './search-result.model'; -import { PaginatedList } from '../../core/data/paginated-list.model'; -import { typedObject } from '../../core/cache/builders/build-decorators'; -import { SEARCH_OBJECTS } from './search-objects.resource-type'; -import { excludeFromEquals } from '../../core/utilities/equals.decorators'; +import { PaginatedList } from '../../../core/data/paginated-list.model'; +import { typedObject } from '../../../core/cache/builders/build-decorators'; +import { SEARCH_OBJECTS } from './types/search-objects.resource-type'; +import { excludeFromEquals } from '../../../core/utilities/equals.decorators'; import { SearchQueryResponse } from './search-query-response.model'; /** diff --git a/src/app/shared/search/search-options.model.spec.ts b/src/app/shared/search/models/search-options.model.spec.ts similarity index 90% rename from src/app/shared/search/search-options.model.spec.ts rename to src/app/shared/search/models/search-options.model.spec.ts index 8bed046736..176d321999 100644 --- a/src/app/shared/search/search-options.model.spec.ts +++ b/src/app/shared/search/models/search-options.model.spec.ts @@ -1,7 +1,6 @@ -import { PaginatedSearchOptions } from './paginated-search-options.model'; import { SearchOptions } from './search-options.model'; import { SearchFilter } from './search-filter.model'; -import { DSpaceObjectType } from '../../core/shared/dspace-object-type.model'; +import { DSpaceObjectType } from '../../../core/shared/dspace-object-type.model'; describe('SearchOptions', () => { let options: SearchOptions; diff --git a/src/app/shared/search/search-options.model.ts b/src/app/shared/search/models/search-options.model.ts similarity index 91% rename from src/app/shared/search/search-options.model.ts rename to src/app/shared/search/models/search-options.model.ts index 591e4fcb04..470ef8a06f 100644 --- a/src/app/shared/search/search-options.model.ts +++ b/src/app/shared/search/models/search-options.model.ts @@ -1,8 +1,8 @@ -import { hasValue, isNotEmpty } from '../empty.util'; -import { URLCombiner } from '../../core/url-combiner/url-combiner'; +import { hasValue, isNotEmpty } from '../../empty.util'; +import { URLCombiner } from '../../../core/url-combiner/url-combiner'; import { SearchFilter } from './search-filter.model'; -import { DSpaceObjectType } from '../../core/shared/dspace-object-type.model'; -import { ViewMode } from '../../core/shared/view-mode.model'; +import { DSpaceObjectType } from '../../../core/shared/dspace-object-type.model'; +import { ViewMode } from '../../../core/shared/view-mode.model'; /** * This model class represents all parameters needed to request information about a certain search request diff --git a/src/app/shared/search/search-query-response.model.ts b/src/app/shared/search/models/search-query-response.model.ts similarity index 87% rename from src/app/shared/search/search-query-response.model.ts rename to src/app/shared/search/models/search-query-response.model.ts index 77e513a918..a436a7c045 100644 --- a/src/app/shared/search/search-query-response.model.ts +++ b/src/app/shared/search/models/search-query-response.model.ts @@ -1,6 +1,6 @@ import { autoserialize } from 'cerialize'; -import { PageInfo } from '../../core/shared/page-info.model'; -import { PaginatedList } from '../../core/data/paginated-list.model'; +import { PageInfo } from '../../../core/shared/page-info.model'; +import { PaginatedList } from '../../../core/data/paginated-list.model'; /** * Class representing the response returned by the server when performing a search request diff --git a/src/app/shared/search/search-result.model.ts b/src/app/shared/search/models/search-result.model.ts similarity index 59% rename from src/app/shared/search/search-result.model.ts rename to src/app/shared/search/models/search-result.model.ts index c221b2e581..6079c4af63 100644 --- a/src/app/shared/search/search-result.model.ts +++ b/src/app/shared/search/models/search-result.model.ts @@ -1,13 +1,13 @@ import { autoserialize, deserialize } from 'cerialize'; -import { typedObject } from '../../core/cache/builders/build-decorators'; -import { DSpaceObject } from '../../core/shared/dspace-object.model'; -import { GenericConstructor } from '../../core/shared/generic-constructor'; -import { HALLink } from '../../core/shared/hal-link.model'; -import { MetadataMap } from '../../core/shared/metadata.models'; -import { excludeFromEquals, fieldsForEquals } from '../../core/utilities/equals.decorators'; -import { ListableObject } from '../object-collection/shared/listable-object.model'; -import { HALResource } from '../../core/shared/hal-resource.model'; -import { SEARCH_RESULT } from './search-result.resource-type'; +import { typedObject } from '../../../core/cache/builders/build-decorators'; +import { DSpaceObject } from '../../../core/shared/dspace-object.model'; +import { GenericConstructor } from '../../../core/shared/generic-constructor'; +import { HALLink } from '../../../core/shared/hal-link.model'; +import { MetadataMap } from '../../../core/shared/metadata.models'; +import { excludeFromEquals, fieldsForEquals } from '../../../core/utilities/equals.decorators'; +import { ListableObject } from '../../object-collection/shared/listable-object.model'; +import { HALResource } from '../../../core/shared/hal-resource.model'; +import { SEARCH_RESULT } from './types/search-result.resource-type'; /** * Represents a search result object of a certain () DSpaceObject diff --git a/src/app/shared/search/facet-config-response.resouce-type.ts b/src/app/shared/search/models/types/facet-config-response.resouce-type.ts similarity index 75% rename from src/app/shared/search/facet-config-response.resouce-type.ts rename to src/app/shared/search/models/types/facet-config-response.resouce-type.ts index 7c3bdef7ca..83f2ca0e66 100644 --- a/src/app/shared/search/facet-config-response.resouce-type.ts +++ b/src/app/shared/search/models/types/facet-config-response.resouce-type.ts @@ -1,4 +1,4 @@ -import { ResourceType } from '../../core/shared/resource-type'; +import { ResourceType } from '../../../../core/shared/resource-type'; /** * The resource type for FacetConfigResponse diff --git a/src/app/shared/search/facet-values.resource-type.ts b/src/app/shared/search/models/types/facet-values.resource-type.ts similarity index 74% rename from src/app/shared/search/facet-values.resource-type.ts rename to src/app/shared/search/models/types/facet-values.resource-type.ts index e1042bbbc0..c9d6c69c2e 100644 --- a/src/app/shared/search/facet-values.resource-type.ts +++ b/src/app/shared/search/models/types/facet-values.resource-type.ts @@ -1,4 +1,4 @@ -import { ResourceType } from '../../core/shared/resource-type'; +import { ResourceType } from '../../../../core/shared/resource-type'; /** * The resource type for FacetValues diff --git a/src/app/shared/search/search-filter-config.resource-type.ts b/src/app/shared/search/models/types/search-filter-config.resource-type.ts similarity index 75% rename from src/app/shared/search/search-filter-config.resource-type.ts rename to src/app/shared/search/models/types/search-filter-config.resource-type.ts index c2da308207..eb7521b8df 100644 --- a/src/app/shared/search/search-filter-config.resource-type.ts +++ b/src/app/shared/search/models/types/search-filter-config.resource-type.ts @@ -1,4 +1,4 @@ -import { ResourceType } from '../../core/shared/resource-type'; +import { ResourceType } from '../../../../core/shared/resource-type'; /** * The resource type for SearchFilterConfig diff --git a/src/app/shared/search/search-objects.resource-type.ts b/src/app/shared/search/models/types/search-objects.resource-type.ts similarity index 74% rename from src/app/shared/search/search-objects.resource-type.ts rename to src/app/shared/search/models/types/search-objects.resource-type.ts index cf5d7c9c9e..650b02f005 100644 --- a/src/app/shared/search/search-objects.resource-type.ts +++ b/src/app/shared/search/models/types/search-objects.resource-type.ts @@ -1,4 +1,4 @@ -import { ResourceType } from '../../core/shared/resource-type'; +import { ResourceType } from '../../../../core/shared/resource-type'; /** * The resource type for SearchObjects diff --git a/src/app/shared/search/search-result.resource-type.ts b/src/app/shared/search/models/types/search-result.resource-type.ts similarity index 73% rename from src/app/shared/search/search-result.resource-type.ts rename to src/app/shared/search/models/types/search-result.resource-type.ts index 4e18f17db6..354c1898c4 100644 --- a/src/app/shared/search/search-result.resource-type.ts +++ b/src/app/shared/search/models/types/search-result.resource-type.ts @@ -1,4 +1,4 @@ -import { ResourceType } from '../../core/shared/resource-type'; +import { ResourceType } from '../../../../core/shared/resource-type'; /** * The resource type for SearchResult diff --git a/src/app/shared/search/search-filters/search-filter/search-authority-filter/search-authority-filter.component.ts b/src/app/shared/search/search-filters/search-filter/search-authority-filter/search-authority-filter.component.ts index 7a20fd5ff0..6dcb47ce9f 100644 --- a/src/app/shared/search/search-filters/search-filter/search-authority-filter/search-authority-filter.component.ts +++ b/src/app/shared/search/search-filters/search-filter/search-authority-filter/search-authority-filter.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { FilterType } from '../../../filter-type.model'; +import { FilterType } from '../../../models/filter-type.model'; import { facetLoad, SearchFacetFilterComponent } from '../search-facet-filter/search-facet-filter.component'; import { renderFacetFor } from '../search-filter-type-decorator'; diff --git a/src/app/shared/search/search-filters/search-filter/search-boolean-filter/search-boolean-filter.component.ts b/src/app/shared/search/search-filters/search-filter/search-boolean-filter/search-boolean-filter.component.ts index 49f361e75e..c9da8500d0 100644 --- a/src/app/shared/search/search-filters/search-filter/search-boolean-filter/search-boolean-filter.component.ts +++ b/src/app/shared/search/search-filters/search-filter/search-boolean-filter/search-boolean-filter.component.ts @@ -1,10 +1,7 @@ import { Component, OnInit } from '@angular/core'; -import { FilterType } from '../../../filter-type.model'; +import { FilterType } from '../../../models/filter-type.model'; import { renderFacetFor } from '../search-filter-type-decorator'; -import { - facetLoad, - SearchFacetFilterComponent -} from '../search-facet-filter/search-facet-filter.component'; +import { facetLoad, SearchFacetFilterComponent } from '../search-facet-filter/search-facet-filter.component'; @Component({ selector: 'ds-search-boolean-filter', diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts index 7299a39c32..b0f2a51460 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts @@ -11,13 +11,11 @@ import { SearchFilterService } from '../../../../../../core/shared/search/search import { SearchService } from '../../../../../../core/shared/search/search.service'; import { RouterStub } from '../../../../../testing/router.stub'; import { SearchServiceStub } from '../../../../../testing/search-service.stub'; -import { FacetValue } from '../../../../facet-value.model'; -import { FilterType } from '../../../../filter-type.model'; -import { SearchFilterConfig } from '../../../../search-filter-config.model'; +import { FacetValue } from '../../../../models/facet-value.model'; +import { FilterType } from '../../../../models/filter-type.model'; +import { SearchFilterConfig } from '../../../../models/search-filter-config.model'; import { SearchFacetOptionComponent } from './search-facet-option.component'; import { PaginationComponentOptions } from '../../../../../pagination/pagination-component-options.model'; -import { SortDirection, SortOptions } from '../../../../../../core/cache/models/sort-options.model'; -import { FindListOptions } from '../../../../../../core/data/request.models'; import { PaginationService } from '../../../../../../core/pagination/pagination.service'; import { PaginationServiceStub } from '../../../../../testing/pagination-service.stub'; diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.ts index 11056a232c..cdbab61a30 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.ts @@ -2,8 +2,8 @@ import { combineLatest as observableCombineLatest, Observable, Subscription } fr import { map } from 'rxjs/operators'; import { Component, Input, OnDestroy, OnInit } from '@angular/core'; import { Router } from '@angular/router'; -import { FacetValue } from '../../../../facet-value.model'; -import { SearchFilterConfig } from '../../../../search-filter-config.model'; +import { FacetValue } from '../../../../models/facet-value.model'; +import { SearchFilterConfig } from '../../../../models/search-filter-config.model'; import { SearchService } from '../../../../../../core/shared/search/search.service'; import { SearchFilterService } from '../../../../../../core/shared/search/search-filter.service'; import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service'; diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.spec.ts index 9ed8dee0ea..e587913491 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.spec.ts @@ -2,9 +2,9 @@ import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { TranslateModule } from '@ngx-translate/core'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { SearchFilterConfig } from '../../../../search-filter-config.model'; -import { FilterType } from '../../../../filter-type.model'; -import { FacetValue } from '../../../../facet-value.model'; +import { SearchFilterConfig } from '../../../../models/search-filter-config.model'; +import { FilterType } from '../../../../models/filter-type.model'; +import { FacetValue } from '../../../../models/facet-value.model'; import { FormsModule } from '@angular/forms'; import { of as observableOf } from 'rxjs'; import { SearchService } from '../../../../../../core/shared/search/search.service'; @@ -20,8 +20,6 @@ import { RANGE_FILTER_MIN_SUFFIX } from '../../search-range-filter/search-range-filter.component'; import { PaginationComponentOptions } from '../../../../../pagination/pagination-component-options.model'; -import { SortDirection, SortOptions } from '../../../../../../core/cache/models/sort-options.model'; -import { FindListOptions } from '../../../../../../core/data/request.models'; import { PaginationService } from '../../../../../../core/pagination/pagination.service'; import { PaginationServiceStub } from '../../../../../testing/pagination-service.stub'; diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.ts index 3d8215b210..b08a54e42b 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.ts @@ -2,8 +2,8 @@ import { Observable, Subscription } from 'rxjs'; import { map } from 'rxjs/operators'; import { Component, Input, OnDestroy, OnInit } from '@angular/core'; import { Router } from '@angular/router'; -import { FacetValue } from '../../../../facet-value.model'; -import { SearchFilterConfig } from '../../../../search-filter-config.model'; +import { FacetValue } from '../../../../models/facet-value.model'; +import { SearchFilterConfig } from '../../../../models/search-filter-config.model'; import { SearchService } from '../../../../../../core/shared/search/search.service'; import { SearchFilterService } from '../../../../../../core/shared/search/search-filter.service'; import { diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.spec.ts index 8f422b41bf..54c447aa61 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.spec.ts @@ -10,13 +10,11 @@ import { SearchFilterService } from '../../../../../../core/shared/search/search import { SearchService } from '../../../../../../core/shared/search/search.service'; import { RouterStub } from '../../../../../testing/router.stub'; import { SearchServiceStub } from '../../../../../testing/search-service.stub'; -import { FacetValue } from '../../../../facet-value.model'; -import { FilterType } from '../../../../filter-type.model'; -import { SearchFilterConfig } from '../../../../search-filter-config.model'; +import { FacetValue } from '../../../../models/facet-value.model'; +import { FilterType } from '../../../../models/filter-type.model'; +import { SearchFilterConfig } from '../../../../models/search-filter-config.model'; import { SearchFacetSelectedOptionComponent } from './search-facet-selected-option.component'; import { PaginationComponentOptions } from '../../../../../pagination/pagination-component-options.model'; -import { SortDirection, SortOptions } from '../../../../../../core/cache/models/sort-options.model'; -import { FindListOptions } from '../../../../../../core/data/request.models'; import { PaginationService } from '../../../../../../core/pagination/pagination.service'; import { PaginationServiceStub } from '../../../../../testing/pagination-service.stub'; diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.ts index d92455fdd9..4566b882eb 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.ts @@ -1,12 +1,12 @@ import { combineLatest as observableCombineLatest, Observable, Subscription } from 'rxjs'; import { Component, Input, OnDestroy, OnInit } from '@angular/core'; import { Router } from '@angular/router'; -import { SearchFilterConfig } from '../../../../search-filter-config.model'; +import { SearchFilterConfig } from '../../../../models/search-filter-config.model'; import { SearchService } from '../../../../../../core/shared/search/search.service'; import { SearchFilterService } from '../../../../../../core/shared/search/search-filter.service'; import { hasValue } from '../../../../../empty.util'; import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service'; -import { FacetValue } from '../../../../facet-value.model'; +import { FacetValue } from '../../../../models/facet-value.model'; import { currentPath } from '../../../../../utils/route.utils'; import { getFacetValueForType } from '../../../../search.utils'; import { PaginationService } from '../../../../../../core/pagination/pagination.service'; 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 6674b090a7..3f83c766fe 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 @@ -1,7 +1,7 @@ import { Component, Injector, Input, OnInit } from '@angular/core'; import { renderFilterType } from '../search-filter-type-decorator'; -import { FilterType } from '../../../filter-type.model'; -import { SearchFilterConfig } from '../../../search-filter-config.model'; +import { FilterType } from '../../../models/filter-type.model'; +import { SearchFilterConfig } from '../../../models/search-filter-config.model'; import { FILTER_CONFIG, IN_PLACE_SEARCH } from '../../../../../core/shared/search/search-filter.service'; import { GenericConstructor } from '../../../../../core/shared/generic-constructor'; import { SearchFacetFilterComponent } from '../search-facet-filter/search-facet-filter.component'; 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 dc58a8c853..919dfc0889 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 @@ -7,9 +7,9 @@ import { IN_PLACE_SEARCH, SearchFilterService } from '../../../../../core/shared/search/search-filter.service'; -import { SearchFilterConfig } from '../../../search-filter-config.model'; -import { FilterType } from '../../../filter-type.model'; -import { FacetValue } from '../../../facet-value.model'; +import { SearchFilterConfig } from '../../../models/search-filter-config.model'; +import { FilterType } from '../../../models/filter-type.model'; +import { FacetValue } from '../../../models/facet-value.model'; import { FormsModule } from '@angular/forms'; import { of as observableOf } from 'rxjs'; import { SearchService } from '../../../../../core/shared/search/search.service'; 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 0b28929554..9b898126f0 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 @@ -15,14 +15,18 @@ import { PaginatedList } from '../../../../../core/data/paginated-list.model'; import { RemoteData } from '../../../../../core/data/remote-data'; import { hasNoValue, hasValue, isNotEmpty } from '../../../../empty.util'; import { EmphasizePipe } from '../../../../utils/emphasize.pipe'; -import { FacetValue } from '../../../facet-value.model'; -import { SearchFilterConfig } from '../../../search-filter-config.model'; +import { FacetValue } from '../../../models/facet-value.model'; +import { SearchFilterConfig } from '../../../models/search-filter-config.model'; import { SearchService } from '../../../../../core/shared/search/search.service'; -import { FILTER_CONFIG, IN_PLACE_SEARCH, SearchFilterService } from '../../../../../core/shared/search/search-filter.service'; +import { + FILTER_CONFIG, + IN_PLACE_SEARCH, + SearchFilterService +} from '../../../../../core/shared/search/search-filter.service'; import { SearchConfigurationService } from '../../../../../core/shared/search/search-configuration.service'; import { getFirstSucceededRemoteData } from '../../../../../core/shared/operators'; import { InputSuggestion } from '../../../../input-suggestions/input-suggestions.model'; -import { SearchOptions } from '../../../search-options.model'; +import { SearchOptions } from '../../../models/search-options.model'; import { SEARCH_CONFIG_SERVICE } from '../../../../../my-dspace-page/my-dspace-page.component'; import { currentPath } from '../../../../utils/route.utils'; import { getFacetValueForType, stripOperatorFromFilterValue } from '../../../search.utils'; diff --git a/src/app/shared/search/search-filters/search-filter/search-filter-type-decorator.ts b/src/app/shared/search/search-filters/search-filter/search-filter-type-decorator.ts index 40cff30d41..7c7d721f2e 100644 --- a/src/app/shared/search/search-filters/search-filter/search-filter-type-decorator.ts +++ b/src/app/shared/search/search-filters/search-filter/search-filter-type-decorator.ts @@ -1,5 +1,4 @@ - -import { FilterType } from '../../filter-type.model'; +import { FilterType } from '../../models/filter-type.model'; /** * Contains the mapping between a facet component and a FilterType diff --git a/src/app/shared/search/search-filters/search-filter/search-filter.actions.ts b/src/app/shared/search/search-filters/search-filter/search-filter.actions.ts index 59a1903eb8..ce1df556c9 100644 --- a/src/app/shared/search/search-filters/search-filter/search-filter.actions.ts +++ b/src/app/shared/search/search-filters/search-filter/search-filter.actions.ts @@ -1,7 +1,7 @@ import { Action } from '@ngrx/store'; import { type } from '../../../ngrx/type'; -import { SearchFilterConfig } from '../../search-filter-config.model'; +import { SearchFilterConfig } from '../../models/search-filter-config.model'; /** * For each action type in an action group, make a simple diff --git a/src/app/shared/search/search-filters/search-filter/search-filter.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-filter.component.spec.ts index ee337a503b..1be4c0f2cb 100644 --- a/src/app/shared/search/search-filters/search-filter/search-filter.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-filter.component.spec.ts @@ -8,8 +8,8 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { SearchFilterService } from '../../../../core/shared/search/search-filter.service'; import { SearchService } from '../../../../core/shared/search/search.service'; import { SearchFilterComponent } from './search-filter.component'; -import { SearchFilterConfig } from '../../search-filter-config.model'; -import { FilterType } from '../../filter-type.model'; +import { SearchFilterConfig } from '../../models/search-filter-config.model'; +import { FilterType } from '../../models/filter-type.model'; import { SearchConfigurationServiceStub } from '../../../testing/search-configuration-service.stub'; import { SEARCH_CONFIG_SERVICE } from '../../../../my-dspace-page/my-dspace-page.component'; import { SequenceService } from '../../../../core/shared/sequence.service'; 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 8bc7502159..1897169a2e 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 @@ -3,7 +3,7 @@ import { Component, Inject, Input, OnInit } from '@angular/core'; import { Observable, of as observableOf } from 'rxjs'; import { filter, map, startWith, switchMap, take } from 'rxjs/operators'; -import { SearchFilterConfig } from '../../search-filter-config.model'; +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'; 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 3b16f84ea5..d2f3de2dc3 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 @@ -1,10 +1,7 @@ import { Component, OnInit } from '@angular/core'; -import { FilterType } from '../../../filter-type.model'; +import { FilterType } from '../../../models/filter-type.model'; import { renderFacetFor } from '../search-filter-type-decorator'; -import { - facetLoad, - SearchFacetFilterComponent -} from '../search-facet-filter/search-facet-filter.component'; +import { facetLoad, SearchFacetFilterComponent } from '../search-facet-filter/search-facet-filter.component'; @Component({ selector: 'ds-search-hierarchy-filter', 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 41f0b4307d..3bdd833c51 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 @@ -7,9 +7,9 @@ import { IN_PLACE_SEARCH, SearchFilterService } from '../../../../../core/shared/search/search-filter.service'; -import { SearchFilterConfig } from '../../../search-filter-config.model'; -import { FilterType } from '../../../filter-type.model'; -import { FacetValue } from '../../../facet-value.model'; +import { SearchFilterConfig } from '../../../models/search-filter-config.model'; +import { FilterType } from '../../../models/filter-type.model'; +import { FacetValue } from '../../../models/facet-value.model'; import { FormsModule } from '@angular/forms'; import { of as observableOf } from 'rxjs'; import { SearchService } from '../../../../../core/shared/search/search.service'; 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 702854dee5..a6b33ddf88 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 @@ -3,11 +3,15 @@ import { map, startWith } from 'rxjs/operators'; import { isPlatformBrowser } from '@angular/common'; import { Component, Inject, OnDestroy, OnInit, PLATFORM_ID } from '@angular/core'; import { RemoteDataBuildService } from '../../../../../core/cache/builders/remote-data-build.service'; -import { FilterType } from '../../../filter-type.model'; +import { FilterType } from '../../../models/filter-type.model'; import { renderFacetFor } from '../search-filter-type-decorator'; import { facetLoad, SearchFacetFilterComponent } from '../search-facet-filter/search-facet-filter.component'; -import { SearchFilterConfig } from '../../../search-filter-config.model'; -import { FILTER_CONFIG, IN_PLACE_SEARCH, SearchFilterService } from '../../../../../core/shared/search/search-filter.service'; +import { SearchFilterConfig } from '../../../models/search-filter-config.model'; +import { + FILTER_CONFIG, + IN_PLACE_SEARCH, + SearchFilterService +} from '../../../../../core/shared/search/search-filter.service'; import { SearchService } from '../../../../../core/shared/search/search.service'; import { Router } from '@angular/router'; import * as moment from 'moment'; diff --git a/src/app/shared/search/search-filters/search-filter/search-text-filter/search-text-filter.component.ts b/src/app/shared/search/search-filters/search-filter/search-text-filter/search-text-filter.component.ts index b2b44ce219..cfd81c3750 100644 --- a/src/app/shared/search/search-filters/search-filter/search-text-filter/search-text-filter.component.ts +++ b/src/app/shared/search/search-filters/search-filter/search-text-filter/search-text-filter.component.ts @@ -1,13 +1,8 @@ import { Component, OnInit } from '@angular/core'; -import { FilterType } from '../../../filter-type.model'; -import { - facetLoad, - SearchFacetFilterComponent -} from '../search-facet-filter/search-facet-filter.component'; +import { FilterType } from '../../../models/filter-type.model'; +import { facetLoad, SearchFacetFilterComponent } from '../search-facet-filter/search-facet-filter.component'; import { renderFacetFor } from '../search-filter-type-decorator'; -import { - addOperatorToFilterValue, -} from '../../../search.utils'; +import { addOperatorToFilterValue, } from '../../../search.utils'; /** * This component renders a simple item page. diff --git a/src/app/shared/search/search-filters/search-filters.component.ts b/src/app/shared/search/search-filters/search-filters.component.ts index 0556da4426..b3850f3b49 100644 --- a/src/app/shared/search/search-filters/search-filters.component.ts +++ b/src/app/shared/search/search-filters/search-filters.component.ts @@ -1,11 +1,11 @@ import { Component, Inject, Input, OnDestroy, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; -import { map, switchMap } from 'rxjs/operators'; +import { map } from 'rxjs/operators'; import { SearchService } from '../../../core/shared/search/search.service'; import { RemoteData } from '../../../core/data/remote-data'; -import { SearchFilterConfig } from '../search-filter-config.model'; +import { SearchFilterConfig } from '../models/search-filter-config.model'; import { SearchConfigurationService } from '../../../core/shared/search/search-configuration.service'; import { SearchFilterService } from '../../../core/shared/search/search-filter.service'; import { getFirstSucceededRemoteData } from '../../../core/shared/operators'; @@ -36,6 +36,16 @@ export class SearchFiltersComponent implements OnInit, OnDestroy { */ clearParams; + /** + * The configuration to use for the search options + */ + @Input() currentConfiguration; + + /** + * The current search scope + */ + @Input() currentScope: string; + /** * True when the search component should show results on the current page */ @@ -56,8 +66,9 @@ export class SearchFiltersComponent implements OnInit, OnDestroy { /** * Initialize instance variables * @param {SearchService} searchService - * @param {SearchConfigurationService} searchConfigService * @param {SearchFilterService} filterService + * @param {Router} router + * @param {SearchConfigurationService} searchConfigService */ constructor( private searchService: SearchService, @@ -82,8 +93,8 @@ export class SearchFiltersComponent implements OnInit, OnDestroy { } initFilters() { - this.filters = this.searchConfigService.searchOptions.pipe( - switchMap((options) => this.searchService.getConfig(options.scope, options.configuration).pipe(getFirstSucceededRemoteData())), + this.filters = this.searchService.getConfig(this.currentScope, this.currentConfiguration).pipe( + getFirstSucceededRemoteData() ); } diff --git a/src/app/shared/search/search-results/search-results.component.html b/src/app/shared/search/search-results/search-results.component.html index 23850f50dd..c383a2fa1a 100644 --- a/src/app/shared/search/search-results/search-results.component.html +++ b/src/app/shared/search/search-results/search-results.component.html @@ -1,5 +1,5 @@

{{ (configuration ? configuration + '.search.results.head' : 'search.results.head') | translate }}

-
+
- + diff --git a/src/app/shared/search/search-results/search-results.component.ts b/src/app/shared/search/search-results/search-results.component.ts index 9e466fd620..e4fccd1269 100644 --- a/src/app/shared/search/search-results/search-results.component.ts +++ b/src/app/shared/search/search-results/search-results.component.ts @@ -2,7 +2,7 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; import { RemoteData } from '../../../core/data/remote-data'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { fadeIn, fadeInOut } from '../../animations/fade'; -import { SearchResult } from '../search-result.model'; +import { SearchResult } from '../models/search-result.model'; import { PaginatedList } from '../../../core/data/paginated-list.model'; import { hasNoValue, isNotEmpty } from '../../empty.util'; import { SortOptions } from '../../../core/cache/models/sort-options.model'; @@ -10,7 +10,12 @@ import { ListableObject } from '../../object-collection/shared/listable-object.m import { CollectionElementLinkType } from '../../object-collection/collection-element-link.type'; import { ViewMode } from '../../../core/shared/view-mode.model'; import { Context } from '../../../core/shared/context.model'; -import { PaginatedSearchOptions } from '../paginated-search-options.model'; +import { PaginatedSearchOptions } from '../models/paginated-search-options.model'; + +export interface SelectionConfig { + repeatable: boolean; + listId: string; +} @Component({ selector: 'ds-search-results', @@ -63,6 +68,9 @@ export class SearchResultsComponent { */ @Input() disableHeader = false; + /** + * A boolean representing if result entries are selectable + */ @Input() selectable = false; @Input() context: Context; @@ -72,12 +80,22 @@ export class SearchResultsComponent { */ @Input() hidePaginationDetail = false; - @Input() selectionConfig: {repeatable: boolean, listId: string}; + /** + * The config option used for selection functionality + */ + @Input() selectionConfig: SelectionConfig = null; @Output() deselectObject: EventEmitter = new EventEmitter(); @Output() selectObject: EventEmitter = new EventEmitter(); + /** + * Check if search results are loading + */ + isLoading() { + return !this.showError() && (hasNoValue(this.searchResults) || hasNoValue(this.searchResults.payload) || this.searchResults.isLoading); + } + showError(): boolean { return this.searchResults?.hasFailed && (!this.searchResults?.errorMessage || this.searchResults?.statusCode !== 400); } diff --git a/src/app/shared/search/search-settings/search-settings.component.html b/src/app/shared/search/search-settings/search-settings.component.html index a31678743d..40bca8e4e8 100644 --- a/src/app/shared/search/search-settings/search-settings.component.html +++ b/src/app/shared/search/search-settings/search-settings.component.html @@ -1,16 +1,14 @@ - +

{{ 'search.sidebar.settings.title' | translate}}

- -
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 6cf8ffc618..06e506ddb0 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 @@ -102,14 +102,12 @@ describe('SearchSettingsComponent', () => { fixture = TestBed.createComponent(SearchSettingsComponent); comp = fixture.componentInstance; - comp.sortOptions = [ + comp.sortOptionsList = [ new SortOptions('score', SortDirection.DESC), new SortOptions('dc.title', SortDirection.ASC), new SortOptions('dc.title', SortDirection.DESC) ]; - comp.searchOptions = paginatedSearchOptions; - // SearchPageComponent test instance fixture.detectChanges(); searchServiceObject = (comp as any).service; @@ -123,7 +121,7 @@ describe('SearchSettingsComponent', () => { const orderSetting = fixture.debugElement.query(By.css('div.result-order-settings')); expect(orderSetting).toBeDefined(); const childElements = orderSetting.queryAll(By.css('option')); - expect(childElements.length).toEqual(comp.sortOptions.length); + expect(childElements.length).toEqual(comp.sortOptionsList.length); }); it('it should show the size settings', () => { 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 9f6cab4a7b..0efd38b5b2 100644 --- a/src/app/shared/search/search-settings/search-settings.component.ts +++ b/src/app/shared/search/search-settings/search-settings.component.ts @@ -2,7 +2,6 @@ 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 { PaginatedSearchOptions } from '../paginated-search-options.model'; 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'; @@ -17,16 +16,15 @@ import { PaginationService } from '../../../core/pagination/pagination.service'; * This component represents the part of the search sidebar that contains the general search settings. */ export class SearchSettingsComponent { - /** - * The configuration for the current paginated search results + * The current sort option used */ - @Input() searchOptions: PaginatedSearchOptions; + @Input() currentSortOption: SortOptions; /** * All sort options that are shown in the settings */ - @Input() sortOptions: SortOptions[]; + @Input() sortOptionsList: SortOptions[]; constructor(private service: SearchService, private route: ActivatedRoute, diff --git a/src/app/shared/search/search-sidebar/search-sidebar.component.html b/src/app/shared/search/search-sidebar/search-sidebar.component.html index 624d094d22..e17fe941ba 100644 --- a/src/app/shared/search/search-sidebar/search-sidebar.component.html +++ b/src/app/shared/search/search-sidebar/search-sidebar.component.html @@ -8,11 +8,20 @@
- +
diff --git a/src/app/shared/search/search-sidebar/search-sidebar.component.ts b/src/app/shared/search/search-sidebar/search-sidebar.component.ts index 7f134cacd3..415cc19d3b 100644 --- a/src/app/shared/search/search-sidebar/search-sidebar.component.ts +++ b/src/app/shared/search/search-sidebar/search-sidebar.component.ts @@ -2,8 +2,9 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; import { SearchConfigurationOption } from '../search-switch-configuration/search-configuration-option.model'; import { Observable } from 'rxjs'; -import { PaginatedSearchOptions } from '../paginated-search-options.model'; +import { PaginatedSearchOptions } from '../models/paginated-search-options.model'; import { SortOptions } from '../../../core/cache/models/sort-options.model'; +import { ViewMode } from '../../../core/shared/view-mode.model'; /** * This component renders a simple item page. @@ -22,11 +23,26 @@ import { SortOptions } from '../../../core/cache/models/sort-options.model'; */ export class SearchSidebarComponent { + /** + * The configuration to use for the search options + */ + @Input() configuration; + /** * The list of available configuration options */ @Input() configurationList: SearchConfigurationOption[]; + /** + * The current search scope + */ + @Input() currentScope: string; + + /** + * The current sort option used + */ + @Input() currentSortOption: SortOptions; + /** * The total amount of results */ @@ -35,7 +51,7 @@ export class SearchSidebarComponent { /** * The list of available view mode options */ - @Input() viewModeList; + @Input() viewModeList: ViewMode[]; /** * Whether to show the view mode switch @@ -55,7 +71,7 @@ export class SearchSidebarComponent { /** * All sort options that are shown in the settings */ - @Input() sortOptions: SortOptions[]; + @Input() sortOptionsList: SortOptions[]; /** * Emits when the search filters values may be stale, and so they must be refreshed. @@ -67,4 +83,14 @@ export class SearchSidebarComponent { */ @Output() toggleSidebar = new EventEmitter(); + /** + * Emits event when the user select a new configuration + */ + @Output() changeConfiguration: EventEmitter = new EventEmitter(); + + /** + * Emits event when the user select a new view mode + */ + @Output() changeViewMode: EventEmitter = new EventEmitter(); + } diff --git a/src/app/shared/search/search-switch-configuration/search-configuration-option.model.ts b/src/app/shared/search/search-switch-configuration/search-configuration-option.model.ts index 6f9a72da48..d59f7b74b1 100644 --- a/src/app/shared/search/search-switch-configuration/search-configuration-option.model.ts +++ b/src/app/shared/search/search-switch-configuration/search-configuration-option.model.ts @@ -1,6 +1,8 @@ /** * Represents a search configuration select option */ +import { Context } from '../../../core/shared/context.model'; + export interface SearchConfigurationOption { /** @@ -12,4 +14,9 @@ export interface SearchConfigurationOption { * The select option label */ label: string; + + /** + * The search context to use with the configuration + */ + context: Context; } diff --git a/src/app/shared/search/search-switch-configuration/search-switch-configuration.component.html b/src/app/shared/search/search-switch-configuration/search-switch-configuration.component.html index e66483b645..f63bf9fa84 100644 --- a/src/app/shared/search/search-switch-configuration/search-switch-configuration.component.html +++ b/src/app/shared/search/search-switch-configuration/search-switch-configuration.component.html @@ -6,7 +6,7 @@ [compareWith]="compare" [(ngModel)]="selectedOption" (change)="onSelect()"> - diff --git a/src/app/shared/search/search-switch-configuration/search-switch-configuration.component.spec.ts b/src/app/shared/search/search-switch-configuration/search-switch-configuration.component.spec.ts index 3c0b9d156b..94e05b64fe 100644 --- a/src/app/shared/search/search-switch-configuration/search-switch-configuration.component.spec.ts +++ b/src/app/shared/search/search-switch-configuration/search-switch-configuration.component.spec.ts @@ -13,6 +13,7 @@ import { SearchService } from '../../../core/shared/search/search.service'; import { MYDSPACE_ROUTE, SEARCH_CONFIG_SERVICE } from '../../../my-dspace-page/my-dspace-page.component'; import { MyDSpaceConfigurationValueType } from '../../../my-dspace-page/my-dspace-configuration-value-type'; import { TranslateLoaderMock } from '../../mocks/translate-loader.mock'; +import { Context } from '../../../core/shared/context.model'; describe('SearchSwitchConfigurationComponent', () => { @@ -25,6 +26,18 @@ describe('SearchSwitchConfigurationComponent', () => { getSearchLink: jasmine.createSpy('getSearchLink') }); + const configurationList = [ + { + value: MyDSpaceConfigurationValueType.Workspace, + label: 'workspace', + context: Context.Workspace + }, + { + value: MyDSpaceConfigurationValueType.Workflow, + label: 'workflow', + context: Context.Workflow + }, + ]; beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [ @@ -52,16 +65,7 @@ describe('SearchSwitchConfigurationComponent', () => { spyOn(searchConfService, 'getCurrentConfiguration').and.returnValue(observableOf(MyDSpaceConfigurationValueType.Workspace)); - comp.configurationList = [ - { - value: MyDSpaceConfigurationValueType.Workspace, - label: 'workspace' - }, - { - value: MyDSpaceConfigurationValueType.Workflow, - label: 'workflow' - }, - ]; + comp.configurationList = configurationList; // SearchSwitchConfigurationComponent test instance fixture.detectChanges(); @@ -69,7 +73,7 @@ describe('SearchSwitchConfigurationComponent', () => { }); it('should init the current configuration name', () => { - expect(comp.selectedOption).toBe(MyDSpaceConfigurationValueType.Workspace); + expect(comp.selectedOption).toBe(configurationList[0]); }); it('should display select field properly', () => { @@ -95,7 +99,8 @@ describe('SearchSwitchConfigurationComponent', () => { it('should navigate to the route when selecting an option', () => { spyOn((comp as any), 'getSearchLinkParts').and.returnValue([MYDSPACE_ROUTE]); - comp.selectedOption = MyDSpaceConfigurationValueType.Workflow; + spyOn((comp as any).changeConfiguration, 'emit'); + comp.selectedOption = configurationList[1]; const navigationExtras: NavigationExtras = { queryParams: { configuration: MyDSpaceConfigurationValueType.Workflow }, }; @@ -105,5 +110,6 @@ describe('SearchSwitchConfigurationComponent', () => { comp.onSelect(); expect((comp as any).router.navigate).toHaveBeenCalledWith([MYDSPACE_ROUTE], navigationExtras); + expect((comp as any).changeConfiguration.emit).toHaveBeenCalled(); }); }); diff --git a/src/app/shared/search/search-switch-configuration/search-switch-configuration.component.ts b/src/app/shared/search/search-switch-configuration/search-switch-configuration.component.ts index 061ca96a70..1852277673 100644 --- a/src/app/shared/search/search-switch-configuration/search-switch-configuration.component.ts +++ b/src/app/shared/search/search-switch-configuration/search-switch-configuration.component.ts @@ -1,4 +1,4 @@ -import { Component, Inject, Input, OnDestroy, OnInit } from '@angular/core'; +import { Component, EventEmitter, Inject, Input, OnDestroy, OnInit, Output } from '@angular/core'; import { NavigationExtras, Router } from '@angular/router'; import { Subscription } from 'rxjs'; @@ -10,6 +10,7 @@ import { MyDSpaceConfigurationValueType } from '../../../my-dspace-page/my-dspac import { SearchConfigurationOption } from './search-configuration-option.model'; import { SearchService } from '../../../core/shared/search/search.service'; import { currentPath } from '../../utils/route.utils'; +import { findIndex } from 'lodash'; @Component({ selector: 'ds-search-switch-configuration', @@ -29,17 +30,25 @@ export class SearchSwitchConfigurationComponent implements OnDestroy, OnInit { * The list of available configuration options */ @Input() configurationList: SearchConfigurationOption[] = []; - + /** + * The default configuration to use if no defined + */ + @Input() defaultConfiguration: string; /** * The selected option */ - public selectedOption: string; + public selectedOption: SearchConfigurationOption; /** * Subscription to unsubscribe from */ private sub: Subscription; + /** + * Emits event when the user select a new configuration + */ + @Output() changeConfiguration: EventEmitter = new EventEmitter(); + constructor(private router: Router, private searchService: SearchService, @Inject(SEARCH_CONFIG_SERVICE) private searchConfigService: SearchConfigurationService) { @@ -49,8 +58,11 @@ export class SearchSwitchConfigurationComponent implements OnDestroy, OnInit { * Init current configuration */ ngOnInit() { - this.searchConfigService.getCurrentConfiguration('default') - .subscribe((currentConfiguration) => this.selectedOption = currentConfiguration); + this.searchConfigService.getCurrentConfiguration(this.defaultConfiguration) + .subscribe((currentConfiguration) => { + const index = findIndex(this.configurationList, {value: currentConfiguration }); + this.selectedOption = this.configurationList[index]; + }); } /** @@ -58,9 +70,10 @@ export class SearchSwitchConfigurationComponent implements OnDestroy, OnInit { */ onSelect() { const navigationExtras: NavigationExtras = { - queryParams: {configuration: this.selectedOption}, + queryParams: {configuration: this.selectedOption.value}, }; + this.changeConfiguration.emit(this.selectedOption); this.router.navigate(this.getSearchLinkParts(), navigationExtras); } diff --git a/src/app/shared/search/search.component.html b/src/app/shared/search/search.component.html new file mode 100644 index 0000000000..5ca3e925a5 --- /dev/null +++ b/src/app/shared/search/search.component.html @@ -0,0 +1,90 @@ +
+
+
+ +
+
+
+ +
+ +
+ + + + + + +
+
+ + +
+
+
+ + +
+ +
+
+
+ + + + + + + + + + +
+
+ +
+
+
diff --git a/src/app/search-page/search.component.scss b/src/app/shared/search/search.component.scss similarity index 100% rename from src/app/search-page/search.component.scss rename to src/app/shared/search/search.component.scss diff --git a/src/app/shared/search/search.component.spec.ts b/src/app/shared/search/search.component.spec.ts new file mode 100644 index 0000000000..11b0293e6c --- /dev/null +++ b/src/app/shared/search/search.component.spec.ts @@ -0,0 +1,296 @@ +import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; + +import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing'; +import { RouterTestingModule } from '@angular/router/testing'; +import { Store } from '@ngrx/store'; +import { TranslateModule } from '@ngx-translate/core'; +import { cold } from 'jasmine-marbles'; +import { BehaviorSubject, of as observableOf } from 'rxjs'; +import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; +import { CommunityDataService } from '../../core/data/community-data.service'; +import { HostWindowService } from '../host-window.service'; +import { PaginationComponentOptions } from '../pagination/pagination-component-options.model'; +import { SearchComponent } from './search.component'; +import { SearchService } from '../../core/shared/search/search.service'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { ActivatedRoute } from '@angular/router'; +import { By } from '@angular/platform-browser'; +import { NgbCollapseModule } from '@ng-bootstrap/ng-bootstrap'; +import { SidebarService } from '../sidebar/sidebar.service'; +import { SearchFilterService } from '../../core/shared/search/search-filter.service'; +import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service'; +import { SEARCH_CONFIG_SERVICE } from '../../my-dspace-page/my-dspace-page.component'; +import { RouteService } from '../../core/services/route.service'; +import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../remote-data.utils'; +import { PaginatedSearchOptions } from './models/paginated-search-options.model'; +import { SidebarServiceStub } from '../testing/sidebar-service.stub'; +import { SearchConfig, SortConfig } from '../../core/shared/search/search-filters/search-config.model'; +import { Item } from '../../core/shared/item.model'; +import { RemoteData } from '../../core/data/remote-data'; +import { SearchObjects } from './models/search-objects.model'; +import { DSpaceObject } from '../../core/shared/dspace-object.model'; +import { Observable } from 'rxjs/internal/Observable'; + +let comp: SearchComponent; +let fixture: ComponentFixture; +let searchServiceObject: SearchService; +let searchConfigurationServiceObject: SearchConfigurationService; +const store: Store = jasmine.createSpyObj('store', { + /* tslint:disable:no-empty */ + dispatch: {}, + /* tslint:enable:no-empty */ + select: observableOf(true) +}); +const sortConfigList: SortConfig[] = [ + { name: 'score', sortOrder: SortDirection.DESC }, + { name: 'dc.title', sortOrder: SortDirection.ASC }, + { name: 'dc.title', sortOrder: SortDirection.DESC } +]; +const sortOptionsList: SortOptions[] = [ + new SortOptions('score', SortDirection.DESC), + new SortOptions('dc.title', SortDirection.ASC), + new SortOptions('dc.title', SortDirection.DESC) +]; +const searchConfig = Object.assign(new SearchConfig(), { + sortOptions: sortConfigList +}); +const paginationId = 'search-test-page-id'; +const pagination: PaginationComponentOptions = new PaginationComponentOptions(); +pagination.id = paginationId; +pagination.currentPage = 1; +pagination.pageSize = 10; +const mockDso = Object.assign(new Item(), { + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'Item nr 1' + } + ] + }, + _links: { + self: { + href: 'selfLink1' + } + } +}); + +const mockDso2 = Object.assign(new Item(), { + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'Item nr 2' + } + ] + }, + _links: { + self: { + href: 'selfLink2' + } + } +}); +const sort: SortOptions = new SortOptions('score', SortDirection.DESC); +const mockSearchResults: SearchObjects = Object.assign(new SearchObjects(), { + page: [mockDso, mockDso2] +}); +const mockResultsRD: RemoteData> = createSuccessfulRemoteDataObject(mockSearchResults); +const mockResultsRD$: Observable>> = observableOf(mockResultsRD); +const searchServiceStub = jasmine.createSpyObj('SearchService', { + search: mockResultsRD$, + getSearchLink: '/search', + getScopes: observableOf(['test-scope']), + getSearchConfigurationFor: createSuccessfulRemoteDataObject$(searchConfig) +}); +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([ + ['query', queryParam], + ['scope', scopeParam] + ]) + }, + queryParams: observableOf({ + query: queryParam, + scope: scopeParam + }) +}; + +const routeServiceStub = { + getRouteParameterValue: () => { + return observableOf(''); + }, + getQueryParameterValue: () => { + return observableOf(''); + }, + getQueryParamsWithPrefix: () => { + return observableOf(''); + }, + setParameter: () => { + return; + } +}; + + +const searchConfigurationServiceStub = jasmine.createSpyObj('SearchConfigurationService', { + getConfigurationSortOptions: jasmine.createSpy('getConfigurationSortOptions'), + getConfigurationSearchConfig: jasmine.createSpy('getConfigurationSearchConfig'), + getCurrentConfiguration: jasmine.createSpy('getCurrentConfiguration'), + getCurrentScope: jasmine.createSpy('getCurrentScope'), + getCurrentSort: jasmine.createSpy('getCurrentSort'), + updateFixedFilter: jasmine.createSpy('updateFixedFilter'), + setPaginationId: jasmine.createSpy('setPaginationId') +}, ['paginatedSearchOptions']); + +export function configureSearchComponentTestingModule(compType, additionalDeclarations: any[] = []) { + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), NoopAnimationsModule, NgbCollapseModule], + declarations: [compType, ...additionalDeclarations], + providers: [ + { provide: SearchService, useValue: searchServiceStub }, + { + provide: CommunityDataService, + useValue: jasmine.createSpyObj('communityService', ['findById', 'findAll']) + }, + { provide: ActivatedRoute, useValue: activatedRouteStub }, + { provide: RouteService, useValue: routeServiceStub }, + { + provide: Store, useValue: store + }, + { + provide: HostWindowService, useValue: jasmine.createSpyObj('hostWindowService', + { + isXs: observableOf(true), + isSm: observableOf(false), + isXsOrSm: observableOf(true) + }) + }, + { + provide: SidebarService, + useValue: SidebarServiceStub + }, + { + provide: SearchFilterService, + useValue: {} + }, + { + provide: SEARCH_CONFIG_SERVICE, + useValue: searchConfigurationServiceStub + } + ], + schemas: [NO_ERRORS_SCHEMA] + }).overrideComponent(compType, { + set: { changeDetection: ChangeDetectionStrategy.Default } + }).compileComponents(); +} + +describe('SearchComponent', () => { + beforeEach(waitForAsync(() => { + configureSearchComponentTestingModule(SearchComponent); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SearchComponent); + comp = fixture.componentInstance; // SearchComponent test instance + comp.inPlaceSearch = false; + comp.paginationId = paginationId; + + searchConfigurationServiceStub.getConfigurationSearchConfig.and.returnValue(observableOf(searchConfig)); + searchConfigurationServiceStub.getConfigurationSortOptions.and.returnValue(sortOptionsList); + searchConfigurationServiceStub.getCurrentConfiguration.and.returnValue(observableOf('default')); + searchConfigurationServiceStub.getCurrentScope.and.returnValue(observableOf('test-id')); + searchConfigurationServiceStub.getCurrentSort.and.returnValue(observableOf(sortOptionsList[0])); + searchConfigurationServiceStub.setPaginationId.and.callFake((pageId) => { + paginatedSearchOptions$.next(Object.assign(paginatedSearchOptions$.value, { + pagination: Object.assign(new PaginationComponentOptions(), { + id: pageId + }) + })); + }); + 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(() => { + spyOn((comp as any), 'retrieveSearchResults').and.callThrough(); + fixture.detectChanges(); + tick(100); + + const expectedSearchOptions = Object.assign(paginatedSearchOptions$.value, { + configuration: 'default', + sort: sortOptionsList[0] + }); + expect(comp.currentConfiguration$).toBeObservable(cold('b', { + b: 'default' + })); + expect(comp.currentSortOptions$).toBeObservable(cold('b', { + b: sortOptionsList[0] + })); + expect(comp.sortOptionsList$).toBeObservable(cold('b', { + b: sortOptionsList + })); + expect(comp.searchOptions$).toBeObservable(cold('b', { + b: expectedSearchOptions + })); + expect((comp as any).retrieveSearchResults).toHaveBeenCalledWith(expectedSearchOptions); + })); + + it('should retrieve SearchResults', fakeAsync(() => { + fixture.detectChanges(); + tick(100); + const expectedResults = mockResultsRD; + expect(comp.resultsRD$).toBeObservable(cold('b', { + b: expectedResults + })); + })); + + it('should emit resultFound event', fakeAsync(() => { + spyOn(comp.resultFound, 'emit'); + const expectedResults = mockSearchResults; + fixture.detectChanges(); + tick(100); + expect(comp.resultFound.emit).toHaveBeenCalledWith(expectedResults); + })); + + describe('when the open sidebar button is clicked in mobile view', () => { + + beforeEach(() => { + spyOn(comp, 'openSidebar'); + }); + + it('should trigger the openSidebar function', fakeAsync(() => { + fixture.detectChanges(); + tick(100); + fixture.detectChanges(); + const openSidebarButton = fixture.debugElement.query(By.css('.open-sidebar')); + openSidebarButton.triggerEventHandler('click', null); + expect(comp.openSidebar).toHaveBeenCalled(); + })); + + }); +}); diff --git a/src/app/shared/search/search.component.ts b/src/app/shared/search/search.component.ts new file mode 100644 index 0000000000..c017a5065b --- /dev/null +++ b/src/app/shared/search/search.component.ts @@ -0,0 +1,382 @@ +import { ChangeDetectionStrategy, Component, EventEmitter, Inject, Input, OnInit, Output } from '@angular/core'; +import { Router } from '@angular/router'; + +import { BehaviorSubject, combineLatest, Observable, Subscription } from 'rxjs'; +import { debounceTime, distinctUntilChanged, filter, map, switchMap } from 'rxjs/operators'; +import { uniqueId } from 'lodash'; + +import { PaginatedList } from '../../core/data/paginated-list.model'; +import { RemoteData } from '../../core/data/remote-data'; +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 } 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'; +import { SearchResult } from './models/search-result.model'; +import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service'; +import { SearchService } from '../../core/shared/search/search.service'; +import { currentPath } from '../utils/route.utils'; +import { Context } from '../../core/shared/context.model'; +import { SortOptions } from '../../core/cache/models/sort-options.model'; +import { SearchConfig } from '../../core/shared/search/search-filters/search-config.model'; +import { SearchConfigurationOption } from './search-switch-configuration/search-configuration-option.model'; +import { getFirstCompletedRemoteData } from '../../core/shared/operators'; +import { followLink } from '../utils/follow-link-config.model'; +import { Item } from '../../core/shared/item.model'; +import { SearchObjects } from './models/search-objects.model'; +import { ViewMode } from '../../core/shared/view-mode.model'; +import { SelectionConfig } from './search-results/search-results.component'; +import { ListableObject } from '../object-collection/shared/listable-object.model'; +import { CollectionElementLinkType } from '../object-collection/collection-element-link.type'; + +@Component({ + selector: 'ds-search', + styleUrls: ['./search.component.scss'], + templateUrl: './search.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + animations: [pushInOut], +}) + +/** + * This component renders a sidebar, a search input bar and the search results. + */ +export class SearchComponent implements OnInit { + + /** + * The list of available configuration options + */ + @Input() configurationList: SearchConfigurationOption[] = []; + + /** + * The current context + * If empty, 'search' is used + */ + @Input() context: Context = Context.Search; + + /** + * The configuration to use for the search options + * If empty, 'default' is used + */ + @Input() configuration = 'default'; + + /** + * The actual query for the fixed filter. + * If empty, the query will be determined by the route parameter called 'filter' + */ + @Input() fixedFilterQuery: string; + + /** + * If this is true, the request will only be sent if there's + * no valid cached version. Defaults to true + */ + @Input() useCachedVersionIfAvailable = true; + + /** + * True when the search component should show results on the current page + */ + @Input() inPlaceSearch = true; + + /** + * The link type of the listed search results + */ + @Input() linkType: CollectionElementLinkType; + + /** + * The pagination id used in the search + */ + @Input() paginationId = 'spc'; + + /** + * Whether or not the search bar should be visible + */ + @Input() searchEnabled = true; + + /** + * The width of the sidebar (bootstrap columns) + */ + @Input() sideBarWidth = 3; + + /** + * The placeholder of the search form input + */ + @Input() searchFormPlaceholder = 'search.search-form.placeholder'; + + /** + * A boolean representing if result entries are selectable + */ + @Input() selectable = false; + + /** + * The config option used for selection functionality + */ + @Input() selectionConfig: SelectionConfig; + + /** + * A boolean representing if show search sidebar button + */ + @Input() showSidebar = true; + + /** + * Whether to show the view mode switch + */ + @Input() showViewModes = true; + + /** + * List of available view mode + */ + @Input() useUniquePageId: false; + + /** + * List of available view mode + */ + @Input() viewModeList: ViewMode[]; + + /** + * The current configuration used during the search + */ + currentConfiguration$: BehaviorSubject = new BehaviorSubject(''); + + /** + * The current context used during the search + */ + currentContext$: BehaviorSubject = new BehaviorSubject(null); + + /** + * The current sort options used + */ + currentScope$: BehaviorSubject = new BehaviorSubject(''); + + /** + * The current sort options used + */ + currentSortOptions$: BehaviorSubject = new BehaviorSubject(null); + + /** + * The current search results + */ + resultsRD$: BehaviorSubject>>> = new BehaviorSubject(null); + + /** + * The current paginated search options + */ + searchOptions$: BehaviorSubject = new BehaviorSubject(null); + + /** + * The available sort options list + */ + sortOptionsList$: BehaviorSubject = new BehaviorSubject([]); + + /** + * TRUE if the search option are initialized + */ + initialized$: BehaviorSubject = new BehaviorSubject(false); + + /** + * Observable for whether or not the sidebar is currently collapsed + */ + isSidebarCollapsed$: Observable; + + /** + * Emits true if were on a small screen + */ + isXsOrSm$: Observable; + + /** + * Link to the search page + */ + searchLink: string; + + /** + * Subscription to unsubscribe from + */ + sub: Subscription; + + /** + * Emits an event with the current search result entries + */ + @Output() resultFound: EventEmitter> = new EventEmitter>(); + + /** + * Emits event when the user deselect result entry + */ + @Output() deselectObject: EventEmitter = new EventEmitter(); + + /** + * Emits event when the user select result entry + */ + @Output() selectObject: EventEmitter = new EventEmitter(); + + constructor(protected service: SearchService, + protected sidebarService: SidebarService, + protected windowService: HostWindowService, + @Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: SearchConfigurationService, + protected routeService: RouteService, + protected router: Router) { + this.isXsOrSm$ = this.windowService.isXsOrSm(); + } + + /** + * Listening to changes in the paginated search options + * If something changes, update the search results + * + * Listen to changes in the scope + * If something changes, update the list of scopes for the dropdown + */ + ngOnInit(): void { + if (this.useUniquePageId) { + // Create an unique pagination id related to the instance of the SearchComponent + this.paginationId = uniqueId(this.paginationId); + } + + this.searchConfigService.setPaginationId(this.paginationId); + + if (hasValue(this.configuration)) { + this.routeService.setParameter('configuration', this.configuration); + } + if (hasValue(this.fixedFilterQuery)) { + this.routeService.setParameter('fixedFilterQuery', this.fixedFilterQuery); + } + + this.isSidebarCollapsed$ = this.isSidebarCollapsed(); + this.searchLink = this.getSearchLink(); + this.currentContext$.next(this.context); + + // 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, this.service)), + map((searchConfig: SearchConfig) => this.searchConfigService.getConfigurationSortOptions(searchConfig)), + distinctUntilChanged() + ); + const sortOption$: Observable = searchSortOptions$.pipe( + switchMap((searchSortOptions: SortOptions[]) => { + const defaultSort: SortOptions = searchSortOptions[0]; + return this.searchConfigService.getCurrentSort(this.paginationId, defaultSort); + }), + distinctUntilChanged() + ); + const searchOptions$: Observable = this.getSearchOptions().pipe(distinctUntilChanged()); + + this.sub = combineLatest([configuration$, searchSortOptions$, searchOptions$, sortOption$]).pipe( + filter(([configuration, searchSortOptions, searchOptions, sortOption]: [string, SortOptions[], PaginatedSearchOptions, SortOptions]) => { + // 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]) => { + // Build the PaginatedSearchOptions object + const combinedOptions = Object.assign({}, searchOptions, + { + configuration: searchOptions.configuration || configuration, + sort: sortOption || searchOptions.sort + }); + const newSearchOptions = new PaginatedSearchOptions(combinedOptions); + // check if search options are changed + // if so retrieve new related results otherwise skip it + if (JSON.stringify(newSearchOptions) !== JSON.stringify(this.searchOptions$.value)) { + // 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); + } + }); + } + + /** + * Change the current context + * @param context + */ + public changeContext(context: Context) { + this.currentContext$.next(context); + } + + /** + * Set the sidebar to a collapsed state + */ + public closeSidebar(): void { + this.sidebarService.collapse(); + } + + /** + * Reset result list on view mode change + */ + public changeViewMode() { + this.resultsRD$.next(null); + } + + /** + * Set the sidebar to an expanded state + */ + public openSidebar(): void { + this.sidebarService.expand(); + } + + /** + * Unsubscribe from the subscription + */ + ngOnDestroy(): void { + if (hasValue(this.sub)) { + this.sub.unsubscribe(); + } + } + + /** + * Get the current paginated search options + * @returns {Observable} + */ + protected getSearchOptions(): Observable { + return this.searchConfigService.paginatedSearchOptions; + } + + /** + * Retrieve search result by the given search options + * @param searchOptions + * @private + */ + private retrieveSearchResults(searchOptions: PaginatedSearchOptions) { + this.resultsRD$.next(null); + this.service.search( + searchOptions, + undefined, + this.useCachedVersionIfAvailable, + true, + followLink('thumbnail', { isOptional: true }) + ).pipe(getFirstCompletedRemoteData()) + .subscribe((results: RemoteData>) => { + if (results.hasSucceeded && results.payload?.page?.length > 0) { + this.resultFound.emit(results.payload); + } + this.resultsRD$.next(results); + }); + } + + /** + * Check if the sidebar is collapsed + * @returns {Observable} emits true if the sidebar is currently collapsed, false if it is expanded + */ + private isSidebarCollapsed(): Observable { + return this.sidebarService.isCollapsed; + } + + /** + * @returns {string} The base path to the search page, or the current page when inPlaceSearch is true + */ + private getSearchLink(): string { + if (this.inPlaceSearch) { + return currentPath(this.router); + } + return this.service.getSearchLink(); + } + + +} diff --git a/src/app/shared/search/search.module.ts b/src/app/shared/search/search.module.ts new file mode 100644 index 0000000000..668d260c23 --- /dev/null +++ b/src/app/shared/search/search.module.ts @@ -0,0 +1,105 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { SearchSwitchConfigurationComponent } from './search-switch-configuration/search-switch-configuration.component'; +import { SearchFiltersComponent } from './search-filters/search-filters.component'; +import { SearchFilterComponent } from './search-filters/search-filter/search-filter.component'; +import { SearchFacetFilterComponent } from './search-filters/search-filter/search-facet-filter/search-facet-filter.component'; +import { SearchLabelsComponent } from './search-labels/search-labels.component'; +import { SearchLabelComponent } from './search-labels/search-label/search-label.component'; +import { SearchFacetFilterWrapperComponent } from './search-filters/search-filter/search-facet-filter-wrapper/search-facet-filter-wrapper.component'; +import { SearchRangeFilterComponent } from './search-filters/search-filter/search-range-filter/search-range-filter.component'; +import { SearchTextFilterComponent } from './search-filters/search-filter/search-text-filter/search-text-filter.component'; +import { SearchHierarchyFilterComponent } from './search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component'; +import { SearchBooleanFilterComponent } from './search-filters/search-filter/search-boolean-filter/search-boolean-filter.component'; +import { SearchFacetOptionComponent } from './search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component'; +import { SearchFacetSelectedOptionComponent } from './search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component'; +import { SearchFacetRangeOptionComponent } from './search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component'; +import { SearchAuthorityFilterComponent } from './search-filters/search-filter/search-authority-filter/search-authority-filter.component'; +import { SearchSidebarComponent } from './search-sidebar/search-sidebar.component'; +import { SearchSettingsComponent } from './search-settings/search-settings.component'; +import { ConfigurationSearchPageComponent } from '../../search-page/configuration-search-page.component'; +import { ThemedConfigurationSearchPageComponent } from '../../search-page/themed-configuration-search-page.component'; +import { SearchObjects } from './models/search-objects.model'; +import { FacetConfigResponse } from './models/facet-config-response.model'; +import { FacetValues } from './models/facet-values.model'; +import { SearchResult } from './models/search-result.model'; +import { MissingTranslationHandler, TranslateModule } from '@ngx-translate/core'; +import { MissingTranslationHelper } from '../translate/missing-translation.helper'; +import { SharedModule } from '../shared.module'; +import { SearchResultsComponent } from './search-results/search-results.component'; +import { SearchComponent } from './search.component'; + +const COMPONENTS = [ + SearchComponent, + SearchResultsComponent, + SearchSidebarComponent, + SearchSettingsComponent, + SearchFiltersComponent, + SearchFilterComponent, + SearchFacetFilterComponent, + SearchLabelsComponent, + SearchLabelComponent, + SearchFacetFilterWrapperComponent, + SearchRangeFilterComponent, + SearchTextFilterComponent, + SearchHierarchyFilterComponent, + SearchBooleanFilterComponent, + SearchFacetOptionComponent, + SearchFacetSelectedOptionComponent, + SearchFacetRangeOptionComponent, + SearchAuthorityFilterComponent, + SearchSwitchConfigurationComponent, + ConfigurationSearchPageComponent, + ThemedConfigurationSearchPageComponent +]; + +const ENTRY_COMPONENTS = [ + SearchFacetFilterComponent, + SearchRangeFilterComponent, + SearchTextFilterComponent, + SearchHierarchyFilterComponent, + SearchBooleanFilterComponent, + SearchFacetOptionComponent, + SearchFacetSelectedOptionComponent, + SearchFacetRangeOptionComponent, + SearchAuthorityFilterComponent, +]; + +/** + * Declaration needed to make sure all decorator functions are called in time + */ +export const MODELS = [ + SearchObjects, + FacetConfigResponse, + FacetValues, + SearchResult +]; + +@NgModule({ + declarations: [ + ...COMPONENTS + ], + imports: [ + CommonModule, + TranslateModule.forChild({ + missingTranslationHandler: { provide: MissingTranslationHandler, useClass: MissingTranslationHelper }, + useDefaultLang: true + }), + SharedModule.withEntryComponents() + ], + exports: [ + ...COMPONENTS + ] +}) +export class SearchModule { + /** + * NOTE: this method allows to resolve issue with components that using a custom decorator + * which are not loaded during SSR otherwise + */ + static withEntryComponents() { + return { + ngModule: SearchModule, + providers: ENTRY_COMPONENTS.map((component) => ({ provide: component })) + }; + } +} diff --git a/src/app/shared/search/search.utils.spec.ts b/src/app/shared/search/search.utils.spec.ts index 40f1328ffe..969ea1927d 100644 --- a/src/app/shared/search/search.utils.spec.ts +++ b/src/app/shared/search/search.utils.spec.ts @@ -1,5 +1,5 @@ -import { FacetValue } from './facet-value.model'; -import { SearchFilterConfig } from './search-filter-config.model'; +import { FacetValue } from './models/facet-value.model'; +import { SearchFilterConfig } from './models/search-filter-config.model'; import { addOperatorToFilterValue, escapeRegExp, diff --git a/src/app/shared/search/search.utils.ts b/src/app/shared/search/search.utils.ts index 2b9944562a..3626567b02 100644 --- a/src/app/shared/search/search.utils.ts +++ b/src/app/shared/search/search.utils.ts @@ -1,5 +1,5 @@ -import { FacetValue } from './facet-value.model'; -import { SearchFilterConfig } from './search-filter-config.model'; +import { FacetValue } from './models/facet-value.model'; +import { SearchFilterConfig } from './models/search-filter-config.model'; import { isNotEmpty } from '../empty.util'; /** diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 2b64260f46..d88445a930 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -6,17 +6,21 @@ import { CdkTreeModule } from '@angular/cdk/tree'; import { DragDropModule } from '@angular/cdk/drag-drop'; import { NouisliderModule } from 'ng2-nouislider'; -import { NgbDatepickerModule, NgbModule, NgbTimepickerModule, NgbTypeaheadModule } from '@ng-bootstrap/ng-bootstrap'; +import { + NgbDatepickerModule, + NgbDropdownModule, + NgbNavModule, + NgbPaginationModule, + NgbTimepickerModule, + NgbTooltipModule, + NgbTypeaheadModule +} from '@ng-bootstrap/ng-bootstrap'; import { MissingTranslationHandler, TranslateModule } from '@ngx-translate/core'; import { NgxPaginationModule } from 'ngx-pagination'; import { FileUploadModule } from 'ng2-file-upload'; import { InfiniteScrollModule } from 'ngx-infinite-scroll'; -import { DYNAMIC_FORM_CONTROL_MAP_FN, DynamicFormsCoreModule } from '@ng-dynamic-forms/core'; -import { DynamicFormsNGBootstrapUIModule } from '@ng-dynamic-forms/ui-ng-bootstrap'; import { TextMaskModule } from 'angular2-text-mask'; import { MomentModule } from 'ngx-moment'; - -import { ComcolRoleComponent } from './comcol-forms/edit-comcol-page/comcol-role/comcol-role.component'; import { ConfirmationModalComponent } from './confirmation-modal/confirmation-modal.component'; import { ExportMetadataSelectorComponent } from './dso-selector/modal-wrappers/export-metadata-selector/export-metadata-selector.component'; import { FileDropzoneNoUploaderComponent } from './file-dropzone-no-uploader/file-dropzone-no-uploader.component'; @@ -35,10 +39,6 @@ import { CommunityGridElementComponent } from './object-grid/community-grid-elem import { AbstractListableElementComponent } from './object-collection/shared/object-collection-element/abstract-listable-element.component'; import { ObjectGridComponent } from './object-grid/object-grid.component'; import { ObjectCollectionComponent } from './object-collection/object-collection.component'; -import { ComcolPageContentComponent } from './comcol-page-content/comcol-page-content.component'; -import { ComcolPageHandleComponent } from './comcol-page-handle/comcol-page-handle.component'; -import { ComcolPageHeaderComponent } from './comcol-page-header/comcol-page-header.component'; -import { ComcolPageLogoComponent } from './comcol-page-logo/comcol-page-logo.component'; import { ErrorComponent } from './error/error.component'; import { LoadingComponent } from './loading/loading.component'; import { PaginationComponent } from './pagination/pagination.component'; @@ -49,14 +49,6 @@ import { ViewModeSwitchComponent } from './view-mode-switch/view-mode-switch.com import { VarDirective } from './utils/var.directive'; import { AuthNavMenuComponent } from './auth-nav-menu/auth-nav-menu.component'; import { LogOutComponent } from './log-out/log-out.component'; -import { FormComponent } from './form/form.component'; -import { DsDynamicOneboxComponent } from './form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component'; -import { DsDynamicScrollableDropdownComponent } from './form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component'; -import { - DsDynamicFormControlContainerComponent, - dsDynamicFormControlMapFn, -} from './form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component'; -import { DsDynamicFormComponent } from './form/builder/ds-dynamic-form-ui/ds-dynamic-form.component'; import { DragClickDirective } from './utils/drag-click.directive'; import { TruncatePipe } from './utils/truncate.pipe'; import { TruncatableComponent } from './truncatable/truncatable.component'; @@ -64,15 +56,7 @@ import { TruncatableService } from './truncatable/truncatable.service'; import { TruncatablePartComponent } from './truncatable/truncatable-part/truncatable-part.component'; import { UploaderComponent } from './uploader/uploader.component'; import { ChipsComponent } from './chips/chips.component'; -import { DsDynamicTagComponent } from './form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component'; -import { DsDynamicListComponent } from './form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component'; -import { DsDynamicFormGroupComponent } from './form/builder/ds-dynamic-form-ui/models/form-group/dynamic-form-group.component'; -import { DsDynamicFormArrayComponent } from './form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component'; -import { DsDynamicRelationGroupComponent } from './form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.components'; -import { DsDatePickerInlineComponent } from './form/builder/ds-dynamic-form-ui/models/date-picker-inline/dynamic-date-picker-inline.component'; import { NumberPickerComponent } from './number-picker/number-picker.component'; -import { DsDatePickerComponent } from './form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component'; -import { DsDynamicLookupComponent } from './form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component'; import { MockAdminGuard } from './mocks/admin-guard.service.mock'; import { AlertComponent } from './alert/alert.component'; import { SearchResultDetailElementComponent } from './object-detail/my-dspace-result-detail-element/search-result-detail-element.component'; @@ -101,14 +85,9 @@ import { LangSwitchComponent } from './lang-switch/lang-switch.component'; import { PlainTextMetadataListElementComponent } from './object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component'; import { ItemMetadataListElementComponent } from './object-list/metadata-representation-list-element/item/item-metadata-list-element.component'; import { MetadataRepresentationListElementComponent } from './object-list/metadata-representation-list-element/metadata-representation-list-element.component'; -import { ComColFormComponent } from './comcol-forms/comcol-form/comcol-form.component'; -import { CreateComColPageComponent } from './comcol-forms/create-comcol-page/create-comcol-page.component'; -import { EditComColPageComponent } from './comcol-forms/edit-comcol-page/edit-comcol-page.component'; -import { DeleteComColPageComponent } from './comcol-forms/delete-comcol-page/delete-comcol-page.component'; import { ObjectValuesPipe } from './utils/object-values-pipe'; import { InListValidator } from './utils/in-list-validator.directive'; import { AutoFocusDirective } from './utils/auto-focus.directive'; -import { ComcolPageBrowseByComponent } from './comcol-page-browse-by/comcol-page-browse-by.component'; import { StartsWithDateComponent } from './starts-with/date/starts-with-date.component'; import { StartsWithTextComponent } from './starts-with/text/starts-with-text.component'; import { DSOSelectorComponent } from './dso-selector/dso-selector/dso-selector.component'; @@ -127,32 +106,11 @@ import { RoleDirective } from './roles/role.directive'; import { UserMenuComponent } from './auth-nav-menu/user-menu/user-menu.component'; import { ClaimedTaskActionsReturnToPoolComponent } from './mydspace-actions/claimed-task/return-to-pool/claimed-task-actions-return-to-pool.component'; import { ItemDetailPreviewFieldComponent } from './object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview-field/item-detail-preview-field.component'; -import { DsDynamicLookupRelationModalComponent } from './form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component'; -import { SearchResultsComponent } from './search/search-results/search-results.component'; -import { SearchSidebarComponent } from './search/search-sidebar/search-sidebar.component'; -import { SearchSettingsComponent } from './search/search-settings/search-settings.component'; import { CollectionSearchResultGridElementComponent } from './object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component'; import { CommunitySearchResultGridElementComponent } from './object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component'; -import { SearchFiltersComponent } from './search/search-filters/search-filters.component'; -import { SearchFilterComponent } from './search/search-filters/search-filter/search-filter.component'; -import { SearchFacetFilterComponent } from './search/search-filters/search-filter/search-facet-filter/search-facet-filter.component'; -import { SearchLabelsComponent } from './search/search-labels/search-labels.component'; -import { SearchFacetFilterWrapperComponent } from './search/search-filters/search-filter/search-facet-filter-wrapper/search-facet-filter-wrapper.component'; -import { SearchRangeFilterComponent } from './search/search-filters/search-filter/search-range-filter/search-range-filter.component'; -import { SearchTextFilterComponent } from './search/search-filters/search-filter/search-text-filter/search-text-filter.component'; -import { SearchHierarchyFilterComponent } from './search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component'; -import { SearchBooleanFilterComponent } from './search/search-filters/search-filter/search-boolean-filter/search-boolean-filter.component'; -import { SearchFacetOptionComponent } from './search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component'; -import { SearchFacetSelectedOptionComponent } from './search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component'; -import { SearchFacetRangeOptionComponent } from './search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component'; -import { SearchSwitchConfigurationComponent } from './search/search-switch-configuration/search-switch-configuration.component'; -import { SearchAuthorityFilterComponent } from './search/search-filters/search-filter/search-authority-filter/search-authority-filter.component'; -import { DsDynamicDisabledComponent } from './form/builder/ds-dynamic-form-ui/models/disabled/dynamic-disabled.component'; -import { DsDynamicLookupRelationSearchTabComponent } from './form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component'; -import { DsDynamicLookupRelationSelectionTabComponent } from './form/builder/ds-dynamic-form-ui/relation-lookup-modal/selection-tab/dynamic-lookup-relation-selection-tab.component'; import { PageSizeSelectorComponent } from './page-size-selector/page-size-selector.component'; import { AbstractTrackableComponent } from './trackable/abstract-trackable.component'; -import { ComcolMetadataComponent } from './comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component'; +import { ComcolMetadataComponent } from './comcol/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component'; import { ItemSelectComponent } from './object-select/item-select/item-select.component'; import { CollectionSelectComponent } from './object-select/collection-select/collection-select.component'; import { FilterInputSuggestionsComponent } from './input-suggestions/filter-suggestions/filter-input-suggestions.component'; @@ -164,48 +122,34 @@ import { MetadataRepresentationDirective } from './metadata-representation/metad import { ListableObjectComponentLoaderComponent } from './object-collection/shared/listable-object/listable-object-component-loader.component'; import { ItemSearchResultListElementComponent } from './object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component'; import { ListableObjectDirective } from './object-collection/shared/listable-object/listable-object.directive'; -import { SearchLabelComponent } from './search/search-labels/search-label/search-label.component'; import { ItemMetadataRepresentationListElementComponent } from './object-list/metadata-representation-list-element/item/item-metadata-representation-list-element.component'; import { PageWithSidebarComponent } from './sidebar/page-with-sidebar.component'; import { SidebarDropdownComponent } from './sidebar/sidebar-dropdown.component'; import { SidebarFilterComponent } from './sidebar/filter/sidebar-filter.component'; import { SidebarFilterSelectedOptionComponent } from './sidebar/filter/sidebar-filter-selected-option.component'; import { SelectableListItemControlComponent } from './object-collection/shared/selectable-list-item-control/selectable-list-item-control.component'; -import { DsDynamicLookupRelationExternalSourceTabComponent } from './form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component'; -import { ExternalSourceEntryImportModalComponent } from './form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component'; import { ImportableListItemControlComponent } from './object-collection/shared/importable-list-item-control/importable-list-item-control.component'; -import { ExistingMetadataListElementComponent } from './form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component'; import { ItemVersionsComponent } from './item/item-versions/item-versions.component'; import { SortablejsModule } from 'ngx-sortablejs'; import { LogInContainerComponent } from './log-in/container/log-in-container.component'; import { LogInShibbolethComponent } from './log-in/methods/shibboleth/log-in-shibboleth.component'; import { LogInPasswordComponent } from './log-in/methods/password/log-in-password.component'; import { LogInComponent } from './log-in/log-in.component'; -import { CustomSwitchComponent } from './form/builder/ds-dynamic-form-ui/models/custom-switch/custom-switch.component'; import { BundleListElementComponent } from './object-list/bundle-list-element/bundle-list-element.component'; import { MissingTranslationHelper } from './translate/missing-translation.helper'; import { ItemVersionsNoticeComponent } from './item/item-versions/notice/item-versions-notice.component'; import { FileValidator } from './utils/require-file.validator'; import { FileValueAccessorDirective } from './utils/file-value-accessor.directive'; import { FileSectionComponent } from '../item-page/simple/field-components/file-section/file-section.component'; -import { ExistingRelationListElementComponent } from './form/builder/ds-dynamic-form-ui/existing-relation-list-element/existing-relation-list-element.component'; import { ModifyItemOverviewComponent } from '../item-page/edit-item-page/modify-item-overview/modify-item-overview.component'; import { ClaimedTaskActionsLoaderComponent } from './mydspace-actions/claimed-task/switcher/claimed-task-actions-loader.component'; import { ClaimedTaskActionsDirective } from './mydspace-actions/claimed-task/switcher/claimed-task-actions.directive'; import { ClaimedTaskActionsEditMetadataComponent } from './mydspace-actions/claimed-task/edit-metadata/claimed-task-actions-edit-metadata.component'; import { ImpersonateNavbarComponent } from './impersonate-navbar/impersonate-navbar.component'; -import { ResourcePoliciesComponent } from './resource-policies/resource-policies.component'; import { NgForTrackByIdDirective } from './ng-for-track-by-id.directive'; -import { ResourcePolicyFormComponent } from './resource-policies/form/resource-policy-form.component'; -import { EpersonGroupListComponent } from './resource-policies/form/eperson-group-list/eperson-group-list.component'; -import { ResourcePolicyTargetResolver } from './resource-policies/resolvers/resource-policy-target.resolver'; -import { ResourcePolicyResolver } from './resource-policies/resolvers/resource-policy.resolver'; -import { EpersonSearchBoxComponent } from './resource-policies/form/eperson-group-list/eperson-search-box/eperson-search-box.component'; -import { GroupSearchBoxComponent } from './resource-policies/form/eperson-group-list/group-search-box/group-search-box.component'; import { FileDownloadLinkComponent } from './file-download-link/file-download-link.component'; import { CollectionDropdownComponent } from './collection-dropdown/collection-dropdown.component'; import { EntityDropdownComponent } from './entity-dropdown/entity-dropdown.component'; -import { DsSelectComponent } from './ds-select/ds-select.component'; import { VocabularyTreeviewComponent } from './vocabulary-treeview/vocabulary-treeview.component'; import { CurationFormComponent } from '../curation-form/curation-form.component'; import { PublicationSidebarSearchListElementComponent } from './object-list/sidebar-search-list-element/item-types/publication/publication-sidebar-search-list-element.component'; @@ -219,53 +163,35 @@ import { HoverClassDirective } from './hover-class.directive'; import { ValidationSuggestionsComponent } from './input-suggestions/validation-suggestions/validation-suggestions.component'; import { ItemAlertsComponent } from './item/item-alerts/item-alerts.component'; import { ItemSearchResultGridElementComponent } from './object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component'; -import { ResourcePolicyEditComponent } from './resource-policies/edit/resource-policy-edit.component'; -import { ResourcePolicyCreateComponent } from './resource-policies/create/resource-policy-create.component'; -import { SearchObjects } from './search/search-objects.model'; -import { SearchResult } from './search/search-result.model'; -import { FacetConfigResponse } from './search/facet-config-response.model'; -import { FacetValues } from './search/facet-values.model'; import { BitstreamDownloadPageComponent } from './bitstream-download-page/bitstream-download-page.component'; import { GenericItemPageFieldComponent } from '../item-page/simple/field-components/specific-field/generic/generic-item-page-field.component'; import { MetadataRepresentationListComponent } from '../item-page/simple/metadata-representation-list/metadata-representation-list.component'; import { RelatedItemsComponent } from '../item-page/simple/related-items/related-items-component'; -import { TabbedRelatedEntitiesSearchComponent } from '../item-page/simple/related-entities/tabbed-related-entities-search/tabbed-related-entities-search.component'; -import { RelatedEntitiesSearchComponent } from '../item-page/simple/related-entities/related-entities-search/related-entities-search.component'; -import { ConfigurationSearchPageComponent } from '../search-page/configuration-search-page.component'; import { LinkMenuItemComponent } from './menu/menu-item/link-menu-item.component'; import { OnClickMenuItemComponent } from './menu/menu-item/onclick-menu-item.component'; import { TextMenuItemComponent } from './menu/menu-item/text-menu-item.component'; -import { ThemedConfigurationSearchPageComponent } from '../search-page/themed-configuration-search-page.component'; import { SearchNavbarComponent } from '../search-navbar/search-navbar.component'; import { ItemVersionsSummaryModalComponent } from './item/item-versions/item-versions-summary-modal/item-versions-summary-modal.component'; import { ItemVersionsDeleteModalComponent } from './item/item-versions/item-versions-delete-modal/item-versions-delete-modal.component'; import { ScopeSelectorModalComponent } from './search-form/scope-selector-modal/scope-selector-modal.component'; import { BitstreamRequestACopyPageComponent } from './bitstream-request-a-copy-page/bitstream-request-a-copy-page.component'; - -/** - * Declaration needed to make sure all decorator functions are called in time - */ -export const MODELS = [ - SearchObjects, - FacetConfigResponse, - FacetValues, - SearchResult -]; +import { DsSelectComponent } from './ds-select/ds-select.component'; const MODULES = [ // Do NOT include UniversalModule, HttpModule, or JsonpModule here CommonModule, SortablejsModule, - DynamicFormsCoreModule, - DynamicFormsNGBootstrapUIModule, FileUploadModule, FormsModule, InfiniteScrollModule, - NgbModule, + NgbNavModule, NgbDatepickerModule, NgbTimepickerModule, NgbTypeaheadModule, NgxPaginationModule, + NgbPaginationModule, + NgbDropdownModule, + NgbTooltipModule, ReactiveFormsModule, RouterModule, NouisliderModule, @@ -302,34 +228,9 @@ const COMPONENTS = [ AuthNavMenuComponent, UserMenuComponent, ChipsComponent, - ComcolPageContentComponent, - ComcolPageHandleComponent, - ComcolPageHeaderComponent, - ComcolPageLogoComponent, - ComColFormComponent, - CreateComColPageComponent, - EditComColPageComponent, - DeleteComColPageComponent, - ComcolPageBrowseByComponent, - ComcolRoleComponent, - DsDynamicFormComponent, - DsDynamicFormControlContainerComponent, - DsDynamicListComponent, - DsDynamicLookupComponent, - DsDynamicDisabledComponent, - DsDynamicLookupRelationModalComponent, - DsDynamicScrollableDropdownComponent, - DsDynamicTagComponent, - DsDynamicOneboxComponent, - DsDynamicRelationGroupComponent, - DsDatePickerComponent, - DsDynamicFormGroupComponent, - DsDynamicFormArrayComponent, - DsDatePickerInlineComponent, DsSelectComponent, ErrorComponent, FileSectionComponent, - FormComponent, LangSwitchComponent, LoadingComponent, LogInComponent, @@ -382,26 +283,9 @@ const COMPONENTS = [ CommunitySearchResultListElementComponent, CollectionSearchResultListElementComponent, BrowseByComponent, - SearchResultsComponent, - SearchSidebarComponent, - SearchSettingsComponent, + CollectionSearchResultGridElementComponent, CommunitySearchResultGridElementComponent, - SearchFiltersComponent, - SearchFilterComponent, - SearchFacetFilterComponent, - SearchLabelsComponent, - SearchLabelComponent, - SearchFacetFilterWrapperComponent, - SearchRangeFilterComponent, - SearchTextFilterComponent, - SearchHierarchyFilterComponent, - SearchBooleanFilterComponent, - SearchFacetOptionComponent, - SearchFacetSelectedOptionComponent, - SearchFacetRangeOptionComponent, - SearchSwitchConfigurationComponent, - SearchAuthorityFilterComponent, PageSizeSelectorComponent, ListableObjectComponentLoaderComponent, CollectionListElementComponent, @@ -414,15 +298,14 @@ const COMPONENTS = [ TypeBadgeComponent, BrowseByComponent, AbstractTrackableComponent, - CustomSwitchComponent, + ItemSelectComponent, CollectionSelectComponent, MetadataRepresentationLoaderComponent, SelectableListItemControlComponent, - ExternalSourceEntryImportModalComponent, + ImportableListItemControlComponent, - ExistingMetadataListElementComponent, - ExistingRelationListElementComponent, + LogInShibbolethComponent, LogInPasswordComponent, LogInContainerComponent, @@ -431,13 +314,6 @@ const COMPONENTS = [ ItemVersionsNoticeComponent, ModifyItemOverviewComponent, ImpersonateNavbarComponent, - ResourcePoliciesComponent, - ResourcePolicyFormComponent, - ResourcePolicyEditComponent, - ResourcePolicyCreateComponent, - EpersonGroupListComponent, - EpersonSearchBoxComponent, - GroupSearchBoxComponent, FileDownloadLinkComponent, BitstreamDownloadPageComponent, BitstreamRequestACopyPageComponent, @@ -458,10 +334,7 @@ const COMPONENTS = [ PlainTextMetadataListElementComponent, ItemMetadataListElementComponent, MetadataRepresentationListElementComponent, - DsDynamicLookupRelationSearchTabComponent, - DsDynamicLookupRelationSelectionTabComponent, ItemMetadataRepresentationListElementComponent, - DsDynamicLookupRelationExternalSourceTabComponent, BundleListElementComponent, StartsWithDateComponent, StartsWithTextComponent, @@ -502,18 +375,7 @@ const ENTRY_COMPONENTS = [ PlainTextMetadataListElementComponent, ItemMetadataListElementComponent, MetadataRepresentationListElementComponent, - CustomSwitchComponent, ItemMetadataRepresentationListElementComponent, - SearchResultsComponent, - SearchFacetFilterComponent, - SearchRangeFilterComponent, - SearchTextFilterComponent, - SearchHierarchyFilterComponent, - SearchBooleanFilterComponent, - SearchFacetOptionComponent, - SearchFacetSelectedOptionComponent, - SearchFacetRangeOptionComponent, - SearchAuthorityFilterComponent, LogInPasswordComponent, LogInShibbolethComponent, BundleListElementComponent, @@ -539,11 +401,6 @@ const ENTRY_COMPONENTS = [ ScopeSelectorModalComponent, ]; -const SHARED_SEARCH_PAGE_COMPONENTS = [ - ConfigurationSearchPageComponent, - ThemedConfigurationSearchPageComponent -]; - const SHARED_ITEM_PAGE_COMPONENTS = [ MetadataFieldWrapperComponent, MetadataValuesComponent, @@ -553,20 +410,13 @@ const SHARED_ITEM_PAGE_COMPONENTS = [ GenericItemPageFieldComponent, MetadataRepresentationListComponent, RelatedItemsComponent, - RelatedEntitiesSearchComponent, - TabbedRelatedEntitiesSearchComponent + ]; const PROVIDERS = [ TruncatableService, MockAdminGuard, - AbstractTrackableComponent, - { - provide: DYNAMIC_FORM_CONTROL_MAP_FN, - useValue: dsDynamicFormControlMapFn - }, - ResourcePolicyResolver, - ResourcePolicyTargetResolver + AbstractTrackableComponent ]; const DIRECTIVES = [ @@ -599,7 +449,6 @@ const DIRECTIVES = [ ...COMPONENTS, ...DIRECTIVES, ...SHARED_ITEM_PAGE_COMPONENTS, - ...SHARED_SEARCH_PAGE_COMPONENTS, ItemVersionsSummaryModalComponent, ItemVersionsDeleteModalComponent, ], @@ -611,7 +460,6 @@ const DIRECTIVES = [ ...PIPES, ...COMPONENTS, ...SHARED_ITEM_PAGE_COMPONENTS, - ...SHARED_SEARCH_PAGE_COMPONENTS, ...DIRECTIVES, TranslateModule ] @@ -628,7 +476,7 @@ export class SharedModule { static withEntryComponents() { return { ngModule: SharedModule, - providers: ENTRY_COMPONENTS.map((component) => ({provide: component})) + providers: ENTRY_COMPONENTS.map((component) => ({ provide: component })) }; } } diff --git a/src/app/shared/view-mode-switch/view-mode-switch.component.html b/src/app/shared/view-mode-switch/view-mode-switch.component.html index b4c1c18d4f..007b124b9c 100644 --- a/src/app/shared/view-mode-switch/view-mode-switch.component.html +++ b/src/app/shared/view-mode-switch/view-mode-switch.component.html @@ -21,7 +21,7 @@ { const searchService = new SearchServiceStub(); let listButton: HTMLElement; let gridButton: HTMLElement; + let detailButton: HTMLElement; beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [ @@ -49,27 +49,76 @@ describe('ViewModeSwitchComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(ViewModeSwitchComponent); comp = fixture.componentInstance; // ViewModeSwitchComponent test instance - fixture.detectChanges(); - const debugElements = fixture.debugElement.queryAll(By.css('a')); - listButton = debugElements[0].nativeElement; - gridButton = debugElements[1].nativeElement; + spyOn(comp.changeViewMode, 'emit'); + }); + + describe('', () => { + beforeEach(fakeAsync(() => { + comp.viewModeList = [ViewMode.ListElement, ViewMode.GridElement]; + comp.currentMode = ViewMode.ListElement; + searchService.setViewMode(ViewMode.ListElement); + tick(); + fixture.detectChanges(); + const debugElements = fixture.debugElement.queryAll(By.css('a')); + listButton = debugElements[0].nativeElement; + gridButton = debugElements[1].nativeElement; + })); + + it('should set list button as active when on list mode', fakeAsync(() => { + comp.switchViewTo(ViewMode.ListElement); + expect(comp.changeViewMode.emit).not.toHaveBeenCalled(); + tick(); + fixture.detectChanges(); + expect(comp.currentMode).toBe(ViewMode.ListElement); + expect(listButton.classList).toContain('active'); + expect(gridButton.classList).not.toContain('active'); + + })); + + it('should set grid button as active when on grid mode', fakeAsync(() => { + comp.switchViewTo(ViewMode.GridElement); + expect(comp.changeViewMode.emit).toHaveBeenCalledWith(ViewMode.GridElement); + tick(); + fixture.detectChanges(); + expect(comp.currentMode).toBe(ViewMode.GridElement); + expect(listButton.classList).not.toContain('active'); + expect(gridButton.classList).toContain('active'); + })); + }); + + + describe('', () => { + beforeEach(fakeAsync(() => { + comp.viewModeList = [ViewMode.ListElement, ViewMode.DetailedListElement]; + comp.currentMode = ViewMode.ListElement; + searchService.setViewMode(ViewMode.ListElement); + tick(); + fixture.detectChanges(); + const debugElements = fixture.debugElement.queryAll(By.css('a')); + listButton = debugElements[0].nativeElement; + detailButton = debugElements[1].nativeElement; + })); + + it('should set list button as active when on list mode', fakeAsync(() => { + comp.switchViewTo(ViewMode.ListElement); + expect(comp.changeViewMode.emit).not.toHaveBeenCalled(); + tick(); + fixture.detectChanges(); + expect(comp.currentMode).toBe(ViewMode.ListElement); + expect(listButton.classList).toContain('active'); + expect(detailButton.classList).not.toContain('active'); + })); + + it('should set detail button as active when on detailed mode', fakeAsync(() => { + comp.switchViewTo(ViewMode.DetailedListElement); + expect(comp.changeViewMode.emit).toHaveBeenCalledWith(ViewMode.DetailedListElement); + tick(); + fixture.detectChanges(); + expect(comp.currentMode).toBe(ViewMode.DetailedListElement); + expect(listButton.classList).not.toContain('active'); + expect(detailButton.classList).toContain('active'); + })); }); - it('should set list button as active when on list mode', fakeAsync(() => { - searchService.setViewMode(ViewMode.ListElement); - tick(); - fixture.detectChanges(); - expect(comp.currentMode).toBe(ViewMode.ListElement); - expect(listButton.classList).toContain('active'); - expect(gridButton.classList).not.toContain('active'); - })); - it('should set grid button as active when on grid mode', fakeAsync(() => { - searchService.setViewMode(ViewMode.GridElement); - tick(); - fixture.detectChanges(); - expect(comp.currentMode).toBe(ViewMode.GridElement); - expect(listButton.classList).not.toContain('active'); - expect(gridButton.classList).toContain('active'); - })); }); diff --git a/src/app/shared/view-mode-switch/view-mode-switch.component.ts b/src/app/shared/view-mode-switch/view-mode-switch.component.ts index 4feb8927c2..95f35abf17 100644 --- a/src/app/shared/view-mode-switch/view-mode-switch.component.ts +++ b/src/app/shared/view-mode-switch/view-mode-switch.component.ts @@ -1,12 +1,13 @@ -import { Component, Input, OnDestroy, OnInit } from '@angular/core'; +import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'; import { Subscription } from 'rxjs'; import { SearchService } from '../../core/shared/search/search.service'; import { ViewMode } from '../../core/shared/view-mode.model'; -import { isEmpty } from '../empty.util'; +import { isEmpty, isNotEmpty } from '../empty.util'; import { currentPath } from '../utils/route.utils'; import { Router } from '@angular/router'; +import { filter } from 'rxjs/operators'; /** * Component to switch between list and grid views. @@ -17,13 +18,17 @@ import { Router } from '@angular/router'; templateUrl: './view-mode-switch.component.html' }) export class ViewModeSwitchComponent implements OnInit, OnDestroy { - @Input() viewModeList: ViewMode[]; /** * True when the search component should show results on the current page */ @Input() inPlaceSearch; + /** + * List of available view mode + */ + @Input() viewModeList: ViewMode[]; + /** * The current view mode */ @@ -33,8 +38,18 @@ export class ViewModeSwitchComponent implements OnInit, OnDestroy { * All available view modes */ viewModeEnum = ViewMode; + + /** + * Subscription to unsubscribe OnDestroy + * @private + */ private sub: Subscription; + /** + * Emits event when the user select a new view mode + */ + @Output() changeViewMode: EventEmitter = new EventEmitter(); + constructor(private searchService: SearchService, private router: Router) { } @@ -46,7 +61,9 @@ export class ViewModeSwitchComponent implements OnInit, OnDestroy { this.viewModeList = [ViewMode.ListElement, ViewMode.GridElement]; } - this.sub = this.searchService.getViewMode().subscribe((viewMode: ViewMode) => { + this.sub = this.searchService.getViewMode().pipe( + filter((viewMode: ViewMode) => isNotEmpty(viewMode)) + ).subscribe((viewMode: ViewMode) => { this.currentMode = viewMode; }); } @@ -56,6 +73,9 @@ export class ViewModeSwitchComponent implements OnInit, OnDestroy { * @param viewMode The new view mode */ switchViewTo(viewMode: ViewMode) { + if (viewMode !== this.currentMode) { + this.changeViewMode.emit(viewMode); + } this.searchService.setViewMode(viewMode, this.getSearchLinkParts()); } diff --git a/src/app/statistics/statistics.service.spec.ts b/src/app/statistics/statistics.service.spec.ts index cdf81afdb6..e4ca6a7059 100644 --- a/src/app/statistics/statistics.service.spec.ts +++ b/src/app/statistics/statistics.service.spec.ts @@ -5,7 +5,7 @@ import { getMockRequestService } from '../shared/mocks/request.service.mock'; import { TrackRequest } from './track-request.model'; import { isEqual } from 'lodash'; import { DSpaceObjectType } from '../core/shared/dspace-object-type.model'; -import { SearchOptions } from '../shared/search/search-options.model'; +import { SearchOptions } from '../shared/search/models/search-options.model'; describe('StatisticsService', () => { let service: StatisticsService; diff --git a/src/app/statistics/statistics.service.ts b/src/app/statistics/statistics.service.ts index 9e12e627b5..81c79c4c43 100644 --- a/src/app/statistics/statistics.service.ts +++ b/src/app/statistics/statistics.service.ts @@ -6,7 +6,7 @@ import { TrackRequest } from './track-request.model'; import { hasValue, isNotEmpty } from '../shared/empty.util'; import { HALEndpointService } from '../core/shared/hal-endpoint.service'; import { RestRequest } from '../core/data/request.models'; -import { SearchOptions } from '../shared/search/search-options.model'; +import { SearchOptions } from '../shared/search/models/search-options.model'; /** * The statistics service diff --git a/src/app/submission/import-external/submission-import-external.component.spec.ts b/src/app/submission/import-external/submission-import-external.component.spec.ts index 20f36995a6..dc53b2e45f 100644 --- a/src/app/submission/import-external/submission-import-external.component.spec.ts +++ b/src/app/submission/import-external/submission-import-external.component.spec.ts @@ -17,7 +17,7 @@ import { createPaginatedList, createTestComponent } from '../../shared/testing/u import { RouterStub } from '../../shared/testing/router.stub'; import { VarDirective } from '../../shared/utils/var.directive'; import { routeServiceStub } from '../../shared/testing/route-service.stub'; -import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; +import { PaginatedSearchOptions } from '../../shared/search/models/paginated-search-options.model'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; import { ExternalSourceEntry } from '../../core/shared/external-source-entry.model'; diff --git a/src/app/submission/submission.module.ts b/src/app/submission/submission.module.ts index e8c96284c0..5f14b5c246 100644 --- a/src/app/submission/submission.module.ts +++ b/src/app/submission/submission.module.ts @@ -37,6 +37,8 @@ import { ResearchEntitiesModule } from '../entity-groups/research-entities/resea import { ThemedSubmissionEditComponent } from './edit/themed-submission-edit.component'; import { ThemedSubmissionSubmitComponent } from './submit/themed-submission-submit.component'; import { ThemedSubmissionImportExternalComponent } from './import-external/themed-submission-import-external.component'; +import { FormModule } from '../shared/form/form.module'; +import { NgbAccordionModule } from '@ng-bootstrap/ng-bootstrap'; const DECLARATIONS = [ SubmissionSectionUploadAccessConditionsComponent, @@ -73,15 +75,17 @@ const ENTRY_COMPONENTS = [ ]; @NgModule({ - imports: [ - CommonModule, - CoreModule.forRoot(), - SharedModule, - StoreModule.forFeature('submission', submissionReducers, storeModuleConfig as StoreConfig), - EffectsModule.forFeature(submissionEffects), - JournalEntitiesModule.withEntryComponents(), - ResearchEntitiesModule.withEntryComponents(), - ], + imports: [ + CommonModule, + CoreModule.forRoot(), + SharedModule, + StoreModule.forFeature('submission', submissionReducers, storeModuleConfig as StoreConfig), + EffectsModule.forFeature(submissionEffects), + JournalEntitiesModule.withEntryComponents(), + ResearchEntitiesModule.withEntryComponents(), + FormModule, + NgbAccordionModule + ], declarations: DECLARATIONS, exports: DECLARATIONS, providers: [ diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 8edc01b278..6b47238f5b 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -2588,7 +2588,7 @@ "mydspace.search-form.placeholder": "Search in mydspace...", - "mydspace.show.workflow": "All tasks", + "mydspace.show.workflow": "Workflow tasks", "mydspace.show.workspace": "Your Submissions", @@ -4019,8 +4019,12 @@ + "workspace.search.results.head": "Your submissions", + "workflowAdmin.search.results.head": "Administer Workflow", + "workflow.search.results.head": "Workflow tasks", + "workflow-item.edit.breadcrumbs": "Edit workflowitem", diff --git a/src/themes/custom/app/search-page/configuration-search-page.component.ts b/src/themes/custom/app/search-page/configuration-search-page.component.ts index b578ed5d8c..159434c7a8 100644 --- a/src/themes/custom/app/search-page/configuration-search-page.component.ts +++ b/src/themes/custom/app/search-page/configuration-search-page.component.ts @@ -1,4 +1,4 @@ -import { Component, ChangeDetectionStrategy } from '@angular/core'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; import { pushInOut } from '../../../../app/shared/animations/push'; import { SEARCH_CONFIG_SERVICE } from '../../../../app/my-dspace-page/my-dspace-page.component'; import { SearchConfigurationService } from '../../../../app/core/shared/search/search-configuration.service'; @@ -7,9 +7,9 @@ import { ConfigurationSearchPageComponent as BaseComponent } from '../../../../a @Component({ selector: 'ds-configuration-search-page', // styleUrls: ['./configuration-search-page.component.scss'], - styleUrls: ['../../../../app/search-page/search.component.scss'], + styleUrls: ['../../../../app/shared/search/search.component.scss'], // templateUrl: './configuration-search-page.component.html' - templateUrl: '../../../../app/search-page/search.component.html', + templateUrl: '../../../../app/shared/search/search.component.html', changeDetection: ChangeDetectionStrategy.OnPush, animations: [pushInOut], providers: [ diff --git a/src/themes/custom/theme.module.ts b/src/themes/custom/theme.module.ts index ba5f660012..a931da5a2a 100644 --- a/src/themes/custom/theme.module.ts +++ b/src/themes/custom/theme.module.ts @@ -79,7 +79,10 @@ import { HeaderComponent } from './app/header/header.component'; import { FooterComponent } from './app/footer/footer.component'; import { BreadcrumbsComponent } from './app/breadcrumbs/breadcrumbs.component'; import { HeaderNavbarWrapperComponent } from './app/header-nav-wrapper/header-navbar-wrapper.component'; -import { FileSectionComponent} from './app/item-page/simple/field-components/file-section/file-section.component'; +import { FileSectionComponent } from './app/item-page/simple/field-components/file-section/file-section.component'; +import { SearchModule } from '../../app/shared/search/search.module'; +import { ResourcePoliciesModule } from '../../app/shared/resource-policies/resource-policies.module'; +import { ComcolModule } from '../../app/shared/comcol/comcol.module'; const DECLARATIONS = [ FileSectionComponent, @@ -168,6 +171,10 @@ const DECLARATIONS = [ SubmissionModule, MyDSpacePageModule, MyDspaceSearchModule, + SearchModule, + FormsModule, + ResourcePoliciesModule, + ComcolModule ], declarations: DECLARATIONS }) diff --git a/src/themes/dspace/theme.module.ts b/src/themes/dspace/theme.module.ts index b03d5af5b4..2a774eb9c8 100644 --- a/src/themes/dspace/theme.module.ts +++ b/src/themes/dspace/theme.module.ts @@ -43,6 +43,9 @@ import { MyDSpacePageModule } from '../../app/my-dspace-page/my-dspace-page.modu import { NavbarComponent } from './app/navbar/navbar.component'; import { HeaderComponent } from './app/header/header.component'; import { HeaderNavbarWrapperComponent } from './app/header-nav-wrapper/header-navbar-wrapper.component'; +import { SearchModule } from '../../app/shared/search/search.module'; +import { ResourcePoliciesModule } from '../../app/shared/resource-policies/resource-policies.module'; +import { ComcolModule } from '../../app/shared/comcol/comcol.module'; const DECLARATIONS = [ HomeNewsComponent, @@ -94,6 +97,10 @@ const DECLARATIONS = [ SubmissionModule, MyDSpacePageModule, MyDspaceSearchModule, + SearchModule, + FormsModule, + ResourcePoliciesModule, + ComcolModule ], declarations: DECLARATIONS })