Skip to content

Commit 31aa680

Browse files
committed
Merged dspace-cris-7 into DSC-1023
2 parents 2f33b32 + 588bbe5 commit 31aa680

File tree

59 files changed

+776
-468
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+776
-468
lines changed

src/app/app-routing-paths.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,4 +142,11 @@ export function getEditItemPageRoute() {
142142
export function getSubscriptionsModuleRoute() {
143143
return `/${SUBSCRIPTIONS_MODULE_PATH}`;
144144
}
145+
145146
export const SUBSCRIPTIONS_MODULE_PATH = 'subscriptions';
147+
148+
export const STATISTICS_PAGE_PATH = 'statistics';
149+
150+
export function getStatisticsModuleRoute() {
151+
return `/${STATISTICS_PAGE_PATH}`;
152+
}

src/app/app-routing.module.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { NgModule } from '@angular/core';
2-
import { RouterModule, NoPreloading } from '@angular/router';
2+
import { NoPreloading, RouterModule } from '@angular/router';
33
import { AuthBlockingGuard } from './core/auth/auth-blocking.guard';
44

55
import { AuthenticatedGuard } from './core/auth/authenticated.guard';
@@ -10,9 +10,9 @@ import {
1010
ACCESS_CONTROL_MODULE_PATH,
1111
ADMIN_MODULE_PATH,
1212
BITSTREAM_MODULE_PATH,
13-
ERROR_PAGE,
1413
BULK_IMPORT_PATH,
1514
EDIT_ITEM_PATH,
15+
ERROR_PAGE,
1616
FORBIDDEN_PATH,
1717
FORGOT_PASSWORD_PATH,
1818
HEALTH_PAGE_PATH,
@@ -22,6 +22,7 @@ import {
2222
PROFILE_MODULE_PATH,
2323
REGISTER_PATH,
2424
REQUEST_COPY_MODULE_PATH,
25+
STATISTICS_PAGE_PATH,
2526
WORKFLOW_ITEM_MODULE_PATH,
2627
} from './app-routing-paths';
2728
import { COLLECTION_MODULE_PATH } from './collection-page/collection-page-routing-paths';
@@ -43,7 +44,7 @@ import { ServerCheckGuard } from './core/server-check/server-check.guard';
4344
import { MenuResolver } from './menu.resolver';
4445
import { ThemedPageErrorComponent } from './page-error/themed-page-error.component';
4546
import { SUGGESTION_MODULE_PATH } from './suggestions-page/suggestions-page-routing-paths';
46-
import { StatisticsAdministratorGuard } from './core/data/feature-authorization/feature-authorization-guard/statistics-administrator.guard';
47+
import { RedirectService } from './redirect/redirect.service';
4748

4849
@NgModule({
4950
imports: [
@@ -247,7 +248,7 @@ import { StatisticsAdministratorGuard } from './core/data/feature-authorization/
247248
component: ThemedForbiddenComponent
248249
},
249250
{
250-
path: 'statistics',
251+
path: STATISTICS_PAGE_PATH,
251252
loadChildren: () => import('./statistics-page/statistics-page-routing.module')
252253
.then((m) => m.StatisticsPageRoutingModule),
253254
},
@@ -282,7 +283,7 @@ import { StatisticsAdministratorGuard } from './core/data/feature-authorization/
282283
loadChildren: () => import('./invitation/invitation.module')
283284
.then((m) => m.InvitationModule)
284285
},
285-
{ path: '**', pathMatch: 'full', component: ThemedPageNotFoundComponent },
286+
{ path: '**', pathMatch: 'full', component: ThemedPageNotFoundComponent, canActivate: [RedirectService] },
286287
]
287288
}
288289
], {

src/app/core/data/base/search-data.spec.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@
88
import { constructSearchEndpointDefault, SearchData, SearchDataImpl } from './search-data';
99
import { FindListOptions } from '../find-list-options.model';
1010
import { followLink } from '../../../shared/utils/follow-link-config.model';
11-
import { of as observableOf } from 'rxjs';
11+
import { of, of as observableOf } from 'rxjs';
1212
import { getMockRequestService } from '../../../shared/mocks/request.service.mock';
1313
import { getMockRemoteDataBuildService } from '../../../shared/mocks/remote-data-build.service.mock';
14+
import { TestScheduler } from 'rxjs/testing';
15+
import { RemoteData } from '../remote-data';
16+
import { RequestEntryState } from '../request-entry-state.model';
1417

1518
/**
1619
* Tests whether calls to `SearchData` methods are correctly patched through in a concrete data service that implements it
@@ -19,6 +22,12 @@ export function testSearchDataImplementation(serviceFactory: () => SearchData<an
1922
let service;
2023

2124
describe('SearchData implementation', () => {
25+
let testScheduler: TestScheduler;
26+
const searchByResp = Object.assign(
27+
new RemoteData(0, 0, 0, undefined, undefined, {}, 200),
28+
{ state: RequestEntryState.Success, payload: 'TEST searchBy' }
29+
);
30+
const searchByResp$ = of(searchByResp);
2231
const OPTIONS = Object.assign(new FindListOptions(), { elementsPerPage: 10, currentPage: 3 });
2332
const FOLLOWLINKS = [
2433
followLink('test'),
@@ -27,16 +36,27 @@ export function testSearchDataImplementation(serviceFactory: () => SearchData<an
2736

2837
beforeAll(() => {
2938
service = serviceFactory();
30-
(service as any).searchData = jasmine.createSpyObj('searchData', {
31-
searchBy: 'TEST searchBy',
39+
(service as any).searchData = jasmine.createSpyObj('searchData', ['searchBy']);
40+
service.searchData.searchBy.and.returnValue(searchByResp$);
41+
});
42+
43+
beforeEach(() => {
44+
testScheduler = new TestScheduler((actual, expected) => {
45+
return expect(actual).toEqual(expected);
3246
});
3347
});
3448

3549
it('should handle calls to searchBy', () => {
50+
const expectedMarbles = '(a|)';
51+
const expectedValues = {
52+
a: searchByResp
53+
};
3654
const out: any = service.searchBy('searchMethod', OPTIONS, false, true, ...FOLLOWLINKS);
3755

3856
expect((service as any).searchData.searchBy).toHaveBeenCalledWith('searchMethod', OPTIONS, false, true, ...FOLLOWLINKS);
39-
expect(out).toBe('TEST searchBy');
57+
testScheduler.run(({ expectObservable }) => {
58+
expectObservable(out).toBe(expectedMarbles, expectedValues);
59+
});
4060
});
4161
});
4262
}

src/app/core/data/bitstream-data.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ export class BitstreamDataService extends IdentifiableDataService<Bitstream> imp
352352
uuid: string,
353353
bundlename: string,
354354
metadataFilters: MetadataFilter[],
355-
options: FindListOptions,
355+
options?: FindListOptions,
356356
useCachedVersionIfAvailable = true,
357357
reRequestOnStale = true,
358358
...linksToFollow: FollowLinkConfig<Bitstream>[]
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { ExportAsConfig, ExportAsService } from 'ngx-export-as';
2+
import { toJpeg, toPng } from 'html-to-image';
3+
import { Options } from 'html-to-image/es/types';
4+
import { saveAs } from 'file-saver';
5+
import { BehaviorSubject } from 'rxjs';
6+
7+
import { ExportImageType, ExportService } from './export.service';
8+
9+
/**
10+
* IMPORTANT
11+
* Due to a problem occurring on SSR with the ExportAsService dependency, which use window object, this service can't be injected.
12+
* So we need to instantiate the class directly based on current the platform whn is needed
13+
* TODO To be refactored when https://github.com/wnabil/ngx-export-as/pull/112 is fixed
14+
*/
15+
export class BrowserExportService implements ExportService {
16+
17+
/**
18+
* Configuration for CSV export process
19+
*/
20+
exportAsConfig: ExportAsConfig;
21+
22+
/**
23+
* Creates excel from the table element reference.
24+
*
25+
* @param type of export.
26+
* @param fileName is the file name to save as.
27+
* @param elementIdOrContent is the content that is being exported.
28+
* @param download option if it's going to be downloaded.
29+
*/
30+
exportAsFile(type: any, elementIdOrContent: string, fileName: string, download: boolean = true) {
31+
32+
this.exportAsConfig = {
33+
type:type,
34+
elementIdOrContent: elementIdOrContent,
35+
fileName:fileName,
36+
download:download
37+
};
38+
39+
const exportAsService: ExportAsService = new ExportAsService();
40+
return exportAsService.save(this.exportAsConfig, fileName);
41+
}
42+
43+
/**
44+
* Creates an image from the given element reference.
45+
*
46+
* @param domNode The HTMLElement.
47+
* @param type The type of image to export.
48+
* @param fileName The file name to save as.
49+
* @param isLoading A boolean representing the exporting process status.
50+
*/
51+
exportAsImage(domNode: HTMLElement, type: ExportImageType, fileName: string, isLoading: BehaviorSubject<boolean>): void {
52+
53+
const options: Options = { backgroundColor: '#ffffff' };
54+
55+
if (type === ExportImageType.png) {
56+
toPng(domNode, options)
57+
.then((dataUrl) => {
58+
saveAs(dataUrl, fileName + '.' + type);
59+
isLoading.next(false);
60+
});
61+
} else {
62+
toJpeg(domNode, options)
63+
.then((dataUrl) => {
64+
saveAs(dataUrl, fileName + '.' + type);
65+
isLoading.next(false);
66+
});
67+
}
68+
69+
}
70+
71+
}
Lines changed: 4 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,21 @@
1-
import { Injectable } from '@angular/core';
2-
3-
import { ExportAsConfig, ExportAsService } from 'ngx-export-as';
4-
import { toJpeg, toPng } from 'html-to-image';
5-
import { Options } from 'html-to-image/es/types';
6-
import { saveAs } from 'file-saver';
71
import { BehaviorSubject } from 'rxjs';
82

93
export enum ExportImageType {
104
png = 'png',
115
jpeg = 'jpeg',
126
}
137

14-
@Injectable()
15-
export class ExportService {
16-
17-
/**
18-
* Configuration for CSV export process
19-
*/
20-
exportAsConfig: ExportAsConfig;
21-
22-
constructor(private exportAsService: ExportAsService) { }
8+
export interface ExportService {
239

2410
/**
2511
* Creates excel from the table element reference.
2612
*
2713
* @param type of export.
2814
* @param fileName is the file name to save as.
2915
* @param elementIdOrContent is the content that is being exported.
30-
* @param download option if its going to be downloaded.
16+
* @param download option if it's going to be downloaded.
3117
*/
32-
exportAsFile(type: any, elementIdOrContent: string, fileName: string, download: boolean = true) {
33-
34-
this.exportAsConfig = {
35-
type:type,
36-
elementIdOrContent: elementIdOrContent,
37-
fileName:fileName,
38-
download:download
39-
};
40-
41-
return this.exportAsService.save(this.exportAsConfig, fileName);
42-
}
18+
exportAsFile(type: any, elementIdOrContent: string, fileName: string, download?: boolean);
4319

4420
/**
4521
* Creates an image from the given element reference.
@@ -49,24 +25,5 @@ export class ExportService {
4925
* @param fileName The file name to save as.
5026
* @param isLoading A boolean representing the exporting process status.
5127
*/
52-
exportAsImage(domNode: HTMLElement, type: ExportImageType, fileName: string, isLoading: BehaviorSubject<boolean>): void {
53-
54-
const options: Options = { backgroundColor: '#ffffff' };
55-
56-
if (type === ExportImageType.png) {
57-
toPng(domNode, options)
58-
.then((dataUrl) => {
59-
saveAs(dataUrl, fileName + '.' + type);
60-
isLoading.next(false);
61-
});
62-
} else {
63-
toJpeg(domNode, options)
64-
.then((dataUrl) => {
65-
saveAs(dataUrl, fileName + '.' + type);
66-
isLoading.next(false);
67-
});
68-
}
69-
70-
}
71-
28+
exportAsImage(domNode: HTMLElement, type: ExportImageType, fileName: string, isLoading: BehaviorSubject<boolean>);
7229
}

src/app/core/export-service/server-export.service.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
1-
import { Injectable } from '@angular/core';
2-
31
import { BehaviorSubject } from 'rxjs';
42

5-
import { ExportImageType } from './export.service';
3+
import { ExportImageType, ExportService } from './export.service';
64

7-
@Injectable()
8-
export class ServerExportService {
5+
export class ServerExportService implements ExportService {
96
/**
107
* Creates excel from the table element reference.
118
*
129
* @param type of export.
1310
* @param fileName is the file name to save as.
1411
* @param elementIdOrContent is the content that is being exported.
15-
* @param download option if its going to be downloaded.
12+
* @param download option if it'ss going to be downloaded.
1613
*/
1714
exportAsFile(type: any, elementIdOrContent: string, fileName: string, download: boolean = true) {
1815
return;

src/app/core/statistics/usage-report-data.service.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ export class UsageReportDataService extends IdentifiableDataService<UsageReport>
7979
}
8080

8181
public searchBy(searchMethod: string, options?: FindListOptions, useCachedVersionIfAvailable?: boolean, reRequestOnStale?: boolean, ...linksToFollow: FollowLinkConfig<UsageReport>[]): Observable<RemoteData<PaginatedList<UsageReport>>> {
82-
return this.searchData.searchBy(searchMethod, options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow);
82+
return this.searchData.searchBy(searchMethod, options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow).pipe(
83+
getFirstSucceededRemoteData()
84+
);
8385
}
8486
}

src/app/cris-layout/cris-layout-matrix/cris-layout-box-container/boxes/metadata/row/metadata-container/metadata-container.component.spec.ts

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ describe('MetadataContainerComponent', () => {
145145
});
146146

147147
const mockBitstreamDataService = jasmine.createSpyObj('BitstreamDataService', {
148-
findAllByItemAndBundleName: jasmine.createSpy('findAllByItemAndBundleName')
148+
findShowableBitstreamsByItem: jasmine.createSpy('findShowableBitstreamsByItem')
149149
});
150150

151151
beforeEach(async () => {
@@ -172,7 +172,10 @@ describe('MetadataContainerComponent', () => {
172172
component = fixture.componentInstance;
173173
component.item = testItem;
174174
component.box = boxMetadata;
175-
mockBitstreamDataService.findAllByItemAndBundleName.and.returnValue(createSuccessfulRemoteDataObject$(createPaginatedList([])));
175+
176+
mockBitstreamDataService.findShowableBitstreamsByItem.and.returnValue(
177+
createSuccessfulRemoteDataObject$(createPaginatedList([]))
178+
);
176179
});
177180

178181
describe('When field rendering type is not structured', () => {
@@ -283,15 +286,15 @@ describe('MetadataContainerComponent', () => {
283286
describe('and item has bitstream', () => {
284287

285288
beforeEach(() => {
286-
mockBitstreamDataService.findAllByItemAndBundleName.and.returnValue(createSuccessfulRemoteDataObject$(createPaginatedList([bitstream1])));
289+
mockBitstreamDataService.findShowableBitstreamsByItem.and.returnValue(createSuccessfulRemoteDataObject$(createPaginatedList([bitstream1])));
287290
fixture.detectChanges();
288291
});
289292

290293
it('should create', () => {
291294
expect(component).toBeTruthy();
292295
});
293296

294-
it('should not render metadata ', (done) => {
297+
it('should render metadata ', (done) => {
295298
const spanValueFound = fixture.debugElement.queryAll(By.css('.test-style-label'));
296299
expect(spanValueFound.length).toBe(1);
297300

@@ -301,6 +304,35 @@ describe('MetadataContainerComponent', () => {
301304
});
302305
});
303306

307+
describe('and bitstream has metadata', () => {
308+
beforeEach(() => {
309+
component.field.bitstream.metadataField = 'metadataFieldTest';
310+
component.field.bitstream.metadataValue = 'metadataValueTest';
311+
fixture.detectChanges();
312+
});
313+
314+
it('should use the metadata in filters', () => {
315+
expect(mockBitstreamDataService.findShowableBitstreamsByItem).toHaveBeenCalledWith(
316+
testItem.uuid,
317+
bitstreamField.bitstream.bundle,
318+
[ { metadataName: 'metadataFieldTest', metadataValue: 'metadataValueTest' } ]
319+
);
320+
});
321+
});
322+
323+
describe('and bitstream doesnt have metadataValue', () => {
324+
beforeEach(() => {
325+
component.field.bitstream.metadataValue = undefined;
326+
fixture.detectChanges();
327+
});
328+
329+
it('should use empty array in filters', () => {
330+
expect(mockBitstreamDataService.findShowableBitstreamsByItem).toHaveBeenCalledWith(
331+
testItem.uuid,
332+
bitstreamField.bitstream.bundle,
333+
[] // <--- empty array of filters
334+
);
335+
});
336+
});
304337
});
305-
})
306-
;
338+
});

0 commit comments

Comments
 (0)