mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
Merge remote-tracking branch 'origin/main' into coar-notify-7
This commit is contained in:
@@ -285,8 +285,17 @@ item:
|
||||
# settings menu. See pageSizeOptions in 'pagination-component-options.model.ts'.
|
||||
pageSize: 5
|
||||
|
||||
# Community Page Config
|
||||
community:
|
||||
# Search tab config
|
||||
searchSection:
|
||||
showSidebar: true
|
||||
|
||||
# Collection Page Config
|
||||
collection:
|
||||
# Search tab config
|
||||
searchSection:
|
||||
showSidebar: true
|
||||
edit:
|
||||
undoTimeout: 10000 # 10 seconds
|
||||
|
||||
@@ -391,4 +400,3 @@ comcolSelectionSort:
|
||||
# suggestion:
|
||||
# - collectionId: 8f7df5ca-f9c2-47a4-81ec-8a6393d6e5af
|
||||
# source: "openaire"
|
||||
|
||||
|
@@ -25,7 +25,7 @@ import { DSOEditMenuResolver } from '../shared/dso-page/dso-edit-menu.resolver';
|
||||
import { ComcolBrowseByComponent } from '../shared/comcol/sections/comcol-browse-by/comcol-browse-by.component';
|
||||
import { BrowseByGuard } from '../browse-by/browse-by-guard';
|
||||
import { BrowseByI18nBreadcrumbResolver } from '../browse-by/browse-by-i18n-breadcrumb.resolver';
|
||||
import { CollectionRecentlyAddedComponent } from './sections/recently-added/collection-recently-added.component';
|
||||
import { ComcolSearchSectionComponent } from '../shared/comcol/sections/comcol-search-section/comcol-search-section.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@@ -73,7 +73,7 @@ import { CollectionRecentlyAddedComponent } from './sections/recently-added/coll
|
||||
{
|
||||
path: '',
|
||||
pathMatch: 'full',
|
||||
component: CollectionRecentlyAddedComponent,
|
||||
component: ComcolSearchSectionComponent,
|
||||
},
|
||||
{
|
||||
path: 'browse/:id',
|
||||
|
@@ -19,7 +19,6 @@ import { ComcolModule } from '../shared/comcol/comcol.module';
|
||||
import { DsoSharedModule } from '../dso-shared/dso-shared.module';
|
||||
import { DsoPageModule } from '../shared/dso-page/dso-page.module';
|
||||
import { BrowseByPageModule } from '../browse-by/browse-by-page.module';
|
||||
import { CollectionRecentlyAddedComponent } from './sections/recently-added/collection-recently-added.component';
|
||||
|
||||
const DECLARATIONS = [
|
||||
CollectionPageComponent,
|
||||
@@ -29,7 +28,6 @@ const DECLARATIONS = [
|
||||
EditItemTemplatePageComponent,
|
||||
ThemedEditItemTemplatePageComponent,
|
||||
CollectionItemMapperComponent,
|
||||
CollectionRecentlyAddedComponent,
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
@@ -1,18 +0,0 @@
|
||||
<ng-container *ngVar="(itemRD$ | async) as itemRD">
|
||||
<div class="mt-4" *ngIf="itemRD?.hasSucceeded" @fadeIn>
|
||||
<h3 class="sr-only">{{'collection.page.browse.recent.head' | translate}}</h3>
|
||||
<ds-viewable-collection
|
||||
[config]="paginationConfig"
|
||||
[sortConfig]="sortConfig"
|
||||
[objects]="itemRD"
|
||||
[hideGear]="true">
|
||||
</ds-viewable-collection>
|
||||
</div>
|
||||
<ds-error *ngIf="itemRD?.hasFailed"
|
||||
message="{{'error.recent-submissions' | translate}}"></ds-error>
|
||||
<ds-themed-loading *ngIf="!itemRD || itemRD.isLoading"
|
||||
message="{{'loading.recent-submissions' | translate}}"></ds-themed-loading>
|
||||
<div *ngIf="!itemRD?.isLoading && itemRD?.payload?.page.length === 0" class="alert alert-info w-100" role="alert">
|
||||
{{'collection.page.browse.recent.empty' | translate}}
|
||||
</div>
|
||||
</ng-container>
|
@@ -1,53 +0,0 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { CollectionRecentlyAddedComponent } from './collection-recently-added.component';
|
||||
import { APP_CONFIG } from '../../../../config/app-config.interface';
|
||||
import { environment } from '../../../../environments/environment.test';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { ActivatedRouteStub } from '../../../shared/testing/active-router.stub';
|
||||
import { PaginationService } from '../../../core/pagination/pagination.service';
|
||||
import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub';
|
||||
import { SearchServiceStub } from '../../../shared/testing/search-service.stub';
|
||||
import { SearchService } from '../../../core/shared/search/search.service';
|
||||
import { VarDirective } from '../../../shared/utils/var.directive';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
|
||||
describe('CollectionRecentlyAddedComponent', () => {
|
||||
let component: CollectionRecentlyAddedComponent;
|
||||
let fixture: ComponentFixture<CollectionRecentlyAddedComponent>;
|
||||
|
||||
let activatedRoute: ActivatedRouteStub;
|
||||
let paginationService: PaginationServiceStub;
|
||||
let searchService: SearchServiceStub;
|
||||
|
||||
beforeEach(async () => {
|
||||
activatedRoute = new ActivatedRouteStub();
|
||||
paginationService = new PaginationServiceStub();
|
||||
searchService = new SearchServiceStub();
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
CollectionRecentlyAddedComponent,
|
||||
VarDirective,
|
||||
],
|
||||
imports: [
|
||||
TranslateModule.forRoot(),
|
||||
],
|
||||
providers: [
|
||||
{ provide: ActivatedRoute, useValue: activatedRoute },
|
||||
{ provide: APP_CONFIG, useValue: environment },
|
||||
{ provide: PaginationService, useValue: paginationService },
|
||||
{ provide: SearchService, useValue: SearchServiceStub },
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(CollectionRecentlyAddedComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@@ -1,82 +0,0 @@
|
||||
import { Component, OnInit, Inject, OnDestroy } from '@angular/core';
|
||||
import { Observable, combineLatest as observableCombineLatest } from 'rxjs';
|
||||
import { RemoteData } from '../../../core/data/remote-data';
|
||||
import { PaginatedList } from '../../../core/data/paginated-list.model';
|
||||
import { Item } from '../../../core/shared/item.model';
|
||||
import { switchMap, map, startWith, take } from 'rxjs/operators';
|
||||
import { getFirstSucceededRemoteData, toDSpaceObjectListRD } from '../../../core/shared/operators';
|
||||
import { PaginatedSearchOptions } from '../../../shared/search/models/paginated-search-options.model';
|
||||
import { DSpaceObjectType } from '../../../core/shared/dspace-object-type.model';
|
||||
import { BROWSE_LINKS_TO_FOLLOW } from '../../../core/browse/browse.service';
|
||||
import { PaginationService } from '../../../core/pagination/pagination.service';
|
||||
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
|
||||
import { SortOptions, SortDirection } from '../../../core/cache/models/sort-options.model';
|
||||
import { APP_CONFIG, AppConfig } from '../../../../config/app-config.interface';
|
||||
import { SearchService } from '../../../core/shared/search/search.service';
|
||||
import { Collection } from '../../../core/shared/collection.model';
|
||||
import { ActivatedRoute, Data } from '@angular/router';
|
||||
import { fadeIn } from '../../../shared/animations/fade';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-collection-recently-added',
|
||||
templateUrl: './collection-recently-added.component.html',
|
||||
styleUrls: ['./collection-recently-added.component.scss'],
|
||||
animations: [fadeIn],
|
||||
})
|
||||
export class CollectionRecentlyAddedComponent implements OnInit, OnDestroy {
|
||||
|
||||
paginationConfig: PaginationComponentOptions;
|
||||
|
||||
sortConfig: SortOptions;
|
||||
|
||||
collectionRD$: Observable<RemoteData<Collection>>;
|
||||
|
||||
itemRD$: Observable<RemoteData<PaginatedList<Item>>>;
|
||||
|
||||
constructor(
|
||||
@Inject(APP_CONFIG) protected appConfig: AppConfig,
|
||||
protected paginationService: PaginationService,
|
||||
protected route: ActivatedRoute,
|
||||
protected searchService: SearchService,
|
||||
) {
|
||||
this.paginationConfig = Object.assign(new PaginationComponentOptions(), {
|
||||
id: 'cp',
|
||||
currentPage: 1,
|
||||
pageSize: this.appConfig.browseBy.pageSize,
|
||||
});
|
||||
|
||||
this.sortConfig = new SortOptions('dc.date.accessioned', SortDirection.DESC);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.collectionRD$ = this.route.data.pipe(
|
||||
map((data: Data) => data.dso as RemoteData<Collection>),
|
||||
take(1),
|
||||
);
|
||||
|
||||
this.itemRD$ = observableCombineLatest([
|
||||
this.paginationService.getCurrentPagination(this.paginationConfig.id, this.paginationConfig),
|
||||
this.paginationService.getCurrentSort(this.paginationConfig.id, this.sortConfig),
|
||||
]).pipe(
|
||||
switchMap(([currentPagination, currentSort]: [PaginationComponentOptions, SortOptions]) => this.collectionRD$.pipe(
|
||||
getFirstSucceededRemoteData(),
|
||||
map((rd: RemoteData<Collection>) => rd.payload.id),
|
||||
switchMap((id: string) => this.searchService.search<Item>(
|
||||
new PaginatedSearchOptions({
|
||||
scope: id,
|
||||
pagination: currentPagination,
|
||||
sort: currentSort,
|
||||
dsoTypes: [DSpaceObjectType.ITEM]
|
||||
}), null, true, true, ...BROWSE_LINKS_TO_FOLLOW).pipe(
|
||||
toDSpaceObjectListRD()
|
||||
) as Observable<RemoteData<PaginatedList<Item>>>),
|
||||
startWith(undefined), // Make sure switching pages shows loading component
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.paginationService.clearPagination(this.paginationConfig.id);
|
||||
}
|
||||
|
||||
}
|
@@ -19,6 +19,8 @@ import { SubComColSectionComponent } from './sections/sub-com-col-section/sub-co
|
||||
import { BrowseByI18nBreadcrumbResolver } from '../browse-by/browse-by-i18n-breadcrumb.resolver';
|
||||
import { BrowseByGuard } from '../browse-by/browse-by-guard';
|
||||
import { ComcolBrowseByComponent } from '../shared/comcol/sections/comcol-browse-by/comcol-browse-by.component';
|
||||
import { ComcolSearchSectionComponent } from '../shared/comcol/sections/comcol-search-section/comcol-search-section.component';
|
||||
import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@@ -56,7 +58,16 @@ import { ComcolBrowseByComponent } from '../shared/comcol/sections/comcol-browse
|
||||
{
|
||||
path: '',
|
||||
pathMatch: 'full',
|
||||
component: ComcolSearchSectionComponent,
|
||||
},
|
||||
{
|
||||
path: 'subcoms-cols',
|
||||
pathMatch: 'full',
|
||||
component: SubComColSectionComponent,
|
||||
resolve: {
|
||||
breadcrumb: I18nBreadcrumbResolver,
|
||||
},
|
||||
data: { breadcrumbKey: 'community.subcoms-cols' },
|
||||
},
|
||||
{
|
||||
path: 'browse/:id',
|
||||
|
@@ -11,6 +11,7 @@ describe('SubComColSectionComponent', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
activatedRoute = new ActivatedRouteStub();
|
||||
activatedRoute.parent = new ActivatedRouteStub();
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
|
@@ -20,7 +20,7 @@ export class SubComColSectionComponent implements OnInit {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.community$ = this.route.data.pipe(
|
||||
this.community$ = this.route.parent.data.pipe(
|
||||
map((data: Data) => (data.dso as RemoteData<Community>).payload),
|
||||
);
|
||||
}
|
||||
|
@@ -1,27 +1,36 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
import { of, forkJoin, Observable } from 'rxjs';
|
||||
import { catchError, map, mergeMap, take } from 'rxjs/operators';
|
||||
import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model';
|
||||
import { FindListOptions } from '../core/data/find-list-options.model';
|
||||
import { PaginatedList } from '../core/data/paginated-list.model';
|
||||
import { RemoteData } from '../core/data/remote-data';
|
||||
import { SuggestionTarget } from '../core/notifications/models/suggestion-target.model';
|
||||
import { SuggestionsDataService } from '../core/notifications/suggestions-data.service';
|
||||
import { SuggestionTargetDataService } from '../core/notifications/target/suggestion-target-data.service';
|
||||
import { ResearcherProfileDataService } from '../core/profile/researcher-profile-data.service';
|
||||
import { NoContent } from '../core/shared/NoContent.model';
|
||||
import { getFirstSucceededRemoteListPayload, getFirstSucceededRemoteDataPayload, getAllSucceededRemoteDataPayload, getFinishedRemoteData } from '../core/shared/operators';
|
||||
import { getSuggestionPageRoute } from '../suggestions-page/suggestions-page-routing-paths';
|
||||
import { environment } from '../../environments/environment';
|
||||
import { SuggestionConfig } from '../../config/suggestion-config.interfaces';
|
||||
import { Suggestion } from '../core/notifications/models/suggestion.model';
|
||||
import { ResearcherProfile } from '../core/profile/model/researcher-profile.model';
|
||||
import { hasValue, isNotEmpty } from '../shared/empty.util';
|
||||
import { WorkspaceitemDataService } from '../core/submission/workspaceitem-data.service';
|
||||
import { WorkspaceItem } from '../core/submission/models/workspaceitem.model';
|
||||
|
||||
import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model';
|
||||
import { RemoteData } from '../core/data/remote-data';
|
||||
import { PaginatedList } from '../core/data/paginated-list.model';
|
||||
import { SuggestionTarget } from '../core/suggestion-notifications/models/suggestion-target.model';
|
||||
import { hasValue, isNotEmpty } from '../shared/empty.util';
|
||||
import { ResearcherProfile } from '../core/profile/model/researcher-profile.model';
|
||||
import {
|
||||
getAllSucceededRemoteDataPayload,
|
||||
getFinishedRemoteData, getFirstCompletedRemoteData,
|
||||
getFirstSucceededRemoteDataPayload,
|
||||
getFirstSucceededRemoteListPayload
|
||||
} from '../core/shared/operators';
|
||||
import { Suggestion } from '../core/suggestion-notifications/models/suggestion.model';
|
||||
import { WorkspaceitemDataService } from '../core/submission/workspaceitem-data.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { NoContent } from '../core/shared/NoContent.model';
|
||||
import { environment } from '../../environments/environment';
|
||||
import { WorkspaceItem } from '../core/submission/models/workspaceitem.model';
|
||||
import {FindListOptions} from '../core/data/find-list-options.model';
|
||||
import {SuggestionConfig} from '../../config/suggestion-config.interfaces';
|
||||
import { ResearcherProfileDataService } from '../core/profile/researcher-profile-data.service';
|
||||
import {
|
||||
SuggestionTargetDataService
|
||||
} from '../core/suggestion-notifications/target/suggestion-target-data.service';
|
||||
import {
|
||||
SuggestionsDataService
|
||||
} from '../core/suggestion-notifications/suggestions-data.service';
|
||||
import { getSuggestionPageRoute } from '../suggestions-page/suggestions-page-routing-paths';
|
||||
|
||||
/**
|
||||
* useful for multiple approvals and ignores operation
|
||||
@@ -146,10 +155,10 @@ export class SuggestionsService {
|
||||
*/
|
||||
public retrieveCurrentUserSuggestions(userUuid: string): Observable<SuggestionTarget[]> {
|
||||
return this.researcherProfileService.findById(userUuid, true).pipe(
|
||||
getFirstSucceededRemoteDataPayload(),
|
||||
mergeMap((profile: ResearcherProfile) => {
|
||||
if (isNotEmpty(profile)) {
|
||||
return this.researcherProfileService.findRelatedItemId(profile).pipe(
|
||||
getFirstCompletedRemoteData(),
|
||||
mergeMap((profile: RemoteData<ResearcherProfile> ) => {
|
||||
if (isNotEmpty(profile) && profile.hasSucceeded && isNotEmpty(profile.payload)) {
|
||||
return this.researcherProfileService.findRelatedItemId(profile.payload).pipe(
|
||||
mergeMap((itemId: string) => {
|
||||
return this.suggestionsDataService.getTargetsByUser(itemId).pipe(
|
||||
getFirstSucceededRemoteListPayload()
|
||||
@@ -160,7 +169,7 @@ export class SuggestionsService {
|
||||
return of([]);
|
||||
}
|
||||
}),
|
||||
take(1)
|
||||
catchError(() => of([]))
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -88,7 +88,7 @@ describe('SearchNavbarComponent', () => {
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
it('to search page with empty query', () => {
|
||||
const extras: NavigationExtras = { queryParams: { query: '' }, queryParamsHandling: 'merge' };
|
||||
const extras: NavigationExtras = { queryParams: { query: '' } };
|
||||
expect(component.onSubmit).toHaveBeenCalledWith({ query: '' });
|
||||
expect(router.navigate).toHaveBeenCalledWith(['search'], extras);
|
||||
});
|
||||
@@ -113,7 +113,7 @@ describe('SearchNavbarComponent', () => {
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
it('to search page with query', async () => {
|
||||
const extras: NavigationExtras = { queryParams: { query: 'test' }, queryParamsHandling: 'merge' };
|
||||
const extras: NavigationExtras = { queryParams: { query: 'test' } };
|
||||
expect(component.onSubmit).toHaveBeenCalledWith({ query: 'test' });
|
||||
|
||||
expect(router.navigate).toHaveBeenCalledWith(['search'], extras);
|
||||
|
@@ -66,8 +66,7 @@ export class SearchNavbarComponent {
|
||||
this.searchForm.reset();
|
||||
|
||||
this.router.navigate(linkToNavigateTo, {
|
||||
queryParams: queryParams,
|
||||
queryParamsHandling: 'merge'
|
||||
queryParams: queryParams
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -8,6 +8,7 @@ import { SearchConfigurationService } from '../core/shared/search/search-configu
|
||||
import { RouteService } from '../core/services/route.service';
|
||||
import { SearchService } from '../core/shared/search/search.service';
|
||||
import { Router } from '@angular/router';
|
||||
import { APP_CONFIG, AppConfig } from '../../config/app-config.interface';
|
||||
|
||||
/**
|
||||
* This component renders a search page using a configuration as input.
|
||||
@@ -32,7 +33,9 @@ export class ConfigurationSearchPageComponent extends SearchComponent {
|
||||
protected windowService: HostWindowService,
|
||||
@Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: SearchConfigurationService,
|
||||
protected routeService: RouteService,
|
||||
protected router: Router) {
|
||||
super(service, sidebarService, windowService, searchConfigService, routeService, router);
|
||||
protected router: Router,
|
||||
@Inject(APP_CONFIG) protected appConfig: AppConfig,
|
||||
) {
|
||||
super(service, sidebarService, windowService, searchConfigService, routeService, router, appConfig);
|
||||
}
|
||||
}
|
||||
|
@@ -55,16 +55,21 @@ export class ComcolPageBrowseByComponent implements OnDestroy, OnInit {
|
||||
if (this.contentType === 'collection') {
|
||||
comColRoute = getCollectionPageRoute(this.id);
|
||||
allOptions.push({
|
||||
id: 'recent_submissions',
|
||||
label: 'collection.page.browse.recent.head',
|
||||
id: 'search',
|
||||
label: 'collection.page.browse.search.head',
|
||||
routerLink: comColRoute,
|
||||
});
|
||||
} else if (this.contentType === 'community') {
|
||||
comColRoute = getCommunityPageRoute(this.id);
|
||||
allOptions.push({
|
||||
id: 'search',
|
||||
label: 'collection.page.browse.search.head',
|
||||
routerLink: comColRoute,
|
||||
});
|
||||
allOptions.push({
|
||||
id: 'comcols',
|
||||
label: 'community.all-lists.head',
|
||||
routerLink: comColRoute,
|
||||
routerLink: `${comColRoute}/subcoms-cols`,
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -18,6 +18,8 @@ import { FormModule } from '../form/form.module';
|
||||
import { UploadModule } from '../upload/upload.module';
|
||||
import { ComcolBrowseByComponent } from './sections/comcol-browse-by/comcol-browse-by.component';
|
||||
import { BrowseByModule } from '../../browse-by/browse-by.module';
|
||||
import { SearchModule } from '../search/search.module';
|
||||
import { ComcolSearchSectionComponent } from './sections/comcol-search-section/comcol-search-section.component';
|
||||
|
||||
const COMPONENTS = [
|
||||
ComcolPageContentComponent,
|
||||
@@ -33,6 +35,7 @@ const COMPONENTS = [
|
||||
ComcolRoleComponent,
|
||||
ThemedComcolPageHandleComponent,
|
||||
ComcolBrowseByComponent,
|
||||
ComcolSearchSectionComponent,
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
@@ -45,6 +48,7 @@ const COMPONENTS = [
|
||||
SharedModule,
|
||||
UploadModule,
|
||||
BrowseByModule,
|
||||
SearchModule,
|
||||
],
|
||||
exports: [
|
||||
...COMPONENTS,
|
||||
|
@@ -0,0 +1,7 @@
|
||||
<ds-themed-search
|
||||
[configuration]="(comcol$ | async)?.type"
|
||||
[showSidebar]="showSidebar$ | async"
|
||||
[showScopeSelector]="false"
|
||||
[hideScopeInUrl]="true"
|
||||
[scope]="(comcol$ | async)?.id">
|
||||
</ds-themed-search>
|
@@ -0,0 +1,35 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { ComcolSearchSectionComponent } from './comcol-search-section.component';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { ActivatedRouteStub } from '../../../testing/active-router.stub';
|
||||
import { APP_CONFIG } from '../../../../../config/app-config.interface';
|
||||
import { environment } from '../../../../../environments/environment.test';
|
||||
|
||||
describe('ComcolSearchSectionComponent', () => {
|
||||
let component: ComcolSearchSectionComponent;
|
||||
let fixture: ComponentFixture<ComcolSearchSectionComponent>;
|
||||
|
||||
let route: ActivatedRouteStub;
|
||||
|
||||
beforeEach(async () => {
|
||||
route = new ActivatedRouteStub();
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
ComcolSearchSectionComponent,
|
||||
],
|
||||
providers: [
|
||||
{ provide: APP_CONFIG, useValue: environment },
|
||||
{ provide: ActivatedRoute, useValue: route },
|
||||
],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ComcolSearchSectionComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@@ -0,0 +1,48 @@
|
||||
import { Component, OnInit, Inject } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { ActivatedRoute, Data } from '@angular/router';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { SEARCH_CONFIG_SERVICE } from '../../../../my-dspace-page/my-dspace-page.component';
|
||||
import { SearchConfigurationService } from '../../../../core/shared/search/search-configuration.service';
|
||||
import { RemoteData } from '../../../../core/data/remote-data';
|
||||
import { Community } from '../../../../core/shared/community.model';
|
||||
import { Collection } from '../../../../core/shared/collection.model';
|
||||
import { APP_CONFIG, AppConfig } from '../../../../../config/app-config.interface';
|
||||
import { hasValue } from '../../../empty.util';
|
||||
|
||||
/**
|
||||
* The search tab on community & collection pages
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ds-comcol-search-section',
|
||||
templateUrl: './comcol-search-section.component.html',
|
||||
styleUrls: ['./comcol-search-section.component.scss'],
|
||||
providers: [
|
||||
{
|
||||
provide: SEARCH_CONFIG_SERVICE,
|
||||
useClass: SearchConfigurationService,
|
||||
},
|
||||
],
|
||||
})
|
||||
export class ComcolSearchSectionComponent implements OnInit {
|
||||
|
||||
comcol$: Observable<Community | Collection>;
|
||||
|
||||
showSidebar$: Observable<boolean>;
|
||||
|
||||
constructor(
|
||||
@Inject(APP_CONFIG) public appConfig: AppConfig,
|
||||
protected route: ActivatedRoute,
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.comcol$ = this.route.data.pipe(
|
||||
map((data: Data) => (data.dso as RemoteData<Community | Collection>).payload),
|
||||
);
|
||||
this.showSidebar$ = this.comcol$.pipe(
|
||||
map((comcol: Community | Collection) => hasValue(comcol) && this.appConfig[comcol.type as any].searchSection.showSidebar),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
import { Component, EventEmitter, Input, Output, OnChanges } from '@angular/core';
|
||||
import { DSpaceObject } from '../../core/shared/dspace-object.model';
|
||||
import { Router } from '@angular/router';
|
||||
import { isNotEmpty } from '../empty.util';
|
||||
import { isNotEmpty, hasValue } from '../empty.util';
|
||||
import { SearchService } from '../../core/shared/search/search.service';
|
||||
import { currentPath } from '../utils/route.utils';
|
||||
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||
@@ -39,6 +39,11 @@ export class SearchFormComponent implements OnChanges {
|
||||
@Input()
|
||||
scope = '';
|
||||
|
||||
/**
|
||||
* Hides the scope in the url, this can be useful when you hardcode the scope in another way
|
||||
*/
|
||||
@Input() hideScopeInUrl = false;
|
||||
|
||||
selectedScope: BehaviorSubject<DSpaceObject> = new BehaviorSubject<DSpaceObject>(undefined);
|
||||
|
||||
@Input() currentUrl: string;
|
||||
@@ -122,6 +127,9 @@ export class SearchFormComponent implements OnChanges {
|
||||
},
|
||||
data
|
||||
);
|
||||
if (hasValue(data.scope) && this.hideScopeInUrl) {
|
||||
delete queryParams.scope;
|
||||
}
|
||||
|
||||
void this.router.navigate(this.getSearchLinkParts(), {
|
||||
queryParams: queryParams,
|
||||
|
@@ -18,6 +18,8 @@ export class ThemedSearchFormComponent extends ThemedComponent<SearchFormCompone
|
||||
|
||||
@Input() scope: string;
|
||||
|
||||
@Input() hideScopeInUrl: boolean;
|
||||
|
||||
@Input() currentUrl: string;
|
||||
|
||||
@Input() large: boolean;
|
||||
@@ -31,7 +33,15 @@ export class ThemedSearchFormComponent extends ThemedComponent<SearchFormCompone
|
||||
@Output() submitSearch: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
protected inAndOutputNames: (keyof SearchFormComponent & keyof this)[] = [
|
||||
'query', 'inPlaceSearch', 'scope', 'currentUrl', 'large', 'brandColor', 'searchPlaceholder', 'showScopeSelector',
|
||||
'query',
|
||||
'inPlaceSearch',
|
||||
'scope',
|
||||
'hideScopeInUrl',
|
||||
'currentUrl',
|
||||
'large',
|
||||
'brandColor',
|
||||
'searchPlaceholder',
|
||||
'showScopeSelector',
|
||||
'submitSearch',
|
||||
];
|
||||
|
||||
|
@@ -27,6 +27,8 @@ import { SearchConfigurationServiceStub } from '../../../../testing/search-confi
|
||||
import { VocabularyEntryDetail } from '../../../../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
|
||||
import { FacetValue} from '../../../models/facet-value.model';
|
||||
import { SearchFilterConfig } from '../../../models/search-filter-config.model';
|
||||
import { APP_CONFIG } from '../../../../../../config/app-config.interface';
|
||||
import { environment } from '../../../../../../environments/environment.test';
|
||||
|
||||
describe('SearchHierarchyFilterComponent', () => {
|
||||
|
||||
@@ -34,7 +36,7 @@ describe('SearchHierarchyFilterComponent', () => {
|
||||
let showVocabularyTreeLink: DebugElement;
|
||||
|
||||
const testSearchLink = 'test-search';
|
||||
const testSearchFilter = 'test-search-filter';
|
||||
const testSearchFilter = 'subject';
|
||||
const VocabularyTreeViewComponent = {
|
||||
select: new EventEmitter<VocabularyEntryDetail>(),
|
||||
};
|
||||
@@ -73,6 +75,7 @@ describe('SearchHierarchyFilterComponent', () => {
|
||||
{ provide: Router, useValue: router },
|
||||
{ provide: NgbModal, useValue: ngbModal },
|
||||
{ provide: VocabularyService, useValue: vocabularyService },
|
||||
{ provide: APP_CONFIG, useValue: environment },
|
||||
{ provide: SEARCH_CONFIG_SERVICE, useValue: new SearchConfigurationServiceStub() },
|
||||
{ provide: IN_PLACE_SEARCH, useValue: false },
|
||||
{ provide: FILTER_CONFIG, useValue: Object.assign(new SearchFilterConfig(), { name: testSearchFilter }) },
|
||||
@@ -86,7 +89,7 @@ describe('SearchHierarchyFilterComponent', () => {
|
||||
function init() {
|
||||
fixture = TestBed.createComponent(SearchHierarchyFilterComponent);
|
||||
fixture.detectChanges();
|
||||
showVocabularyTreeLink = fixture.debugElement.query(By.css('a#show-test-search-filter-tree'));
|
||||
showVocabularyTreeLink = fixture.debugElement.query(By.css(`a#show-${testSearchFilter}-tree`));
|
||||
}
|
||||
|
||||
describe('if the vocabulary doesn\'t exist', () => {
|
||||
|
@@ -24,9 +24,11 @@ import { filter, map, take } from 'rxjs/operators';
|
||||
import { VocabularyService } from '../../../../../core/submission/vocabularies/vocabulary.service';
|
||||
import { Observable, BehaviorSubject } from 'rxjs';
|
||||
import { PageInfo } from '../../../../../core/shared/page-info.model';
|
||||
import { environment } from '../../../../../../environments/environment';
|
||||
import { addOperatorToFilterValue } from '../../../search.utils';
|
||||
import { VocabularyTreeviewModalComponent } from '../../../../form/vocabulary-treeview-modal/vocabulary-treeview-modal.component';
|
||||
import { hasValue } from '../../../../empty.util';
|
||||
import { APP_CONFIG, AppConfig } from '../../../../../../config/app-config.interface';
|
||||
import { FilterVocabularyConfig } from '../../../../../../config/filter-vocabulary-config';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-search-hierarchy-filter',
|
||||
@@ -47,6 +49,7 @@ export class SearchHierarchyFilterComponent extends SearchFacetFilterComponent i
|
||||
protected router: Router,
|
||||
protected modalService: NgbModal,
|
||||
protected vocabularyService: VocabularyService,
|
||||
@Inject(APP_CONFIG) protected appConfig: AppConfig,
|
||||
@Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: SearchConfigurationService,
|
||||
@Inject(IN_PLACE_SEARCH) public inPlaceSearch: boolean,
|
||||
@Inject(FILTER_CONFIG) public filterConfig: SearchFilterConfig,
|
||||
@@ -67,17 +70,20 @@ export class SearchHierarchyFilterComponent extends SearchFacetFilterComponent i
|
||||
super.onSubmit(addOperatorToFilterValue(data, 'query'));
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
ngOnInit(): void {
|
||||
super.ngOnInit();
|
||||
this.vocabularyExists$ = this.vocabularyService.searchTopEntries(
|
||||
this.getVocabularyEntry(), new PageInfo(), true, false,
|
||||
).pipe(
|
||||
filter(rd => rd.hasCompleted),
|
||||
take(1),
|
||||
map(rd => {
|
||||
return rd.hasSucceeded;
|
||||
}),
|
||||
);
|
||||
const vocabularyName: string = this.getVocabularyEntry();
|
||||
if (hasValue(vocabularyName)) {
|
||||
this.vocabularyExists$ = this.vocabularyService.searchTopEntries(
|
||||
vocabularyName, new PageInfo(), true, false,
|
||||
).pipe(
|
||||
filter(rd => rd.hasCompleted),
|
||||
take(1),
|
||||
map(rd => {
|
||||
return rd.hasSucceeded;
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,11 +99,11 @@ export class SearchHierarchyFilterComponent extends SearchFacetFilterComponent i
|
||||
name: this.getVocabularyEntry(),
|
||||
closed: true
|
||||
};
|
||||
modalRef.result.then((detail: VocabularyEntryDetail) => {
|
||||
this.selectedValues$
|
||||
void modalRef.result.then((detail: VocabularyEntryDetail) => {
|
||||
this.subs.push(this.selectedValues$
|
||||
.pipe(take(1))
|
||||
.subscribe((selectedValues) => {
|
||||
this.router.navigate(
|
||||
void this.router.navigate(
|
||||
[this.searchService.getSearchLink()],
|
||||
{
|
||||
queryParams: {
|
||||
@@ -107,16 +113,16 @@ export class SearchHierarchyFilterComponent extends SearchFacetFilterComponent i
|
||||
queryParamsHandling: 'merge',
|
||||
},
|
||||
);
|
||||
});
|
||||
}).catch();
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the matching vocabulary entry for the given search filter.
|
||||
* These are configurable in the config file.
|
||||
*/
|
||||
getVocabularyEntry() {
|
||||
const foundVocabularyConfig = environment.vocabularies.filter((v) => v.filter === this.filterConfig.name);
|
||||
getVocabularyEntry(): string {
|
||||
const foundVocabularyConfig: FilterVocabularyConfig[] = this.appConfig.vocabularies.filter((v: FilterVocabularyConfig) => v.filter === this.filterConfig.name);
|
||||
if (foundVocabularyConfig.length > 0 && foundVocabularyConfig[0].enabled === true) {
|
||||
return foundVocabularyConfig[0].vocabulary;
|
||||
}
|
||||
|
@@ -85,6 +85,7 @@
|
||||
<ds-themed-search-form *ngIf="searchEnabled" id="search-form"
|
||||
[query]="(searchOptions$ | async)?.query"
|
||||
[scope]="(searchOptions$ | async)?.scope"
|
||||
[hideScopeInUrl]="hideScopeInUrl"
|
||||
[currentUrl]="searchLink"
|
||||
[showScopeSelector]="showScopeSelector"
|
||||
[inPlaceSearch]="inPlaceSearch"
|
||||
|
@@ -33,6 +33,8 @@ import { SearchFilterConfig } from './models/search-filter-config.model';
|
||||
import { FilterType } from './models/filter-type.model';
|
||||
import { getCommunityPageRoute } from '../../community-page/community-page-routing-paths';
|
||||
import { getCollectionPageRoute } from '../../collection-page/collection-page-routing-paths';
|
||||
import { environment } from '../../../environments/environment.test';
|
||||
import { APP_CONFIG } from '../../../config/app-config.interface';
|
||||
|
||||
let comp: SearchComponent;
|
||||
let fixture: ComponentFixture<SearchComponent>;
|
||||
@@ -209,7 +211,8 @@ export function configureSearchComponentTestingModule(compType, additionalDeclar
|
||||
{
|
||||
provide: SEARCH_CONFIG_SERVICE,
|
||||
useValue: searchConfigurationServiceStub
|
||||
}
|
||||
},
|
||||
{ provide: APP_CONFIG, useValue: environment },
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
}).overrideComponent(compType, {
|
||||
|
@@ -31,13 +31,13 @@ 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';
|
||||
import { environment } from 'src/environments/environment';
|
||||
import { SubmissionObject } from '../../core/submission/models/submission-object.model';
|
||||
import { SearchFilterConfig } from './models/search-filter-config.model';
|
||||
import { WorkspaceItem } from '../../core/submission/models/workspaceitem.model';
|
||||
import { ITEM_MODULE_PATH } from '../../item-page/item-page-routing-paths';
|
||||
import { COLLECTION_MODULE_PATH } from '../../collection-page/collection-page-routing-paths';
|
||||
import { COMMUNITY_MODULE_PATH } from '../../community-page/community-page-routing-paths';
|
||||
import { AppConfig, APP_CONFIG } from '../../../config/app-config.interface';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-search',
|
||||
@@ -171,6 +171,11 @@ export class SearchComponent implements OnDestroy, OnInit {
|
||||
*/
|
||||
@Input() scope: string;
|
||||
|
||||
/**
|
||||
* Hides the scope in the url, this can be useful when you hardcode the scope in another way
|
||||
*/
|
||||
@Input() hideScopeInUrl: boolean;
|
||||
|
||||
/**
|
||||
* The current configuration used during the search
|
||||
*/
|
||||
@@ -278,7 +283,9 @@ export class SearchComponent implements OnDestroy, OnInit {
|
||||
protected windowService: HostWindowService,
|
||||
@Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: SearchConfigurationService,
|
||||
protected routeService: RouteService,
|
||||
protected router: Router) {
|
||||
protected router: Router,
|
||||
@Inject(APP_CONFIG) protected appConfig: AppConfig,
|
||||
) {
|
||||
this.isXsOrSm$ = this.windowService.isXsOrSm();
|
||||
}
|
||||
|
||||
@@ -445,8 +452,10 @@ export class SearchComponent implements OnDestroy, OnInit {
|
||||
let followLinks = [
|
||||
followLink<Item>('thumbnail', { isOptional: true }),
|
||||
followLink<SubmissionObject>('item', { isOptional: true }, followLink<Item>('thumbnail', { isOptional: true })) as any,
|
||||
followLink<Item>('accessStatus', { isOptional: true, shouldEmbed: environment.item.showAccessStatuses }),
|
||||
];
|
||||
if (this.appConfig.item.showAccessStatuses) {
|
||||
followLinks.push(followLink<Item>('accessStatus', { isOptional: true }));
|
||||
}
|
||||
if (this.configuration === 'supervision') {
|
||||
followLinks.push(followLink<WorkspaceItem>('supervisionOrders', { isOptional: true }) as any);
|
||||
}
|
||||
@@ -476,18 +485,20 @@ export class SearchComponent implements OnDestroy, OnInit {
|
||||
* This method should only be called once and is essentially what SearchTrackingComponent used to do (now removed)
|
||||
* @private
|
||||
*/
|
||||
private subscribeToRoutingEvents() {
|
||||
this.subs.push(
|
||||
this.router.events.pipe(
|
||||
filter((event) => event instanceof NavigationStart),
|
||||
map((event: NavigationStart) => this.getDsoUUIDFromUrl(event.url)),
|
||||
hasValueOperator(),
|
||||
).subscribe((uuid) => {
|
||||
if (this.resultsRD$.value.hasSucceeded) {
|
||||
this.service.trackSearch(this.searchOptions$.value, this.resultsRD$.value.payload as SearchObjects<DSpaceObject>, uuid);
|
||||
}
|
||||
}),
|
||||
);
|
||||
private subscribeToRoutingEvents(): void {
|
||||
if (this.trackStatistics) {
|
||||
this.subs.push(
|
||||
this.router.events.pipe(
|
||||
filter((event) => event instanceof NavigationStart),
|
||||
map((event: NavigationStart) => this.getDsoUUIDFromUrl(event.url)),
|
||||
hasValueOperator(),
|
||||
).subscribe((uuid) => {
|
||||
if (this.resultsRD$.value.hasSucceeded) {
|
||||
this.service.trackSearch(this.searchOptions$.value, this.resultsRD$.value.payload as SearchObjects<DSpaceObject>, uuid);
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -43,6 +43,7 @@ export class ThemedSearchComponent extends ThemedComponent<SearchComponent> {
|
||||
'trackStatistics',
|
||||
'query',
|
||||
'scope',
|
||||
'hideScopeInUrl',
|
||||
'resultFound',
|
||||
'deselectObject',
|
||||
'selectObject',
|
||||
@@ -94,6 +95,8 @@ export class ThemedSearchComponent extends ThemedComponent<SearchComponent> {
|
||||
|
||||
@Input() scope: string;
|
||||
|
||||
@Input() hideScopeInUrl: boolean;
|
||||
|
||||
@Output() resultFound: EventEmitter<SearchObjects<DSpaceObject>> = new EventEmitter();
|
||||
|
||||
@Output() deselectObject: EventEmitter<ListableObject> = new EventEmitter();
|
||||
|
@@ -3,10 +3,12 @@
|
||||
<div class="row-with-sidebar row-offcanvas row-offcanvas-left"
|
||||
[@pushInOut]="(isSidebarCollapsed$ | async) ? 'collapsed' : 'expanded'">
|
||||
<div id="{{id}}-sidebar-content"
|
||||
[class.invisible]="(isSidebarCollapsed$ | async) === true && (isXsOrSm$ | async) === true"
|
||||
class="col-12 col-md-{{sideBarWidth}} sidebar-content {{sidebarClasses | async}}">
|
||||
<ng-container *ngTemplateOutlet="sidebarContent"></ng-container>
|
||||
</div>
|
||||
<div class="col-12 col-md-{{12 - sideBarWidth}}">
|
||||
<div class="col-12 col-md-{{12 - sideBarWidth}}"
|
||||
[class.invisible]="(isSidebarCollapsed$ | async) === false && (isXsOrSm$ | async) === true">
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -1,19 +1,19 @@
|
||||
import { map } from 'rxjs/operators';
|
||||
import { convertToParamMap, Params } from '@angular/router';
|
||||
|
||||
import { ActivatedRoute, convertToParamMap, Data, Params } from '@angular/router';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
|
||||
export class ActivatedRouteStub {
|
||||
|
||||
private _testParams?: any;
|
||||
private _testData?: any;
|
||||
private _testParams?: Params;
|
||||
private _testData?: Data;
|
||||
// ActivatedRoute.params is Observable
|
||||
private subject?: BehaviorSubject<any> = new BehaviorSubject(this.testParams);
|
||||
private dataSubject?: BehaviorSubject<any> = new BehaviorSubject(this.testData);
|
||||
private subject?: BehaviorSubject<Params> = new BehaviorSubject(this.testParams);
|
||||
private dataSubject?: BehaviorSubject<Data> = new BehaviorSubject(this.testData);
|
||||
|
||||
params = this.subject.asObservable();
|
||||
queryParams = this.subject.asObservable();
|
||||
paramMap = this.subject.asObservable().pipe(map((params: Params) => convertToParamMap(params)));
|
||||
parent: ActivatedRoute | ActivatedRouteStub;
|
||||
queryParamMap = this.subject.asObservable().pipe(map((params: Params) => convertToParamMap(params)));
|
||||
data = this.dataSubject.asObservable();
|
||||
|
||||
@@ -35,17 +35,17 @@ export class ActivatedRouteStub {
|
||||
return this._testParams;
|
||||
}
|
||||
|
||||
set testParams(params: {}) {
|
||||
set testParams(params: Params) {
|
||||
this._testParams = params;
|
||||
this.subject.next(params);
|
||||
}
|
||||
|
||||
// Test data
|
||||
get testData() {
|
||||
return this._testParams;
|
||||
return this._testData;
|
||||
}
|
||||
|
||||
set testData(data: {}) {
|
||||
set testData(data: Data) {
|
||||
this._testData = data;
|
||||
this.dataSubject.next(data);
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Angulartics2 } from 'angulartics2';
|
||||
import { Angulartics2, EventTrack } from 'angulartics2';
|
||||
import { StatisticsService } from '../statistics.service';
|
||||
|
||||
/**
|
||||
@@ -23,7 +23,7 @@ export class Angulartics2DSpace {
|
||||
.subscribe((event) => this.eventTrack(event));
|
||||
}
|
||||
|
||||
private eventTrack(event) {
|
||||
private eventTrack(event: Partial<EventTrack>): void {
|
||||
if (event.action === 'page_view') {
|
||||
this.statisticsService.trackViewEvent(event.properties.object, event.properties.referrer);
|
||||
} else if (event.action === 'search') {
|
||||
@@ -32,7 +32,7 @@ export class Angulartics2DSpace {
|
||||
event.properties.page,
|
||||
event.properties.sort,
|
||||
event.properties.filters,
|
||||
event.properties.clickedObject,
|
||||
event.properties.clickedObject?.split('?')[0],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -1108,9 +1108,7 @@
|
||||
|
||||
"collection.logo": "Collection logo",
|
||||
|
||||
"collection.page.browse.recent.head": "Recent Submissions",
|
||||
|
||||
"collection.page.browse.recent.empty": "No items to show",
|
||||
"collection.page.browse.search.head": "Search",
|
||||
|
||||
"collection.page.edit": "Edit this collection",
|
||||
|
||||
@@ -1120,6 +1118,8 @@
|
||||
|
||||
"collection.page.news": "News",
|
||||
|
||||
"collection.search.results.head": "Search Results",
|
||||
|
||||
"collection.select.confirm": "Confirm selected",
|
||||
|
||||
"collection.select.empty": "No collections to show",
|
||||
@@ -1196,6 +1196,8 @@
|
||||
|
||||
"community.browse.logo": "Browse for a community logo",
|
||||
|
||||
"community.subcoms-cols.breadcrumbs": "Subcommunities and Collections",
|
||||
|
||||
"community.create.head": "Create a Community",
|
||||
|
||||
"community.create.notifications.success": "Successfully created the Community",
|
||||
@@ -1348,6 +1350,8 @@
|
||||
|
||||
"community.all-lists.head": "Subcommunities and Collections",
|
||||
|
||||
"community.search.results.head": "Search Results",
|
||||
|
||||
"community.sub-collection-list.head": "Collections in this Community",
|
||||
|
||||
"community.sub-community-list.head": "Communities in this Community",
|
||||
|
@@ -8,6 +8,7 @@ import { SubmissionConfig } from './submission-config.interface';
|
||||
import { FormConfig } from './form-config.interfaces';
|
||||
import { LangConfig } from './lang-config.interface';
|
||||
import { ItemConfig } from './item-config.interface';
|
||||
import { CommunityPageConfig } from './community-page-config.interface';
|
||||
import { CollectionPageConfig } from './collection-page-config.interface';
|
||||
import { ThemeConfig } from './theme.config';
|
||||
import { AuthConfig } from './auth-config.interfaces';
|
||||
@@ -41,6 +42,7 @@ interface AppConfig extends Config {
|
||||
communityList: CommunityListConfig;
|
||||
homePage: HomeConfig;
|
||||
item: ItemConfig;
|
||||
community: CommunityPageConfig;
|
||||
collection: CollectionPageConfig;
|
||||
themes: ThemeConfig[];
|
||||
mediaViewer: MediaViewerConfig;
|
||||
|
@@ -1,7 +1,18 @@
|
||||
import { Config } from './config.interface';
|
||||
|
||||
/**
|
||||
* Collection Page Config
|
||||
*/
|
||||
export interface CollectionPageConfig extends Config {
|
||||
searchSection: CollectionSearchSectionConfig;
|
||||
edit: {
|
||||
undoTimeout: number;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Config related to the collection's search tab
|
||||
*/
|
||||
export interface CollectionSearchSectionConfig {
|
||||
showSidebar: boolean;
|
||||
}
|
||||
|
15
src/config/community-page-config.interface.ts
Normal file
15
src/config/community-page-config.interface.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Config } from './config.interface';
|
||||
|
||||
/**
|
||||
* Community Page Config
|
||||
*/
|
||||
export interface CommunityPageConfig extends Config {
|
||||
searchSection: CommunitySearchSectionConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Config related to the community's search tab
|
||||
*/
|
||||
export interface CommunitySearchSectionConfig {
|
||||
showSidebar: boolean;
|
||||
}
|
@@ -23,6 +23,7 @@ import { HomeConfig } from './homepage-config.interface';
|
||||
import { MarkdownConfig } from './markdown-config.interface';
|
||||
import { FilterVocabularyConfig } from './filter-vocabulary-config';
|
||||
import { DiscoverySortConfig } from './discovery-sort.config';
|
||||
import { CommunityPageConfig } from './community-page-config.interface';
|
||||
import {QualityAssuranceConfig} from './quality-assurance.config';
|
||||
|
||||
export class DefaultAppConfig implements AppConfig {
|
||||
@@ -291,8 +292,18 @@ export class DefaultAppConfig implements AppConfig {
|
||||
}
|
||||
};
|
||||
|
||||
// Community Page Config
|
||||
community: CommunityPageConfig = {
|
||||
searchSection: {
|
||||
showSidebar: true,
|
||||
},
|
||||
};
|
||||
|
||||
// Collection Page Config
|
||||
collection: CollectionPageConfig = {
|
||||
searchSection: {
|
||||
showSidebar: true,
|
||||
},
|
||||
edit: {
|
||||
undoTimeout: 10000 // 10 seconds
|
||||
}
|
||||
|
@@ -257,7 +257,15 @@ export const environment: BuildConfig = {
|
||||
pageSize: 5
|
||||
}
|
||||
},
|
||||
community: {
|
||||
searchSection: {
|
||||
showSidebar: true,
|
||||
},
|
||||
},
|
||||
collection: {
|
||||
searchSection: {
|
||||
showSidebar: true,
|
||||
},
|
||||
edit: {
|
||||
undoTimeout: 10000 // 10 seconds
|
||||
}
|
||||
|
Reference in New Issue
Block a user