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 27daa30a0f..de932fab02 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
@@ -23,7 +23,7 @@ import { SearchConfigurationServiceStub } from '../shared/testing/search-configu
import { SearchService } from '../+search-page/search-service/search.service';
import { SearchConfigurationService } from '../+search-page/search-service/search-configuration.service';
import { PaginatedSearchOptions } from '../+search-page/paginated-search-options.model';
-import { SearchSidebarService } from '../+search-page/search-sidebar/search-sidebar.service';
+import { SidebarService } from '../shared/sidebar/sidebar.service';
import { SearchFilterService } from '../+search-page/search-filters/search-filter/search-filter.service';
import { RoleDirective } from '../shared/roles/role.directive';
import { RoleService } from '../core/roles/role.service';
@@ -108,7 +108,7 @@ describe('MyDSpacePageComponent', () => {
})
},
{
- provide: SearchSidebarService,
+ provide: SidebarService,
useValue: sidebarService
},
{
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 251bf50bd1..bb43ed1183 100644
--- a/src/app/+my-dspace-page/my-dspace-page.component.ts
+++ b/src/app/+my-dspace-page/my-dspace-page.component.ts
@@ -17,7 +17,7 @@ import { pushInOut } from '../shared/animations/push';
import { HostWindowService } from '../shared/host-window.service';
import { PaginatedSearchOptions } from '../+search-page/paginated-search-options.model';
import { SearchService } from '../+search-page/search-service/search.service';
-import { SearchSidebarService } from '../+search-page/search-sidebar/search-sidebar.service';
+import { SidebarService } from '../shared/sidebar/sidebar.service';
import { hasValue } from '../shared/empty.util';
import { getSucceededRemoteData } from '../core/shared/operators';
import { MyDSpaceResult } from './my-dspace-result.model';
@@ -96,7 +96,7 @@ export class MyDSpacePageComponent implements OnInit {
viewModeList = [ViewMode.List, ViewMode.Detail];
constructor(private service: SearchService,
- private sidebarService: SearchSidebarService,
+ private sidebarService: SidebarService,
private windowService: HostWindowService,
@Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: MyDSpaceConfigurationService) {
this.isXsOrSm$ = this.windowService.isXsOrSm();
diff --git a/src/app/+search-page/configuration-search-page.component.ts b/src/app/+search-page/configuration-search-page.component.ts
index b1a94fc086..dbe54de72f 100644
--- a/src/app/+search-page/configuration-search-page.component.ts
+++ b/src/app/+search-page/configuration-search-page.component.ts
@@ -1,6 +1,6 @@
import { HostWindowService } from '../shared/host-window.service';
import { SearchService } from './search-service/search.service';
-import { SearchSidebarService } from './search-sidebar/search-sidebar.service';
+import { SidebarService } from '../shared/sidebar/sidebar.service';
import { SearchPageComponent } from './search-page.component';
import { ChangeDetectionStrategy, Component, Inject, Input, OnInit } from '@angular/core';
import { pushInOut } from '../shared/animations/push';
@@ -36,7 +36,7 @@ export class ConfigurationSearchPageComponent extends SearchPageComponent implem
@Input() configuration: string;
constructor(protected service: SearchService,
- protected sidebarService: SearchSidebarService,
+ protected sidebarService: SidebarService,
protected windowService: HostWindowService,
@Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: SearchConfigurationService,
protected routeService: RouteService) {
diff --git a/src/app/+search-page/filtered-search-page.component.ts b/src/app/+search-page/filtered-search-page.component.ts
index 0bcc9e14e3..5da23bd853 100644
--- a/src/app/+search-page/filtered-search-page.component.ts
+++ b/src/app/+search-page/filtered-search-page.component.ts
@@ -1,6 +1,6 @@
import { HostWindowService } from '../shared/host-window.service';
import { SearchService } from './search-service/search.service';
-import { SearchSidebarService } from './search-sidebar/search-sidebar.service';
+import { SidebarService } from '../shared/sidebar/sidebar.service';
import { SearchPageComponent } from './search-page.component';
import { ChangeDetectionStrategy, Component, Inject, Input, OnInit } from '@angular/core';
import { pushInOut } from '../shared/animations/push';
@@ -38,7 +38,7 @@ export class FilteredSearchPageComponent extends SearchPageComponent implements
@Input() fixedFilterQuery: string;
constructor(protected service: SearchService,
- protected sidebarService: SearchSidebarService,
+ protected sidebarService: SidebarService,
protected windowService: HostWindowService,
@Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: SearchConfigurationService,
protected routeService: RouteService) {
diff --git a/src/app/+search-page/search-filters/search-filter/search-filter.service.spec.ts b/src/app/+search-page/search-filters/search-filter/search-filter.service.spec.ts
index aefa5c145f..0ba1f88cc3 100644
--- a/src/app/+search-page/search-filters/search-filter/search-filter.service.spec.ts
+++ b/src/app/+search-page/search-filters/search-filter/search-filter.service.spec.ts
@@ -138,7 +138,7 @@ describe('SearchFilterService', () => {
service.expand(mockFilterConfig.name);
});
- it('SearchSidebarExpandAction should be dispatched to the store', () => {
+ it('SidebarExpandAction should be dispatched to the store', () => {
expect(store.dispatch).toHaveBeenCalledWith(new SearchFilterExpandAction(mockFilterConfig.name));
});
});
diff --git a/src/app/+search-page/search-page.component.html b/src/app/+search-page/search-page.component.html
index 85ad8286bf..7efd22d5a9 100644
--- a/src/app/+search-page/search-page.component.html
+++ b/src/app/+search-page/search-page.component.html
@@ -1,43 +1,50 @@
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/app/+search-page/search-page.component.scss b/src/app/+search-page/search-page.component.scss
index 05abf74f05..9c3da88be6 100644
--- a/src/app/+search-page/search-page.component.scss
+++ b/src/app/+search-page/search-page.component.scss
@@ -1,52 +1,10 @@
-
@include media-breakpoint-down(md) {
- .container {
- width: 100%;
- max-width: none;
- }
+ .container {
+ width: 100%;
+ max-width: none;
+ }
}
/deep/ .search-controls {
margin-bottom: $spacer;
}
-
-#search-body {
- &.row-offcanvas {
- width: 100%;
- }
- @include media-breakpoint-down(sm) {
- position: relative;
-
- &.row-offcanvas {
- position: relative;
- }
-
- &.row-offcanvas-right #search-sidebar-sm {
- right: -100%;
- }
-
- &.row-offcanvas-left #search-sidebar-sm {
- left: -100%;
- }
-
- #search-sidebar-sm {
- position: absolute;
- top: 0;
- width: 100%;
- }
- }
-}
-
-@include media-breakpoint-up(md) {
- .sidebar-md-sticky {
- position: sticky;
- position: -webkit-sticky;
- top: 0;
- z-index: $zindex-sticky;
- padding-top: $content-spacing;
- margin-top: -$content-spacing;
- align-self: flex-start;
- display: block;
- }
-}
-
diff --git a/src/app/+search-page/search-page.component.spec.ts b/src/app/+search-page/search-page.component.spec.ts
index d072c80628..9f17beeab3 100644
--- a/src/app/+search-page/search-page.component.spec.ts
+++ b/src/app/+search-page/search-page.component.spec.ts
@@ -16,7 +16,7 @@ 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 { SearchSidebarService } from './search-sidebar/search-sidebar.service';
+import { SidebarService } from '../shared/sidebar/sidebar.service';
import { SearchFilterService } from './search-filters/search-filter/search-filter.service';
import { SearchConfigurationService } from './search-service/search-configuration.service';
import { RemoteData } from '../core/data/remote-data';
@@ -115,7 +115,7 @@ export function configureSearchComponentTestingModule(compType) {
})
},
{
- provide: SearchSidebarService,
+ provide: SidebarService,
useValue: sidebarService
},
{
@@ -191,34 +191,4 @@ describe('SearchPageComponent', () => {
});
});
-
- describe('when sidebarCollapsed is true in mobile view', () => {
- let menu: HTMLElement;
-
- beforeEach(() => {
- menu = fixture.debugElement.query(By.css('#search-sidebar-sm')).nativeElement;
- (comp as any).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 as any).isSidebarCollapsed$ = observableOf(false);
- fixture.detectChanges();
- });
-
- it('should open the menu', () => {
- expect(menu.classList).toContain('active');
- });
-
- });
});
diff --git a/src/app/+search-page/search-page.component.ts b/src/app/+search-page/search-page.component.ts
index 0558065142..bf0c2e3e73 100644
--- a/src/app/+search-page/search-page.component.ts
+++ b/src/app/+search-page/search-page.component.ts
@@ -9,7 +9,7 @@ import { HostWindowService } from '../shared/host-window.service';
import { PaginatedSearchOptions } from './paginated-search-options.model';
import { SearchResult } from './search-result.model';
import { SearchService } from './search-service/search.service';
-import { SearchSidebarService } from './search-sidebar/search-sidebar.service';
+import { SidebarService } from '../shared/sidebar/sidebar.service';
import { hasValue, isNotEmpty } from '../shared/empty.util';
import { SearchConfigurationService } from './search-service/search-configuration.service';
import { getSucceededRemoteData } from '../core/shared/operators';
@@ -102,7 +102,7 @@ export class SearchPageComponent implements OnInit {
isSidebarCollapsed$: Observable
;
constructor(protected service: SearchService,
- protected sidebarService: SearchSidebarService,
+ protected sidebarService: SidebarService,
protected windowService: HostWindowService,
@Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: SearchConfigurationService,
protected routeService: RouteService) {
diff --git a/src/app/+search-page/search-page.module.ts b/src/app/+search-page/search-page.module.ts
index 6ca449460b..a500cc42d7 100644
--- a/src/app/+search-page/search-page.module.ts
+++ b/src/app/+search-page/search-page.module.ts
@@ -9,8 +9,8 @@ import { ItemSearchResultGridElementComponent } from '../shared/object-grid/sear
import { CommunitySearchResultGridElementComponent } from '../shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component'
import { CollectionSearchResultGridElementComponent } from '../shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component';
import { SearchSidebarComponent } from './search-sidebar/search-sidebar.component';
-import { SearchSidebarService } from './search-sidebar/search-sidebar.service';
-import { SearchSidebarEffects } from './search-sidebar/search-sidebar.effects';
+import { SidebarService } from '../shared/sidebar/sidebar.service';
+import { SidebarEffects } from '../shared/sidebar/sidebar-effects.service';
import { SearchSettingsComponent } from './search-settings/search-settings.component';
import { EffectsModule } from '@ngrx/effects';
import { SearchFiltersComponent } from './search-filters/search-filters.component';
@@ -36,7 +36,7 @@ import { ConfigurationSearchPageGuard } from './configuration-search-page.guard'
import { FilteredSearchPageComponent } from './filtered-search-page.component';
const effects = [
- SearchSidebarEffects
+ SidebarEffects
];
const components = [
@@ -73,11 +73,11 @@ const components = [
CommonModule,
SharedModule,
EffectsModule.forFeature(effects),
- CoreModule.forRoot()
+ CoreModule.forRoot(),
],
declarations: components,
providers: [
- SearchSidebarService,
+ SidebarService,
SearchFilterService,
SearchFixedFilterService,
ConfigurationSearchPageGuard,
diff --git a/src/app/+search-page/search-settings/search-settings.component.spec.ts b/src/app/+search-page/search-settings/search-settings.component.spec.ts
index b9b5c5a5eb..729c228f44 100644
--- a/src/app/+search-page/search-settings/search-settings.component.spec.ts
+++ b/src/app/+search-page/search-settings/search-settings.component.spec.ts
@@ -7,7 +7,7 @@ import { SortDirection, SortOptions } from '../../core/cache/models/sort-options
import { TranslateModule } from '@ngx-translate/core';
import { RouterTestingModule } from '@angular/router/testing';
import { ActivatedRoute } from '@angular/router';
-import { SearchSidebarService } from '../search-sidebar/search-sidebar.service';
+import { SidebarService } from '../../shared/sidebar/sidebar.service';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { EnumKeysPipe } from '../../shared/utils/enum-keys-pipe';
import { By } from '@angular/platform-browser';
@@ -65,7 +65,7 @@ describe('SearchSettingsComponent', () => {
{ provide: ActivatedRoute, useValue: activatedRouteStub },
{
- provide: SearchSidebarService,
+ provide: SidebarService,
useValue: sidebarService
},
{
diff --git a/src/app/+search-page/search-sidebar/search-sidebar.reducer.ts b/src/app/+search-page/search-sidebar/search-sidebar.reducer.ts
deleted file mode 100644
index a01f0ff6d6..0000000000
--- a/src/app/+search-page/search-sidebar/search-sidebar.reducer.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-import { SearchSidebarAction, SearchSidebarActionTypes } from './search-sidebar.actions';
-
-/**
- * Interface that represents the state of the sidebar
- */
-export interface SearchSidebarState {
- sidebarCollapsed: boolean;
-}
-
-const initialState: SearchSidebarState = {
- sidebarCollapsed: true
-};
-
-/**
- * Performs a search sidebar action on the current state
- * @param {SearchSidebarState} state The state before the action is performed
- * @param {SearchSidebarAction} action The action that should be performed
- * @returns {SearchSidebarState} The state after the action is performed
- */
-export function sidebarReducer(state = initialState, action: SearchSidebarAction): SearchSidebarState {
- switch (action.type) {
-
- case SearchSidebarActionTypes.COLLAPSE: {
- return Object.assign({}, state, {
- sidebarCollapsed: true
- });
- }
-
- case SearchSidebarActionTypes.EXPAND: {
- return Object.assign({}, state, {
- sidebarCollapsed: false
- });
-
- }
-
- case SearchSidebarActionTypes.TOGGLE: {
- return Object.assign({}, state, {
- sidebarCollapsed: !state.sidebarCollapsed
- });
-
- }
-
- default: {
- return state;
- }
- }
-}
diff --git a/src/app/app.reducer.ts b/src/app/app.reducer.ts
index bc84f961fb..fbdce542a8 100644
--- a/src/app/app.reducer.ts
+++ b/src/app/app.reducer.ts
@@ -3,9 +3,9 @@ import * as fromRouter from '@ngrx/router-store';
import { hostWindowReducer, HostWindowState } from './shared/host-window.reducer';
import { formReducer, FormState } from './shared/form/form.reducer';
import {
- SearchSidebarState,
+ SidebarState,
sidebarReducer
-} from './+search-page/search-sidebar/search-sidebar.reducer';
+} from './shared/sidebar/sidebar.reducer';
import {
filterReducer,
SearchFiltersState
@@ -37,7 +37,7 @@ export interface AppState {
metadataRegistry: MetadataRegistryState;
bitstreamFormats: BitstreamFormatRegistryState;
notifications: NotificationsState;
- searchSidebar: SearchSidebarState;
+ searchSidebar: SidebarState;
searchFilter: SearchFiltersState;
truncatable: TruncatablesState;
cssVariables: CSSVariablesState;
diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts
index ed9f8efa93..5a1c2de26f 100644
--- a/src/app/shared/shared.module.ts
+++ b/src/app/shared/shared.module.ts
@@ -147,6 +147,7 @@ import { TypedItemSearchResultGridElementComponent } from './object-grid/item-gr
import { PublicationGridElementComponent } from './object-grid/item-grid-element/item-types/publication/publication-grid-element.component';
import { ItemTypeBadgeComponent } from './object-list/item-type-badge/item-type-badge.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';
const MODULES = [
// Do NOT include UniversalModule, HttpModule, or JsonpModule here
@@ -233,6 +234,7 @@ const COMPONENTS = [
ObjectCollectionComponent,
PaginationComponent,
SearchFormComponent,
+ PageWithSidebarComponent,
ThumbnailComponent,
GridThumbnailComponent,
UploaderComponent,
diff --git a/src/app/shared/sidebar/page-with-sidebar.component.html b/src/app/shared/sidebar/page-with-sidebar.component.html
new file mode 100644
index 0000000000..9feb6c792e
--- /dev/null
+++ b/src/app/shared/sidebar/page-with-sidebar.component.html
@@ -0,0 +1,14 @@
+
diff --git a/src/app/shared/sidebar/page-with-sidebar.component.scss b/src/app/shared/sidebar/page-with-sidebar.component.scss
new file mode 100644
index 0000000000..8be48cea2b
--- /dev/null
+++ b/src/app/shared/sidebar/page-with-sidebar.component.scss
@@ -0,0 +1,52 @@
+@include media-breakpoint-down(md) {
+ .container {
+ width: 100%;
+ max-width: none;
+ }
+}
+
+.row-with-sidebar {
+
+ &.row-offcanvas {
+ width: 100%;
+ }
+
+ @include media-breakpoint-up(md) {
+ display: flex;
+ }
+
+ @include media-breakpoint-down(sm) {
+ position: relative;
+
+ &.row-offcanvas {
+ position: relative;
+ }
+
+ &.row-offcanvas-right .sidebar-content {
+ right: -100%;
+ }
+
+ &.row-offcanvas-left .sidebar-content {
+ left: -100%;
+ }
+
+ .sidebar-content {
+ position: absolute;
+ top: 0;
+ width: 100%;
+ }
+ }
+}
+
+@include media-breakpoint-up(md) {
+ .sidebar-content {
+ position: sticky;
+ position: -webkit-sticky;
+ top: 0;
+ z-index: $zindex-sticky;
+ padding-top: $content-spacing;
+ margin-top: -$content-spacing;
+ align-self: flex-start;
+ display: block;
+ }
+}
diff --git a/src/app/shared/sidebar/page-with-sidebar.component.spec.ts b/src/app/shared/sidebar/page-with-sidebar.component.spec.ts
new file mode 100644
index 0000000000..dfe035d2be
--- /dev/null
+++ b/src/app/shared/sidebar/page-with-sidebar.component.spec.ts
@@ -0,0 +1,75 @@
+import { By } from '@angular/platform-browser';
+import { of as observableOf } from 'rxjs';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { PageWithSidebarComponent } from './page-with-sidebar.component';
+import { SidebarService } from './sidebar/sidebar.service';
+import { HostWindowService } from '../shared/host-window.service';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+
+describe('PageWithSidebarComponent', () => {
+ let comp:PageWithSidebarComponent;
+ let fixture:ComponentFixture;
+
+ const sidebarService = {
+ isCollapsed: observableOf(true),
+ collapse: () => this.isCollapsed = observableOf(true),
+ expand: () => this.isCollapsed = observableOf(false)
+ };
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports: [NoopAnimationsModule],
+ providers: [
+ {
+ provide: SidebarService,
+ useValue: sidebarService
+ },
+ {
+ provide: HostWindowService, useValue: jasmine.createSpyObj('hostWindowService',
+ {
+ isXs: observableOf(true),
+ isSm: observableOf(false),
+ isXsOrSm: observableOf(true)
+ })
+ },
+ ],
+ declarations: [PageWithSidebarComponent]
+ }).compileComponents();
+ fixture = TestBed.createComponent(PageWithSidebarComponent);
+ comp = fixture.componentInstance;
+ comp.id = 'mock-id';
+ fixture.detectChanges();
+ });
+
+ describe('when sidebarCollapsed is true in mobile view', () => {
+ let menu:HTMLElement;
+
+ beforeEach(() => {
+ menu = fixture.debugElement.query(By.css('#mock-id-sidebar-content')).nativeElement;
+ (comp as any).sidebarService.isCollapsed = observableOf(true);
+ comp.ngOnInit();
+ 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('#mock-id-sidebar-content')).nativeElement;
+ (comp as any).sidebarService.isCollapsed = observableOf(false);
+ comp.ngOnInit();
+ fixture.detectChanges();
+ });
+
+ it('should open the menu', () => {
+ expect(menu.classList).toContain('active');
+ });
+
+ });
+});
diff --git a/src/app/shared/sidebar/page-with-sidebar.component.ts b/src/app/shared/sidebar/page-with-sidebar.component.ts
new file mode 100644
index 0000000000..8020d492ec
--- /dev/null
+++ b/src/app/shared/sidebar/page-with-sidebar.component.ts
@@ -0,0 +1,71 @@
+import { Component, Input, OnInit, TemplateRef } from '@angular/core';
+import { SidebarService } from './sidebar.service';
+import { HostWindowService } from '../host-window.service';
+import { combineLatest as observableCombineLatest, Observable } from 'rxjs';
+import { pushInOut } from '../animations/push';
+import { map } from 'rxjs/operators';
+
+@Component({
+ selector: 'ds-page-with-sidebar',
+ styleUrls: ['./page-with-sidebar.component.scss'],
+ templateUrl: './page-with-sidebar.component.html',
+ animations: [pushInOut],
+})
+export class PageWithSidebarComponent implements OnInit {
+ @Input() id:string;
+ @Input() sidebarContent:TemplateRef;
+
+ /**
+ * Emits true if were on a small screen
+ */
+ isXsOrSm$:Observable;
+
+ /**
+ * The width of the sidebar (bootstrap columns)
+ */
+ @Input()
+ sideBarWidth = 3;
+
+ /**
+ * Observable for whether or not the sidebar is currently collapsed
+ */
+ isSidebarCollapsed$:Observable;
+
+ sidebarClasses:Observable;
+
+ constructor(protected sidebarService:SidebarService,
+ protected windowService:HostWindowService,
+ ) {
+ }
+
+ ngOnInit():void {
+ this.isXsOrSm$ = this.windowService.isXsOrSm();
+ this.isSidebarCollapsed$ = this.isSidebarCollapsed();
+ this.sidebarClasses = this.isSidebarCollapsed$.pipe(
+ map((isCollapsed) => isCollapsed ? '' : 'active')
+ );
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * 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();
+ }
+
+}
diff --git a/src/app/+search-page/search-sidebar/search-sidebar.effects.spec.ts b/src/app/shared/sidebar/search-sidebar.effects.spec.ts
similarity index 68%
rename from src/app/+search-page/search-sidebar/search-sidebar.effects.spec.ts
rename to src/app/shared/sidebar/search-sidebar.effects.spec.ts
index f34f6b72de..da675a38ce 100644
--- a/src/app/+search-page/search-sidebar/search-sidebar.effects.spec.ts
+++ b/src/app/shared/sidebar/search-sidebar.effects.spec.ts
@@ -3,24 +3,24 @@ import { Observable } from 'rxjs';
import { provideMockActions } from '@ngrx/effects/testing';
import { cold, hot } from 'jasmine-marbles';
import * as fromRouter from '@ngrx/router-store';
-import { SearchSidebarCollapseAction } from './search-sidebar.actions';
-import { SearchSidebarEffects } from './search-sidebar.effects';
+import { SidebarCollapseAction } from './sidebar.actions';
+import { SidebarEffects } from './sidebar-effects.service';
-describe('SearchSidebarEffects', () => {
- let sidebarEffects: SearchSidebarEffects;
+describe('SidebarEffects', () => {
+ let sidebarEffects: SidebarEffects;
let actions: Observable;
const dummyURL = 'http://f4fb15e2-1bd3-4e63-8d0d-486ad8bc714a';
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
- SearchSidebarEffects,
+ SidebarEffects,
provideMockActions(() => actions),
// other providers
],
});
- sidebarEffects = TestBed.get(SearchSidebarEffects);
+ sidebarEffects = TestBed.get(SidebarEffects);
});
describe('routeChange$', () => {
@@ -28,7 +28,7 @@ describe('SearchSidebarEffects', () => {
it('should return a COLLAPSE action in response to an UPDATE_LOCATION action to a new route', () => {
actions = hot('--a-', { a: { type: fromRouter.ROUTER_NAVIGATION, payload: {routerState: {url: dummyURL}} } });
- const expected = cold('--b-', { b: new SearchSidebarCollapseAction() });
+ const expected = cold('--b-', { b: new SidebarCollapseAction() });
expect(sidebarEffects.routeChange$).toBeObservable(expected);
});
diff --git a/src/app/+search-page/search-sidebar/search-sidebar.effects.ts b/src/app/shared/sidebar/sidebar-effects.service.ts
similarity index 85%
rename from src/app/+search-page/search-sidebar/search-sidebar.effects.ts
rename to src/app/shared/sidebar/sidebar-effects.service.ts
index 1f5fb0ef60..fc6643be4b 100644
--- a/src/app/+search-page/search-sidebar/search-sidebar.effects.ts
+++ b/src/app/shared/sidebar/sidebar-effects.service.ts
@@ -3,14 +3,14 @@ import { Injectable } from '@angular/core';
import { Effect, Actions, ofType } from '@ngrx/effects'
import * as fromRouter from '@ngrx/router-store';
-import { SearchSidebarCollapseAction } from './search-sidebar.actions';
+import { SidebarCollapseAction } from './sidebar.actions';
import { URLBaser } from '../../core/url-baser/url-baser';
/**
* Makes sure that if the user navigates to another route, the sidebar is collapsed
*/
@Injectable()
-export class SearchSidebarEffects {
+export class SidebarEffects {
private previousPath: string;
@Effect() routeChange$ = this.actions$
.pipe(
@@ -19,7 +19,7 @@ export class SearchSidebarEffects {
tap((action) => {
this.previousPath = this.getBaseUrl(action)
}),
- map(() => new SearchSidebarCollapseAction())
+ map(() => new SidebarCollapseAction())
);
constructor(private actions$: Actions) {
diff --git a/src/app/+search-page/search-sidebar/search-sidebar.actions.ts b/src/app/shared/sidebar/sidebar.actions.ts
similarity index 51%
rename from src/app/+search-page/search-sidebar/search-sidebar.actions.ts
rename to src/app/shared/sidebar/sidebar.actions.ts
index 84a34b2790..4a7c85696a 100644
--- a/src/app/+search-page/search-sidebar/search-sidebar.actions.ts
+++ b/src/app/shared/sidebar/sidebar.actions.ts
@@ -1,6 +1,6 @@
import { Action } from '@ngrx/store';
-import { type } from '../../shared/ngrx/type';
+import { type } from '../ngrx/type';
/**
* For each action type in an action group, make a simple
@@ -10,32 +10,32 @@ import { type } from '../../shared/ngrx/type';
* literal types and runs a simple check to guarantee all
* action types in the application are unique.
*/
-export const SearchSidebarActionTypes = {
- COLLAPSE: type('dspace/search-sidebar/COLLAPSE'),
- EXPAND: type('dspace/search-sidebar/EXPAND'),
- TOGGLE: type('dspace/search-sidebar/TOGGLE')
+export const SidebarActionTypes = {
+ COLLAPSE: type('dspace/sidebar/COLLAPSE'),
+ EXPAND: type('dspace/sidebar/EXPAND'),
+ TOGGLE: type('dspace/sidebar/TOGGLE')
};
/* tslint:disable:max-classes-per-file */
/**
* Used to collapse the sidebar
*/
-export class SearchSidebarCollapseAction implements Action {
- type = SearchSidebarActionTypes.COLLAPSE;
+export class SidebarCollapseAction implements Action {
+ type = SidebarActionTypes.COLLAPSE;
}
/**
* Used to expand the sidebar
*/
-export class SearchSidebarExpandAction implements Action {
- type = SearchSidebarActionTypes.EXPAND;
+export class SidebarExpandAction implements Action {
+ type = SidebarActionTypes.EXPAND;
}
/**
* Used to collapse the sidebar when it's expanded and expand it when it's collapsed
*/
-export class SearchSidebarToggleAction implements Action {
- type = SearchSidebarActionTypes.TOGGLE;
+export class SidebarToggleAction implements Action {
+ type = SidebarActionTypes.TOGGLE;
}
/* tslint:enable:max-classes-per-file */
@@ -43,7 +43,7 @@ export class SearchSidebarToggleAction implements Action {
* Export a type alias of all actions in this action group
* so that reducers can easily compose action types
*/
-export type SearchSidebarAction
- = SearchSidebarCollapseAction
- | SearchSidebarExpandAction
- | SearchSidebarToggleAction
+export type SidebarAction
+ = SidebarCollapseAction
+ | SidebarExpandAction
+ | SidebarToggleAction
diff --git a/src/app/+search-page/search-sidebar/search-sidebar.reducer.spec.ts b/src/app/shared/sidebar/sidebar.reducer.spec.ts
similarity index 80%
rename from src/app/+search-page/search-sidebar/search-sidebar.reducer.spec.ts
rename to src/app/shared/sidebar/sidebar.reducer.spec.ts
index dfdead4369..0fbfce84fc 100644
--- a/src/app/+search-page/search-sidebar/search-sidebar.reducer.spec.ts
+++ b/src/app/shared/sidebar/sidebar.reducer.spec.ts
@@ -1,12 +1,12 @@
import * as deepFreeze from 'deep-freeze';
-import { sidebarReducer } from './search-sidebar.reducer';
+import { sidebarReducer } from './sidebar.reducer';
import {
- SearchSidebarCollapseAction, SearchSidebarExpandAction,
- SearchSidebarToggleAction
-} from './search-sidebar.actions';
+ SidebarCollapseAction, SidebarExpandAction,
+ SidebarToggleAction
+} from './sidebar.actions';
-class NullAction extends SearchSidebarCollapseAction {
+class NullAction extends SidebarCollapseAction {
type = null;
constructor() {
@@ -34,7 +34,7 @@ describe('sidebarReducer', () => {
it('should set sidebarCollapsed to true in response to the COLLAPSE action', () => {
const state = { sidebarCollapsed: false };
- const action = new SearchSidebarCollapseAction();
+ const action = new SidebarCollapseAction();
const newState = sidebarReducer(state, action);
expect(newState.sidebarCollapsed).toEqual(true);
@@ -44,7 +44,7 @@ describe('sidebarReducer', () => {
const state = { sidebarCollapsed: false };
deepFreeze([state]);
- const action = new SearchSidebarCollapseAction();
+ const action = new SidebarCollapseAction();
sidebarReducer(state, action);
// no expect required, deepFreeze will ensure an exception is thrown if the state
@@ -53,7 +53,7 @@ describe('sidebarReducer', () => {
it('should set sidebarCollapsed to false in response to the EXPAND action', () => {
const state = { sidebarCollapsed: true };
- const action = new SearchSidebarExpandAction();
+ const action = new SidebarExpandAction();
const newState = sidebarReducer(state, action);
expect(newState.sidebarCollapsed).toEqual(false);
@@ -63,13 +63,13 @@ describe('sidebarReducer', () => {
const state = { sidebarCollapsed: true };
deepFreeze([state]);
- const action = new SearchSidebarExpandAction();
+ const action = new SidebarExpandAction();
sidebarReducer(state, action);
});
it('should flip the value of sidebarCollapsed in response to the TOGGLE action', () => {
const state1 = { sidebarCollapsed: true };
- const action = new SearchSidebarToggleAction();
+ const action = new SidebarToggleAction();
const state2 = sidebarReducer(state1, action);
const state3 = sidebarReducer(state2, action);
@@ -82,7 +82,7 @@ describe('sidebarReducer', () => {
const state = { sidebarCollapsed: true };
deepFreeze([state]);
- const action = new SearchSidebarToggleAction();
+ const action = new SidebarToggleAction();
sidebarReducer(state, action);
});
diff --git a/src/app/shared/sidebar/sidebar.reducer.ts b/src/app/shared/sidebar/sidebar.reducer.ts
new file mode 100644
index 0000000000..3c3dc63b0d
--- /dev/null
+++ b/src/app/shared/sidebar/sidebar.reducer.ts
@@ -0,0 +1,47 @@
+import { SidebarAction, SidebarActionTypes } from './sidebar.actions';
+
+/**
+ * Interface that represents the state of the sidebar
+ */
+export interface SidebarState {
+ sidebarCollapsed: boolean;
+}
+
+const initialState: SidebarState = {
+ sidebarCollapsed: true
+};
+
+/**
+ * Performs a search sidebar action on the current state
+ * @param {SidebarState} state The state before the action is performed
+ * @param {SidebarAction} action The action that should be performed
+ * @returns {SidebarState} The state after the action is performed
+ */
+export function sidebarReducer(state = initialState, action: SidebarAction): SidebarState {
+ switch (action.type) {
+
+ case SidebarActionTypes.COLLAPSE: {
+ return Object.assign({}, state, {
+ sidebarCollapsed: true
+ });
+ }
+
+ case SidebarActionTypes.EXPAND: {
+ return Object.assign({}, state, {
+ sidebarCollapsed: false
+ });
+
+ }
+
+ case SidebarActionTypes.TOGGLE: {
+ return Object.assign({}, state, {
+ sidebarCollapsed: !state.sidebarCollapsed
+ });
+
+ }
+
+ default: {
+ return state;
+ }
+ }
+}
diff --git a/src/app/+search-page/search-sidebar/search-sidebar.service.spec.ts b/src/app/shared/sidebar/sidebar.service.spec.ts
similarity index 61%
rename from src/app/+search-page/search-sidebar/search-sidebar.service.spec.ts
rename to src/app/shared/sidebar/sidebar.service.spec.ts
index 0cccf9ea40..6d8e845836 100644
--- a/src/app/+search-page/search-sidebar/search-sidebar.service.spec.ts
+++ b/src/app/shared/sidebar/sidebar.service.spec.ts
@@ -1,13 +1,13 @@
import { Store } from '@ngrx/store';
-import { SearchSidebarService } from './search-sidebar.service';
+import { SidebarService } from './sidebar.service';
import { AppState } from '../../app.reducer';
import { async, TestBed } from '@angular/core/testing';
import { of as observableOf } from 'rxjs';
-import { SearchSidebarCollapseAction, SearchSidebarExpandAction } from './search-sidebar.actions';
-import { HostWindowService } from '../../shared/host-window.service';
+import { SidebarCollapseAction, SidebarExpandAction } from './sidebar.actions';
+import { HostWindowService } from '../host-window.service';
-describe('SearchSidebarService', () => {
- let service: SearchSidebarService;
+describe('SidebarService', () => {
+ let service: SidebarService;
const store: Store = jasmine.createSpyObj('store', {
/* tslint:disable:no-empty */
dispatch: {},
@@ -35,7 +35,7 @@ describe('SearchSidebarService', () => {
}));
beforeEach(() => {
- service = new SearchSidebarService(store, windowService);
+ service = new SidebarService(store, windowService);
}) ;
describe('when the collapse method is triggered', () => {
@@ -43,8 +43,8 @@ describe('SearchSidebarService', () => {
service.collapse();
});
- it('SearchSidebarCollapseAction should be dispatched to the store', () => {
- expect(store.dispatch).toHaveBeenCalledWith(new SearchSidebarCollapseAction());
+ it('SidebarCollapseAction should be dispatched to the store', () => {
+ expect(store.dispatch).toHaveBeenCalledWith(new SidebarCollapseAction());
});
});
@@ -54,8 +54,8 @@ describe('SearchSidebarService', () => {
service.expand();
});
- it('SearchSidebarExpandAction should be dispatched to the store', () => {
- expect(store.dispatch).toHaveBeenCalledWith(new SearchSidebarExpandAction());
+ it('SidebarExpandAction should be dispatched to the store', () => {
+ expect(store.dispatch).toHaveBeenCalledWith(new SidebarExpandAction());
});
});
diff --git a/src/app/+search-page/search-sidebar/search-sidebar.service.ts b/src/app/shared/sidebar/sidebar.service.ts
similarity index 77%
rename from src/app/+search-page/search-sidebar/search-sidebar.service.ts
rename to src/app/shared/sidebar/sidebar.service.ts
index 7185984538..2e3303887b 100644
--- a/src/app/+search-page/search-sidebar/search-sidebar.service.ts
+++ b/src/app/shared/sidebar/sidebar.service.ts
@@ -1,20 +1,20 @@
import { combineLatest as observableCombineLatest, Observable } from 'rxjs';
import { Injectable } from '@angular/core';
-import { SearchSidebarState } from './search-sidebar.reducer';
+import { SidebarState } from './sidebar.reducer';
import { createSelector, select, Store } from '@ngrx/store';
-import { SearchSidebarCollapseAction, SearchSidebarExpandAction } from './search-sidebar.actions';
+import { SidebarCollapseAction, SidebarExpandAction } from './sidebar.actions';
import { AppState } from '../../app.reducer';
-import { HostWindowService } from '../../shared/host-window.service';
+import { HostWindowService } from '../host-window.service';
import { map } from 'rxjs/operators';
const sidebarStateSelector = (state: AppState) => state.searchSidebar;
-const sidebarCollapsedSelector = createSelector(sidebarStateSelector, (sidebar: SearchSidebarState) => sidebar.sidebarCollapsed);
+const sidebarCollapsedSelector = createSelector(sidebarStateSelector, (sidebar: SidebarState) => sidebar.sidebarCollapsed);
/**
* Service that performs all actions that have to do with the search sidebar
*/
@Injectable()
-export class SearchSidebarService {
+export class SidebarService {
/**
* Emits true is the current screen size is mobile
*/
@@ -47,13 +47,13 @@ export class SearchSidebarService {
* Dispatches a collapse action to the store
*/
public collapse(): void {
- this.store.dispatch(new SearchSidebarCollapseAction());
+ this.store.dispatch(new SidebarCollapseAction());
}
/**
* Dispatches an expand action to the store
*/
public expand(): void {
- this.store.dispatch(new SearchSidebarExpandAction());
+ this.store.dispatch(new SidebarExpandAction());
}
}