;
diff --git a/src/app/shared/authority-confidence/authority-confidence-state.directive.ts b/src/app/shared/form/directives/authority-confidence-state.directive.ts
similarity index 83%
rename from src/app/shared/authority-confidence/authority-confidence-state.directive.ts
rename to src/app/shared/form/directives/authority-confidence-state.directive.ts
index bf6f949575..49eee5ae8f 100644
--- a/src/app/shared/authority-confidence/authority-confidence-state.directive.ts
+++ b/src/app/shared/form/directives/authority-confidence-state.directive.ts
@@ -1,3 +1,11 @@
+/**
+ * The contents of this file are subject to the license and copyright
+ * detailed in the LICENSE and NOTICE files at the root of the source
+ * tree and available online at
+ *
+ * http://www.dspace.org/license/
+ */
+
import {
AfterViewInit,
Directive,
@@ -13,13 +21,13 @@ import {
import findIndex from 'lodash/findIndex';
-import { VocabularyEntry } from '../../core/submission/vocabularies/models/vocabulary-entry.model';
-import { FormFieldMetadataValueObject } from '../form/builder/models/form-field-metadata-value.model';
-import { ConfidenceType } from '../../core/shared/confidence-type';
-import { isNotEmpty, isNull } from '../empty.util';
-import { ConfidenceIconConfig } from '../../../config/submission-config.interface';
-import { environment } from '../../../environments/environment';
-import { VocabularyEntryDetail } from '../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
+import { VocabularyEntry } from '../../../core/submission/vocabularies/models/vocabulary-entry.model';
+import { FormFieldMetadataValueObject } from '../builder/models/form-field-metadata-value.model';
+import { ConfidenceType } from '../../../core/shared/confidence-type';
+import { isNotEmpty, isNull } from '../../empty.util';
+import { ConfidenceIconConfig } from '../../../../config/submission-config.interface';
+import { environment } from '../../../../environments/environment';
+import { VocabularyEntryDetail } from '../../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
/**
* Directive to add to the element a bootstrap utility class based on metadata confidence value
diff --git a/src/app/shared/form/form.module.ts b/src/app/shared/form/form.module.ts
index 62ab5bd647..c3062b4231 100644
--- a/src/app/shared/form/form.module.ts
+++ b/src/app/shared/form/form.module.ts
@@ -2,10 +2,7 @@ import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormComponent } from './form.component';
import { DsDynamicFormComponent } from './builder/ds-dynamic-form-ui/ds-dynamic-form.component';
-import {
- DsDynamicFormControlContainerComponent,
- dsDynamicFormControlMapFn
-} from './builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component';
+import { DsDynamicFormControlContainerComponent, dsDynamicFormControlMapFn } from './builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component';
import { DsDynamicListComponent } from './builder/ds-dynamic-form-ui/models/list/dynamic-list.component';
import { DsDynamicLookupComponent } from './builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component';
import { DsDynamicDisabledComponent } from './builder/ds-dynamic-form-ui/models/disabled/dynamic-disabled.component';
@@ -24,12 +21,23 @@ import { DsDynamicLookupRelationExternalSourceTabComponent } from './builder/ds-
import { SharedModule } from '../shared.module';
import { TranslateModule } from '@ngx-translate/core';
import { SearchModule } from '../search/search.module';
-import { DYNAMIC_FORM_CONTROL_MAP_FN, DynamicFormsCoreModule } from '@ng-dynamic-forms/core';
+import { DYNAMIC_FORM_CONTROL_MAP_FN, DYNAMIC_MATCHER_PROVIDERS, DynamicFormLayoutService, DynamicFormsCoreModule, DynamicFormService, DynamicFormValidationService } from '@ng-dynamic-forms/core';
import { ExistingMetadataListElementComponent } from './builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component';
import { ExistingRelationListElementComponent } from './builder/ds-dynamic-form-ui/existing-relation-list-element/existing-relation-list-element.component';
import { ExternalSourceEntryImportModalComponent } from './builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component';
import { CustomSwitchComponent } from './builder/ds-dynamic-form-ui/models/custom-switch/custom-switch.component';
import { DynamicFormsNGBootstrapUIModule } from '@ng-dynamic-forms/ui-ng-bootstrap';
+import { ChipsComponent } from './chips/chips.component';
+import { NumberPickerComponent } from './number-picker/number-picker.component';
+import { AuthorityConfidenceStateDirective } from './directives/authority-confidence-state.directive';
+import { SortablejsModule } from 'ngx-sortablejs';
+import { VocabularyTreeviewComponent } from './vocabulary-treeview/vocabulary-treeview.component';
+import { VocabularyTreeviewService } from './vocabulary-treeview/vocabulary-treeview.service';
+import { FormBuilderService } from './builder/form-builder.service';
+import { DsDynamicTypeBindRelationService } from './builder/ds-dynamic-form-ui/ds-dynamic-type-bind-relation.service';
+import { FormService } from './form.service';
+import { NgxMaskModule } from 'ngx-mask';
+import { ThemedExternalSourceEntryImportModalComponent } from './builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/themed-external-source-entry-import-modal.component';
const COMPONENTS = [
CustomSwitchComponent,
@@ -53,12 +61,21 @@ const COMPONENTS = [
ExistingMetadataListElementComponent,
ExistingRelationListElementComponent,
ExternalSourceEntryImportModalComponent,
- FormComponent
+ FormComponent,
+ ChipsComponent,
+ NumberPickerComponent,
+ VocabularyTreeviewComponent,
+ ThemedExternalSourceEntryImportModalComponent
+];
+
+const DIRECTIVES = [
+ AuthorityConfidenceStateDirective,
];
@NgModule({
declarations: [
- ...COMPONENTS
+ ...COMPONENTS,
+ ...DIRECTIVES,
],
imports: [
CommonModule,
@@ -66,16 +83,27 @@ const COMPONENTS = [
DynamicFormsNGBootstrapUIModule,
SearchModule,
SharedModule,
- TranslateModule
+ TranslateModule,
+ SortablejsModule,
+ NgxMaskModule.forRoot(),
],
exports: [
- ...COMPONENTS
+ ...COMPONENTS,
+ ...DIRECTIVES,
],
providers: [
{
provide: DYNAMIC_FORM_CONTROL_MAP_FN,
useValue: dsDynamicFormControlMapFn
- }
+ },
+ ...DYNAMIC_MATCHER_PROVIDERS,
+ VocabularyTreeviewService,
+ DynamicFormLayoutService,
+ DynamicFormService,
+ DynamicFormValidationService,
+ FormBuilderService,
+ DsDynamicTypeBindRelationService,
+ FormService,
]
})
export class FormModule {
diff --git a/src/app/shared/number-picker/number-picker.component.html b/src/app/shared/form/number-picker/number-picker.component.html
similarity index 100%
rename from src/app/shared/number-picker/number-picker.component.html
rename to src/app/shared/form/number-picker/number-picker.component.html
diff --git a/src/app/shared/number-picker/number-picker.component.scss b/src/app/shared/form/number-picker/number-picker.component.scss
similarity index 100%
rename from src/app/shared/number-picker/number-picker.component.scss
rename to src/app/shared/form/number-picker/number-picker.component.scss
diff --git a/src/app/shared/number-picker/number-picker.component.spec.ts b/src/app/shared/form/number-picker/number-picker.component.spec.ts
similarity index 96%
rename from src/app/shared/number-picker/number-picker.component.spec.ts
rename to src/app/shared/form/number-picker/number-picker.component.spec.ts
index 0cc073644e..d4484dbfa3 100644
--- a/src/app/shared/number-picker/number-picker.component.spec.ts
+++ b/src/app/shared/form/number-picker/number-picker.component.spec.ts
@@ -2,12 +2,11 @@
import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { ComponentFixture, inject, TestBed, waitForAsync, } from '@angular/core/testing';
-import { UploaderService } from '../uploader/uploader.service';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { By } from '@angular/platform-browser';
import { NumberPickerComponent } from './number-picker.component';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
-import { createTestComponent } from '../testing/utils.test';
+import { createTestComponent } from '../../testing/utils.test';
describe('NumberPickerComponent test suite', () => {
@@ -33,7 +32,6 @@ describe('NumberPickerComponent test suite', () => {
providers: [
ChangeDetectorRef,
NumberPickerComponent,
- UploaderService
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
});
diff --git a/src/app/shared/number-picker/number-picker.component.ts b/src/app/shared/form/number-picker/number-picker.component.ts
similarity index 98%
rename from src/app/shared/number-picker/number-picker.component.ts
rename to src/app/shared/form/number-picker/number-picker.component.ts
index 465e905713..0df1e050cd 100644
--- a/src/app/shared/number-picker/number-picker.component.ts
+++ b/src/app/shared/form/number-picker/number-picker.component.ts
@@ -1,6 +1,6 @@
import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, SimpleChanges, } from '@angular/core';
import { ControlValueAccessor, FormBuilder, NG_VALUE_ACCESSOR } from '@angular/forms';
-import { isEmpty } from '../empty.util';
+import { isEmpty } from '../../empty.util';
@Component({
selector: 'ds-number-picker',
diff --git a/src/app/shared/vocabulary-treeview/vocabulary-tree-flat-data-source.ts b/src/app/shared/form/vocabulary-treeview/vocabulary-tree-flat-data-source.ts
similarity index 100%
rename from src/app/shared/vocabulary-treeview/vocabulary-tree-flat-data-source.ts
rename to src/app/shared/form/vocabulary-treeview/vocabulary-tree-flat-data-source.ts
diff --git a/src/app/shared/vocabulary-treeview/vocabulary-tree-flattener.ts b/src/app/shared/form/vocabulary-treeview/vocabulary-tree-flattener.ts
similarity index 100%
rename from src/app/shared/vocabulary-treeview/vocabulary-tree-flattener.ts
rename to src/app/shared/form/vocabulary-treeview/vocabulary-tree-flattener.ts
diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview-node.model.ts b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview-node.model.ts
similarity index 88%
rename from src/app/shared/vocabulary-treeview/vocabulary-treeview-node.model.ts
rename to src/app/shared/form/vocabulary-treeview/vocabulary-treeview-node.model.ts
index 63039e6c75..c167328cab 100644
--- a/src/app/shared/vocabulary-treeview/vocabulary-treeview-node.model.ts
+++ b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview-node.model.ts
@@ -1,7 +1,7 @@
/* eslint-disable max-classes-per-file */
import { BehaviorSubject } from 'rxjs';
-import { VocabularyEntryDetail } from '../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
-import { PageInfo } from '../../core/shared/page-info.model';
+import { VocabularyEntryDetail } from '../../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
+import { PageInfo } from '../../../core/shared/page-info.model';
export const LOAD_MORE = 'LOAD_MORE';
export const LOAD_MORE_ROOT = 'LOAD_MORE_ROOT';
diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.html b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.html
similarity index 100%
rename from src/app/shared/vocabulary-treeview/vocabulary-treeview.component.html
rename to src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.html
diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.scss b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.scss
similarity index 100%
rename from src/app/shared/vocabulary-treeview/vocabulary-treeview.component.scss
rename to src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.scss
diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.spec.ts b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.spec.ts
similarity index 91%
rename from src/app/shared/vocabulary-treeview/vocabulary-treeview.component.spec.ts
rename to src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.spec.ts
index 1bdf4b9df7..cf8fbd8c49 100644
--- a/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.spec.ts
+++ b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.spec.ts
@@ -8,18 +8,18 @@ import { TranslateModule } from '@ngx-translate/core';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { provideMockStore } from '@ngrx/store/testing';
-import { createTestComponent } from '../testing/utils.test';
+import { createTestComponent } from '../../testing/utils.test';
import { VocabularyTreeviewComponent } from './vocabulary-treeview.component';
import { VocabularyTreeviewService } from './vocabulary-treeview.service';
-import { VocabularyEntryDetail } from '../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
+import { VocabularyEntryDetail } from '../../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
import { TreeviewFlatNode } from './vocabulary-treeview-node.model';
-import { FormFieldMetadataValueObject } from '../form/builder/models/form-field-metadata-value.model';
-import { VocabularyOptions } from '../../core/submission/vocabularies/models/vocabulary-options.model';
-import { PageInfo } from '../../core/shared/page-info.model';
-import { VocabularyEntry } from '../../core/submission/vocabularies/models/vocabulary-entry.model';
-import { AuthTokenInfo } from '../../core/auth/models/auth-token-info.model';
-import { authReducer } from '../../core/auth/auth.reducer';
-import { storeModuleConfig } from '../../app.reducer';
+import { FormFieldMetadataValueObject } from '../builder/models/form-field-metadata-value.model';
+import { VocabularyOptions } from '../../../core/submission/vocabularies/models/vocabulary-options.model';
+import { PageInfo } from '../../../core/shared/page-info.model';
+import { VocabularyEntry } from '../../../core/submission/vocabularies/models/vocabulary-entry.model';
+import { AuthTokenInfo } from '../../../core/auth/models/auth-token-info.model';
+import { authReducer } from '../../../core/auth/auth.reducer';
+import { storeModuleConfig } from '../../../app.reducer';
describe('VocabularyTreeviewComponent test suite', () => {
diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts
similarity index 93%
rename from src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts
rename to src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts
index 9850947f60..408d656f42 100644
--- a/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts
+++ b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts
@@ -7,17 +7,17 @@ import { Observable, Subscription } from 'rxjs';
import { select, Store } from '@ngrx/store';
import { TranslateService } from '@ngx-translate/core';
-import { VocabularyEntryDetail } from '../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
-import { hasValue, isEmpty, isNotEmpty } from '../empty.util';
-import { isAuthenticated } from '../../core/auth/selectors';
+import { VocabularyEntryDetail } from '../../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
+import { hasValue, isEmpty, isNotEmpty } from '../../empty.util';
+import { isAuthenticated } from '../../../core/auth/selectors';
import { VocabularyTreeviewService } from './vocabulary-treeview.service';
import { LOAD_MORE, LOAD_MORE_ROOT, TreeviewFlatNode, TreeviewNode } from './vocabulary-treeview-node.model';
-import { VocabularyOptions } from '../../core/submission/vocabularies/models/vocabulary-options.model';
-import { PageInfo } from '../../core/shared/page-info.model';
-import { VocabularyEntry } from '../../core/submission/vocabularies/models/vocabulary-entry.model';
+import { VocabularyOptions } from '../../../core/submission/vocabularies/models/vocabulary-options.model';
+import { PageInfo } from '../../../core/shared/page-info.model';
+import { VocabularyEntry } from '../../../core/submission/vocabularies/models/vocabulary-entry.model';
import { VocabularyTreeFlattener } from './vocabulary-tree-flattener';
import { VocabularyTreeFlatDataSource } from './vocabulary-tree-flat-data-source';
-import { CoreState } from '../../core/core-state.model';
+import { CoreState } from '../../../core/core-state.model';
/**
* Component that show a hierarchical vocabulary in a tree view
diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.spec.ts b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.service.spec.ts
similarity index 94%
rename from src/app/shared/vocabulary-treeview/vocabulary-treeview.service.spec.ts
rename to src/app/shared/form/vocabulary-treeview/vocabulary-treeview.service.spec.ts
index c1c64c80bd..752ef10fee 100644
--- a/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.spec.ts
+++ b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.service.spec.ts
@@ -5,15 +5,15 @@ import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-transla
import { cold, getTestScheduler, hot } from 'jasmine-marbles';
import { VocabularyTreeviewService } from './vocabulary-treeview.service';
-import { VocabularyService } from '../../core/submission/vocabularies/vocabulary.service';
-import { TranslateLoaderMock } from '../mocks/translate-loader.mock';
-import { VocabularyOptions } from '../../core/submission/vocabularies/models/vocabulary-options.model';
+import { VocabularyService } from '../../../core/submission/vocabularies/vocabulary.service';
+import { TranslateLoaderMock } from '../../mocks/translate-loader.mock';
+import { VocabularyOptions } from '../../../core/submission/vocabularies/models/vocabulary-options.model';
import { LOAD_MORE_NODE, LOAD_MORE_ROOT_NODE, TreeviewFlatNode, TreeviewNode } from './vocabulary-treeview-node.model';
-import { PageInfo } from '../../core/shared/page-info.model';
-import { VocabularyEntryDetail } from '../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
-import { buildPaginatedList } from '../../core/data/paginated-list.model';
-import { createSuccessfulRemoteDataObject } from '../remote-data.utils';
-import { VocabularyEntry } from '../../core/submission/vocabularies/models/vocabulary-entry.model';
+import { PageInfo } from '../../../core/shared/page-info.model';
+import { VocabularyEntryDetail } from '../../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
+import { buildPaginatedList } from '../../../core/data/paginated-list.model';
+import { createSuccessfulRemoteDataObject } from '../../remote-data.utils';
+import { VocabularyEntry } from '../../../core/submission/vocabularies/models/vocabulary-entry.model';
import { expand, map, switchMap } from 'rxjs/operators';
import { from as observableFrom } from 'rxjs';
diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.ts b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.service.ts
similarity index 94%
rename from src/app/shared/vocabulary-treeview/vocabulary-treeview.service.ts
rename to src/app/shared/form/vocabulary-treeview/vocabulary-treeview.service.ts
index f04cd1bc28..8804716927 100644
--- a/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.ts
+++ b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.service.ts
@@ -10,17 +10,17 @@ import {
TreeviewFlatNode,
TreeviewNode
} from './vocabulary-treeview-node.model';
-import { VocabularyEntry } from '../../core/submission/vocabularies/models/vocabulary-entry.model';
-import { VocabularyService } from '../../core/submission/vocabularies/vocabulary.service';
-import { PageInfo } from '../../core/shared/page-info.model';
-import { isEmpty, isNotEmpty } from '../empty.util';
-import { VocabularyOptions } from '../../core/submission/vocabularies/models/vocabulary-options.model';
+import { VocabularyEntry } from '../../../core/submission/vocabularies/models/vocabulary-entry.model';
+import { VocabularyService } from '../../../core/submission/vocabularies/vocabulary.service';
+import { PageInfo } from '../../../core/shared/page-info.model';
+import { isEmpty, isNotEmpty } from '../../empty.util';
+import { VocabularyOptions } from '../../../core/submission/vocabularies/models/vocabulary-options.model';
import {
getFirstSucceededRemoteDataPayload,
getFirstSucceededRemoteListPayload
-} from '../../core/shared/operators';
-import { PaginatedList } from '../../core/data/paginated-list.model';
-import { VocabularyEntryDetail } from '../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
+} from '../../../core/shared/operators';
+import { PaginatedList } from '../../../core/data/paginated-list.model';
+import { VocabularyEntryDetail } from '../../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
/**
* A service that provides methods to deal with vocabulary tree
diff --git a/src/app/shared/interfaces/modal-before-dismiss.interface.ts b/src/app/shared/interfaces/modal-before-dismiss.interface.ts
index fca28e1cff..f884432fb8 100644
--- a/src/app/shared/interfaces/modal-before-dismiss.interface.ts
+++ b/src/app/shared/interfaces/modal-before-dismiss.interface.ts
@@ -1,4 +1,3 @@
-import { NgbModalConfig, NgbModal } from '@ng-bootstrap/ng-bootstrap';
/**
* If a component implementing this interface is used to create a modal (i.e. it is passed to {@link NgbModal#open}),
diff --git a/src/app/shared/menu/menu-item/link-menu-item.component.ts b/src/app/shared/menu/menu-item/link-menu-item.component.ts
index c9a60f0c28..78d5b2fc6f 100644
--- a/src/app/shared/menu/menu-item/link-menu-item.component.ts
+++ b/src/app/shared/menu/menu-item/link-menu-item.component.ts
@@ -1,4 +1,4 @@
-import { Component, Inject, Input, OnInit } from '@angular/core';
+import { Component, Inject, OnInit } from '@angular/core';
import { LinkMenuItemModel } from './models/link.model';
import { rendersMenuItemForType } from '../menu-item.decorator';
import { isNotEmpty } from '../../empty.util';
diff --git a/src/app/shared/menu/menu-item/text-menu-item.component.ts b/src/app/shared/menu/menu-item/text-menu-item.component.ts
index af690d198c..25549f53a8 100644
--- a/src/app/shared/menu/menu-item/text-menu-item.component.ts
+++ b/src/app/shared/menu/menu-item/text-menu-item.component.ts
@@ -1,4 +1,4 @@
-import { Component, Inject, Input } from '@angular/core';
+import { Component, Inject } from '@angular/core';
import { TextMenuItemModel } from './models/text.model';
import { rendersMenuItemForType } from '../menu-item.decorator';
import { MenuItemType } from '../menu-item-type.model';
diff --git a/src/app/shared/menu/menu.module.ts b/src/app/shared/menu/menu.module.ts
index 1d186a9b7d..c007af517d 100644
--- a/src/app/shared/menu/menu.module.ts
+++ b/src/app/shared/menu/menu.module.ts
@@ -12,8 +12,11 @@ import { ExternalLinkMenuItemComponent } from './menu-item/external-link-menu-it
const COMPONENTS = [
MenuSectionComponent,
MenuComponent,
- LinkMenuItemComponent,
+];
+
+const ENTRY_COMPONENTS = [
TextMenuItemComponent,
+ LinkMenuItemComponent,
OnClickMenuItemComponent,
ExternalLinkMenuItemComponent,
];
@@ -32,10 +35,12 @@ const PROVIDERS = [
...MODULES
],
declarations: [
- ...COMPONENTS
+ ...COMPONENTS,
+ ...ENTRY_COMPONENTS,
],
providers: [
- ...PROVIDERS
+ ...PROVIDERS,
+ ...ENTRY_COMPONENTS,
],
exports: [
...COMPONENTS
diff --git a/src/app/shared/mydspace-actions/claimed-task/approve/claimed-task-actions-approve.component.spec.ts b/src/app/shared/mydspace-actions/claimed-task/approve/claimed-task-actions-approve.component.spec.ts
index ce67da1349..f43316c4e1 100644
--- a/src/app/shared/mydspace-actions/claimed-task/approve/claimed-task-actions-approve.component.spec.ts
+++ b/src/app/shared/mydspace-actions/claimed-task/approve/claimed-task-actions-approve.component.spec.ts
@@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, Injector, NO_ERRORS_SCHEMA } from '@angular/core';
-import { async, ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { of, of as observableOf } from 'rxjs';
diff --git a/src/app/shared/object-collection/shared/listable-object/listable-object.decorator.spec.ts b/src/app/shared/object-collection/shared/listable-object/listable-object.decorator.spec.ts
index eb5219fab8..f7d00510f6 100644
--- a/src/app/shared/object-collection/shared/listable-object/listable-object.decorator.spec.ts
+++ b/src/app/shared/object-collection/shared/listable-object/listable-object.decorator.spec.ts
@@ -1,5 +1,4 @@
/* eslint-disable max-classes-per-file */
-import { Item } from '../../../../core/shared/item.model';
import { ViewMode } from '../../../../core/shared/view-mode.model';
import { DEFAULT_VIEW_MODE, getListableObjectComponent, listableObjectComponent } from './listable-object.decorator';
import { Context } from '../../../../core/shared/context.model';
diff --git a/src/app/shared/object-list/listable-notification-object/listable-notification-object.component.html b/src/app/shared/object-list/listable-notification-object/listable-notification-object.component.html
new file mode 100644
index 0000000000..d29199bae3
--- /dev/null
+++ b/src/app/shared/object-list/listable-notification-object/listable-notification-object.component.html
@@ -0,0 +1 @@
+{{ object?.message | translate }}
diff --git a/src/app/shared/object-list/listable-notification-object/listable-notification-object.component.scss b/src/app/shared/object-list/listable-notification-object/listable-notification-object.component.scss
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/src/app/shared/object-list/listable-notification-object/listable-notification-object.component.spec.ts b/src/app/shared/object-list/listable-notification-object/listable-notification-object.component.spec.ts
new file mode 100644
index 0000000000..3cf05f7fec
--- /dev/null
+++ b/src/app/shared/object-list/listable-notification-object/listable-notification-object.component.spec.ts
@@ -0,0 +1,43 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ListableNotificationObjectComponent } from './listable-notification-object.component';
+import { NotificationType } from '../../notifications/models/notification-type';
+import { ListableNotificationObject } from './listable-notification-object.model';
+import { By } from '@angular/platform-browser';
+import { TranslateModule } from '@ngx-translate/core';
+
+describe('ListableNotificationObjectComponent', () => {
+ let component: ListableNotificationObjectComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [
+ TranslateModule.forRoot(),
+ ],
+ declarations: [
+ ListableNotificationObjectComponent,
+ ],
+ }).compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ListableNotificationObjectComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ describe('ui', () => {
+ it('should display the given error message', () => {
+ component.object = new ListableNotificationObject(NotificationType.Error, 'test error message');
+ fixture.detectChanges();
+
+ const listableNotificationObject: Element = fixture.debugElement.query(By.css('.alert')).nativeElement;
+ expect(listableNotificationObject.className).toContain(NotificationType.Error);
+ expect(listableNotificationObject.innerHTML).toBe('test error message');
+ });
+ });
+
+ afterEach(() => {
+ fixture.debugElement.nativeElement.remove();
+ });
+});
diff --git a/src/app/shared/object-list/listable-notification-object/listable-notification-object.component.ts b/src/app/shared/object-list/listable-notification-object/listable-notification-object.component.ts
new file mode 100644
index 0000000000..ca23ee76a2
--- /dev/null
+++ b/src/app/shared/object-list/listable-notification-object/listable-notification-object.component.ts
@@ -0,0 +1,21 @@
+import { Component } from '@angular/core';
+import {
+ AbstractListableElementComponent
+} from '../../object-collection/shared/object-collection-element/abstract-listable-element.component';
+import { ListableNotificationObject } from './listable-notification-object.model';
+import { listableObjectComponent } from '../../object-collection/shared/listable-object/listable-object.decorator';
+import { ViewMode } from '../../../core/shared/view-mode.model';
+import { LISTABLE_NOTIFICATION_OBJECT } from './listable-notification-object.resource-type';
+
+/**
+ * The component for displaying a notifications inside an object list
+ */
+@listableObjectComponent(ListableNotificationObject, ViewMode.ListElement)
+@listableObjectComponent(LISTABLE_NOTIFICATION_OBJECT.value, ViewMode.ListElement)
+@Component({
+ selector: 'ds-listable-notification-object',
+ templateUrl: './listable-notification-object.component.html',
+ styleUrls: ['./listable-notification-object.component.scss'],
+})
+export class ListableNotificationObjectComponent extends AbstractListableElementComponent {
+}
diff --git a/src/app/shared/object-list/listable-notification-object/listable-notification-object.model.ts b/src/app/shared/object-list/listable-notification-object/listable-notification-object.model.ts
new file mode 100644
index 0000000000..163d9096a2
--- /dev/null
+++ b/src/app/shared/object-list/listable-notification-object/listable-notification-object.model.ts
@@ -0,0 +1,36 @@
+import { ListableObject } from '../../object-collection/shared/listable-object.model';
+import { typedObject } from '../../../core/cache/builders/build-decorators';
+import { TypedObject } from '../../../core/cache/typed-object.model';
+import { LISTABLE_NOTIFICATION_OBJECT } from './listable-notification-object.resource-type';
+import { GenericConstructor } from '../../../core/shared/generic-constructor';
+import { NotificationType } from '../../notifications/models/notification-type';
+import { ResourceType } from '../../../core/shared/resource-type';
+
+/**
+ * Object representing a notification message inside a list of objects
+ */
+@typedObject
+export class ListableNotificationObject extends ListableObject implements TypedObject {
+
+ static type: ResourceType = LISTABLE_NOTIFICATION_OBJECT;
+ type: ResourceType = LISTABLE_NOTIFICATION_OBJECT;
+
+ protected renderTypes: string[];
+
+ constructor(
+ public notificationType: NotificationType = NotificationType.Error,
+ public message: string = 'listable-notification-object.default-message',
+ ...renderTypes: string[]
+ ) {
+ super();
+ this.renderTypes = renderTypes;
+ }
+
+ /**
+ * Method that returns as which type of object this object should be rendered.
+ */
+ getRenderTypes(): (string | GenericConstructor)[] {
+ return [...this.renderTypes, this.constructor as GenericConstructor];
+ }
+
+}
diff --git a/src/app/shared/object-list/listable-notification-object/listable-notification-object.resource-type.ts b/src/app/shared/object-list/listable-notification-object/listable-notification-object.resource-type.ts
new file mode 100644
index 0000000000..ed458126bb
--- /dev/null
+++ b/src/app/shared/object-list/listable-notification-object/listable-notification-object.resource-type.ts
@@ -0,0 +1,9 @@
+import { ResourceType } from '../../../core/shared/resource-type';
+
+/**
+ * The resource type for {@link ListableNotificationObject}
+ *
+ * Needs to be in a separate file to prevent circular
+ * dependencies in webpack.
+ */
+export const LISTABLE_NOTIFICATION_OBJECT = new ResourceType('listable-notification-object');
diff --git a/src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.spec.ts b/src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.spec.ts
index 897ec43491..226c1be33e 100644
--- a/src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.spec.ts
+++ b/src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.spec.ts
@@ -11,7 +11,6 @@ import { createSuccessfulRemoteDataObject$ } from '../../remote-data.utils';
import { HALResource } from '../../../core/shared/hal-resource.model';
import { ChildHALResource } from '../../../core/shared/child-hal-resource.model';
import { DSONameService } from '../../../core/breadcrumbs/dso-name.service';
-import { DSONameServiceMock } from '../../mocks/dso-name.service.mock';
export function createSidebarSearchListElementTests(
componentClass: any,
diff --git a/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.spec.ts b/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.spec.ts
index 7db53425d5..bac6b89583 100644
--- a/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.spec.ts
+++ b/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.spec.ts
@@ -11,8 +11,6 @@ import { createSuccessfulRemoteDataObject } from '../remote-data.utils';
import { createPaginatedList } from '../testing/utils.test';
import { ObjectValuesPipe } from '../utils/object-values-pipe';
import { PaginationService } from '../../core/pagination/pagination.service';
-import { PaginationComponentOptions } from '../pagination/pagination-component-options.model';
-import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
import { PaginationServiceStub } from '../testing/pagination-service.stub';
import { FieldUpdates } from '../../core/data/object-updates/field-updates.model';
diff --git a/src/app/shared/pagination/pagination.component.spec.ts b/src/app/shared/pagination/pagination.component.spec.ts
index 2d913da8a3..30ace4b2b9 100644
--- a/src/app/shared/pagination/pagination.component.spec.ts
+++ b/src/app/shared/pagination/pagination.component.spec.ts
@@ -32,8 +32,7 @@ import { SortDirection, SortOptions } from '../../core/cache/models/sort-options
import { createTestComponent } from '../testing/utils.test';
import { storeModuleConfig } from '../../app.reducer';
import { PaginationService } from '../../core/pagination/pagination.service';
-import { BehaviorSubject, of as observableOf } from 'rxjs';
-import { PaginationServiceStub } from '../testing/pagination-service.stub';
+import { BehaviorSubject } from 'rxjs';
import { FindListOptions } from '../../core/data/find-list-options.model';
function expectPages(fixture: ComponentFixture, pagesDef: string[]): void {
diff --git a/src/app/shared/rss-feed/rss.component.spec.ts b/src/app/shared/rss-feed/rss.component.spec.ts
index fd7f2c5321..61b54a1125 100644
--- a/src/app/shared/rss-feed/rss.component.spec.ts
+++ b/src/app/shared/rss-feed/rss.component.spec.ts
@@ -1,5 +1,4 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
-import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
import { ConfigurationDataService } from '../../core/data/configuration-data.service';
import { RemoteData } from '../../core/data/remote-data';
import { GroupDataService } from '../../core/eperson/group-data.service';
@@ -23,7 +22,6 @@ import { RouterMock } from '../mocks/router.mock';
describe('RssComponent', () => {
let comp: RSSComponent;
- let options: SortOptions;
let fixture: ComponentFixture;
let uuid: string;
let query: string;
@@ -63,7 +61,6 @@ describe('RssComponent', () => {
pageSize: 10,
currentPage: 1
}),
- sort: new SortOptions('dc.title', SortDirection.ASC),
}));
groupDataService = jasmine.createSpyObj('groupsDataService', {
findListByHref: createSuccessfulRemoteDataObject$(createPaginatedList([])),
@@ -88,7 +85,6 @@ describe('RssComponent', () => {
}));
beforeEach(() => {
- options = new SortOptions('dc.title', SortDirection.DESC);
uuid = '2cfcf65e-0a51-4bcb-8592-b8db7b064790';
query = 'test';
fixture = TestBed.createComponent(RSSComponent);
@@ -96,18 +92,18 @@ describe('RssComponent', () => {
});
it('should formulate the correct url given params in url', () => {
- const route = comp.formulateRoute(uuid, 'opensearch', options, query);
- expect(route).toBe('/opensearch/search?format=atom&scope=2cfcf65e-0a51-4bcb-8592-b8db7b064790&sort=dc.title&sort_direction=DESC&query=test');
+ const route = comp.formulateRoute(uuid, 'opensearch/search', query);
+ expect(route).toBe('/opensearch/search?format=atom&scope=2cfcf65e-0a51-4bcb-8592-b8db7b064790&query=test');
});
it('should skip uuid if its null', () => {
- const route = comp.formulateRoute(null, 'opensearch', options, query);
- expect(route).toBe('/opensearch/search?format=atom&sort=dc.title&sort_direction=DESC&query=test');
+ const route = comp.formulateRoute(null, 'opensearch/search', query);
+ expect(route).toBe('/opensearch/search?format=atom&query=test');
});
it('should default to query * if none provided', () => {
- const route = comp.formulateRoute(null, 'opensearch', options, null);
- expect(route).toBe('/opensearch/search?format=atom&sort=dc.title&sort_direction=DESC&query=*');
+ const route = comp.formulateRoute(null, 'opensearch/search', null);
+ expect(route).toBe('/opensearch/search?format=atom&query=*');
});
});
diff --git a/src/app/shared/rss-feed/rss.component.ts b/src/app/shared/rss-feed/rss.component.ts
index 3fdb859bdc..8a33aeeb68 100644
--- a/src/app/shared/rss-feed/rss.component.ts
+++ b/src/app/shared/rss-feed/rss.component.ts
@@ -12,7 +12,6 @@ import { ConfigurationDataService } from '../../core/data/configuration-data.ser
import { getFirstCompletedRemoteData } from '../../core/shared/operators';
import { environment } from '../../../../src/environments/environment';
import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service';
-import { SortOptions } from '../../core/cache/models/sort-options.model';
import { PaginationService } from '../../core/pagination/pagination.service';
import { Router } from '@angular/router';
import { map, switchMap } from 'rxjs/operators';
@@ -39,7 +38,6 @@ export class RSSComponent implements OnInit, OnDestroy {
uuid: string;
configuration$: Observable;
- sortOption$: Observable;
subs: Subscription[] = [];
@@ -93,7 +91,7 @@ export class RSSComponent implements OnInit, OnDestroy {
return null;
}
this.uuid = this.groupDataService.getUUIDFromString(this.router.url);
- const route = environment.rest.baseUrl + this.formulateRoute(this.uuid, openSearchUri, searchOptions.sort, searchOptions.query);
+ const route = environment.rest.baseUrl + this.formulateRoute(this.uuid, openSearchUri, searchOptions.query);
this.addLinks(route);
this.linkHeadService.addTag({
href: environment.rest.baseUrl + '/' + openSearchUri + '/service',
@@ -109,24 +107,20 @@ export class RSSComponent implements OnInit, OnDestroy {
* Function created a route given the different params available to opensearch
* @param uuid The uuid if a scope is present
* @param opensearch openSearch uri
- * @param sort The sort options for the opensearch request
* @param query The query string that was provided in the search
* @returns The combine URL to opensearch
*/
- formulateRoute(uuid: string, opensearch: string, sort: SortOptions, query: string): string {
- let route = 'search?format=atom';
+ formulateRoute(uuid: string, opensearch: string, query: string): string {
+ let route = '?format=atom';
if (uuid) {
route += `&scope=${uuid}`;
}
- if (sort && sort.direction && sort.field && sort.field !== 'id') {
- route += `&sort=${sort.field}&sort_direction=${sort.direction}`;
- }
if (query) {
route += `&query=${query}`;
} else {
route += `&query=*`;
}
- route = '/' + opensearch + '/' + route;
+ route = '/' + opensearch + route;
return route;
}
diff --git a/src/app/shared/search-form/scope-selector-modal/scope-selector-modal.component.html b/src/app/shared/search-form/scope-selector-modal/scope-selector-modal.component.html
index bf5c15e963..e7165a9213 100644
--- a/src/app/shared/search-form/scope-selector-modal/scope-selector-modal.component.html
+++ b/src/app/shared/search-form/scope-selector-modal/scope-selector-modal.component.html
@@ -9,7 +9,7 @@
diff --git a/src/app/shared/search/search-labels/search-label/search-label.component.spec.ts b/src/app/shared/search/search-labels/search-label/search-label.component.spec.ts
index 50bcbc6938..b2be2ae53f 100644
--- a/src/app/shared/search/search-labels/search-label/search-label.component.spec.ts
+++ b/src/app/shared/search/search-labels/search-label/search-label.component.spec.ts
@@ -12,11 +12,9 @@ import { SearchServiceStub } from '../../../testing/search-service.stub';
import { SearchConfigurationServiceStub } from '../../../testing/search-configuration-service.stub';
import { SearchService } from '../../../../core/shared/search/search.service';
import { PaginationComponentOptions } from '../../../pagination/pagination-component-options.model';
-import { SortDirection, SortOptions } from '../../../../core/cache/models/sort-options.model';
import { PaginationService } from '../../../../core/pagination/pagination.service';
import { SearchConfigurationService } from '../../../../core/shared/search/search-configuration.service';
import { PaginationServiceStub } from '../../../testing/pagination-service.stub';
-import { FindListOptions } from '../../../../core/data/find-list-options.model';
describe('SearchLabelComponent', () => {
let comp: SearchLabelComponent;
diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts
index f723f081d3..2ec8fb1553 100644
--- a/src/app/shared/shared.module.ts
+++ b/src/app/shared/shared.module.ts
@@ -17,7 +17,6 @@ import {
} from '@ng-bootstrap/ng-bootstrap';
import { MissingTranslationHandler, TranslateModule } from '@ngx-translate/core';
import { NgxPaginationModule } from 'ngx-pagination';
-import { FileUploadModule } from 'ng2-file-upload';
import { InfiniteScrollModule } from 'ngx-infinite-scroll';
import { ConfirmationModalComponent } from './confirmation-modal/confirmation-modal.component';
import {
@@ -29,7 +28,6 @@ import {
import {
ImportBatchSelectorComponent
} from './dso-selector/modal-wrappers/import-batch-selector/import-batch-selector.component';
-import { FileDropzoneNoUploaderComponent } from './file-dropzone-no-uploader/file-dropzone-no-uploader.component';
import { ItemListElementComponent } from './object-list/item-list-element/item-types/item/item-list-element.component';
import { EnumKeysPipe } from './utils/enum-keys-pipe';
import { FileSizePipe } from './utils/file-size-pipe';
@@ -72,9 +70,6 @@ import { TruncatePipe } from './utils/truncate.pipe';
import { TruncatableComponent } from './truncatable/truncatable.component';
import { TruncatableService } from './truncatable/truncatable.service';
import { TruncatablePartComponent } from './truncatable/truncatable-part/truncatable-part.component';
-import { UploaderComponent } from './uploader/uploader.component';
-import { ChipsComponent } from './chips/chips.component';
-import { NumberPickerComponent } from './number-picker/number-picker.component';
import { MockAdminGuard } from './mocks/admin-guard.service.mock';
import { AlertComponent } from './alert/alert.component';
import {
@@ -110,7 +105,6 @@ import { EmphasizePipe } from './utils/emphasize.pipe';
import { InputSuggestionsComponent } from './input-suggestions/input-suggestions.component';
import { CapitalizePipe } from './utils/capitalize.pipe';
import { ObjectKeysPipe } from './utils/object-keys-pipe';
-import { AuthorityConfidenceStateDirective } from './authority-confidence/authority-confidence-state.directive';
import { LangSwitchComponent } from './lang-switch/lang-switch.component';
import {
PlainTextMetadataListElementComponent
@@ -231,7 +225,6 @@ import {
ImportableListItemControlComponent
} from './object-collection/shared/importable-list-item-control/importable-list-item-control.component';
import { ItemVersionsComponent } from './item/item-versions/item-versions.component';
-import { SortablejsModule } from 'ngx-sortablejs';
import { LogInContainerComponent } from './log-in/container/log-in-container.component';
import { LogInShibbolethComponent } from './log-in/methods/shibboleth/log-in-shibboleth.component';
import { LogInPasswordComponent } from './log-in/methods/password/log-in-password.component';
@@ -257,7 +250,6 @@ import { NgForTrackByIdDirective } from './ng-for-track-by-id.directive';
import { FileDownloadLinkComponent } from './file-download-link/file-download-link.component';
import { CollectionDropdownComponent } from './collection-dropdown/collection-dropdown.component';
import { EntityDropdownComponent } from './entity-dropdown/entity-dropdown.component';
-import { VocabularyTreeviewComponent } from './vocabulary-treeview/vocabulary-treeview.component';
import { CurationFormComponent } from '../curation-form/curation-form.component';
import {
PublicationSidebarSearchListElementComponent
@@ -292,9 +284,6 @@ import {
MetadataRepresentationListComponent
} from '../item-page/simple/metadata-representation-list/metadata-representation-list.component';
import { RelatedItemsComponent } from '../item-page/simple/related-items/related-items-component';
-import { LinkMenuItemComponent } from './menu/menu-item/link-menu-item.component';
-import { OnClickMenuItemComponent } from './menu/menu-item/onclick-menu-item.component';
-import { TextMenuItemComponent } from './menu/menu-item/text-menu-item.component';
import { SearchNavbarComponent } from '../search-navbar/search-navbar.component';
import { ThemedSearchNavbarComponent } from '../search-navbar/themed-search-navbar.component';
import {
@@ -311,7 +300,6 @@ import { DsSelectComponent } from './ds-select/ds-select.component';
import { LogInOidcComponent } from './log-in/methods/oidc/log-in-oidc.component';
import { ThemedItemListPreviewComponent } from './object-list/my-dspace-result-list-element/item-list-preview/themed-item-list-preview.component';
import { RSSComponent } from './rss-feed/rss.component';
-import { ExternalLinkMenuItemComponent } from './menu/menu-item/external-link-menu-item.component';
import { DsoPageOrcidButtonComponent } from './dso-page/dso-page-orcid-button/dso-page-orcid-button.component';
import { LogInOrcidComponent } from './log-in/methods/orcid/log-in-orcid.component';
import { BrowserOnlyPipe } from './utils/browser-only.pipe';
@@ -323,11 +311,14 @@ import {
} from '../item-page/simple/field-components/specific-field/title/item-page-title-field.component';
import { MarkdownPipe } from './utils/markdown.pipe';
import { GoogleRecaptchaModule } from '../core/google-recaptcha/google-recaptcha.module';
+import { MenuModule } from './menu/menu.module';
+import {
+ ListableNotificationObjectComponent
+} from './object-list/listable-notification-object/listable-notification-object.component';
+import { ThemedCollectionDropdownComponent } from './collection-dropdown/themed-collection-dropdown.component';
const MODULES = [
CommonModule,
- SortablejsModule,
- FileUploadModule,
FormsModule,
InfiniteScrollModule,
NgbNavModule,
@@ -344,6 +335,7 @@ const MODULES = [
DragDropModule,
CdkTreeModule,
GoogleRecaptchaModule,
+ MenuModule,
];
const ROOT_MODULES = [
@@ -375,7 +367,6 @@ const COMPONENTS = [
AuthNavMenuComponent,
ThemedAuthNavMenuComponent,
UserMenuComponent,
- ChipsComponent,
DsSelectComponent,
ErrorComponent,
FileSectionComponent,
@@ -384,7 +375,6 @@ const COMPONENTS = [
ThemedLoadingComponent,
LogInComponent,
LogOutComponent,
- NumberPickerComponent,
ObjectListComponent,
ThemedObjectListComponent,
ObjectDetailComponent,
@@ -399,8 +389,6 @@ const COMPONENTS = [
SidebarFilterComponent,
SidebarFilterSelectedOptionComponent,
ThumbnailComponent,
- UploaderComponent,
- FileDropzoneNoUploaderComponent,
ItemListPreviewComponent,
ThemedItemListPreviewComponent,
MyDSpaceItemStatusComponent,
@@ -408,10 +396,6 @@ const COMPONENTS = [
ItemDetailPreviewComponent,
ItemDetailPreviewFieldComponent,
ClaimedTaskActionsComponent,
- ClaimedTaskActionsApproveComponent,
- ClaimedTaskActionsRejectComponent,
- ClaimedTaskActionsReturnToPoolComponent,
- ClaimedTaskActionsEditMetadataComponent,
ClaimedTaskActionsLoaderComponent,
ItemActionsComponent,
PoolTaskActionsComponent,
@@ -426,90 +410,33 @@ const COMPONENTS = [
ValidationSuggestionsComponent,
DsoInputSuggestionsComponent,
DSOSelectorComponent,
- CreateCommunityParentSelectorComponent,
- ThemedCreateCommunityParentSelectorComponent,
- CreateCollectionParentSelectorComponent,
- ThemedCreateCollectionParentSelectorComponent,
- CreateItemParentSelectorComponent,
- ThemedCreateItemParentSelectorComponent,
- EditCommunitySelectorComponent,
- ThemedEditCommunitySelectorComponent,
- EditCollectionSelectorComponent,
- ThemedEditCollectionSelectorComponent,
- EditItemSelectorComponent,
- ThemedEditItemSelectorComponent,
- CommunitySearchResultListElementComponent,
- CollectionSearchResultListElementComponent,
- BrowseByComponent,
-
- CollectionSearchResultGridElementComponent,
- CommunitySearchResultGridElementComponent,
SearchExportCsvComponent,
PageSizeSelectorComponent,
ListableObjectComponentLoaderComponent,
- CollectionListElementComponent,
- CommunityListElementComponent,
- CollectionGridElementComponent,
- CommunityGridElementComponent,
- BrowseByComponent,
AbstractTrackableComponent,
ComcolMetadataComponent,
TypeBadgeComponent,
AccessStatusBadgeComponent,
- BrowseByComponent,
- AbstractTrackableComponent,
-
ItemSelectComponent,
CollectionSelectComponent,
MetadataRepresentationLoaderComponent,
SelectableListItemControlComponent,
-
ImportableListItemControlComponent,
-
- LogInShibbolethComponent,
- LogInOidcComponent,
- LogInOrcidComponent,
- LogInPasswordComponent,
LogInContainerComponent,
ItemVersionsComponent,
- ItemSearchResultListElementComponent,
ItemVersionsNoticeComponent,
ModifyItemOverviewComponent,
ImpersonateNavbarComponent,
- FileDownloadLinkComponent,
- BitstreamDownloadPageComponent,
- BitstreamRequestACopyPageComponent,
- CollectionDropdownComponent,
EntityDropdownComponent,
ExportMetadataSelectorComponent,
ImportBatchSelectorComponent,
ExportBatchSelectorComponent,
ConfirmationModalComponent,
- VocabularyTreeviewComponent,
AuthorizedCollectionSelectorComponent,
- CurationFormComponent,
- SearchResultListElementComponent,
- SearchResultGridElementComponent,
- ItemListElementComponent,
- ItemGridElementComponent,
- ItemSearchResultGridElementComponent,
- BrowseEntryListElementComponent,
- SearchResultDetailElementComponent,
- PlainTextMetadataListElementComponent,
- ItemMetadataListElementComponent,
- MetadataRepresentationListElementComponent,
- ItemMetadataRepresentationListElementComponent,
- BundleListElementComponent,
- StartsWithDateComponent,
- StartsWithTextComponent,
- SidebarSearchListElementComponent,
- PublicationSidebarSearchListElementComponent,
- CollectionSidebarSearchListElementComponent,
- CommunitySidebarSearchListElementComponent,
SearchNavbarComponent,
- ScopeSelectorModalComponent,
ItemPageTitleFieldComponent,
ThemedSearchNavbarComponent,
+ ListableNotificationObjectComponent,
];
const ENTRY_COMPONENTS = [
@@ -558,6 +485,7 @@ const ENTRY_COMPONENTS = [
ClaimedTaskActionsReturnToPoolComponent,
ClaimedTaskActionsEditMetadataComponent,
CollectionDropdownComponent,
+ ThemedCollectionDropdownComponent,
FileDownloadLinkComponent,
BitstreamDownloadPageComponent,
BitstreamRequestACopyPageComponent,
@@ -566,16 +494,12 @@ const ENTRY_COMPONENTS = [
ImportBatchSelectorComponent,
ExportBatchSelectorComponent,
ConfirmationModalComponent,
- VocabularyTreeviewComponent,
SidebarSearchListElementComponent,
PublicationSidebarSearchListElementComponent,
CollectionSidebarSearchListElementComponent,
CommunitySidebarSearchListElementComponent,
- LinkMenuItemComponent,
- OnClickMenuItemComponent,
- TextMenuItemComponent,
ScopeSelectorModalComponent,
- ExternalLinkMenuItemComponent
+ ListableNotificationObjectComponent,
];
const SHARED_ITEM_PAGE_COMPONENTS = [
@@ -603,7 +527,6 @@ const DIRECTIVES = [
DragClickDirective,
DebounceDirective,
ClickOutsideDirective,
- AuthorityConfidenceStateDirective,
InListValidator,
AutoFocusDirective,
RoleDirective,
@@ -626,6 +549,7 @@ const DIRECTIVES = [
declarations: [
...PIPES,
...COMPONENTS,
+ ...ENTRY_COMPONENTS,
...DIRECTIVES,
...SHARED_ITEM_PAGE_COMPONENTS,
ItemVersionsSummaryModalComponent,
@@ -638,9 +562,10 @@ const DIRECTIVES = [
...MODULES,
...PIPES,
...COMPONENTS,
+ ...ENTRY_COMPONENTS,
...SHARED_ITEM_PAGE_COMPONENTS,
...DIRECTIVES,
- TranslateModule
+ TranslateModule,
]
})
diff --git a/src/app/shared/starts-with/date/starts-with-date.component.spec.ts b/src/app/shared/starts-with/date/starts-with-date.component.spec.ts
index 3cd22a625f..2407f21fdf 100644
--- a/src/app/shared/starts-with/date/starts-with-date.component.spec.ts
+++ b/src/app/shared/starts-with/date/starts-with-date.component.spec.ts
@@ -11,11 +11,8 @@ import { StartsWithDateComponent } from './starts-with-date.component';
import { ActivatedRouteStub } from '../../testing/active-router.stub';
import { EnumKeysPipe } from '../../utils/enum-keys-pipe';
import { RouterStub } from '../../testing/router.stub';
-import { PaginationComponentOptions } from '../../pagination/pagination-component-options.model';
-import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model';
import { PaginationService } from '../../../core/pagination/pagination.service';
import { PaginationServiceStub } from '../../testing/pagination-service.stub';
-import { FindListOptions } from '../../../core/data/find-list-options.model';
describe('StartsWithDateComponent', () => {
let comp: StartsWithDateComponent;
diff --git a/src/app/shared/starts-with/text/starts-with-text.component.spec.ts b/src/app/shared/starts-with/text/starts-with-text.component.spec.ts
index c08ef5cfdc..b717c72d76 100644
--- a/src/app/shared/starts-with/text/starts-with-text.component.spec.ts
+++ b/src/app/shared/starts-with/text/starts-with-text.component.spec.ts
@@ -1,5 +1,5 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
-import { ActivatedRoute, NavigationExtras, Router } from '@angular/router';
+import { ActivatedRoute, Router } from '@angular/router';
import { CommonModule } from '@angular/common';
import { RouterTestingModule } from '@angular/router/testing';
import { TranslateModule } from '@ngx-translate/core';
@@ -8,12 +8,8 @@ import { EnumKeysPipe } from '../../utils/enum-keys-pipe';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { By } from '@angular/platform-browser';
import { StartsWithTextComponent } from './starts-with-text.component';
-import { PaginationComponentOptions } from '../../pagination/pagination-component-options.model';
-import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model';
-import { of as observableOf } from 'rxjs';
import { PaginationService } from '../../../core/pagination/pagination.service';
import { PaginationServiceStub } from '../../testing/pagination-service.stub';
-import { FindListOptions } from '../../../core/data/find-list-options.model';
describe('StartsWithTextComponent', () => {
let comp: StartsWithTextComponent;
diff --git a/src/app/shared/testing/group-mock.ts b/src/app/shared/testing/group-mock.ts
index a6db4c922e..0d6f924c01 100644
--- a/src/app/shared/testing/group-mock.ts
+++ b/src/app/shared/testing/group-mock.ts
@@ -1,6 +1,5 @@
import { Group } from '../../core/eperson/models/group.model';
import { EPersonMock } from './eperson.mock';
-import { of } from 'rxjs';
import { createSuccessfulRemoteDataObject$ } from '../remote-data.utils';
export const GroupMock2: Group = Object.assign(new Group(), {
diff --git a/src/app/shared/theme-support/themed.component.spec.ts b/src/app/shared/theme-support/themed.component.spec.ts
index 404e970a7a..7776e60379 100644
--- a/src/app/shared/theme-support/themed.component.spec.ts
+++ b/src/app/shared/theme-support/themed.component.spec.ts
@@ -71,6 +71,12 @@ describe('ThemedComponent', () => {
expect((component as any).compRef.instance.testInput).toEqual('changed');
});
}));
+
+ it(`should set usedTheme to the name of the matched theme`, waitForAsync(() => {
+ fixture.whenStable().then(() => {
+ expect(component.usedTheme).toEqual('custom');
+ });
+ }));
});
describe('when the current theme doesn\'t match a themed component', () => {
@@ -92,6 +98,12 @@ describe('ThemedComponent', () => {
expect((component as any).compRef.instance.testInput).toEqual('changed');
});
}));
+
+ it(`should set usedTheme to the name of the base theme`, waitForAsync(() => {
+ fixture.whenStable().then(() => {
+ expect(component.usedTheme).toEqual('base');
+ });
+ }));
});
describe('and it extends another theme', () => {
@@ -117,6 +129,12 @@ describe('ThemedComponent', () => {
expect((component as any).compRef.instance.testInput).toEqual('changed');
});
}));
+
+ it(`should set usedTheme to the name of the base theme`, waitForAsync(() => {
+ fixture.whenStable().then(() => {
+ expect(component.usedTheme).toEqual('base');
+ });
+ }));
});
describe('that does match it', () => {
@@ -141,6 +159,12 @@ describe('ThemedComponent', () => {
expect((component as any).compRef.instance.testInput).toEqual('changed');
});
}));
+
+ it(`should set usedTheme to the name of the matched theme`, waitForAsync(() => {
+ fixture.whenStable().then(() => {
+ expect(component.usedTheme).toEqual('custom');
+ });
+ }));
});
describe('that extends another theme that doesn\'t match it either', () => {
@@ -167,6 +191,12 @@ describe('ThemedComponent', () => {
expect((component as any).compRef.instance.testInput).toEqual('changed');
});
}));
+
+ it(`should set usedTheme to the name of the base theme`, waitForAsync(() => {
+ fixture.whenStable().then(() => {
+ expect(component.usedTheme).toEqual('base');
+ });
+ }));
});
describe('that extends another theme that does match it', () => {
@@ -193,6 +223,12 @@ describe('ThemedComponent', () => {
expect((component as any).compRef.instance.testInput).toEqual('changed');
});
}));
+
+ it(`should set usedTheme to the name of the matched theme`, waitForAsync(() => {
+ fixture.whenStable().then(() => {
+ expect(component.usedTheme).toEqual('custom');
+ });
+ }));
});
});
});
diff --git a/src/app/shared/theme-support/themed.component.ts b/src/app/shared/theme-support/themed.component.ts
index 87f182a5ff..995122d284 100644
--- a/src/app/shared/theme-support/themed.component.ts
+++ b/src/app/shared/theme-support/themed.component.ts
@@ -8,13 +8,15 @@ import {
OnDestroy,
ComponentFactoryResolver,
ChangeDetectorRef,
- OnChanges
+ OnChanges,
+ HostBinding
} from '@angular/core';
import { hasValue, isNotEmpty } from '../empty.util';
-import { from as fromPromise, Observable, of as observableOf, Subscription } from 'rxjs';
+import { from as fromPromise, Observable, of as observableOf, Subscription, BehaviorSubject } from 'rxjs';
import { ThemeService } from './theme.service';
-import { catchError, switchMap, map } from 'rxjs/operators';
+import { catchError, switchMap, map, tap } from 'rxjs/operators';
import { GenericConstructor } from '../../core/shared/generic-constructor';
+import { BASE_THEME_NAME } from './theme.constants';
@Component({
selector: 'ds-themed',
@@ -25,11 +27,22 @@ export abstract class ThemedComponent implements OnInit, OnDestroy, OnChanges
@ViewChild('vcr', { read: ViewContainerRef }) vcr: ViewContainerRef;
protected compRef: ComponentRef;
+ /**
+ * A reference to the themed component. Will start as undefined and emit every time the themed
+ * component is rendered
+ */
+ public compRef$: BehaviorSubject> = new BehaviorSubject(undefined);
+
protected lazyLoadSub: Subscription;
protected themeSub: Subscription;
protected inAndOutputNames: (keyof T & keyof this)[] = [];
+ /**
+ * A data attribute on the ThemedComponent to indicate which theme the rendered component came from.
+ */
+ @HostBinding('attr.data-used-theme') usedTheme: string;
+
constructor(
protected resolver: ComponentFactoryResolver,
protected cdr: ChangeDetectorRef,
@@ -80,6 +93,7 @@ export abstract class ThemedComponent implements OnInit, OnDestroy, OnChanges
} else {
// otherwise import and return the default component
return fromPromise(this.importUnthemedComponent()).pipe(
+ tap(() => this.usedTheme = BASE_THEME_NAME),
map((unthemedFile: any) => {
return unthemedFile[this.getComponentName()];
})
@@ -90,6 +104,7 @@ export abstract class ThemedComponent implements OnInit, OnDestroy, OnChanges
const factory = this.resolver.resolveComponentFactory(constructor);
this.compRef = this.vcr.createComponent(factory);
this.connectInputsAndOutputs();
+ this.compRef$.next(this.compRef);
this.cdr.markForCheck();
});
}
@@ -123,6 +138,7 @@ export abstract class ThemedComponent implements OnInit, OnDestroy, OnChanges
private resolveThemedComponent(themeName?: string, checkedThemeNames: string[] = []): Observable {
if (isNotEmpty(themeName)) {
return fromPromise(this.importThemedComponent(themeName)).pipe(
+ tap(() => this.usedTheme = themeName),
catchError(() => {
// Try the next ancestor theme instead
const nextTheme = this.themeService.getThemeConfigFor(themeName)?.extends;
diff --git a/src/app/shared/file-dropzone-no-uploader/file-dropzone-no-uploader.component.html b/src/app/shared/upload/file-dropzone-no-uploader/file-dropzone-no-uploader.component.html
similarity index 100%
rename from src/app/shared/file-dropzone-no-uploader/file-dropzone-no-uploader.component.html
rename to src/app/shared/upload/file-dropzone-no-uploader/file-dropzone-no-uploader.component.html
diff --git a/src/app/shared/file-dropzone-no-uploader/file-dropzone-no-uploader.component.ts b/src/app/shared/upload/file-dropzone-no-uploader/file-dropzone-no-uploader.component.ts
similarity index 100%
rename from src/app/shared/file-dropzone-no-uploader/file-dropzone-no-uploader.component.ts
rename to src/app/shared/upload/file-dropzone-no-uploader/file-dropzone-no-uploader.component.ts
diff --git a/src/app/shared/file-dropzone-no-uploader/file-dropzone-no-uploader.scss b/src/app/shared/upload/file-dropzone-no-uploader/file-dropzone-no-uploader.scss
similarity index 100%
rename from src/app/shared/file-dropzone-no-uploader/file-dropzone-no-uploader.scss
rename to src/app/shared/upload/file-dropzone-no-uploader/file-dropzone-no-uploader.scss
diff --git a/src/app/shared/upload/upload.module.ts b/src/app/shared/upload/upload.module.ts
new file mode 100644
index 0000000000..9f2895d7ac
--- /dev/null
+++ b/src/app/shared/upload/upload.module.ts
@@ -0,0 +1,38 @@
+/**
+ * The contents of this file are subject to the license and copyright
+ * detailed in the LICENSE and NOTICE files at the root of the source
+ * tree and available online at
+ *
+ * http://www.dspace.org/license/
+ */
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { SharedModule } from '../shared.module';
+import { FileUploadModule } from 'ng2-file-upload';
+import { UploaderComponent } from './uploader/uploader.component';
+import { FileDropzoneNoUploaderComponent } from './file-dropzone-no-uploader/file-dropzone-no-uploader.component';
+
+const COMPONENTS = [
+ UploaderComponent,
+ FileDropzoneNoUploaderComponent,
+];
+
+@NgModule({
+ imports: [
+ CommonModule,
+ SharedModule,
+ FileUploadModule,
+ ],
+ declarations: [
+ ...COMPONENTS,
+ ],
+ providers: [
+ ...COMPONENTS,
+ ],
+ exports: [
+ ...COMPONENTS,
+ FileUploadModule,
+ ]
+})
+export class UploadModule {
+}
diff --git a/src/app/shared/uploader/uploader-error.model.ts b/src/app/shared/upload/uploader/uploader-error.model.ts
similarity index 100%
rename from src/app/shared/uploader/uploader-error.model.ts
rename to src/app/shared/upload/uploader/uploader-error.model.ts
diff --git a/src/app/shared/uploader/uploader-options.model.ts b/src/app/shared/upload/uploader/uploader-options.model.ts
similarity index 86%
rename from src/app/shared/uploader/uploader-options.model.ts
rename to src/app/shared/upload/uploader/uploader-options.model.ts
index 959e5c3295..559fb0485b 100644
--- a/src/app/shared/uploader/uploader-options.model.ts
+++ b/src/app/shared/upload/uploader/uploader-options.model.ts
@@ -1,4 +1,4 @@
-import { RestRequestMethod } from '../../core/data/rest-request-method';
+import { RestRequestMethod } from '../../../core/data/rest-request-method';
export class UploaderOptions {
/**
diff --git a/src/app/shared/uploader/uploader-properties.model.ts b/src/app/shared/upload/uploader/uploader-properties.model.ts
similarity index 83%
rename from src/app/shared/uploader/uploader-properties.model.ts
rename to src/app/shared/upload/uploader/uploader-properties.model.ts
index bc0376b809..b84ae30bf8 100644
--- a/src/app/shared/uploader/uploader-properties.model.ts
+++ b/src/app/shared/upload/uploader/uploader-properties.model.ts
@@ -1,4 +1,4 @@
-import { MetadataMap } from '../../core/shared/metadata.models';
+import { MetadataMap } from '../../../core/shared/metadata.models';
/**
* Properties to send to the REST API for uploading a bitstream
diff --git a/src/app/shared/uploader/uploader.component.html b/src/app/shared/upload/uploader/uploader.component.html
similarity index 100%
rename from src/app/shared/uploader/uploader.component.html
rename to src/app/shared/upload/uploader/uploader.component.html
diff --git a/src/app/shared/uploader/uploader.component.scss b/src/app/shared/upload/uploader/uploader.component.scss
similarity index 100%
rename from src/app/shared/uploader/uploader.component.scss
rename to src/app/shared/upload/uploader/uploader.component.scss
diff --git a/src/app/shared/uploader/uploader.component.spec.ts b/src/app/shared/upload/uploader/uploader.component.spec.ts
similarity index 86%
rename from src/app/shared/uploader/uploader.component.spec.ts
rename to src/app/shared/upload/uploader/uploader.component.spec.ts
index 84fee2e147..8ea23c8acb 100644
--- a/src/app/shared/uploader/uploader.component.spec.ts
+++ b/src/app/shared/upload/uploader/uploader.component.spec.ts
@@ -4,16 +4,16 @@ import { ComponentFixture, inject, TestBed, waitForAsync, } from '@angular/core/
import { ScrollToService } from '@nicky-lenaers/ngx-scroll-to';
-import { UploaderService } from './uploader.service';
+import { DragService } from '../../../core/drag.service';
import { UploaderOptions } from './uploader-options.model';
import { UploaderComponent } from './uploader.component';
import { FileUploadModule } from 'ng2-file-upload';
import { TranslateModule } from '@ngx-translate/core';
-import { createTestComponent } from '../testing/utils.test';
+import { createTestComponent } from '../../testing/utils.test';
import { HttpXsrfTokenExtractor } from '@angular/common/http';
-import { CookieService } from '../../core/services/cookie.service';
-import { CookieServiceMock } from '../mocks/cookie.service.mock';
-import { HttpXsrfTokenExtractorMock } from '../mocks/http-xsrf-token-extractor.mock';
+import { CookieService } from '../../../core/services/cookie.service';
+import { CookieServiceMock } from '../../mocks/cookie.service.mock';
+import { HttpXsrfTokenExtractorMock } from '../../mocks/http-xsrf-token-extractor.mock';
describe('Chips component', () => {
@@ -37,7 +37,7 @@ describe('Chips component', () => {
ChangeDetectorRef,
ScrollToService,
UploaderComponent,
- UploaderService,
+ DragService,
{ provide: HttpXsrfTokenExtractor, useValue: new HttpXsrfTokenExtractorMock('mock-token') },
{ provide: CookieService, useValue: new CookieServiceMock() },
],
diff --git a/src/app/shared/uploader/uploader.component.ts b/src/app/shared/upload/uploader/uploader.component.ts
similarity index 93%
rename from src/app/shared/uploader/uploader.component.ts
rename to src/app/shared/upload/uploader/uploader.component.ts
index 3cbf033b17..14b1ca9b94 100644
--- a/src/app/shared/uploader/uploader.component.ts
+++ b/src/app/shared/upload/uploader/uploader.component.ts
@@ -6,12 +6,12 @@ import uniqueId from 'lodash/uniqueId';
import { ScrollToService } from '@nicky-lenaers/ngx-scroll-to';
import { UploaderOptions } from './uploader-options.model';
-import { hasValue, isNotEmpty, isUndefined } from '../empty.util';
-import { UploaderService } from './uploader.service';
+import { hasValue, isNotEmpty, isUndefined } from '../../empty.util';
import { UploaderProperties } from './uploader-properties.model';
import { HttpXsrfTokenExtractor } from '@angular/common/http';
-import { XSRF_COOKIE, XSRF_REQUEST_HEADER, XSRF_RESPONSE_HEADER } from '../../core/xsrf/xsrf.interceptor';
-import { CookieService } from '../../core/services/cookie.service';
+import { XSRF_COOKIE, XSRF_REQUEST_HEADER, XSRF_RESPONSE_HEADER } from '../../../core/xsrf/xsrf.interceptor';
+import { CookieService } from '../../../core/services/cookie.service';
+import { DragService } from '../../../core/drag.service';
@Component({
selector: 'ds-uploader',
@@ -76,7 +76,7 @@ export class UploaderComponent {
@HostListener('window:dragover', ['$event'])
onDragOver(event: any) {
- if (this.enableDragOverDocument && this.uploaderService.isAllowedDragOverPage()) {
+ if (this.enableDragOverDocument && this.dragService.isAllowedDragOverPage()) {
// Show drop area on the page
event.preventDefault();
if ((event.target as any).tagName !== 'HTML') {
@@ -85,9 +85,13 @@ export class UploaderComponent {
}
}
- constructor(private cdr: ChangeDetectorRef, private scrollToService: ScrollToService,
- private uploaderService: UploaderService, private tokenExtractor: HttpXsrfTokenExtractor,
- private cookieService: CookieService) {
+ constructor(
+ private cdr: ChangeDetectorRef,
+ private scrollToService: ScrollToService,
+ private dragService: DragService,
+ private tokenExtractor: HttpXsrfTokenExtractor,
+ private cookieService: CookieService
+ ) {
}
/**
diff --git a/src/app/statistics-page/statistics-table/statistics-table.component.html b/src/app/statistics-page/statistics-table/statistics-table.component.html
index 3ecd256812..fb042b25c3 100644
--- a/src/app/statistics-page/statistics-table/statistics-table.component.html
+++ b/src/app/statistics-page/statistics-table/statistics-table.component.html
@@ -10,7 +10,7 @@
- |
+ |