diff --git a/mock-nodemon.json b/mock-nodemon.json new file mode 100644 index 0000000000..18fc86bd9d --- /dev/null +++ b/mock-nodemon.json @@ -0,0 +1,5 @@ +{ + "watch": ["src/environments/mock-environment.ts"], + "ext": "ts", + "exec": "ts-node --project ./tsconfig.ts-node.json scripts/set-mock-env.ts" +} diff --git a/nodemon.json b/nodemon.json index c1b149691c..39e9d9aa5b 100644 --- a/nodemon.json +++ b/nodemon.json @@ -1,6 +1,6 @@ { "watch": ["src/environments"], "ext": "ts", - "ignore": ["src/environments/environment.ts"], + "ignore": ["src/environments/environment.ts", "src/environments/mock-environment.ts"], "exec": "ts-node --project ./tsconfig.ts-node.json scripts/set-env.ts --dev" } diff --git a/package.json b/package.json index 27f33ee515..6fd39420b5 100644 --- a/package.json +++ b/package.json @@ -5,11 +5,13 @@ "ng": "ng", "config:dev": "ts-node --project ./tsconfig.ts-node.json scripts/set-env.ts --dev", "config:prod": "ts-node --project ./tsconfig.ts-node.json scripts/set-env.ts --prod", - "config:test": "ts-node --project ./tsconfig.ts-node.json scripts/set-env.ts --test", + "config:test": "ts-node --project ./tsconfig.ts-node.json scripts/set-mock-env.ts", + "config:test:watch": "nodemon --config mock-nodemon.json", "config:dev:watch": "nodemon", "prestart:dev": "yarn run config:dev", "prebuild": "yarn run config:dev", "pretest": "yarn run config:test", + "pretest:watch": "yarn run config:test", "pretest:headless": "yarn run config:test", "prebuild:prod": "yarn run config:prod", "pree2e": "yarn run config:prod", @@ -22,7 +24,8 @@ "build:prod": "yarn run build:ssr", "build:ssr": "yarn run build:client-and-server-bundles && yarn run compile:server", "build:client-and-server-bundles": "node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng build --prod && ng run dspace-angular-cli:server:production --bundleDependencies all", - "test": "node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng test --sourceMap=true", + "test:watch": "npm-run-all --parallel config:test:watch test", + "test": "node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng test --sourceMap=true --watch=true", "test:headless": "node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng test --watch=false --sourceMap=true --browsers=ChromeHeadless --code-coverage", "lint": "ng lint", "e2e": "ng e2e", diff --git a/scripts/set-mock-env.ts b/scripts/set-mock-env.ts new file mode 100644 index 0000000000..5271432896 --- /dev/null +++ b/scripts/set-mock-env.ts @@ -0,0 +1,11 @@ +import { copyFile } from 'fs'; + +// Configure Angular `environment.ts` file path +const sourcePath = './src/environments/mock-environment.ts'; +const targetPath = './src/environments/environment.ts'; + +// destination.txt will be created or overwritten by default. +copyFile(sourcePath, targetPath, (err) => { + if (err) throw err; + console.log(sourcePath + ' was copied to ' + targetPath); +}); diff --git a/src/app/community-list-page/community-list-service.spec.ts b/src/app/community-list-page/community-list-service.spec.ts index 3589f55952..6b7ab2bd77 100644 --- a/src/app/community-list-page/community-list-service.spec.ts +++ b/src/app/community-list-page/community-list-service.spec.ts @@ -22,99 +22,110 @@ describe('CommunityListService', () => { const standardElementsPerPage = 2; let collectionDataServiceStub: any; let communityDataServiceStub: any; - const mockSubcommunities1Page1 = [Object.assign(new Community(), { - id: 'ce64f48e-2c9b-411a-ac36-ee429c0e6a88', - uuid: 'ce64f48e-2c9b-411a-ac36-ee429c0e6a88', - }), - Object.assign(new Community(), { - id: '59ee713b-ee53-4220-8c3f-9860dc84fe33', - uuid: '59ee713b-ee53-4220-8c3f-9860dc84fe33', - }) - ]; - const mockCollectionsPage1 = [ - Object.assign(new Collection(), { - id: 'e9dbf393-7127-415f-8919-55be34a6e9ed', - uuid: 'e9dbf393-7127-415f-8919-55be34a6e9ed', - name: 'Collection 1' - }), - Object.assign(new Collection(), { - id: '59da2ff0-9bf4-45bf-88be-e35abd33f304', - uuid: '59da2ff0-9bf4-45bf-88be-e35abd33f304', - name: 'Collection 2' - }) - ]; - const mockCollectionsPage2 = [ - Object.assign(new Collection(), { - id: 'a5159760-f362-4659-9e81-e3253ad91ede', - uuid: 'a5159760-f362-4659-9e81-e3253ad91ede', - name: 'Collection 3' - }), - Object.assign(new Collection(), { - id: 'a392e16b-fcf2-400a-9a88-53ef7ecbdcd3', - uuid: 'a392e16b-fcf2-400a-9a88-53ef7ecbdcd3', - name: 'Collection 4' - }) - ]; - const mockListOfTopCommunitiesPage1 = [ - Object.assign(new Community(), { - id: '7669c72a-3f2a-451f-a3b9-9210e7a4c02f', - uuid: '7669c72a-3f2a-451f-a3b9-9210e7a4c02f', - subcommunities: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), mockSubcommunities1Page1)), - collections: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), - }), - Object.assign(new Community(), { - id: '9076bd16-e69a-48d6-9e41-0238cb40d863', - uuid: '9076bd16-e69a-48d6-9e41-0238cb40d863', - subcommunities: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), - collections: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [...mockCollectionsPage1, ...mockCollectionsPage2])), - }), - Object.assign(new Community(), { - id: 'efbf25e1-2d8c-4c28-8f3e-2e04c215be24', - uuid: 'efbf25e1-2d8c-4c28-8f3e-2e04c215be24', - subcommunities: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), - collections: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), - }), - ]; - const mockListOfTopCommunitiesPage2 = [ - Object.assign(new Community(), { - id: 'c2e04392-3b8a-4dfa-976d-d76fb1b8a4b6', - uuid: 'c2e04392-3b8a-4dfa-976d-d76fb1b8a4b6', - subcommunities: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), - collections: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), - }), - ]; - const mockTopCommunitiesWithChildrenArraysPage1 = [ - { - id: '7669c72a-3f2a-451f-a3b9-9210e7a4c02f', - uuid: '7669c72a-3f2a-451f-a3b9-9210e7a4c02f', - subcommunities: mockSubcommunities1Page1, - collections: [], - }, - { - id: '9076bd16-e69a-48d6-9e41-0238cb40d863', - uuid: '9076bd16-e69a-48d6-9e41-0238cb40d863', - subcommunities: [], - collections: [...mockCollectionsPage1, ...mockCollectionsPage2], - }, - { - id: 'efbf25e1-2d8c-4c28-8f3e-2e04c215be24', - uuid: 'efbf25e1-2d8c-4c28-8f3e-2e04c215be24', - subcommunities: [], - collections: [], - }]; - const mockTopCommunitiesWithChildrenArraysPage2 = [ - { - id: 'c2e04392-3b8a-4dfa-976d-d76fb1b8a4b6', - uuid: 'c2e04392-3b8a-4dfa-976d-d76fb1b8a4b6', - subcommunities: [], - collections: [], - }]; - - const allCommunities = [...mockTopCommunitiesWithChildrenArraysPage1, ...mockTopCommunitiesWithChildrenArraysPage2, ...mockSubcommunities1Page1]; let service: CommunityListService; + let mockSubcommunities1Page1; + let mockCollectionsPage1; + let mockCollectionsPage2; + let mockListOfTopCommunitiesPage1; + let mockListOfTopCommunitiesPage2; + let mockTopCommunitiesWithChildrenArraysPage1; + let mockTopCommunitiesWithChildrenArraysPage2; + let allCommunities; + function init() { + mockSubcommunities1Page1 = [Object.assign(new Community(), { + id: 'ce64f48e-2c9b-411a-ac36-ee429c0e6a88', + uuid: 'ce64f48e-2c9b-411a-ac36-ee429c0e6a88', + }), + Object.assign(new Community(), { + id: '59ee713b-ee53-4220-8c3f-9860dc84fe33', + uuid: '59ee713b-ee53-4220-8c3f-9860dc84fe33', + }) + ]; + mockCollectionsPage1 = [ + Object.assign(new Collection(), { + id: 'e9dbf393-7127-415f-8919-55be34a6e9ed', + uuid: 'e9dbf393-7127-415f-8919-55be34a6e9ed', + name: 'Collection 1' + }), + Object.assign(new Collection(), { + id: '59da2ff0-9bf4-45bf-88be-e35abd33f304', + uuid: '59da2ff0-9bf4-45bf-88be-e35abd33f304', + name: 'Collection 2' + }) + ]; + mockCollectionsPage2 = [ + Object.assign(new Collection(), { + id: 'a5159760-f362-4659-9e81-e3253ad91ede', + uuid: 'a5159760-f362-4659-9e81-e3253ad91ede', + name: 'Collection 3' + }), + Object.assign(new Collection(), { + id: 'a392e16b-fcf2-400a-9a88-53ef7ecbdcd3', + uuid: 'a392e16b-fcf2-400a-9a88-53ef7ecbdcd3', + name: 'Collection 4' + }) + ]; + mockListOfTopCommunitiesPage1 = [ + Object.assign(new Community(), { + id: '7669c72a-3f2a-451f-a3b9-9210e7a4c02f', + uuid: '7669c72a-3f2a-451f-a3b9-9210e7a4c02f', + subcommunities: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), mockSubcommunities1Page1)), + collections: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), + }), + Object.assign(new Community(), { + id: '9076bd16-e69a-48d6-9e41-0238cb40d863', + uuid: '9076bd16-e69a-48d6-9e41-0238cb40d863', + subcommunities: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), + collections: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [...mockCollectionsPage1, ...mockCollectionsPage2])), + }), + Object.assign(new Community(), { + id: 'efbf25e1-2d8c-4c28-8f3e-2e04c215be24', + uuid: 'efbf25e1-2d8c-4c28-8f3e-2e04c215be24', + subcommunities: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), + collections: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), + }), + ]; + mockListOfTopCommunitiesPage2 = [ + Object.assign(new Community(), { + id: 'c2e04392-3b8a-4dfa-976d-d76fb1b8a4b6', + uuid: 'c2e04392-3b8a-4dfa-976d-d76fb1b8a4b6', + subcommunities: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), + collections: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), + }), + ]; + mockTopCommunitiesWithChildrenArraysPage1 = [ + { + id: '7669c72a-3f2a-451f-a3b9-9210e7a4c02f', + uuid: '7669c72a-3f2a-451f-a3b9-9210e7a4c02f', + subcommunities: mockSubcommunities1Page1, + collections: [], + }, + { + id: '9076bd16-e69a-48d6-9e41-0238cb40d863', + uuid: '9076bd16-e69a-48d6-9e41-0238cb40d863', + subcommunities: [], + collections: [...mockCollectionsPage1, ...mockCollectionsPage2], + }, + { + id: 'efbf25e1-2d8c-4c28-8f3e-2e04c215be24', + uuid: 'efbf25e1-2d8c-4c28-8f3e-2e04c215be24', + subcommunities: [], + collections: [], + }]; + mockTopCommunitiesWithChildrenArraysPage2 = [ + { + id: 'c2e04392-3b8a-4dfa-976d-d76fb1b8a4b6', + uuid: 'c2e04392-3b8a-4dfa-976d-d76fb1b8a4b6', + subcommunities: [], + collections: [], + }]; - beforeEach(async(() => { + allCommunities = [...mockTopCommunitiesWithChildrenArraysPage1, ...mockTopCommunitiesWithChildrenArraysPage2, ...mockSubcommunities1Page1]; + + } + beforeEach(() => { + init(); communityDataServiceStub = { findTop(options: FindListOptions = {}) { const allTopComs = [...mockListOfTopCommunitiesPage1, ...mockListOfTopCommunitiesPage2]; @@ -188,7 +199,7 @@ describe('CommunityListService', () => { }); store = TestBed.get(Store); service = new CommunityListService(communityDataServiceStub, collectionDataServiceStub, store); - })); + }); it('should create', inject([CommunityListService], (serviceIn: CommunityListService) => { expect(serviceIn).toBeTruthy(); @@ -316,7 +327,10 @@ describe('CommunityListService', () => { describe('transformListOfCommunities', () => { describe('should transform list of communities in a list of flatnodes with possible subcoms and collections as subflatnodes if they\'re expanded', () => { describe('list of communities with possible children', () => { - const listOfCommunities = mockListOfTopCommunitiesPage1; + let listOfCommunities; + beforeEach(() => { + listOfCommunities = mockListOfTopCommunitiesPage1; + }); let flatNodeList; describe('None expanded: should return list containing only flatnodes of the communities in the test list', () => { beforeEach(() => { @@ -469,18 +483,19 @@ describe('CommunityListService', () => { }); describe('topcommunity with collections, expanded, on second page of collections', () => { describe('should return list containing flatnodes of that community, its collections of the first two pages', () => { - const communityWithCollections = Object.assign(new Community(), { - id: '9076bd16-e69a-48d6-9e41-0238cb40d863', - uuid: '9076bd16-e69a-48d6-9e41-0238cb40d863', - subcommunities: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), - collections: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [...mockCollectionsPage1, ...mockCollectionsPage2])), - metadata: { - 'dc.description': [{ language: 'en_US', value: '2 subcoms, no coll' }], - 'dc.title': [{ language: 'en_US', value: 'Community 1' }] - } - }); + let communityWithCollections; let flatNodeList; beforeEach(() => { + communityWithCollections = Object.assign(new Community(), { + id: '9076bd16-e69a-48d6-9e41-0238cb40d863', + uuid: '9076bd16-e69a-48d6-9e41-0238cb40d863', + subcommunities: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), + collections: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [...mockCollectionsPage1, ...mockCollectionsPage2])), + metadata: { + 'dc.description': [{ language: 'en_US', value: '2 subcoms, no coll' }], + 'dc.title': [{ language: 'en_US', value: 'Community 1' }] + } + }); const communityFlatNode = toFlatNode(communityWithCollections, observableOf(true), 0, true, null); communityFlatNode.currentCollectionPage = 2; communityFlatNode.currentCommunityPage = 1; diff --git a/src/app/core/shared/hal-endpoint.service.spec.ts b/src/app/core/shared/hal-endpoint.service.spec.ts index 5b0c860af2..5f5c31f29d 100644 --- a/src/app/core/shared/hal-endpoint.service.spec.ts +++ b/src/app/core/shared/hal-endpoint.service.spec.ts @@ -59,7 +59,6 @@ describe('HALEndpointService', () => { }); describe('getRootEndpointMap', () => { - it('should configure a new EndpointMapRequest', () => { (service as any).getRootEndpointMap(); const expected = new EndpointMapRequest(requestService.generateRequestId(), environment.rest.baseUrl); diff --git a/src/app/core/url-combiner/url-combiner.ts b/src/app/core/url-combiner/url-combiner.ts index e7468c6107..d294539ca4 100644 --- a/src/app/core/url-combiner/url-combiner.ts +++ b/src/app/core/url-combiner/url-combiner.ts @@ -30,6 +30,8 @@ export class URLCombiner { * The combined URL */ toString(): string { + debugger; + if (isEmpty(this.parts)) { return ''; } else { diff --git a/src/app/shared/mocks/dspace-rest-v2/endpoint-mocking-rest.service.spec.ts b/src/app/shared/mocks/dspace-rest-v2/endpoint-mocking-rest.service.spec.ts index ce3af5006c..c35713669f 100644 --- a/src/app/shared/mocks/dspace-rest-v2/endpoint-mocking-rest.service.spec.ts +++ b/src/app/shared/mocks/dspace-rest-v2/endpoint-mocking-rest.service.spec.ts @@ -7,17 +7,21 @@ import { ResponseMapMock } from './mocks/response-map.mock'; describe('EndpointMockingRestService', () => { let service: EndpointMockingRestService; - const serverHttpResponse: HttpResponse = { - body: { bar: false }, - headers: new HttpHeaders(), - statusText: '200' - } as HttpResponse; + let serverHttpResponse: HttpResponse; - const mockResponseMap: ResponseMapMock = new Map([ - [ '/foo', { bar: true } ] - ]); + let mockResponseMap: ResponseMapMock; beforeEach(() => { + serverHttpResponse = { + body: { bar: false }, + headers: new HttpHeaders(), + statusText: '200' + } as HttpResponse; + + mockResponseMap = new Map([ + [ '/foo', { bar: true } ] + ]); + const httpStub = jasmine.createSpyObj('http', { get: observableOf(serverHttpResponse), request: observableOf(serverHttpResponse) diff --git a/src/environments/environment.test.ts b/src/environments/environment.test.ts deleted file mode 100644 index 566e6dec49..0000000000 --- a/src/environments/environment.test.ts +++ /dev/null @@ -1,82 +0,0 @@ -// This configuration is currently only being used for unit tests, end-to-end tests use environment.dev.ts -import { GlobalConfig } from '../config/global-config.interface'; - -export const environment: Partial = { - rest: { - ssl: true, - host: 'rest.com', - port: 443, - // NOTE: Space is capitalized because 'namespace' is a reserved string in TypeScript - nameSpace: '/api' - }, - ui: { - ssl: false, - host: 'dspace.com', - port: 80, - // NOTE: Space is capitalized because 'namespace' is a reserved string in TypeScript - nameSpace: '/angular-dspace', - }, - item: { - edit: { - undoTimeout: 10 - } - }, - submission: { - autosave: { - // NOTE: which metadata trigger an autosave - metadata: ['dc.title', 'dc.identifier.doi', 'dc.identifier.pmid', 'dc.identifier.arxiv'], - // NOTE: every how many minutes submission is saved automatically - timer: 5 - }, - icons: { - metadata: [ - { - name: 'mainField', - style: 'fas fa-user' - }, - { - name: 'relatedField', - style: 'fas fa-university' - }, - { - name: 'otherRelatedField', - style: 'fas fa-circle' - }, - { - name: 'default', - style: '' - } - ], - authority: { - confidence: [ - { - value: 600, - style: 'text-success' - }, - { - value: 500, - style: 'text-info' - }, - { - value: 400, - style: 'text-warning' - }, - { - value: 'default', - style: 'text-muted' - }, - - ] - } - } - }, - languages: [{ - code: 'en', - label: 'English', - active: true, - }, { - code: 'de', - label: 'Deutsch', - active: true, - }] -}; diff --git a/src/environments/mock-environment.ts b/src/environments/mock-environment.ts new file mode 100644 index 0000000000..7bf6d6c846 --- /dev/null +++ b/src/environments/mock-environment.ts @@ -0,0 +1,199 @@ +// This configuration is only used for unit tests, end-to-end tests use environment.prod.ts +import { BrowseByType } from '../app/+browse-by/+browse-by-switcher/browse-by-decorator'; +import { RestRequestMethod } from '../app/core/data/rest-request-method'; +import { NotificationAnimationsType } from '../app/shared/notifications/models/notification-animations-type'; +import { GlobalConfig } from '../config/global-config.interface'; + +export const environment: Partial = { + rest: { + ssl: true, + host: 'rest.com', + port: 443, + // NOTE: Space is capitalized because 'namespace' is a reserved string in TypeScript + nameSpace: '/api', + baseUrl: 'https://rest.api/' + }, + ui: { + ssl: false, + host: 'dspace.com', + port: 80, + // NOTE: Space is capitalized because 'namespace' is a reserved string in TypeScript + nameSpace: '/angular-dspace', + }, + // Caching settings + cache: { + // NOTE: how long should objects be cached for by default + msToLive: { + default: 15 * 60 * 1000, // 15 minutes + }, + // msToLive: 1000, // 15 minutes + control: 'max-age=60', // revalidate browser + autoSync: { + defaultTime: 0, + maxBufferSize: 100, + timePerMethod: {[RestRequestMethod.PATCH]: 3} as any // time in seconds + } + }, + // Form settings + form: { + // NOTE: Map server-side validators to comparative Angular form validators + validatorMap: { + required: 'required', + regex: 'pattern' + } + }, + // Notifications + notifications: { + rtl: false, + position: ['top', 'right'], + maxStack: 8, + // NOTE: after how many seconds notification is closed automatically. If set to zero notifications are not closed automatically + timeOut: 5000, // 5 second + clickToClose: true, + // NOTE: 'fade' | 'fromTop' | 'fromRight' | 'fromBottom' | 'fromLeft' | 'rotate' | 'scale' + animate: NotificationAnimationsType.Scale + }, + // Submission settings + submission: { + autosave: { + // NOTE: which metadata trigger an autosave + metadata: ['dc.title', 'dc.identifier.doi', 'dc.identifier.pmid', 'dc.identifier.arxiv'], + // NOTE: every how many minutes submission is saved automatically + timer: 5 + }, + icons: { + metadata: [ + { + name: 'mainField', + style: 'fas fa-user' + }, + { + name: 'relatedField', + style: 'fas fa-university' + }, + { + name: 'otherRelatedField', + style: 'fas fa-circle' + }, + { + name: 'default', + style: '' + } + ], + authority: { + confidence: [ + { + value: 600, + style: 'text-success' + }, + { + value: 500, + style: 'text-info' + }, + { + value: 400, + style: 'text-warning' + }, + { + value: 'default', + style: 'text-muted' + }, + + ] + } + } + }, + // Angular Universal settings + universal: { + preboot: true, + async: true, + time: false + }, + // Google Analytics tracking id + gaTrackingId: '', + // Log directory + logDirectory: '.', + // NOTE: will log all redux actions and transfers in console + debug: false, + // Default Language in which the UI will be rendered if the user's browser language is not an active language + defaultLanguage: 'en', + // Languages. DSpace Angular holds a message catalog for each of the following languages. + // When set to active, users will be able to switch to the use of this language in the user interface. + languages: [{ + code: 'en', + label: 'English', + active: true, + }, { + code: 'de', + label: 'Deutsch', + active: true, + }, { + code: 'cs', + label: 'Čeština', + active: true, + }, { + code: 'nl', + label: 'Nederlands', + active: true, + }, { + code: 'pt', + label: 'Português', + active: true, + }, { + code: 'fr', + label: 'Français', + active: true, + }, { + code: 'lv', + label: 'Latviešu', + active: true, + }], + // Browse-By Pages + browseBy: { + // Amount of years to display using jumps of one year (current year - oneYearLimit) + oneYearLimit: 10, + // Limit for years to display using jumps of five years (current year - fiveYearLimit) + fiveYearLimit: 30, + // The absolute lowest year to display in the dropdown (only used when no lowest date can be found for all items) + defaultLowerLimit: 1900, + // List of all the active Browse-By types + // Adding a type will activate their Browse-By page and add them to the global navigation menu, + // as well as community and collection pages + // Allowed fields and their purpose: + // id: The browse id to use for fetching info from the rest api + // type: The type of Browse-By page to display + // metadataField: The metadata-field used to create starts-with options (only necessary when the type is set to 'date') + types: [ + { + id: 'title', + type: BrowseByType.Title, + }, + { + id: 'dateissued', + type: BrowseByType.Date, + metadataField: 'dc.date.issued' + }, + { + id: 'author', + type: BrowseByType.Metadata + }, + { + id: 'subject', + type: BrowseByType.Metadata + } + ] + }, + item: { + edit: { + undoTimeout: 10000 // 10 seconds + } + }, + collection: { + edit: { + undoTimeout: 10000 // 10 seconds + } + }, + theme: { + name: 'default', + } +};