From fb40b8f0315641e5e3d0fb858842688175ae0ea9 Mon Sep 17 00:00:00 2001 From: Matteo Perelli Date: Thu, 18 Jun 2020 16:16:31 +0200 Subject: [PATCH 001/170] Submission from an external source initial commit --- .../import-external-page.component.html | 1 + .../import-external-page.component.scss | 0 .../import-external-page.component.spec.ts | 26 ++++ .../import-external-page.component.ts | 13 ++ .../import-external-page.module.ts | 28 ++++ .../import-external-routing.module.ts | 24 +++ .../my-dspace-new-submission.component.html | 3 + src/app/app-routing.module.ts | 1 + src/app/core/data/external-source.service.ts | 17 ++- ...n-import-external-searchbar.component.html | 24 +++ ...n-import-external-searchbar.component.scss | 12 ++ ...ion-import-external-searchbar.component.ts | 143 ++++++++++++++++++ .../submission-import-external.component.html | 24 +++ .../submission-import-external.component.scss | 0 .../submission-import-external.component.ts | 35 +++++ src/app/submission/submission.module.ts | 7 +- src/assets/i18n/en.json5 | 28 ++++ 17 files changed, 383 insertions(+), 3 deletions(-) create mode 100644 src/app/+import-external-page/import-external-page.component.html create mode 100644 src/app/+import-external-page/import-external-page.component.scss create mode 100644 src/app/+import-external-page/import-external-page.component.spec.ts create mode 100644 src/app/+import-external-page/import-external-page.component.ts create mode 100644 src/app/+import-external-page/import-external-page.module.ts create mode 100644 src/app/+import-external-page/import-external-routing.module.ts create mode 100644 src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html create mode 100644 src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.scss create mode 100644 src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts create mode 100644 src/app/submission/import-external/submission-import-external.component.html create mode 100644 src/app/submission/import-external/submission-import-external.component.scss create mode 100644 src/app/submission/import-external/submission-import-external.component.ts diff --git a/src/app/+import-external-page/import-external-page.component.html b/src/app/+import-external-page/import-external-page.component.html new file mode 100644 index 0000000000..5edccd55cb --- /dev/null +++ b/src/app/+import-external-page/import-external-page.component.html @@ -0,0 +1 @@ + diff --git a/src/app/+import-external-page/import-external-page.component.scss b/src/app/+import-external-page/import-external-page.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/+import-external-page/import-external-page.component.spec.ts b/src/app/+import-external-page/import-external-page.component.spec.ts new file mode 100644 index 0000000000..e673959a32 --- /dev/null +++ b/src/app/+import-external-page/import-external-page.component.spec.ts @@ -0,0 +1,26 @@ +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { ImportExternalPageComponent } from './import-external-page.component'; + +fdescribe('ImportExternalPageComponent', () => { + let component: ImportExternalPageComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ImportExternalPageComponent ], + schemas: [NO_ERRORS_SCHEMA] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ImportExternalPageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create ImportExternalPageComponent', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/+import-external-page/import-external-page.component.ts b/src/app/+import-external-page/import-external-page.component.ts new file mode 100644 index 0000000000..c205482cb3 --- /dev/null +++ b/src/app/+import-external-page/import-external-page.component.ts @@ -0,0 +1,13 @@ +import { Component, Injector, OnInit } from '@angular/core'; + +/** + * Component representing the external import page of the submission. + */ +@Component({ + selector: 'ds-import-external-page', + templateUrl: './import-external-page.component.html', + styleUrls: ['./import-external-page.component.scss'] +}) +export class ImportExternalPageComponent { + +} diff --git a/src/app/+import-external-page/import-external-page.module.ts b/src/app/+import-external-page/import-external-page.module.ts new file mode 100644 index 0000000000..c81e80615f --- /dev/null +++ b/src/app/+import-external-page/import-external-page.module.ts @@ -0,0 +1,28 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; + +import { SharedModule } from '../shared/shared.module'; +import { CoreModule } from '../core/core.module'; +import { ImportExternalRoutingModule } from './import-external-routing.module'; +import { SubmissionImportExternalComponent } from '../submission/import-external/submission-import-external.component'; +import { SubmissionImportExternalSearchbarComponent } from '../submission/import-external/import-external-searchbar/submission-import-external-searchbar.component'; +import { SubmissionModule } from '../submission/submission.module'; + +@NgModule({ + imports: [ + CommonModule, + SharedModule, + CoreModule.forRoot(), + ImportExternalRoutingModule, + SubmissionModule, + ], + declarations: [ ], + entryComponents: [ ] +}) + +/** + * This module handles all components that are necessary for the submission external import page + */ +export class ImportExternalPageModule { + +} diff --git a/src/app/+import-external-page/import-external-routing.module.ts b/src/app/+import-external-page/import-external-routing.module.ts new file mode 100644 index 0000000000..91cdbf9877 --- /dev/null +++ b/src/app/+import-external-page/import-external-routing.module.ts @@ -0,0 +1,24 @@ +import { NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; +import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; +import { SubmissionImportExternalComponent } from '../submission/import-external/submission-import-external.component'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + { + canActivate: [ AuthenticatedGuard ], + path: '', + component: SubmissionImportExternalComponent, + pathMatch: 'full', + data: { + title: 'submission.import-external.page.title' + } + } + ]) + ], + providers: [ ] +}) +export class ImportExternalRoutingModule { + +} diff --git a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html index 911ba26b31..3adaea7128 100644 --- a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html +++ b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html @@ -10,6 +10,9 @@ {{'mydspace.new-submission' | translate}} + + {{'mydspace.new-submission-external' | translate}} + diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 0ba0851e4e..655f0f94fc 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -86,6 +86,7 @@ export function getDSOPath(dso: DSpaceObject): string { { path: 'login', loadChildren: './+login-page/login-page.module#LoginPageModule' }, { path: 'logout', loadChildren: './+logout-page/logout-page.module#LogoutPageModule' }, { path: 'submit', loadChildren: './+submit-page/submit-page.module#SubmitPageModule' }, + { path: 'import-external', loadChildren: './+import-external-page/import-external-page.module#ImportExternalPageModule' }, { path: 'workspaceitems', loadChildren: './+workspaceitems-edit-page/workspaceitems-edit-page.module#WorkspaceitemsEditPageModule' diff --git a/src/app/core/data/external-source.service.ts b/src/app/core/data/external-source.service.ts index 0c1a8d255c..8ad0494f3d 100644 --- a/src/app/core/data/external-source.service.ts +++ b/src/app/core/data/external-source.service.ts @@ -11,7 +11,7 @@ import { NotificationsService } from '../../shared/notifications/notifications.s import { HttpClient } from '@angular/common/http'; import { FindListOptions, GetRequest } from './request.models'; import { Observable } from 'rxjs/internal/Observable'; -import { distinctUntilChanged, map, switchMap } from 'rxjs/operators'; +import { distinctUntilChanged, map, switchMap, take, flatMap } from 'rxjs/operators'; import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; import { hasValue, isNotEmptyOperator } from '../../shared/empty.util'; import { configureRequest } from '../shared/operators'; @@ -19,6 +19,7 @@ import { RemoteData } from './remote-data'; import { PaginatedList } from './paginated-list'; import { ExternalSourceEntry } from '../shared/external-source-entry.model'; import { DefaultChangeAnalyzer } from './default-change-analyzer.service'; +import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; /** * A service handling all external source requests @@ -59,6 +60,20 @@ export class ExternalSourceService extends DataService { ); } + /** + * Return the list of external sources. + * + * @param options + * Find list options object. + * @param linksToFollow + * List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved. + * @return Observable>> + * The list of the external sources. + */ + getAllExternalSources(options: FindListOptions = {}, ...linksToFollow: Array>): Observable>> { + return this.findAll(options, ...linksToFollow); + } + /** * Get the entries for an external source * @param externalSourceId The id of the external source to fetch entries for diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html new file mode 100644 index 0000000000..f7a971a381 --- /dev/null +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html @@ -0,0 +1,24 @@ +
+ +
+
+ + + +
+
+
diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.scss b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.scss new file mode 100644 index 0000000000..076ceae9b8 --- /dev/null +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.scss @@ -0,0 +1,12 @@ +.input-group-append .btn.btn { + margin-left: -1px; +} + +.input-group-append .dropdown-toggle { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.w-fx { + min-width: 200px; +} diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts new file mode 100644 index 0000000000..e13c8dad3b --- /dev/null +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts @@ -0,0 +1,143 @@ +import { Component, OnInit, ChangeDetectorRef, Output, EventEmitter } from '@angular/core'; +import { of as observableOf } from 'rxjs'; +import { ExternalSourceService } from '../../../core/data/external-source.service'; +import { catchError, first, tap } from 'rxjs/operators'; +import { ExternalSource } from '../../../core/shared/external-source.model'; +import { PaginatedList } from '../../../core/data/paginated-list'; +import { RemoteData } from '../../../core/data/remote-data'; +import { PageInfo } from '../../../core/shared/page-info.model'; +import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils'; +import { FindListOptions } from '../../../core/data/request.models'; + +/** + * Interface for the selected external source element. + */ +interface SourceElement { + id: string; + name: string; +} + +/** + * Interface for the external source data to export. + */ +export interface ExternalSourceData { + query: string; + sourceId: string; +} + +/** + * This component builds the searchbar for the submission external import. + */ +@Component({ + selector: 'ds-submission-import-external-searchbar', + styleUrls: ['./submission-import-external-searchbar.component.scss'], + templateUrl: './submission-import-external-searchbar.component.html' +}) +export class SubmissionImportExternalSearchbarComponent implements OnInit { + /** + * The selected external sources. + */ + public selectedElement: SourceElement; + /** + * The list of external sources. + */ + public sourceList: SourceElement[] = []; + /** + * The string used to search items in the external sources. + */ + public searchString: string; + /** + * The external sources loading status. + */ + public sourceListloading = false; + /** + * The external source data to use to perform the search. + */ + @Output() public externalSourceData: EventEmitter = new EventEmitter(); + + /** + * The external sources pagination data. + */ + protected pageInfo: PageInfo; + /** + * The options for REST data retireval. + */ + protected findListOptions: FindListOptions; + + /** + * Initialize the component variables. + * @param {ExternalSourceService} externalService + * @param {ChangeDetectorRef} cdr + */ + constructor( + private externalService: ExternalSourceService, + private cdr: ChangeDetectorRef, + ) { } + + /** + * Component intitialization and retireve first page of external sources. + */ + ngOnInit() { + this.searchString = ''; + this.selectedElement = {id: '', name: 'loading'}; + this.findListOptions = { + elementsPerPage: 5, + currentPage: 0, + }; + this.externalService.getAllExternalSources(this.findListOptions).pipe( + catchError(() => { + const pageInfo = new PageInfo(); + const paginatedList = new PaginatedList(pageInfo, []); + const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); + return observableOf(paginatedListRD); + }), + first() + ).subscribe((externalSource: RemoteData>) => { + externalSource.payload.page.forEach((element) => { + this.sourceList.push({id: element.id, name: element.name}); + this.selectedElement = this.sourceList[0]; + }); + this.pageInfo = externalSource.payload.pageInfo; + this.cdr.detectChanges(); + }); + } + + /** + * Set the selected external source. + */ + makeSourceSelection(source) { + this.selectedElement = source; + } + + /** + * Load the next pages of external sources. + */ + onScroll() { + if (!this.sourceListloading && this.pageInfo.currentPage <= this.pageInfo.totalPages) { + this.sourceListloading = true; + this.findListOptions.currentPage++; + this.externalService.getAllExternalSources(this.findListOptions).pipe( + catchError(() => { + const pageInfo = new PageInfo(); + const paginatedList = new PaginatedList(pageInfo, []); + const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); + return observableOf(paginatedListRD); + }), + tap(() => this.sourceListloading = false)) + .subscribe((externalSource: RemoteData>) => { + externalSource.payload.page.forEach((element) => { + this.sourceList.push({id: element.id, name: element.name}); + }) + this.pageInfo = externalSource.payload.pageInfo; + this.cdr.detectChanges(); + }) + } + } + + /** + * Passes the search parameters to the parent component. + */ + public search() { + this.externalSourceData.emit({sourceId: this.selectedElement.id, query: this.searchString}); + } +} diff --git a/src/app/submission/import-external/submission-import-external.component.html b/src/app/submission/import-external/submission-import-external.component.html new file mode 100644 index 0000000000..1d2c7cb7c7 --- /dev/null +++ b/src/app/submission/import-external/submission-import-external.component.html @@ -0,0 +1,24 @@ +
+
+
+ + + +
+
+
+
+ DATA
+ {{(externalSourceData)?externalSourceData.sourceId:''}} : {{(externalSourceData)?externalSourceData.query:''}} +
+
+ +
diff --git a/src/app/submission/import-external/submission-import-external.component.scss b/src/app/submission/import-external/submission-import-external.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/submission/import-external/submission-import-external.component.ts b/src/app/submission/import-external/submission-import-external.component.ts new file mode 100644 index 0000000000..2b53961540 --- /dev/null +++ b/src/app/submission/import-external/submission-import-external.component.ts @@ -0,0 +1,35 @@ +import { Component, OnInit, ChangeDetectorRef } from '@angular/core'; +import { Observable, of as observableOf } from 'rxjs'; +import { ExternalSourceService } from '../../core/data/external-source.service'; +import { ExternalSourceData } from './import-external-searchbar/submission-import-external-searchbar.component'; + +/** + * This component allows to submit a new workspaceitem importing the data from an external source. + */ +@Component({ + selector: 'ds-submission-import-external', + styleUrls: ['./submission-import-external.component.scss'], + templateUrl: './submission-import-external.component.html' +}) +export class SubmissionImportExternalComponent { + /** + * The external source search data. + */ + public externalSourceData: ExternalSourceData; + + /** + * Initialize the component variables. + * @param {ExternalSourceService} externalService + */ + constructor( + private externalService: ExternalSourceService, + private cdr: ChangeDetectorRef, + ) { } + + /** + * Get the data to submit a search. + */ + public getExternalsourceData(event: ExternalSourceData) { + this.externalSourceData = event; + } +} diff --git a/src/app/submission/submission.module.ts b/src/app/submission/submission.module.ts index 806258baa8..f7accaf0ca 100644 --- a/src/app/submission/submission.module.ts +++ b/src/app/submission/submission.module.ts @@ -28,7 +28,8 @@ import { SubmissionSectionUploadFileViewComponent } from './sections/upload/file import { SubmissionSectionUploadAccessConditionsComponent } from './sections/upload/accessConditions/submission-section-upload-access-conditions.component'; import { SubmissionSubmitComponent } from './submit/submission-submit.component'; import { storeModuleConfig } from '../app.reducer'; -import { CoreState } from '../core/core.reducers'; +import { SubmissionImportExternalComponent } from './import-external/submission-import-external.component'; +import { SubmissionImportExternalSearchbarComponent } from './import-external/import-external-searchbar/submission-import-external-searchbar.component'; @NgModule({ imports: [ @@ -55,7 +56,9 @@ import { CoreState } from '../core/core.reducers'; SubmissionUploadFilesComponent, SubmissionSectionUploadFileComponent, SubmissionSectionUploadFileEditComponent, - SubmissionSectionUploadFileViewComponent + SubmissionSectionUploadFileViewComponent, + SubmissionImportExternalComponent, + SubmissionImportExternalSearchbarComponent, ], entryComponents: [ SubmissionSectionUploadComponent, diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 4173fa1cf2..bd0f23d24e 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1767,6 +1767,8 @@ "mydspace.new-submission": "New submission", + "mydspace.new-submission-external": "Import from external source", + "mydspace.results.head": "Your submissions", "mydspace.results.no-abstract": "No Abstract", @@ -2396,6 +2398,32 @@ "submission.general.save-later": "Save for later", + "submission.import-external.page.title": "Import metadata from an external source", + + "submission.import-external.title": "Import metadata from an external source", + + "submission.import-external.back-to-my-dspace": "Back to MyDSpace", + + "submission.import-external.search.placeholder": "Search the external source", + + "submission.import-external.search.button": "Search", + + "submission.import-external.search.button.hint": "Write some words to search", + + "submission.import-external.search.source.hint": "Pick an external source", + + "submission.import-external.source.loading": "Loading ...", + + "submission.import-external.source.sherpaJournal": "SHERPA Journals", + + "submission.import-external.source.sherpaPublisher": "SHERPA Publishers", + + "submission.import-external.source.orcidV2": "ORCID", + + "submission.import-external.source.pubmed": "Pubmed", + + "submission.import-external.source.lcname": "Library of Congress Names", + "submission.sections.describe.relationship-lookup.close": "Close", From 63cff331d2445718b39941a4548b87654d81c81b Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 18 Jun 2020 19:01:34 +0200 Subject: [PATCH 002/170] Fixed scrollable dropdown --- ...n-import-external-searchbar.component.html | 34 ++++++----- ...n-import-external-searchbar.component.scss | 22 +++++++- ...ion-import-external-searchbar.component.ts | 56 ++++++++++++------- .../submission-import-external.component.html | 1 + 4 files changed, 72 insertions(+), 41 deletions(-) diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html index f7a971a381..a63828568d 100644 --- a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html @@ -1,24 +1,22 @@
-
-
- - diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.scss b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.scss index 076ceae9b8..562b5b5613 100644 --- a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.scss +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.scss @@ -1,12 +1,28 @@ -.input-group-append .btn.btn { +.input-group-append .btn { margin-left: -1px; + border-top-left-radius: 0; + border-bottom-left-radius: 0; } .input-group-append .dropdown-toggle { - border-top-right-radius: 0; - border-bottom-right-radius: 0; + border-radius: 0; } .w-fx { min-width: 200px; } + +.scrollable-menu { + height: auto; + max-height: $dropdown-menu-max-height; + overflow-x: hidden; +} + +.scrollable-dropdown-loading { + background-color: map-get($theme-colors, primary); + color: white; + height: $spacer * 2 !important; + line-height: $spacer * 2; + position: sticky; + bottom: 0; +} diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts index e13c8dad3b..039d11de30 100644 --- a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts @@ -1,13 +1,17 @@ -import { Component, OnInit, ChangeDetectorRef, Output, EventEmitter } from '@angular/core'; +import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; + import { of as observableOf } from 'rxjs'; +import { catchError, tap } from 'rxjs/operators'; + import { ExternalSourceService } from '../../../core/data/external-source.service'; -import { catchError, first, tap } from 'rxjs/operators'; import { ExternalSource } from '../../../core/shared/external-source.model'; import { PaginatedList } from '../../../core/data/paginated-list'; import { RemoteData } from '../../../core/data/remote-data'; import { PageInfo } from '../../../core/shared/page-info.model'; import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils'; import { FindListOptions } from '../../../core/data/request.models'; +import { isEmpty } from '../../../shared/empty.util'; +import { getFirstSucceededRemoteDataPayload } from '../../../core/shared/operators'; /** * Interface for the selected external source element. @@ -34,6 +38,10 @@ export interface ExternalSourceData { templateUrl: './submission-import-external-searchbar.component.html' }) export class SubmissionImportExternalSearchbarComponent implements OnInit { + /** + * The init external source value. + */ + @Input() public initExternalSourceValue: string; /** * The selected external sources. */ @@ -49,7 +57,7 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { /** * The external sources loading status. */ - public sourceListloading = false; + public sourceListLoading = false; /** * The external source data to use to perform the search. */ @@ -72,18 +80,19 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { constructor( private externalService: ExternalSourceService, private cdr: ChangeDetectorRef, - ) { } + ) { + } /** - * Component intitialization and retireve first page of external sources. + * Component initialization and retrieve first page of external sources. */ ngOnInit() { this.searchString = ''; - this.selectedElement = {id: '', name: 'loading'}; - this.findListOptions = { + this.selectedElement = { id: '', name: 'loading' }; + this.findListOptions = Object.assign({}, new FindListOptions(), { elementsPerPage: 5, currentPage: 0, - }; + }); this.externalService.getAllExternalSources(this.findListOptions).pipe( catchError(() => { const pageInfo = new PageInfo(); @@ -91,13 +100,17 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); return observableOf(paginatedListRD); }), - first() - ).subscribe((externalSource: RemoteData>) => { - externalSource.payload.page.forEach((element) => { - this.sourceList.push({id: element.id, name: element.name}); - this.selectedElement = this.sourceList[0]; + getFirstSucceededRemoteDataPayload() + ).subscribe((externalSource: PaginatedList) => { + let initEntry; + externalSource.page.forEach((element) => { + this.sourceList.push({ id: element.id, name: element.name }); + if (isEmpty(initEntry) || this.initExternalSourceValue === element.id) { + initEntry = { id: element.id, name: element.name } + } }); - this.pageInfo = externalSource.payload.pageInfo; + this.selectedElement = initEntry; + this.pageInfo = externalSource.pageInfo; this.cdr.detectChanges(); }); } @@ -113,9 +126,12 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { * Load the next pages of external sources. */ onScroll() { - if (!this.sourceListloading && this.pageInfo.currentPage <= this.pageInfo.totalPages) { - this.sourceListloading = true; - this.findListOptions.currentPage++; + if (!this.sourceListLoading && this.pageInfo.currentPage <= this.pageInfo.totalPages) { + this.sourceListLoading = true; + this.findListOptions = Object.assign({}, new FindListOptions(), { + elementsPerPage: 5, + currentPage: this.findListOptions.currentPage + 1, + }); this.externalService.getAllExternalSources(this.findListOptions).pipe( catchError(() => { const pageInfo = new PageInfo(); @@ -123,10 +139,10 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); return observableOf(paginatedListRD); }), - tap(() => this.sourceListloading = false)) + tap(() => this.sourceListLoading = false)) .subscribe((externalSource: RemoteData>) => { externalSource.payload.page.forEach((element) => { - this.sourceList.push({id: element.id, name: element.name}); + this.sourceList.push({ id: element.id, name: element.name }); }) this.pageInfo = externalSource.payload.pageInfo; this.cdr.detectChanges(); @@ -138,6 +154,6 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { * Passes the search parameters to the parent component. */ public search() { - this.externalSourceData.emit({sourceId: this.selectedElement.id, query: this.searchString}); + this.externalSourceData.emit({ sourceId: this.selectedElement.id, query: this.searchString }); } } diff --git a/src/app/submission/import-external/submission-import-external.component.html b/src/app/submission/import-external/submission-import-external.component.html index 1d2c7cb7c7..43e1c8ba71 100644 --- a/src/app/submission/import-external/submission-import-external.component.html +++ b/src/app/submission/import-external/submission-import-external.component.html @@ -3,6 +3,7 @@
From e7ef9dab20b7265555123df69ca0f1a27ab6cb20 Mon Sep 17 00:00:00 2001 From: Matteo Perelli Date: Mon, 22 Jun 2020 19:59:10 +0200 Subject: [PATCH 003/170] External source items import code completed --- .../import-external-page.component.spec.ts | 2 +- .../core/data/external-source.service.spec.ts | 17 +++ src/app/core/data/external-source.service.ts | 16 +- ...ion-import-external-searchbar.component.ts | 20 ++- .../submission-import-external.component.html | 29 +++- .../submission-import-external.component.ts | 137 ++++++++++++++++-- src/app/submission/submission.module.ts | 6 +- src/assets/i18n/en.json5 | 10 ++ 8 files changed, 213 insertions(+), 24 deletions(-) diff --git a/src/app/+import-external-page/import-external-page.component.spec.ts b/src/app/+import-external-page/import-external-page.component.spec.ts index e673959a32..5a2b7c5f8e 100644 --- a/src/app/+import-external-page/import-external-page.component.spec.ts +++ b/src/app/+import-external-page/import-external-page.component.spec.ts @@ -2,7 +2,7 @@ import { NO_ERRORS_SCHEMA } from '@angular/core'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { ImportExternalPageComponent } from './import-external-page.component'; -fdescribe('ImportExternalPageComponent', () => { +describe('ImportExternalPageComponent', () => { let component: ImportExternalPageComponent; let fixture: ComponentFixture; diff --git a/src/app/core/data/external-source.service.spec.ts b/src/app/core/data/external-source.service.spec.ts index 7c7d676bc7..2fc4589bed 100644 --- a/src/app/core/data/external-source.service.spec.ts +++ b/src/app/core/data/external-source.service.spec.ts @@ -74,4 +74,21 @@ describe('ExternalSourceService', () => { }); }); }); + + describe('getAllExternalSources', () => { + it('should call findAll', () => { + spyOn(service, 'findAll'); + service.getAllExternalSources(); + expect(service.findAll).toHaveBeenCalled(); + }); + }); + + describe('getExternalSource', () => { + it('should call findById', () => { + const externalSourceId = 'orcidV2'; + spyOn(service, 'findById'); + service.getExternalSource(externalSourceId); + expect(service.findById).toHaveBeenCalledWith(externalSourceId); + }); + }); }); diff --git a/src/app/core/data/external-source.service.ts b/src/app/core/data/external-source.service.ts index 8ad0494f3d..eda0440b4a 100644 --- a/src/app/core/data/external-source.service.ts +++ b/src/app/core/data/external-source.service.ts @@ -11,7 +11,7 @@ import { NotificationsService } from '../../shared/notifications/notifications.s import { HttpClient } from '@angular/common/http'; import { FindListOptions, GetRequest } from './request.models'; import { Observable } from 'rxjs/internal/Observable'; -import { distinctUntilChanged, map, switchMap, take, flatMap } from 'rxjs/operators'; +import { distinctUntilChanged, map, switchMap, take, flatMap, catchError } from 'rxjs/operators'; import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; import { hasValue, isNotEmptyOperator } from '../../shared/empty.util'; import { configureRequest } from '../shared/operators'; @@ -60,6 +60,20 @@ export class ExternalSourceService extends DataService { ); } + /** + * Return a single external source. + * + * @param id + * The external source id. + * @param linksToFollow + * List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved. + * @return Observable> + * The list of the external sources. + */ + getExternalSource(id: string, ...linksToFollow: Array>): Observable> { + return this.findById(id, ...linksToFollow); + } + /** * Return the list of external sources. * diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts index 039d11de30..cd2f24eb2c 100644 --- a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts @@ -41,7 +41,7 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { /** * The init external source value. */ - @Input() public initExternalSourceValue: string; + @Input() public initExternalSourceData: ExternalSourceData; /** * The selected external sources. */ @@ -49,7 +49,7 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { /** * The list of external sources. */ - public sourceList: SourceElement[] = []; + public sourceList: SourceElement[]; /** * The string used to search items in the external sources. */ @@ -87,8 +87,12 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { * Component initialization and retrieve first page of external sources. */ ngOnInit() { + this.selectedElement = { + id: '', + name: 'loading' + }; this.searchString = ''; - this.selectedElement = { id: '', name: 'loading' }; + this.sourceList = []; this.findListOptions = Object.assign({}, new FindListOptions(), { elementsPerPage: 5, currentPage: 0, @@ -102,14 +106,16 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { }), getFirstSucceededRemoteDataPayload() ).subscribe((externalSource: PaginatedList) => { - let initEntry; externalSource.page.forEach((element) => { this.sourceList.push({ id: element.id, name: element.name }); - if (isEmpty(initEntry) || this.initExternalSourceValue === element.id) { - initEntry = { id: element.id, name: element.name } + if (this.initExternalSourceData.sourceId === element.id) { + this.selectedElement = { id: element.id, name: element.name }; + this.searchString = this.initExternalSourceData.query; } }); - this.selectedElement = initEntry; + if (this.selectedElement.id === '') { + this.selectedElement = this.sourceList[0]; + } this.pageInfo = externalSource.pageInfo; this.cdr.detectChanges(); }); diff --git a/src/app/submission/import-external/submission-import-external.component.html b/src/app/submission/import-external/submission-import-external.component.html index 43e1c8ba71..2aac8557aa 100644 --- a/src/app/submission/import-external/submission-import-external.component.html +++ b/src/app/submission/import-external/submission-import-external.component.html @@ -3,15 +3,36 @@
-
- DATA
- {{(externalSourceData)?externalSourceData.sourceId:''}} : {{(externalSourceData)?externalSourceData.query:''}} +
+ +

{{ 'submission.sections.describe.relationship-lookup.selection-tab.title.' + routeData.sourceId | translate}}

+ + + +
+ {{ 'search.results.empty' | translate }} +
+
+
+
+
+

{{'submission.import-external.page.hint' | translate}}

+
diff --git a/src/app/submission/import-external/submission-import-external.component.ts b/src/app/submission/import-external/submission-import-external.component.ts index 2b53961540..47ae781baa 100644 --- a/src/app/submission/import-external/submission-import-external.component.ts +++ b/src/app/submission/import-external/submission-import-external.component.ts @@ -1,7 +1,22 @@ -import { Component, OnInit, ChangeDetectorRef } from '@angular/core'; -import { Observable, of as observableOf } from 'rxjs'; +import { Component, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; +import { combineLatest, BehaviorSubject } from 'rxjs'; import { ExternalSourceService } from '../../core/data/external-source.service'; import { ExternalSourceData } from './import-external-searchbar/submission-import-external-searchbar.component'; +import { RemoteData } from '../../core/data/remote-data'; +import { PaginatedList } from '../../core/data/paginated-list'; +import { ExternalSourceEntry } from '../../core/shared/external-source-entry.model'; +import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service'; +import { switchMap, filter } from 'rxjs/operators'; +import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; +import { Context } from '../../core/shared/context.model'; +import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; +import { RouteService } from '../../core/services/route.service'; +import { createSuccessfulRemoteDataObject } from '../../shared/remote-data.utils'; +import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; +import { SubmissionImportExternalPreviewComponent } from './import-external-preview/submission-import-external-preview.component'; +import { fadeIn } from '../../shared/animations/fade'; +import { createPaginatedList } from '../../shared/testing/utils.test'; /** * This component allows to submit a new workspaceitem importing the data from an external source. @@ -9,27 +24,129 @@ import { ExternalSourceData } from './import-external-searchbar/submission-impor @Component({ selector: 'ds-submission-import-external', styleUrls: ['./submission-import-external.component.scss'], - templateUrl: './submission-import-external.component.html' + templateUrl: './submission-import-external.component.html', + animations: [ fadeIn ] }) -export class SubmissionImportExternalComponent { +export class SubmissionImportExternalComponent implements OnInit { /** - * The external source search data. + * The external source search data from the routing service. */ - public externalSourceData: ExternalSourceData; + public routeData: ExternalSourceData; + /** + * The displayed list of entries + */ + public entriesRD$: BehaviorSubject>>; + /** + * TRUE if the REST service is called to retrieve the external source items + */ + public isLoading$: BehaviorSubject; + /** + * Configuration to use for the import buttons + */ + public importConfig: { buttonLabel: string }; + /** + * Suffix for button label + */ + public label: string; + /** + * The ID of the list to add/remove selected items to/from + */ + public listId: string; + /** + * TRUE if the selection is repeatable + */ + public repeatable: boolean; + /** + * The initial pagination options + */ + public initialPagination = Object.assign(new PaginationComponentOptions(), { + id: 'submission-external-source-relation-list', + pageSize: 5 + }); + /** + * The context to displaying lists for + */ + public context: Context; + /** + * The modal for the entry preview + */ + modalRef: NgbModalRef; /** * Initialize the component variables. + * @param {SearchConfigurationService} searchConfigService * @param {ExternalSourceService} externalService + * @param {RouteService} routeService + * @param {Router} router + * @param {NgbModal} modalService */ constructor( + public searchConfigService: SearchConfigurationService, private externalService: ExternalSourceService, - private cdr: ChangeDetectorRef, + private routeService: RouteService, + private router: Router, + private modalService: NgbModal, ) { } /** - * Get the data to submit a search. + * Get the entries for the selected external source and set initial configuration. */ - public getExternalsourceData(event: ExternalSourceData) { - this.externalSourceData = event; + ngOnInit(): void { + this.label = 'Journal'; + this.listId = 'list-submission-external-sources'; + this.context = Context.SubmissionModal; + this.repeatable = false; + this.routeData = { sourceId: '', query: '' }; + this.importConfig = { + buttonLabel: 'submission.sections.describe.relationship-lookup.external-source.import-button-title.' + this.label + }; + this.entriesRD$ = new BehaviorSubject(createSuccessfulRemoteDataObject(createPaginatedList([]))); + this.isLoading$ = new BehaviorSubject(false); + combineLatest( + [ + this.routeService.getQueryParameterValue('source'), + this.routeService.getQueryParameterValue('query') + ]).pipe( + filter(([source, query]) => source && query && source !== '' && query !== ''), + filter(([source, query]) => source !== this.routeData.sourceId || query !== this.routeData.query), + switchMap(([source, query]) => { + this.routeData.sourceId = source; + this.routeData.query = query; + this.isLoading$.next(true); + return this.searchConfigService.paginatedSearchOptions.pipe( + switchMap((searchOptions: PaginatedSearchOptions) => { + return this.externalService.getExternalSourceEntries(this.routeData.sourceId, searchOptions); + }) + ) + }), + ).subscribe((rdData) => { + this.entriesRD$.next(rdData); + this.isLoading$.next(false); + }); + } + + /** + * Get the data from the searchbar and changes the router data. + */ + public getExternalsourceData(event: ExternalSourceData): void { + this.router.navigate( + [], + { + queryParams: { source: event.sourceId, query: event.query }, + replaceUrl: true + } + ); + } + + /** + * Display an item preview by opening up an import modal window. + * @param entry The entry to import + */ + public import(entry): void { + this.modalRef = this.modalService.open(SubmissionImportExternalPreviewComponent, { + size: 'lg', + }); + const modalComp = this.modalRef.componentInstance; + modalComp.externalSourceEntry = entry; } } diff --git a/src/app/submission/submission.module.ts b/src/app/submission/submission.module.ts index f7accaf0ca..7ff8b98d9e 100644 --- a/src/app/submission/submission.module.ts +++ b/src/app/submission/submission.module.ts @@ -30,6 +30,7 @@ import { SubmissionSubmitComponent } from './submit/submission-submit.component' import { storeModuleConfig } from '../app.reducer'; import { SubmissionImportExternalComponent } from './import-external/submission-import-external.component'; import { SubmissionImportExternalSearchbarComponent } from './import-external/import-external-searchbar/submission-import-external-searchbar.component'; +import { SubmissionImportExternalPreviewComponent } from './import-external/import-external-preview/submission-import-external-preview.component'; @NgModule({ imports: [ @@ -59,12 +60,15 @@ import { SubmissionImportExternalSearchbarComponent } from './import-external/im SubmissionSectionUploadFileViewComponent, SubmissionImportExternalComponent, SubmissionImportExternalSearchbarComponent, + SubmissionImportExternalPreviewComponent ], entryComponents: [ SubmissionSectionUploadComponent, SubmissionSectionformComponent, SubmissionSectionLicenseComponent, - SubmissionSectionContainerComponent], + SubmissionSectionContainerComponent, + SubmissionImportExternalPreviewComponent + ], exports: [ SubmissionEditComponent, SubmissionFormComponent, diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index bd0f23d24e..3e2994142d 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -2402,6 +2402,8 @@ "submission.import-external.title": "Import metadata from an external source", + "submission.import-external.page.hint": "Search items using external sources.", + "submission.import-external.back-to-my-dspace": "Back to MyDSpace", "submission.import-external.search.placeholder": "Search the external source", @@ -2424,6 +2426,12 @@ "submission.import-external.source.lcname": "Library of Congress Names", + "submission.import-external.preview.title": "Item Preview", + + "submission.import-external.preview.subtitle": "The metadata below was imported from an external source. It will be pre-filled when you start the submission.", + + "submission.import-external.preview.button.import": "Start submission", + "submission.sections.describe.relationship-lookup.close": "Close", @@ -2555,6 +2563,8 @@ "submission.sections.describe.relationship-lookup.selection-tab.title.orcidV2": "Search Results", + "submission.sections.describe.relationship-lookup.selection-tab.title.orcidv2": "Search Results", + "submission.sections.describe.relationship-lookup.selection-tab.title.lcname": "Search Results", "submission.sections.describe.relationship-lookup.name-variant.notification.content": "Would you like to save \"{{ value }}\" as a name variant for this person so you and others can reuse it for future submissions? If you don\'t you can still use it for this submission.", From 2f04b6ae831c72cb129edb4b0ad7e46b9dee8692 Mon Sep 17 00:00:00 2001 From: Matteo Perelli Date: Mon, 22 Jun 2020 19:59:29 +0200 Subject: [PATCH 004/170] External source items import new files --- .../mocks/external-source.service.mock.ts | 12 +++ ...ion-import-external-preview.component.html | 39 ++++++++ ...ion-import-external-preview.component.scss | 3 + ...ssion-import-external-preview.component.ts | 70 ++++++++++++++ ...mport-external-searchbar.component.spec.ts | 91 +++++++++++++++++++ ...bmission-import-external.component.spec.ts | 0 6 files changed, 215 insertions(+) create mode 100644 src/app/shared/mocks/external-source.service.mock.ts create mode 100644 src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.html create mode 100644 src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.scss create mode 100644 src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.ts create mode 100644 src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.spec.ts create mode 100644 src/app/submission/import-external/submission-import-external.component.spec.ts diff --git a/src/app/shared/mocks/external-source.service.mock.ts b/src/app/shared/mocks/external-source.service.mock.ts new file mode 100644 index 0000000000..80e40512c5 --- /dev/null +++ b/src/app/shared/mocks/external-source.service.mock.ts @@ -0,0 +1,12 @@ +// import { ExternalSourceService } from '../../core/data/external-source.service'; + +/** + * Mock for [[ExternalSourceService]] + */ +/*export function getMockExternalSourceService(): +ExternalSourceService { + return jasmine.createSpyObj('ExternalSourceService', { + getAllExternalSources: jasmine.createSpy('getAllExternalSources'), + getExternalSourceEntries: jasmine.createSpy('getExternalSourceEntries'), + }); +}*/ diff --git a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.html b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.html new file mode 100644 index 0000000000..29f1804f1f --- /dev/null +++ b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.html @@ -0,0 +1,39 @@ + + diff --git a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.scss b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.scss new file mode 100644 index 0000000000..1a70081367 --- /dev/null +++ b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.scss @@ -0,0 +1,3 @@ +.close:focus { + outline: none !important; +} diff --git a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.ts b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.ts new file mode 100644 index 0000000000..de86bba3b1 --- /dev/null +++ b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.ts @@ -0,0 +1,70 @@ +import { Component, OnInit } from '@angular/core'; +import { NgbActiveModal, NgbModalRef, NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { ExternalSourceEntry } from '../../../core/shared/external-source-entry.model'; +import { MetadataValue } from '../../../core/shared/metadata.models'; +import { Metadata } from '../../../core/shared/metadata.utils'; + +/** + * This component display a preview of an external source item. + */ +@Component({ + selector: 'ds-submission-import-external-preview', + styleUrls: ['./submission-import-external-preview.component.scss'], + templateUrl: './submission-import-external-preview.component.html' +}) +export class SubmissionImportExternalPreviewComponent implements OnInit { + /** + * The external source entry + */ + public externalSourceEntry: ExternalSourceEntry; + /** + * The entry metadata list + */ + public metadataList: Array<{ key: string, value: MetadataValue }>; + /** + * The modal for the entry preview + */ + modalRef: NgbModalRef; + + /** + * Initialize the component variables. + * @param {NgbActiveModal} activeModal + */ + constructor( + private activeModal: NgbActiveModal, + private modalService: NgbModal + ) { } + + /** + * Metadata initialization for HTML display. + */ + ngOnInit(): void { + this.metadataList = []; + const metadataKeys = Object.keys(this.externalSourceEntry.metadata); + metadataKeys.forEach((key) => { + this.metadataList.push({ + key: key, + value: Metadata.first(this.externalSourceEntry.metadata, key) + }); + }) + } + + /** + * Closes the modal. + */ + public closeMetadataModal(): void { + this.activeModal.dismiss(false); + } + + /** + * Start the import of an entry by opening up an import modal window. + * @param entry The entry to import + */ + public import(entry): void { + this.modalRef = this.modalService.open(SubmissionImportExternalPreviewComponent, { + size: 'lg', + }); + const modalComp = this.modalRef.componentInstance; + modalComp.externalSourceEntry = entry; + } +} diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.spec.ts b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.spec.ts new file mode 100644 index 0000000000..66ce798ed9 --- /dev/null +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.spec.ts @@ -0,0 +1,91 @@ +// import { Component, NO_ERRORS_SCHEMA, ChangeDetectorRef } from '@angular/core'; +// import { async, TestBed, ComponentFixture, inject } from '@angular/core/testing'; +// import { TranslateModule } from '@ngx-translate/core'; +// import { SubmissionImportExternalSearchbarComponent } from './submission-import-external-searchbar.component'; +// import { ExternalSourceService } from '../../../core/data/external-source.service'; +// import { createTestComponent } from '../../../shared/testing/utils.test'; +// import { getMockExternalSourceService } from '../../../shared/mocks/external-source.service.mock'; +// import { SubmissionModule } from '../../submission.module'; + +/*describe('SubmissionImportExternalSearchbarComponent test suite', () => { + let comp: SubmissionImportExternalSearchbarComponent; + let compAsAny: any; + let fixture: ComponentFixture; + + beforeEach(async (() => { + TestBed.configureTestingModule({ + imports: [ + SubmissionModule, + TranslateModule.forRoot(), + ], + declarations: [ + SubmissionImportExternalSearchbarComponent, + TestComponent, + ], + providers: [ + { provide: ExternalSourceService, useClass: getMockExternalSourceService }, + ChangeDetectorRef, + SubmissionImportExternalSearchbarComponent + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents().then(); + })); + + // First test to check the correct component creation + describe('', () => { + let testComp: TestComponent; + let testFixture: ComponentFixture; + + // synchronous beforeEach + beforeEach(() => { + const html = ` + `; + testFixture = createTestComponent(html, TestComponent) as ComponentFixture; + testComp = testFixture.componentInstance; + }); + + afterEach(() => { + testFixture.destroy(); + }); + + it('should create SubmissionImportExternalSearchbarComponent', inject([SubmissionImportExternalSearchbarComponent], (app: SubmissionImportExternalSearchbarComponent) => { + expect(app).toBeDefined(); + })); + });*/ + + /*describe('', () => { + beforeEach(() => { + fixture = TestBed.createComponent(SubmissionImportExternalSearchbarComponent); + comp = fixture.componentInstance; + compAsAny = comp; + // compAsAny.externalService.getAllExternalSources.and.returnValue(observableOf([ + + // ])); + }); + + afterEach(() => { + fixture.destroy(); + comp = null; + compAsAny = null; + }); + + it('Should init component properly', () => { + comp.ngOnInit(); + fixture.detectChanges(); + + expect(comp.selectedElement) + expect(compAsAny.pageInfo) + expect(comp.sourceList) + }); + });*/ +/* +}); + +// declare a test component +@Component({ + selector: 'ds-test-cmp', + template: `` +}) +class TestComponent { + +}*/ diff --git a/src/app/submission/import-external/submission-import-external.component.spec.ts b/src/app/submission/import-external/submission-import-external.component.spec.ts new file mode 100644 index 0000000000..e69de29bb2 From b4ec056d036ce8a39150e289365bc3e7b4e353cd Mon Sep 17 00:00:00 2001 From: Matteo Perelli Date: Mon, 22 Jun 2020 20:23:54 +0200 Subject: [PATCH 005/170] Removing file for conflicts --- .../my-dspace-new-submission.component.html | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html diff --git a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html deleted file mode 100644 index 3adaea7128..0000000000 --- a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html +++ /dev/null @@ -1,18 +0,0 @@ - From c2c650fa1a17c1e879b7f1ccf3c68d6c27809e28 Mon Sep 17 00:00:00 2001 From: Matteo Perelli Date: Mon, 22 Jun 2020 20:26:04 +0200 Subject: [PATCH 006/170] External import button added --- .../my-dspace-new-submission.component.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html index 4809f206ae..da5519eb07 100644 --- a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html +++ b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html @@ -10,6 +10,9 @@ + + {{'mydspace.new-submission-external' | translate}} +
From e1b80bcbafc6ce71d1dbdaecc601452e2739761e Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Tue, 23 Jun 2020 18:12:02 +0200 Subject: [PATCH 007/170] [CST-3088] changed buildHrefFromFindOptions in the way to use search params while building url --- src/app/core/data/data.service.spec.ts | 24 +++++++++++++++++++++++- src/app/core/data/data.service.ts | 19 ++++++++++++++----- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/app/core/data/data.service.spec.ts b/src/app/core/data/data.service.spec.ts index a99fc54269..31013c5132 100644 --- a/src/app/core/data/data.service.spec.ts +++ b/src/app/core/data/data.service.spec.ts @@ -18,6 +18,7 @@ import { FindListOptions, PatchRequest } from './request.models'; import { RequestService } from './request.service'; import { getMockRequestService } from '../../shared/mocks/request.service.mock'; import { HALEndpointServiceStub } from '../../shared/testing/hal-endpoint-service.stub'; +import { RequestParam } from '../cache/models/request-param.model'; const endpoint = 'https://rest.api/core'; @@ -150,7 +151,8 @@ describe('DataService', () => { currentPage: 6, elementsPerPage: 10, sort: sortOptions, - startsWith: 'ab' + startsWith: 'ab', + }; const expected = `${endpoint}?page=${options.currentPage - 1}&size=${options.elementsPerPage}` + `&sort=${sortOptions.field},${sortOptions.direction}&startsWith=${options.startsWith}`; @@ -160,6 +162,26 @@ describe('DataService', () => { }); }); + it('should include all searchParams in href if any provided in options', () => { + options = { searchParams: [ + new RequestParam('param1', 'test'), + new RequestParam('param2', 'test2'), + ] }; + const expected = `${endpoint}?param1=test¶m2=test2`; + + (service as any).getFindAllHref(options).subscribe((value) => { + expect(value).toBe(expected); + }); + }); + + it('should include linkPath in href if any provided', () => { + const expected = `${endpoint}/test/entries`; + + (service as any).getFindAllHref({}, 'test/entries').subscribe((value) => { + expect(value).toBe(expected); + }); + }); + it('should include single linksToFollow as embed', () => { const expected = `${endpoint}?embed=bundles`; diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index ca59daa5af..d7e24892ef 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -86,13 +86,17 @@ export abstract class DataService { * Return an observable that emits created HREF * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved */ - protected getFindAllHref(options: FindListOptions = {}, linkPath?: string, ...linksToFollow: Array>): Observable { - let result$: Observable; + public getFindAllHref(options: FindListOptions = {}, linkPath?: string, ...linksToFollow: Array>): Observable { + let endpoint$: Observable; const args = []; - result$ = this.getBrowseEndpoint(options, linkPath).pipe(distinctUntilChanged()); + endpoint$ = this.getBrowseEndpoint(options).pipe( + filter((href: string) => isNotEmpty(href)), + map((href: string) => isNotEmpty(linkPath) ? `${href}/${linkPath}` : href), + distinctUntilChanged() + ); - return result$.pipe(map((result: string) => this.buildHrefFromFindOptions(result, options, args, ...linksToFollow))); + return endpoint$.pipe(map((result: string) => this.buildHrefFromFindOptions(result, options, args, ...linksToFollow))); } /** @@ -104,7 +108,7 @@ export abstract class DataService { * Return an observable that emits created HREF * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved */ - protected getSearchByHref(searchMethod: string, options: FindListOptions = {}, ...linksToFollow: Array>): Observable { + public getSearchByHref(searchMethod: string, options: FindListOptions = {}, ...linksToFollow: Array>): Observable { let result$: Observable; const args = []; @@ -145,6 +149,11 @@ export abstract class DataService { if (hasValue(options.startsWith)) { args = [...args, `startsWith=${options.startsWith}`]; } + if (hasValue(options.searchParams)) { + options.searchParams.forEach((param: RequestParam) => { + args = [...args, `${param.fieldName}=${param.fieldValue}`]; + }) + } args = this.addEmbedParams(args, ...linksToFollow); if (isNotEmpty(args)) { return new URLCombiner(href, `?${args.join('&')}`).toString(); From 1156bd3934932858da65f25a2dd902401cb5852d Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Tue, 23 Jun 2020 18:17:47 +0200 Subject: [PATCH 008/170] [CST-3088] Added vocabulary service and models --- src/app/core/core.module.ts | 28 +- src/app/core/data/request.models.ts | 10 + .../models/vocabularies.resource-type.ts | 11 + .../models/vocabulary-entry.model.ts | 103 +++++++ .../vocabularies/models/vocabulary.model.ts | 61 ++++ ...y-entries-response-parsing.service.spec.ts | 111 ++++++++ ...bulary-entries-response-parsing.service.ts | 20 ++ .../vocabularies/vocabulary.service.spec.ts | 269 ++++++++++++++++++ .../vocabularies/vocabulary.service.ts | 194 +++++++++++++ 9 files changed, 796 insertions(+), 11 deletions(-) create mode 100644 src/app/core/submission/vocabularies/models/vocabularies.resource-type.ts create mode 100644 src/app/core/submission/vocabularies/models/vocabulary-entry.model.ts create mode 100644 src/app/core/submission/vocabularies/models/vocabulary.model.ts create mode 100644 src/app/core/submission/vocabularies/vocabulary-entries-response-parsing.service.spec.ts create mode 100644 src/app/core/submission/vocabularies/vocabulary-entries-response-parsing.service.ts create mode 100644 src/app/core/submission/vocabularies/vocabulary.service.spec.ts create mode 100644 src/app/core/submission/vocabularies/vocabulary.service.ts diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index 715f7a5cc0..a92b52b339 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -16,8 +16,8 @@ import { MenuService } from '../shared/menu/menu.service'; import { EndpointMockingRestService } from '../shared/mocks/dspace-rest-v2/endpoint-mocking-rest.service'; import { MOCK_RESPONSE_MAP, - ResponseMapMock, - mockResponseMap + mockResponseMap, + ResponseMapMock } from '../shared/mocks/dspace-rest-v2/mocks/response-map.mock'; import { NotificationsService } from '../shared/notifications/notifications.service'; import { SelectableListService } from '../shared/object-list/selectable-list/selectable-list.service'; @@ -145,6 +145,9 @@ import { Version } from './shared/version.model'; import { VersionHistory } from './shared/version-history.model'; import { WorkflowActionDataService } from './data/workflow-action-data.service'; import { WorkflowAction } from './tasks/models/workflow-action-object.model'; +import { VocabularyEntry } from './submission/vocabularies/models/vocabulary-entry.model'; +import { Vocabulary } from './submission/vocabularies/models/vocabulary.model'; +import { VocabularyEntriesResponseParsingService } from './submission/vocabularies/vocabulary-entries-response-parsing.service'; /** * When not in production, endpoint responses can be mocked for testing purposes @@ -178,7 +181,7 @@ const PROVIDERS = [ SiteDataService, DSOResponseParsingService, { provide: MOCK_RESPONSE_MAP, useValue: mockResponseMap }, - { provide: DSpaceRESTv2Service, useFactory: restServiceFactory, deps: [MOCK_RESPONSE_MAP, HttpClient]}, + { provide: DSpaceRESTv2Service, useFactory: restServiceFactory, deps: [MOCK_RESPONSE_MAP, HttpClient] }, DynamicFormLayoutService, DynamicFormService, DynamicFormValidationService, @@ -272,7 +275,8 @@ const PROVIDERS = [ }, NotificationsService, FilteredDiscoveryPageResponseParsingService, - { provide: NativeWindowService, useFactory: NativeWindowFactory } + { provide: NativeWindowService, useFactory: NativeWindowFactory }, + VocabularyEntriesResponseParsingService ]; /** @@ -314,7 +318,9 @@ export const models = ExternalSourceEntry, Version, VersionHistory, - WorkflowAction + WorkflowAction, + Vocabulary, + VocabularyEntry ]; @NgModule({ @@ -333,6 +339,12 @@ export const models = }) export class CoreModule { + constructor(@Optional() @SkipSelf() parentModule: CoreModule) { + if (isNotEmpty(parentModule)) { + throw new Error('CoreModule is already loaded. Import it in the AppModule only'); + } + } + static forRoot(): ModuleWithProviders { return { ngModule: CoreModule, @@ -341,10 +353,4 @@ export class CoreModule { ] }; } - - constructor(@Optional() @SkipSelf() parentModule: CoreModule) { - if (isNotEmpty(parentModule)) { - throw new Error('CoreModule is already loaded. Import it in the AppModule only'); - } - } } diff --git a/src/app/core/data/request.models.ts b/src/app/core/data/request.models.ts index 5866cce797..c9fe1fe0ce 100644 --- a/src/app/core/data/request.models.ts +++ b/src/app/core/data/request.models.ts @@ -20,6 +20,7 @@ import { URLCombiner } from '../url-combiner/url-combiner'; import { TaskResponseParsingService } from '../tasks/task-response-parsing.service'; import { ContentSourceResponseParsingService } from './content-source-response-parsing.service'; import { MappedCollectionsReponseParsingService } from './mapped-collections-reponse-parsing.service'; +import { VocabularyEntriesResponseParsingService } from '../submission/vocabularies/vocabulary-entries-response-parsing.service'; /* tslint:disable:max-classes-per-file */ @@ -442,6 +443,15 @@ export class MyDSpaceRequest extends GetRequest { public responseMsToLive = 10 * 1000; } +/** + * Request to get vocabulary entries + */ +export class VocabularyEntriesRequest extends FindListRequest { + getResponseParser(): GenericConstructor { + return VocabularyEntriesResponseParsingService; + } +} + export class RequestError extends Error { statusCode: number; statusText: string; diff --git a/src/app/core/submission/vocabularies/models/vocabularies.resource-type.ts b/src/app/core/submission/vocabularies/models/vocabularies.resource-type.ts new file mode 100644 index 0000000000..4d49abd823 --- /dev/null +++ b/src/app/core/submission/vocabularies/models/vocabularies.resource-type.ts @@ -0,0 +1,11 @@ +import { ResourceType } from '../../../shared/resource-type'; + +/** + * The resource type for vocabulary models + * + * Needs to be in a separate file to prevent circular + * dependencies in webpack. + */ + +export const VOCABULARY = new ResourceType('vocabulary'); +export const VOCABULARY_ENTRY = new ResourceType('vocabularyEntry'); diff --git a/src/app/core/submission/vocabularies/models/vocabulary-entry.model.ts b/src/app/core/submission/vocabularies/models/vocabulary-entry.model.ts new file mode 100644 index 0000000000..5fe951c8aa --- /dev/null +++ b/src/app/core/submission/vocabularies/models/vocabulary-entry.model.ts @@ -0,0 +1,103 @@ +import { autoserialize, deserialize } from 'cerialize'; + +import { HALLink } from '../../../shared/hal-link.model'; +import { VOCABULARY_ENTRY } from './vocabularies.resource-type'; +import { typedObject } from '../../../cache/builders/build-decorators'; +import { excludeFromEquals } from '../../../utilities/equals.decorators'; +import { PLACEHOLDER_PARENT_METADATA } from '../../../../shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.model'; +import { OtherInformation } from '../../../../shared/form/builder/models/form-field-metadata-value.model'; +import { isNotEmpty } from '../../../../shared/empty.util'; +import { ListableObject } from '../../../../shared/object-collection/shared/listable-object.model'; +import { GenericConstructor } from '../../../shared/generic-constructor'; + +/** + * Model class for a Vocabulary + */ +@typedObject +export class VocabularyEntry extends ListableObject { + static type = VOCABULARY_ENTRY; + + /** + * The identifier of this vocabulary entry + */ + @autoserialize + authority: string; + + /** + * The display value of this vocabulary entry + */ + @autoserialize + display: string; + + /** + * The value of this vocabulary entry + */ + @autoserialize + value: string; + + /** + * An object containing additional information related to this vocabulary entry + */ + @autoserialize + otherInformation: OtherInformation; + + /** + * A string representing the kind of vocabulary entry + */ + @excludeFromEquals + @autoserialize + public type: any; + + /** + * The {@link HALLink}s for this ExternalSourceEntry + */ + @deserialize + _links: { + self: HALLink; + vocabularyEntryDetail: HALLink; + }; + + /** + * This method checks if entry has an authority value + * + * @return boolean + */ + hasAuthority(): boolean { + return isNotEmpty(this.authority); + } + + /** + * This method checks if entry has a value + * + * @return boolean + */ + hasValue(): boolean { + return isNotEmpty(this.value); + } + + /** + * This method checks if entry has related information object + * + * @return boolean + */ + hasOtherInformation(): boolean { + return isNotEmpty(this.otherInformation); + } + + /** + * This method checks if entry has a placeholder as value + * + * @return boolean + */ + hasPlaceholder(): boolean { + return this.hasValue() && this.value === PLACEHOLDER_PARENT_METADATA; + } + + /** + * Method that returns as which type of object this object should be rendered + */ + getRenderTypes(): Array> { + return [this.constructor as GenericConstructor]; + } + +} diff --git a/src/app/core/submission/vocabularies/models/vocabulary.model.ts b/src/app/core/submission/vocabularies/models/vocabulary.model.ts new file mode 100644 index 0000000000..8672d1c6ed --- /dev/null +++ b/src/app/core/submission/vocabularies/models/vocabulary.model.ts @@ -0,0 +1,61 @@ +import { autoserialize, deserialize } from 'cerialize'; + +import { HALLink } from '../../../shared/hal-link.model'; +import { VOCABULARY } from './vocabularies.resource-type'; +import { CacheableObject } from '../../../cache/object-cache.reducer'; +import { typedObject } from '../../../cache/builders/build-decorators'; +import { excludeFromEquals } from '../../../utilities/equals.decorators'; + +/** + * Model class for a Vocabulary + */ +@typedObject +export class Vocabulary implements CacheableObject { + static type = VOCABULARY; + /** + * The identifier of this Vocabulary + */ + @autoserialize + id: string; + + /** + * The name of this Vocabulary + */ + @autoserialize + name: string; + + /** + * True if it is possible to scroll all the entries in the vocabulary without providing a filter parameter + */ + @autoserialize + scrollable: boolean; + + /** + * True if the vocabulary exposes a tree structure where some entries are parent of others + */ + @autoserialize + hierarchical: boolean; + + /** + * For hierarchical vocabularies express the preference to preload the tree at a specific + * level of depth (0 only the top nodes are shown, 1 also their children are preloaded and so on) + */ + @autoserialize + preloadLevel: any; + + /** + * A string representing the kind of Vocabulary model + */ + @excludeFromEquals + @autoserialize + public type: any; + + /** + * The {@link HALLink}s for this Vocabulary + */ + @deserialize + _links: { + self: HALLink, + entries: HALLink + }; +} diff --git a/src/app/core/submission/vocabularies/vocabulary-entries-response-parsing.service.spec.ts b/src/app/core/submission/vocabularies/vocabulary-entries-response-parsing.service.spec.ts new file mode 100644 index 0000000000..592ed234a7 --- /dev/null +++ b/src/app/core/submission/vocabularies/vocabulary-entries-response-parsing.service.spec.ts @@ -0,0 +1,111 @@ +import { getMockObjectCacheService } from '../../../shared/mocks/object-cache.service.mock'; +import { ErrorResponse, GenericSuccessResponse } from '../../cache/response.models'; +import { DSpaceRESTV2Response } from '../../dspace-rest-v2/dspace-rest-v2-response.model'; +import { VocabularyEntriesResponseParsingService } from './vocabulary-entries-response-parsing.service'; +import { VocabularyEntriesRequest } from '../../data/request.models'; + +fdescribe('VocabularyEntriesResponseParsingService', () => { + let service: VocabularyEntriesResponseParsingService; + const metadata = 'dc.type'; + const collectionUUID = '8b39g7ya-5a4b-438b-851f-be1d5b4a1c5a'; + const entriesRequestURL = `https://rest.api/rest/api/submission/vocabularies/types/entries?metadata=${metadata}&collection=${collectionUUID}` + + beforeEach(() => { + service = new VocabularyEntriesResponseParsingService(getMockObjectCacheService()); + }); + + describe('parse', () => { + const request = new VocabularyEntriesRequest('client/f5b4ccb8-fbb0-4548-b558-f234d9fdfad6', entriesRequestURL); + + const validResponse = { + payload: { + _embedded: { + entries: [ + { + display: 'testValue1', + value: 'testValue1', + otherInformation: {}, + type: 'vocabularyEntry' + }, + { + display: 'testValue2', + value: 'testValue2', + otherInformation: {}, + type: 'vocabularyEntry' + }, + { + display: 'testValue3', + value: 'testValue3', + otherInformation: {}, + type: 'vocabularyEntry' + }, + { + authority: 'authorityId1', + display: 'testValue1', + value: 'testValue1', + otherInformation: { + id: 'VR131402', + parent: 'Research Subject Categories::SOCIAL SCIENCES::Social sciences::Social work', + hasChildren: 'false', + note: 'Familjeforskning' + }, + type: 'vocabularyEntry', + _links: { + vocabularyEntryDetail: { + href: 'https://rest.api/rest/api/submission/vocabularyEntryDetails/srsc:VR131402' + } + } + } + ] + }, + _links: { + first: { + href: 'https://rest.api/discover/browses/author/entries?page=0&size=5' + }, + self: { + href: 'https://rest.api/discover/browses/author/entries' + }, + next: { + href: 'https://rest.api/discover/browses/author/entries?page=1&size=5' + }, + last: { + href: 'https://rest.api/discover/browses/author/entries?page=9&size=5' + } + }, + page: { + size: 5, + totalElements: 50, + totalPages: 10, + number: 0 + } + }, + statusCode: 200, + statusText: 'OK' + } as DSpaceRESTV2Response; + + const invalidResponseNotAList = { + statusCode: 200, + statusText: 'OK' + } as DSpaceRESTV2Response; + + const invalidResponseStatusCode = { + payload: {}, statusCode: 500, statusText: 'Internal Server Error' + } as DSpaceRESTV2Response; + + it('should return a GenericSuccessResponse if data contains a valid browse entries response', () => { + const response = service.parse(request, validResponse); + expect(response.constructor).toBe(GenericSuccessResponse); + }); + + it('should return an ErrorResponse if data contains an invalid browse entries response', () => { + const response = service.parse(request, invalidResponseNotAList); + expect(response.constructor).toBe(ErrorResponse); + }); + + it('should return an ErrorResponse if data contains a statuscode other than 200', () => { + const response = service.parse(request, invalidResponseStatusCode); + expect(response.constructor).toBe(ErrorResponse); + }); + + }); +}); diff --git a/src/app/core/submission/vocabularies/vocabulary-entries-response-parsing.service.ts b/src/app/core/submission/vocabularies/vocabulary-entries-response-parsing.service.ts new file mode 100644 index 0000000000..680b949733 --- /dev/null +++ b/src/app/core/submission/vocabularies/vocabulary-entries-response-parsing.service.ts @@ -0,0 +1,20 @@ +import { Injectable } from '@angular/core'; + +import { ObjectCacheService } from '../../cache/object-cache.service'; +import { BrowseEntriesResponseParsingService } from '../../data/browse-entries-response-parsing.service'; + +/** + * A service responsible for parsing data for a vocabulary entries response + */ +@Injectable() +export class VocabularyEntriesResponseParsingService extends BrowseEntriesResponseParsingService { + + protected toCache = false; + + constructor( + protected objectCache: ObjectCacheService, + ) { + super(objectCache); + } + +} diff --git a/src/app/core/submission/vocabularies/vocabulary.service.spec.ts b/src/app/core/submission/vocabularies/vocabulary.service.spec.ts new file mode 100644 index 0000000000..2596e368b5 --- /dev/null +++ b/src/app/core/submission/vocabularies/vocabulary.service.spec.ts @@ -0,0 +1,269 @@ +import { HttpClient } from '@angular/common/http'; + +import { cold, getTestScheduler, hot } from 'jasmine-marbles'; +import { of as observableOf } from 'rxjs'; +import { TestScheduler } from 'rxjs/testing'; + +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { RemoteDataBuildService } from '../../cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../../cache/object-cache.service'; +import { HALEndpointService } from '../../shared/hal-endpoint.service'; +import { RequestService } from '../../data/request.service'; +import { FindListOptions, VocabularyEntriesRequest } from '../../data/request.models'; +import { RequestParam } from '../../cache/models/request-param.model'; +import { PageInfo } from '../../shared/page-info.model'; +import { PaginatedList } from '../../data/paginated-list'; +import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils'; +import { RequestEntry } from '../../data/request.reducer'; +import { RestResponse } from '../../cache/response.models'; +import { VocabularyService } from './vocabulary.service'; +import { getMockRequestService } from '../../../shared/mocks/request.service.mock'; +import { getMockRemoteDataBuildService } from '../../../shared/mocks/remote-data-build.service.mock'; + +describe('VocabularyService', () => { + let scheduler: TestScheduler; + let service: VocabularyService; + let requestService: RequestService; + let rdbService: RemoteDataBuildService; + let objectCache: ObjectCacheService; + let halService: HALEndpointService; + let responseCacheEntry: RequestEntry; + + const vocabulary: any = { + id: 'types', + name: 'types', + scrollable: true, + hierarchical: false, + preloadLevel: 1, + type: 'vocabulary', + uuid: 'vocabulary-types', + _links: { + self: { + href: 'https://rest.api/rest/api/submission/vocabularies/types' + }, + entries: { + href: 'https://rest.api/rest/api/submission/vocabularies/types/entries' + }, + } + }; + + const anotherVocabulary: any = { + id: 'srsc', + name: 'srsc', + scrollable: false, + hierarchical: true, + preloadLevel: 2, + type: 'vocabulary', + uuid: 'vocabulary-srsc', + _links: { + self: { + href: 'https://rest.api/rest/api/submission/vocabularies/types' + }, + entries: { + href: 'https://rest.api/rest/api/submission/vocabularies/types/entries' + }, + } + }; + + const vocabularyEntry: any = { + display: 'testValue1', + value: 'testValue1', + otherInformation: {}, + type: 'vocabularyEntry' + }; + + const vocabularyEntryWithAuthority: any = { + authority: 'authorityId1', + display: 'testValue1', + value: 'testValue1', + otherInformation: { + id: 'VR131402', + parent: 'Research Subject Categories::SOCIAL SCIENCES::Social sciences::Social work', + hasChildren: 'false', + note: 'Familjeforskning' + }, + type: 'vocabularyEntry', + _links: { + vocabularyEntryDetail: { + href: 'https://rest.api/rest/api/submission/vocabularyEntryDetails/srsc:VR131402' + } + } + }; + const endpointURL = `https://rest.api/rest/api/submission/vocabularies`; + const requestURL = `https://rest.api/rest/api/submission/vocabularies/${vocabulary.id}`; + const requestUUID = '8b3c613a-5a4b-438b-9686-be1d5b4a1c5a'; + const vocabularyId = 'types'; + const metadata = 'dc.type'; + const collectionUUID = '8b39g7ya-5a4b-438b-851f-be1d5b4a1c5a'; + const searchRequestURL = `https://rest.api/rest/api/submission/vocabularies/search/byMetadataAndCollection?metadata=${metadata}&collection=${collectionUUID}`; + const entriesRequestURL = `https://rest.api/rest/api/submission/vocabularies/${vocabulary.id}/entries?metadata=${metadata}&collection=${collectionUUID}`; + + const pageInfo = new PageInfo(); + const array = [vocabulary, anotherVocabulary]; + const paginatedList = new PaginatedList(pageInfo, array); + const vocabularyRD = createSuccessfulRemoteDataObject(vocabulary); + const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); + const getRequestEntry$ = (successful: boolean) => { + return observableOf({ + response: { isSuccessful: successful, payload: vocabulary } as any + } as RequestEntry) + }; + objectCache = {} as ObjectCacheService; + const notificationsService = {} as NotificationsService; + const http = {} as HttpClient; + const comparator = {} as any; + + function initTestService() { + return new VocabularyService( + requestService, + rdbService, + objectCache, + halService, + notificationsService, + http, + comparator + ); + } + + beforeEach(() => { + scheduler = getTestScheduler(); + + halService = jasmine.createSpyObj('halService', { + getEndpoint: cold('a', { a: endpointURL }) + }); + + responseCacheEntry = new RequestEntry(); + responseCacheEntry.response = new RestResponse(true, 200, 'Success'); + + requestService = jasmine.createSpyObj('requestService', { + generateRequestId: requestUUID, + configure: true, + removeByHrefSubstring: {}, + getByHref: observableOf(responseCacheEntry), + getByUUID: observableOf(responseCacheEntry), + }); + rdbService = jasmine.createSpyObj('rdbService', { + buildSingle: hot('a|', { + a: vocabularyRD + }), + buildList: hot('a|', { + a: paginatedListRD + }), + }); + + service = initTestService(); + + spyOn((service as any).dataService, 'findById').and.callThrough(); + spyOn((service as any).dataService, 'findAll').and.callThrough(); + spyOn((service as any).dataService, 'findByHref').and.callThrough(); + spyOn((service as any).dataService, 'searchBy').and.callThrough(); + spyOn((service as any).dataService, 'getSearchByHref').and.returnValue(observableOf(searchRequestURL)); + spyOn((service as any).dataService, 'getFindAllHref').and.returnValue(observableOf(entriesRequestURL)); + }); + + afterEach(() => { + service = null; + }); + + describe('findById', () => { + it('should proxy the call to dataservice.findById', () => { + scheduler.schedule(() => service.findById(vocabularyId)); + scheduler.flush(); + + expect((service as any).dataService.findById).toHaveBeenCalledWith(vocabularyId); + }); + + it('should return a RemoteData for the object with the given id', () => { + const result = service.findById(vocabularyId); + const expected = cold('a|', { + a: vocabularyRD + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('findByHref', () => { + it('should proxy the call to dataservice.findByHref', () => { + scheduler.schedule(() => service.findByHref(requestURL)); + scheduler.flush(); + + expect((service as any).dataService.findByHref).toHaveBeenCalledWith(requestURL); + }); + + it('should return a RemoteData for the object with the given URL', () => { + const result = service.findByHref(requestURL); + const expected = cold('a|', { + a: vocabularyRD + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('findAll', () => { + it('should proxy the call to dataservice.findAll', () => { + scheduler.schedule(() => service.findAll()); + scheduler.flush(); + + expect((service as any).dataService.findAll).toHaveBeenCalled(); + }); + + it('should return a RemoteData>', () => { + const result = service.findAll(); + const expected = cold('a|', { + a: paginatedListRD + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('searchByMetadataAndCollection', () => { + it('should proxy the call to dataservice.findByHref', () => { + const options = new FindListOptions(); + options.searchParams = [ + new RequestParam('metadata', metadata), + new RequestParam('collection', collectionUUID) + ]; + scheduler.schedule(() => service.searchByMetadataAndCollection(metadata, collectionUUID).subscribe()); + scheduler.flush(); + + expect((service as any).dataService.findByHref).toHaveBeenCalledWith(searchRequestURL); + }); + + it('should return a RemoteData for the search', () => { + const result = service.searchByMetadataAndCollection(metadata, collectionUUID); + const expected = cold('a|', { + a: vocabularyRD + }); + expect(result).toBeObservable(expected); + }); + + }); + + describe('getVocabularyEntries', () => { + + beforeEach(() => { + requestService = getMockRequestService(getRequestEntry$(true)); + rdbService = getMockRemoteDataBuildService(); + spyOn(rdbService, 'toRemoteDataObservable').and.callThrough(); + service = initTestService(); + }); + + it('should configure a new VocabularyEntriesRequest', () => { + const expected = new VocabularyEntriesRequest(requestService.generateRequestId(), entriesRequestURL); + + scheduler.schedule(() => service.getVocabularyEntries(vocabularyId, metadata, collectionUUID).subscribe()); + scheduler.flush(); + + expect(requestService.configure).toHaveBeenCalledWith(expected); + }); + + it('should call RemoteDataBuildService to create the RemoteData Observable', () => { + service.getVocabularyEntries(vocabularyId, metadata, collectionUUID); + + expect(rdbService.toRemoteDataObservable).toHaveBeenCalled(); + + }); + + }); + +}); diff --git a/src/app/core/submission/vocabularies/vocabulary.service.ts b/src/app/core/submission/vocabularies/vocabulary.service.ts new file mode 100644 index 0000000000..cfb795c942 --- /dev/null +++ b/src/app/core/submission/vocabularies/vocabulary.service.ts @@ -0,0 +1,194 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; + +import { Store } from '@ngrx/store'; +import { Observable } from 'rxjs'; +import { distinctUntilChanged, first, flatMap, map } from 'rxjs/operators'; + +import { FollowLinkConfig } from '../../../shared/utils/follow-link-config.model'; +import { dataService } from '../../cache/builders/build-decorators'; +import { DataService } from '../../data/data.service'; +import { RequestService } from '../../data/request.service'; +import { FindListOptions, RestRequest, VocabularyEntriesRequest } from '../../data/request.models'; +import { HALEndpointService } from '../../shared/hal-endpoint.service'; +import { RemoteData } from '../../data/remote-data'; +import { RemoteDataBuildService } from '../../cache/builders/remote-data-build.service'; +import { CoreState } from '../../core.reducers'; +import { ObjectCacheService } from '../../cache/object-cache.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { ChangeAnalyzer } from '../../data/change-analyzer'; +import { DefaultChangeAnalyzer } from '../../data/default-change-analyzer.service'; +import { PaginatedList } from '../../data/paginated-list'; +import { RequestParam } from '../../cache/models/request-param.model'; +import { Vocabulary } from './models/vocabulary.model'; +import { VOCABULARY } from './models/vocabularies.resource-type'; +import { VocabularyEntry } from './models/vocabulary-entry.model'; +import { hasValue, isNotEmptyOperator } from '../../../shared/empty.util'; +import { configureRequest, filterSuccessfulResponses, getRequestFromRequestHref } from '../../shared/operators'; +import { GenericSuccessResponse } from '../../cache/response.models'; + +/* tslint:disable:max-classes-per-file */ + +/** + * A private DataService implementation to delegate specific methods to. + */ +class DataServiceImpl extends DataService { + protected linkPath = 'vocabularies'; + + constructor( + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected store: Store, + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected notificationsService: NotificationsService, + protected http: HttpClient, + protected comparator: ChangeAnalyzer) { + super(); + } + +} + +/** + * A service responsible for fetching/sending data from/to the REST API on the vocabularies endpoint + */ +@Injectable({ + providedIn: 'root' +}) +@dataService(VOCABULARY) +export class VocabularyService { + protected searchByMetadataAndCollectionMethod = 'byMetadataAndCollection'; + private dataService: DataServiceImpl; + + constructor( + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected notificationsService: NotificationsService, + protected http: HttpClient, + protected comparator: DefaultChangeAnalyzer) { + this.dataService = new DataServiceImpl(requestService, rdbService, null, objectCache, halService, notificationsService, http, comparator); + } + + /** + * Returns an observable of {@link RemoteData} of a {@link Vocabulary}, based on an href, with a list of {@link FollowLinkConfig}, + * to automatically resolve {@link HALLink}s of the {@link Vocabulary} + * @param href The url of {@link Vocabulary} we want to retrieve + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved + * @return {Observable>} + * Return an observable that emits vocabulary object + */ + findByHref(href: string, ...linksToFollow: Array>): Observable> { + return this.dataService.findByHref(href, ...linksToFollow); + } + + /** + * Returns an observable of {@link RemoteData} of a {@link Vocabulary}, based on its ID, with a list of {@link FollowLinkConfig}, + * to automatically resolve {@link HALLink}s of the object + * @param id ID of {@link Vocabulary} we want to retrieve + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved + * @return {Observable>} + * Return an observable that emits vocabulary object + */ + findById(id: string, ...linksToFollow: Array>): Observable> { + return this.dataService.findById(id, ...linksToFollow); + } + + /** + * Returns {@link RemoteData} of all object with a list of {@link FollowLinkConfig}, to indicate which embedded + * info should be added to the objects + * + * @param options Find list options object + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved + * @return {Observable>>} + * Return an observable that emits object list + */ + findAll(options: FindListOptions = {}, ...linksToFollow: Array>): Observable>> { + return this.dataService.findAll(options, ...linksToFollow); + } + + /** + * Return the {@link VocabularyEntry} list for a given {@link Vocabulary} + * + * @param id The vocabulary id to retrieve the entries for + * @param metadata The metadata name + * @param collectionUUID The collection UUID + * @param options The {@link FindListOptions} for the request + * @return {Observable>>} + * Return an observable that emits object list + */ + getVocabularyEntries(id: string, metadata: string, collectionUUID: string, options: FindListOptions = {}): Observable>> { + options = Object.assign({}, options, { + searchParams: [ + new RequestParam('metadata', metadata), + new RequestParam('collection', collectionUUID) + ] + }); + + return this.dataService.getFindAllHref(options, `${id}/entries`).pipe( + isNotEmptyOperator(), + distinctUntilChanged(), + getVocabularyEntriesFor(this.requestService, this.rdbService) + ); + } + + /** + * Return the controlled {@link Vocabulary} configured for the specified metadata and collection if any. + * + * @param metadata The metadata name + * @param collectionUUID The collection UUID + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved + * @return {Observable>>} + * Return an observable that emits object list + */ + searchByMetadataAndCollection(metadata: string, collectionUUID: string, ...linksToFollow: Array>): Observable> { + const options = new FindListOptions(); + options.searchParams = [ + new RequestParam('metadata', metadata), + new RequestParam('collection', collectionUUID) + ]; + + return this.dataService.getSearchByHref(this.searchByMetadataAndCollectionMethod, options).pipe( + first((href: string) => hasValue(href)), + flatMap((href: string) => this.dataService.findByHref(href)) + ) + } + +} + +/** + * Operator for turning a href into a PaginatedList of VocabularyEntry + * @param requestService + * @param rdb + */ +export const getVocabularyEntriesFor = (requestService: RequestService, rdb: RemoteDataBuildService) => + (source: Observable): Observable>> => + source.pipe( + map((href: string) => new VocabularyEntriesRequest(requestService.generateRequestId(), href)), + configureRequest(requestService), + toRDPaginatedVocabularyEntries(requestService, rdb) + ); + +/** + * Operator for turning a RestRequest into a PaginatedList of VocabularyEntry + * @param requestService + * @param rdb + */ +export const toRDPaginatedVocabularyEntries = (requestService: RequestService, rdb: RemoteDataBuildService) => + (source: Observable): Observable>> => { + const href$ = source.pipe(map((request: RestRequest) => request.href)); + + const requestEntry$ = href$.pipe(getRequestFromRequestHref(requestService)); + + const payload$ = requestEntry$.pipe( + filterSuccessfulResponses(), + map((response: GenericSuccessResponse) => new PaginatedList(response.pageInfo, response.payload)), + map((list: PaginatedList) => Object.assign(list, { + page: list.page ? list.page.map((entry: VocabularyEntry) => Object.assign(new VocabularyEntry(), entry)) : list.page + })), + distinctUntilChanged() + ); + + return rdb.toRemoteDataObservable(requestEntry$, payload$); + }; From 43f5e08530c7a8838eb028131df65c69c3069d24 Mon Sep 17 00:00:00 2001 From: Matteo Perelli Date: Wed, 24 Jun 2020 10:16:30 +0200 Subject: [PATCH 009/170] External source import completed with tests --- .../import-external-page.component.ts | 2 +- .../import-external-page.module.ts | 2 - .../collection-dropdown.component.ts | 2 +- .../mocks/external-source.service.mock.ts | 53 +++++- src/app/shared/shared.module.ts | 3 +- .../shared/testing/submission-service.stub.ts | 1 + ...-import-external-collection.component.html | 11 ++ ...-import-external-collection.component.scss | 3 + ...port-external-collection.component.spec.ts | 89 ++++++++++ ...on-import-external-collection.component.ts | 40 +++++ ...ion-import-external-preview.component.html | 4 +- ...-import-external-preview.component.spec.ts | 153 +++++++++++++++++ ...ssion-import-external-preview.component.ts | 44 ++++- ...mport-external-searchbar.component.spec.ts | 102 ++++++++--- ...ion-import-external-searchbar.component.ts | 23 ++- ...bmission-import-external.component.spec.ts | 159 ++++++++++++++++++ .../submission-import-external.component.ts | 2 +- src/app/submission/submission.module.ts | 7 +- src/app/submission/submission.service.spec.ts | 13 ++ src/app/submission/submission.service.ts | 18 ++ src/assets/i18n/en.json5 | 4 + 21 files changed, 681 insertions(+), 54 deletions(-) create mode 100644 src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.html create mode 100644 src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.scss create mode 100644 src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.spec.ts create mode 100644 src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.ts create mode 100644 src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts diff --git a/src/app/+import-external-page/import-external-page.component.ts b/src/app/+import-external-page/import-external-page.component.ts index c205482cb3..00709dad16 100644 --- a/src/app/+import-external-page/import-external-page.component.ts +++ b/src/app/+import-external-page/import-external-page.component.ts @@ -1,4 +1,4 @@ -import { Component, Injector, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; /** * Component representing the external import page of the submission. diff --git a/src/app/+import-external-page/import-external-page.module.ts b/src/app/+import-external-page/import-external-page.module.ts index c81e80615f..8dae7c2f88 100644 --- a/src/app/+import-external-page/import-external-page.module.ts +++ b/src/app/+import-external-page/import-external-page.module.ts @@ -4,8 +4,6 @@ import { NgModule } from '@angular/core'; import { SharedModule } from '../shared/shared.module'; import { CoreModule } from '../core/core.module'; import { ImportExternalRoutingModule } from './import-external-routing.module'; -import { SubmissionImportExternalComponent } from '../submission/import-external/submission-import-external.component'; -import { SubmissionImportExternalSearchbarComponent } from '../submission/import-external/import-external-searchbar/submission-import-external-searchbar.component'; import { SubmissionModule } from '../submission/submission.module'; @NgModule({ diff --git a/src/app/shared/collection-dropdown/collection-dropdown.component.ts b/src/app/shared/collection-dropdown/collection-dropdown.component.ts index 0e9a4ab629..49af24ad3d 100644 --- a/src/app/shared/collection-dropdown/collection-dropdown.component.ts +++ b/src/app/shared/collection-dropdown/collection-dropdown.component.ts @@ -24,7 +24,7 @@ interface CollectionListEntryItem { /** * An interface to represent an entry in the collection list */ -interface CollectionListEntry { +export interface CollectionListEntry { communities: CollectionListEntryItem[], collection: CollectionListEntryItem } diff --git a/src/app/shared/mocks/external-source.service.mock.ts b/src/app/shared/mocks/external-source.service.mock.ts index 80e40512c5..4edf9efb14 100644 --- a/src/app/shared/mocks/external-source.service.mock.ts +++ b/src/app/shared/mocks/external-source.service.mock.ts @@ -1,12 +1,59 @@ -// import { ExternalSourceService } from '../../core/data/external-source.service'; +import { ExternalSourceService } from '../../core/data/external-source.service'; +import { ExternalSource } from '../../core/shared/external-source.model'; +import { ResourceType } from '../../core/shared/resource-type'; + +export const externalSourceOrcid: ExternalSource = { + type: new ResourceType('externalsource'), + id: 'orcid', + name: 'orcid', + hierarchical: false, + _links: { + entries: { + href: "https://dspace7.4science.cloud/server/api/integration/externalsources/orcid/entries" + }, + self: { + href: "https://dspace7.4science.cloud/server/api/integration/externalsources/orcid" + } + } +}; + +export const externalSourceCiencia: ExternalSource = { + type: new ResourceType('externalsource'), + id: 'ciencia', + name: 'ciencia', + hierarchical: false, + _links: { + entries: { + href: "https://dspace7.4science.cloud/server/api/integration/externalsources/ciencia/entries" + }, + self: { + href: "https://dspace7.4science.cloud/server/api/integration/externalsources/ciencia" + } + } +}; + +export const externalSourceMyStaffDb: ExternalSource = { + type: new ResourceType('externalsource'), + id: 'my_staff_db', + name: 'my_staff_db', + hierarchical: false, + _links: { + entries: { + href: "https://dspace7.4science.cloud/server/api/integration/externalsources/my_staff_db/entries" + }, + self: { + href: "https://dspace7.4science.cloud/server/api/integration/externalsources/my_staff_db" + } + } +}; /** * Mock for [[ExternalSourceService]] */ -/*export function getMockExternalSourceService(): +export function getMockExternalSourceService(): ExternalSourceService { return jasmine.createSpyObj('ExternalSourceService', { getAllExternalSources: jasmine.createSpy('getAllExternalSources'), getExternalSourceEntries: jasmine.createSpy('getExternalSourceEntries'), }); -}*/ +} diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 8ef3f91257..e83e1179f6 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -461,7 +461,8 @@ const ENTRY_COMPONENTS = [ ClaimedTaskActionsApproveComponent, ClaimedTaskActionsRejectComponent, ClaimedTaskActionsReturnToPoolComponent, - ClaimedTaskActionsEditMetadataComponent + ClaimedTaskActionsEditMetadataComponent, + CollectionDropdownComponent ]; const SHARED_ITEM_PAGE_COMPONENTS = [ diff --git a/src/app/shared/testing/submission-service.stub.ts b/src/app/shared/testing/submission-service.stub.ts index a330fa3eee..35c3ddfee0 100644 --- a/src/app/shared/testing/submission-service.stub.ts +++ b/src/app/shared/testing/submission-service.stub.ts @@ -2,6 +2,7 @@ export class SubmissionServiceStub { changeSubmissionCollection = jasmine.createSpy('changeSubmissionCollection'); createSubmission = jasmine.createSpy('createSubmission'); + createSubmissionFromExternalSource = jasmine.createSpy('createSubmissionFromExternalSource'); depositSubmission = jasmine.createSpy('depositSubmission'); discardSubmission = jasmine.createSpy('discardSubmission'); dispatchInit = jasmine.createSpy('dispatchInit'); diff --git a/src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.html b/src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.html new file mode 100644 index 0000000000..73b41378c8 --- /dev/null +++ b/src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.html @@ -0,0 +1,11 @@ +
+ + +
diff --git a/src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.scss b/src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.scss new file mode 100644 index 0000000000..1a70081367 --- /dev/null +++ b/src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.scss @@ -0,0 +1,3 @@ +.close:focus { + outline: none !important; +} diff --git a/src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.spec.ts b/src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.spec.ts new file mode 100644 index 0000000000..5002c4f94a --- /dev/null +++ b/src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.spec.ts @@ -0,0 +1,89 @@ +import { Component, NO_ERRORS_SCHEMA, EventEmitter } from '@angular/core'; +import { async, TestBed, ComponentFixture, inject } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { createTestComponent } from '../../../shared/testing/utils.test'; +import { SubmissionImportExternalCollectionComponent } from './submission-import-external-collection.component'; +import { CollectionListEntry } from '../../../shared/collection-dropdown/collection-dropdown.component'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; + +describe('SubmissionImportExternalCollectionComponent test suite', () => { + let comp: SubmissionImportExternalCollectionComponent; + let compAsAny: any; + let fixture: ComponentFixture; + + beforeEach(async (() => { + TestBed.configureTestingModule({ + imports: [ + TranslateModule.forRoot(), + ], + declarations: [ + SubmissionImportExternalCollectionComponent, + TestComponent, + ], + providers: [ + NgbActiveModal, + SubmissionImportExternalCollectionComponent + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents().then(); + })); + + // First test to check the correct component creation + describe('', () => { + let testComp: TestComponent; + let testFixture: ComponentFixture; + + // synchronous beforeEach + beforeEach(() => { + const html = ` + `; + testFixture = createTestComponent(html, TestComponent) as ComponentFixture; + testComp = testFixture.componentInstance; + }); + + afterEach(() => { + testFixture.destroy(); + }); + + it('should create SubmissionImportExternalCollectionComponent', inject([SubmissionImportExternalCollectionComponent], (app: SubmissionImportExternalCollectionComponent) => { + expect(app).toBeDefined(); + })); + }); + + describe('', () => { + beforeEach(() => { + fixture = TestBed.createComponent(SubmissionImportExternalCollectionComponent); + comp = fixture.componentInstance; + compAsAny = comp; + }); + + afterEach(() => { + fixture.destroy(); + comp = null; + compAsAny = null; + }); + + it('The variable \'selectedEvent\' should be assigned', () => { + const event = new EventEmitter(); + comp.selectObject(event); + + expect(comp.selectedEvent).toEqual(event); + }); + + it('The variable \'selectedEvent\' should be assigned', () => { + spyOn(compAsAny.activeModal, 'dismiss'); + comp.closeCollectionModal(); + + expect(compAsAny.activeModal.dismiss).toHaveBeenCalled(); + }); + }); +}); + +// declare a test component +@Component({ + selector: 'ds-test-cmp', + template: `` +}) +class TestComponent { + +} diff --git a/src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.ts b/src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.ts new file mode 100644 index 0000000000..cbac0cb710 --- /dev/null +++ b/src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.ts @@ -0,0 +1,40 @@ +import { Component, Output, EventEmitter } from '@angular/core'; +import { CollectionListEntry } from '../../../shared/collection-dropdown/collection-dropdown.component'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; + +/** + * Wrap component for 'ds-collection-dropdown'. + */ +@Component({ + selector: 'ds-submission-import-external-collection', + styleUrls: ['./submission-import-external-collection.component.scss'], + templateUrl: './submission-import-external-collection.component.html' +}) +export class SubmissionImportExternalCollectionComponent { + /** + * The event passed by 'ds-collection-dropdown'. + */ + @Output() public selectedEvent = new EventEmitter(); + + /** + * Initialize the component variables. + * @param {NgbActiveModal} activeModal + */ + constructor( + private activeModal: NgbActiveModal + ) { } + + /** + * This method populates the 'selectedEvent' variable. + */ + public selectObject(event): void { + this.selectedEvent.emit(event); + } + + /** + * This method closes the modal. + */ + public closeCollectionModal(): void { + this.activeModal.dismiss(false); + } +} diff --git a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.html b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.html index 29f1804f1f..0f155286ce 100644 --- a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.html +++ b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.html @@ -30,9 +30,9 @@
diff --git a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts new file mode 100644 index 0000000000..66dfc72e6b --- /dev/null +++ b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts @@ -0,0 +1,153 @@ +import { Component, NO_ERRORS_SCHEMA } from '@angular/core'; +import { async, TestBed, ComponentFixture, inject } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { Router } from '@angular/router'; +import { NgbModal, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { of as observableOf, of } from 'rxjs/internal/observable/of'; +import { SubmissionImportExternalPreviewComponent } from './submission-import-external-preview.component'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { RouterStub } from '../../../shared/testing/router.stub'; +import { SubmissionService } from '../../submission.service'; +import { createTestComponent } from '../../../shared/testing/utils.test'; +import { SubmissionServiceStub } from '../../../shared/testing/submission-service.stub'; +import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub'; +import { ExternalSourceEntry } from '../../../core/shared/external-source-entry.model'; +import { Metadata } from '../../../core/shared/metadata.utils'; +import { SubmissionImportExternalCollectionComponent } from '../import-external-collection/submission-import-external-collection.component'; +import { CollectionListEntry } from '../../../shared/collection-dropdown/collection-dropdown.component'; + +describe('SubmissionImportExternalPreviewComponent test suite', () => { + let comp: SubmissionImportExternalPreviewComponent; + let compAsAny: any; + let fixture: ComponentFixture; + let submissionServiceStub: SubmissionServiceStub; + const externalEntry = Object.assign(new ExternalSourceEntry(), { + id: '0001-0001-0001-0001', + display: 'John Doe', + value: 'John, Doe', + metadata: { + 'dc.identifier.uri': [ + { + value: 'https://orcid.org/0001-0001-0001-0001' + } + ] + }, + _links: { self: { href: 'http://test-rest.com/server/api/integration/externalSources/orcidV2/entryValues/0000-0003-4851-8004' } } + }); + + beforeEach(async (() => { + TestBed.configureTestingModule({ + imports: [ + TranslateModule.forRoot() + ], + declarations: [ + SubmissionImportExternalPreviewComponent, + TestComponent + ], + providers: [ + { provide: Router, useValue: new RouterStub() }, + { provide: SubmissionService, useValue: new SubmissionServiceStub() }, + { provide: NotificationsService, useValue: new NotificationsServiceStub() }, + NgbModal, + NgbActiveModal, + SubmissionImportExternalPreviewComponent + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents().then(); + })); + + // First test to check the correct component creation + describe('', () => { + let testComp: TestComponent; + let testFixture: ComponentFixture; + + // synchronous beforeEach + beforeEach(() => { + const html = ` + `; + testFixture = createTestComponent(html, TestComponent) as ComponentFixture; + testComp = testFixture.componentInstance; + }); + + afterEach(() => { + testFixture.destroy(); + }); + + it('should create SubmissionImportExternalComponent', inject([SubmissionImportExternalPreviewComponent], (app: SubmissionImportExternalPreviewComponent) => { + expect(app).toBeDefined(); + })); + }); + + describe('', () => { + beforeEach(() => { + fixture = TestBed.createComponent(SubmissionImportExternalPreviewComponent); + comp = fixture.componentInstance; + compAsAny = comp; + submissionServiceStub = TestBed.get(SubmissionService); + }); + + afterEach(() => { + fixture.destroy(); + comp = null; + compAsAny = null; + }); + + it('Should init component properly', () => { + comp.externalSourceEntry = externalEntry; + const expected = [ + { key: 'dc.identifier.uri', value: Metadata.first(comp.externalSourceEntry.metadata, 'dc.identifier.uri') } + ]; + comp.ngOnInit(); + fixture.detectChanges(); + + expect(comp.metadataList).toEqual(expected); + }); + + it('Should close the modal calling \'activeModal.dismiss\'', () => { + spyOn(compAsAny.activeModal, 'dismiss'); + comp.closeMetadataModal(); + + expect(compAsAny.activeModal.dismiss).toHaveBeenCalled(); + }); + + it('Should start the import process opening a modal', () => { + const emittedEvent: CollectionListEntry = { + communities: [ + { + id: 'dummy', + uuid: 'dummy', + name: 'dummy', + } + ], + collection: { + id: 'ce64f48e-2c9b-411a-ac36-ee429c0e6a88', + uuid: 'ce64f48e-2c9b-411a-ac36-ee429c0e6a88', + name: 'Collection 1', + } + }; + const submissionObjects = [ + { id: 'jk11k13o-9v4z-632i-sr88-wq071n0h1d47' } + ]; + comp.externalSourceEntry = externalEntry; + spyOn(compAsAny.modalService, 'open').and.returnValue({componentInstance: { selectedEvent: observableOf(emittedEvent)}}); + spyOn(comp, 'closeMetadataModal'); + submissionServiceStub.createSubmissionFromExternalSource.and.returnValue(observableOf(submissionObjects)); + spyOn(compAsAny.router, 'navigateByUrl'); + comp.import(); + + expect(compAsAny.modalService.open).toHaveBeenCalledWith(SubmissionImportExternalCollectionComponent, { size: 'lg' }); + expect(comp.closeMetadataModal).toHaveBeenCalled(); + expect(compAsAny.submissionService.createSubmissionFromExternalSource).toHaveBeenCalledWith(externalEntry._links.self.href, emittedEvent.collection.id); + expect(compAsAny.router.navigateByUrl).toHaveBeenCalledWith('/workspaceitems/' + submissionObjects[0].id + '/edit'); + }); + }); +}); + +// declare a test component +@Component({ + selector: 'ds-test-cmp', + template: `` +}) +class TestComponent { + +} diff --git a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.ts b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.ts index de86bba3b1..8294ec66ba 100644 --- a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.ts +++ b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.ts @@ -1,8 +1,15 @@ import { Component, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; import { NgbActiveModal, NgbModalRef, NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { ExternalSourceEntry } from '../../../core/shared/external-source-entry.model'; import { MetadataValue } from '../../../core/shared/metadata.models'; import { Metadata } from '../../../core/shared/metadata.utils'; +import { CollectionListEntry } from '../../../shared/collection-dropdown/collection-dropdown.component'; +import { mergeMap } from 'rxjs/operators'; +import { SubmissionService } from '../../submission.service'; +import { SubmissionObject } from '../../../core/submission/models/submission-object.model'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { SubmissionImportExternalCollectionComponent } from '../import-external-collection/submission-import-external-collection.component'; /** * This component display a preview of an external source item. @@ -29,10 +36,17 @@ export class SubmissionImportExternalPreviewComponent implements OnInit { /** * Initialize the component variables. * @param {NgbActiveModal} activeModal + * @param {SubmissionService} submissionService + * @param {NgbModal} modalService + * @param {Router} router + * @param {NotificationsService} notificationService */ constructor( private activeModal: NgbActiveModal, - private modalService: NgbModal + private submissionService: SubmissionService, + private modalService: NgbModal, + private router: Router, + private notificationService: NotificationsService ) { } /** @@ -57,14 +71,30 @@ export class SubmissionImportExternalPreviewComponent implements OnInit { } /** - * Start the import of an entry by opening up an import modal window. - * @param entry The entry to import + * Start the import of an entry by opening up a collection choice modal window. */ - public import(entry): void { - this.modalRef = this.modalService.open(SubmissionImportExternalPreviewComponent, { + public import(): void { + this.modalRef = this.modalService.open(SubmissionImportExternalCollectionComponent, { size: 'lg', }); - const modalComp = this.modalRef.componentInstance; - modalComp.externalSourceEntry = entry; + this.closeMetadataModal(); + + this.modalRef.componentInstance.selectedEvent.pipe( + mergeMap((collectionListEntry: CollectionListEntry) => { + return this.submissionService.createSubmissionFromExternalSource(this.externalSourceEntry._links.self.href, collectionListEntry.collection.id); + }) + ).subscribe((submissionObjects: SubmissionObject[]) => { + let isValid = false + if (submissionObjects.length === 1) { + if (submissionObjects[0] !== null) { + isValid = true; + this.router.navigateByUrl('/workspaceitems/' + submissionObjects[0].id + '/edit'); + } + } + if (!isValid) { + this.notificationService.error('submission.import-external.preview.error.import.title', 'submission.import-external.preview.error.import.body'); + } + this.modalRef.close(); + }); } } diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.spec.ts b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.spec.ts index 66ce798ed9..1f77374932 100644 --- a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.spec.ts +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.spec.ts @@ -1,13 +1,18 @@ -// import { Component, NO_ERRORS_SCHEMA, ChangeDetectorRef } from '@angular/core'; -// import { async, TestBed, ComponentFixture, inject } from '@angular/core/testing'; -// import { TranslateModule } from '@ngx-translate/core'; -// import { SubmissionImportExternalSearchbarComponent } from './submission-import-external-searchbar.component'; -// import { ExternalSourceService } from '../../../core/data/external-source.service'; -// import { createTestComponent } from '../../../shared/testing/utils.test'; -// import { getMockExternalSourceService } from '../../../shared/mocks/external-source.service.mock'; -// import { SubmissionModule } from '../../submission.module'; +import { Component, NO_ERRORS_SCHEMA, ChangeDetectorRef } from '@angular/core'; +import { async, TestBed, ComponentFixture, inject } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { of as observableOf } from 'rxjs'; +import { SubmissionImportExternalSearchbarComponent, SourceElement } from './submission-import-external-searchbar.component'; +import { ExternalSourceService } from '../../../core/data/external-source.service'; +import { createTestComponent } from '../../../shared/testing/utils.test'; +import { getMockExternalSourceService, externalSourceOrcid, externalSourceCiencia, externalSourceMyStaffDb } from '../../../shared/mocks/external-source.service.mock'; +import { PageInfo } from '../../../core/shared/page-info.model'; +import { PaginatedList } from '../../../core/data/paginated-list'; +import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils'; +import { ExternalSource } from '../../../core/shared/external-source.model'; +import { FindListOptions } from '../../../core/data/request.models'; -/*describe('SubmissionImportExternalSearchbarComponent test suite', () => { +describe('SubmissionImportExternalSearchbarComponent test suite', () => { let comp: SubmissionImportExternalSearchbarComponent; let compAsAny: any; let fixture: ComponentFixture; @@ -15,7 +20,6 @@ beforeEach(async (() => { TestBed.configureTestingModule({ imports: [ - SubmissionModule, TranslateModule.forRoot(), ], declarations: [ @@ -51,16 +55,25 @@ it('should create SubmissionImportExternalSearchbarComponent', inject([SubmissionImportExternalSearchbarComponent], (app: SubmissionImportExternalSearchbarComponent) => { expect(app).toBeDefined(); })); - });*/ + }); + + describe('', () => { + let sourceList: SourceElement[]; + let paginatedList: PaginatedList; - /*describe('', () => { beforeEach(() => { fixture = TestBed.createComponent(SubmissionImportExternalSearchbarComponent); comp = fixture.componentInstance; compAsAny = comp; - // compAsAny.externalService.getAllExternalSources.and.returnValue(observableOf([ - - // ])); + const pageInfo = new PageInfo(); + paginatedList = new PaginatedList(pageInfo, [externalSourceOrcid, externalSourceCiencia, externalSourceMyStaffDb]); + const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); + compAsAny.externalService.getAllExternalSources.and.returnValue(observableOf(paginatedListRD)); + sourceList = [ + {id: 'orcid', name: 'orcid'}, + {id: 'ciencia', name: 'ciencia'}, + {id: 'my_staff_db', name: 'my_staff_db'}, + ]; }); afterEach(() => { @@ -69,16 +82,61 @@ compAsAny = null; }); - it('Should init component properly', () => { + it('Should init component properly (without initExternalSourceData)', () => { + comp.initExternalSourceData = { sourceId: '', query: '' }; comp.ngOnInit(); fixture.detectChanges(); - expect(comp.selectedElement) - expect(compAsAny.pageInfo) - expect(comp.sourceList) + expect(comp.selectedElement).toEqual(sourceList[0]); + expect(compAsAny.pageInfo).toEqual(paginatedList.pageInfo); + expect(comp.sourceList).toEqual(sourceList); }); - });*/ -/* + + it('Should init component properly (with initExternalSourceData populated)', () => { + comp.initExternalSourceData = { query: 'dummy', sourceId: 'ciencia' }; + comp.ngOnInit(); + fixture.detectChanges(); + + expect(comp.selectedElement).toEqual(sourceList[1]); + expect(compAsAny.pageInfo).toEqual(paginatedList.pageInfo); + expect(comp.sourceList).toEqual(sourceList); + }); + + it('Variable \'selectedElement\' should be assigned', () => { + const selectedElement = {id: 'orcid', name: 'orcid'}; + comp.makeSourceSelection(selectedElement); + expect(comp.selectedElement).toEqual(selectedElement); + }); + + it('Should load additional external sources', () => { + comp.sourceListLoading = false; + compAsAny.pageInfo = new PageInfo({ + elementsPerPage: 3, + totalElements: 6, + totalPages: 2, + currentPage: 0 + }); + compAsAny.findListOptions = Object.assign({}, new FindListOptions(), { + elementsPerPage: 3, + currentPage: 0, + }); + comp.sourceList = sourceList; + const expected = sourceList.concat(sourceList); + comp.onScroll(); + + expect(comp.sourceList).toEqual(expected); + }); + + it('The \'search\' method should call \'emit\'', () => { + comp.selectedElement = { id: 'orcidV2', name: 'orcidV2' }; + comp.searchString = 'dummy'; + const expected = { sourceId: comp.selectedElement.id, query: comp.searchString }; + spyOn(comp.externalSourceData, 'emit'); + comp.search(); + + expect(comp.externalSourceData.emit).toHaveBeenCalledWith(expected); + }); + }); }); // declare a test component @@ -88,4 +146,4 @@ }) class TestComponent { -}*/ +} diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts index cd2f24eb2c..efbcbad60c 100644 --- a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts @@ -10,13 +10,12 @@ import { RemoteData } from '../../../core/data/remote-data'; import { PageInfo } from '../../../core/shared/page-info.model'; import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils'; import { FindListOptions } from '../../../core/data/request.models'; -import { isEmpty } from '../../../shared/empty.util'; import { getFirstSucceededRemoteDataPayload } from '../../../core/shared/operators'; /** * Interface for the selected external source element. */ -interface SourceElement { +export interface SourceElement { id: string; name: string; } @@ -124,14 +123,14 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { /** * Set the selected external source. */ - makeSourceSelection(source) { + public makeSourceSelection(source): void { this.selectedElement = source; } /** * Load the next pages of external sources. */ - onScroll() { + public onScroll(): void { if (!this.sourceListLoading && this.pageInfo.currentPage <= this.pageInfo.totalPages) { this.sourceListLoading = true; this.findListOptions = Object.assign({}, new FindListOptions(), { @@ -145,21 +144,21 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); return observableOf(paginatedListRD); }), - tap(() => this.sourceListLoading = false)) - .subscribe((externalSource: RemoteData>) => { - externalSource.payload.page.forEach((element) => { - this.sourceList.push({ id: element.id, name: element.name }); - }) - this.pageInfo = externalSource.payload.pageInfo; - this.cdr.detectChanges(); + tap(() => this.sourceListLoading = false) + ).subscribe((externalSource: RemoteData>) => { + externalSource.payload.page.forEach((element) => { + this.sourceList.push({ id: element.id, name: element.name }); }) + this.pageInfo = externalSource.payload.pageInfo; + this.cdr.detectChanges(); + }) } } /** * Passes the search parameters to the parent component. */ - public search() { + public search(): void { this.externalSourceData.emit({ sourceId: this.selectedElement.id, query: this.searchString }); } } diff --git a/src/app/submission/import-external/submission-import-external.component.spec.ts b/src/app/submission/import-external/submission-import-external.component.spec.ts index e69de29bb2..6b5ec05171 100644 --- a/src/app/submission/import-external/submission-import-external.component.spec.ts +++ b/src/app/submission/import-external/submission-import-external.component.spec.ts @@ -0,0 +1,159 @@ +import { Component, NO_ERRORS_SCHEMA } from '@angular/core'; +import { async, TestBed, ComponentFixture, inject } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { Router } from '@angular/router'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { of as observableOf, of } from 'rxjs/internal/observable/of'; +import { SubmissionImportExternalComponent } from './submission-import-external.component'; +import { ExternalSourceService } from '../../core/data/external-source.service'; +import { getMockExternalSourceService } from '../../shared/mocks/external-source.service.mock'; +import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service'; +import { RouteService } from '../../core/services/route.service'; +import { createTestComponent, createPaginatedList } from '../../shared/testing/utils.test'; +import { RouterStub } from '../../shared/testing/router.stub'; +import { VarDirective } from '../../shared/utils/var.directive'; +import { routeServiceStub } from '../../shared/testing/route-service.stub'; +import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; +import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; +import { createSuccessfulRemoteDataObject } from '../../shared/remote-data.utils'; +import { ExternalSourceEntry } from '../../core/shared/external-source-entry.model'; +import { SubmissionImportExternalPreviewComponent } from './import-external-preview/submission-import-external-preview.component'; + +describe('SubmissionImportExternalComponent test suite', () => { + let comp: SubmissionImportExternalComponent; + let compAsAny: any; + let fixture: ComponentFixture; + const mockSearchOptions = of(new PaginatedSearchOptions({ + pagination: Object.assign(new PaginationComponentOptions(), { + pageSize: 10, + currentPage: 0 + }) + })); + const searchConfigServiceStub = { + paginatedSearchOptions: mockSearchOptions + }; + + beforeEach(async (() => { + TestBed.configureTestingModule({ + imports: [ + TranslateModule.forRoot() + ], + declarations: [ + SubmissionImportExternalComponent, + TestComponent, + VarDirective + ], + providers: [ + { provide: ExternalSourceService, useClass: getMockExternalSourceService }, + { provide: SearchConfigurationService, useValue: searchConfigServiceStub }, + { provide: RouteService, useValue: routeServiceStub }, + { provide: Router, useValue: new RouterStub() }, + NgbModal, + SubmissionImportExternalComponent + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents().then(); + })); + + // First test to check the correct component creation + describe('', () => { + let testComp: TestComponent; + let testFixture: ComponentFixture; + + // synchronous beforeEach + beforeEach(() => { + const html = ` + `; + testFixture = createTestComponent(html, TestComponent) as ComponentFixture; + testComp = testFixture.componentInstance; + }); + + afterEach(() => { + testFixture.destroy(); + }); + + it('should create SubmissionImportExternalComponent', inject([SubmissionImportExternalComponent], (app: SubmissionImportExternalComponent) => { + expect(app).toBeDefined(); + })); + }); + + describe('', () => { + beforeEach(() => { + fixture = TestBed.createComponent(SubmissionImportExternalComponent); + comp = fixture.componentInstance; + compAsAny = comp; + }); + + afterEach(() => { + fixture.destroy(); + comp = null; + compAsAny = null; + }); + + it('Should init component properly (without route data)', () => { + const expectedEntries = createSuccessfulRemoteDataObject(createPaginatedList([])); + spyOn(compAsAny.routeService, 'getQueryParameterValue').and.returnValue(observableOf('')); + comp.ngOnInit(); + fixture.detectChanges(); + + expect(comp.routeData).toEqual({ sourceId: '', query: '' }); + expect(comp.isLoading$.value).toBe(false); + expect(comp.entriesRD$.value).toEqual(expectedEntries); + }); + + it('Should init component properly (with route data)', () => { + const expectedEntries = createSuccessfulRemoteDataObject(createPaginatedList([])); + const searchOptions = new PaginatedSearchOptions({ + pagination: Object.assign(new PaginationComponentOptions(), { + pageSize: 10, + currentPage: 0 + }) + }); + spyOn(compAsAny.routeService, 'getQueryParameterValue').and.returnValue(observableOf('dummy')); + comp.ngOnInit(); + fixture.detectChanges(); + + expect(comp.routeData).toEqual({ sourceId: 'dummy', query: 'dummy' }); + expect(comp.isLoading$.value).toBe(true); + expect(comp.entriesRD$.value).toEqual(expectedEntries); + expect(compAsAny.externalService.getExternalSourceEntries).toHaveBeenCalledWith('dummy', searchOptions); + }); + + it('Should call \'router.navigate\'', () => { + const event = { sourceId: 'orcidV2', query: 'dummy' }; + comp.getExternalsourceData(event); + + expect(compAsAny.router.navigate).toHaveBeenCalledWith([], { queryParams: { source: event.sourceId, query: event.query }, replaceUrl: true }); + }); + + it('Entry should be passed to the component loaded inside the modal', () => { + const entry = Object.assign(new ExternalSourceEntry(), { + id: '0001-0001-0001-0001', + display: 'John Doe', + value: 'John, Doe', + metadata: { + 'dc.identifier.uri': [ + { + value: 'https://orcid.org/0001-0001-0001-0001' + } + ] + } + }); + spyOn(compAsAny.modalService, 'open').and.returnValue({componentInstance: { externalSourceEntry: null}}); + comp.import(entry); + + expect(compAsAny.modalService.open).toHaveBeenCalledWith(SubmissionImportExternalPreviewComponent, { size: 'lg' }); + expect(comp.modalRef.componentInstance.externalSourceEntry).toEqual(entry); + }); + }); + +}); + +// declare a test component +@Component({ + selector: 'ds-test-cmp', + template: `` +}) +class TestComponent { + +} diff --git a/src/app/submission/import-external/submission-import-external.component.ts b/src/app/submission/import-external/submission-import-external.component.ts index 47ae781baa..70fdd5f477 100644 --- a/src/app/submission/import-external/submission-import-external.component.ts +++ b/src/app/submission/import-external/submission-import-external.component.ts @@ -70,7 +70,7 @@ export class SubmissionImportExternalComponent implements OnInit { /** * The modal for the entry preview */ - modalRef: NgbModalRef; + public modalRef: NgbModalRef; /** * Initialize the component variables. diff --git a/src/app/submission/submission.module.ts b/src/app/submission/submission.module.ts index 7ff8b98d9e..4e5e5bc6da 100644 --- a/src/app/submission/submission.module.ts +++ b/src/app/submission/submission.module.ts @@ -31,6 +31,7 @@ import { storeModuleConfig } from '../app.reducer'; import { SubmissionImportExternalComponent } from './import-external/submission-import-external.component'; import { SubmissionImportExternalSearchbarComponent } from './import-external/import-external-searchbar/submission-import-external-searchbar.component'; import { SubmissionImportExternalPreviewComponent } from './import-external/import-external-preview/submission-import-external-preview.component'; +import { SubmissionImportExternalCollectionComponent } from './import-external/import-external-collection/submission-import-external-collection.component'; @NgModule({ imports: [ @@ -60,14 +61,16 @@ import { SubmissionImportExternalPreviewComponent } from './import-external/impo SubmissionSectionUploadFileViewComponent, SubmissionImportExternalComponent, SubmissionImportExternalSearchbarComponent, - SubmissionImportExternalPreviewComponent + SubmissionImportExternalPreviewComponent, + SubmissionImportExternalCollectionComponent ], entryComponents: [ SubmissionSectionUploadComponent, SubmissionSectionformComponent, SubmissionSectionLicenseComponent, SubmissionSectionContainerComponent, - SubmissionImportExternalPreviewComponent + SubmissionImportExternalPreviewComponent, + SubmissionImportExternalCollectionComponent ], exports: [ SubmissionEditComponent, diff --git a/src/app/submission/submission.service.spec.ts b/src/app/submission/submission.service.spec.ts index eb7538ec69..9cb678dbb3 100644 --- a/src/app/submission/submission.service.spec.ts +++ b/src/app/submission/submission.service.spec.ts @@ -410,6 +410,19 @@ describe('SubmissionService test suite', () => { }); }); + describe('createSubmissionFromExternalSource', () => { + it('should deposit submission', () => { + const options: HttpOptions = Object.create({}); + let headers = new HttpHeaders(); + headers = headers.append('Content-Type', 'text/uri-list'); + options.headers = headers; + + service.createSubmissionFromExternalSource(selfUrl, collectionId); + + expect((service as any).restService.postToEndpoint).toHaveBeenCalledWith('workspaceitems', selfUrl, null, options, collectionId); + }); + }); + describe('depositSubmission', () => { it('should deposit submission', () => { const options: HttpOptions = Object.create({}); diff --git a/src/app/submission/submission.service.ts b/src/app/submission/submission.service.ts index f06f6ea069..7aa02c6c07 100644 --- a/src/app/submission/submission.service.ts +++ b/src/app/submission/submission.service.ts @@ -113,6 +113,24 @@ export class SubmissionService { catchError(() => observableOf({} as SubmissionObject))) } + /** + * Perform a REST call to deposit a workspaceitem and return response + * + * @param selfUrl + * The workspaceitem self url + * @param collectionId + * Optional collection id + * @return Observable + * observable of SubmissionObject + */ + createSubmissionFromExternalSource(selfUrl: string, collectionId?: string): Observable { + const options: HttpOptions = Object.create({}); + let headers = new HttpHeaders(); + headers = headers.append('Content-Type', 'text/uri-list'); + options.headers = headers; + return this.restService.postToEndpoint(this.workspaceLinkPath, selfUrl, null, options, collectionId) as Observable; + } + /** * Perform a REST call to deposit a workspaceitem and return response * diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 3e2994142d..fdacf7cd44 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -2432,6 +2432,10 @@ "submission.import-external.preview.button.import": "Start submission", + "submission.import-external.preview.error.import.title": "Submission error", + + "submission.import-external.preview.error.import.body": "An error occurs during the external source entry import process.", + "submission.sections.describe.relationship-lookup.close": "Close", From 1f54094d5a7554cf577bf243fdd8571314fc1691 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Wed, 24 Jun 2020 10:31:54 +0200 Subject: [PATCH 010/170] Fixed components import --- src/app/+import-external-page/import-external-page.module.ts | 5 ++++- src/app/submission/submission.module.ts | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/app/+import-external-page/import-external-page.module.ts b/src/app/+import-external-page/import-external-page.module.ts index 8dae7c2f88..017c723ad9 100644 --- a/src/app/+import-external-page/import-external-page.module.ts +++ b/src/app/+import-external-page/import-external-page.module.ts @@ -5,6 +5,7 @@ import { SharedModule } from '../shared/shared.module'; import { CoreModule } from '../core/core.module'; import { ImportExternalRoutingModule } from './import-external-routing.module'; import { SubmissionModule } from '../submission/submission.module'; +import { ImportExternalPageComponent } from './import-external-page.component'; @NgModule({ imports: [ @@ -14,7 +15,9 @@ import { SubmissionModule } from '../submission/submission.module'; ImportExternalRoutingModule, SubmissionModule, ], - declarations: [ ], + declarations: [ + ImportExternalPageComponent + ], entryComponents: [ ] }) diff --git a/src/app/submission/submission.module.ts b/src/app/submission/submission.module.ts index 4e5e5bc6da..9446286c52 100644 --- a/src/app/submission/submission.module.ts +++ b/src/app/submission/submission.module.ts @@ -75,7 +75,8 @@ import { SubmissionImportExternalCollectionComponent } from './import-external/i exports: [ SubmissionEditComponent, SubmissionFormComponent, - SubmissionSubmitComponent + SubmissionSubmitComponent, + SubmissionImportExternalComponent ], providers: [ SectionUploadService, From 74d1e0bccb53c8d4995c8f034eadbcecde415b54 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Wed, 24 Jun 2020 10:48:29 +0200 Subject: [PATCH 011/170] Fixed issue with spyOn --- .../import-external/submission-import-external.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/submission/import-external/submission-import-external.component.ts b/src/app/submission/import-external/submission-import-external.component.ts index 70fdd5f477..9988f098c9 100644 --- a/src/app/submission/import-external/submission-import-external.component.ts +++ b/src/app/submission/import-external/submission-import-external.component.ts @@ -16,7 +16,7 @@ import { createSuccessfulRemoteDataObject } from '../../shared/remote-data.utils import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { SubmissionImportExternalPreviewComponent } from './import-external-preview/submission-import-external-preview.component'; import { fadeIn } from '../../shared/animations/fade'; -import { createPaginatedList } from '../../shared/testing/utils.test'; +import { PageInfo } from '../../core/shared/page-info.model'; /** * This component allows to submit a new workspaceitem importing the data from an external source. @@ -100,7 +100,7 @@ export class SubmissionImportExternalComponent implements OnInit { this.importConfig = { buttonLabel: 'submission.sections.describe.relationship-lookup.external-source.import-button-title.' + this.label }; - this.entriesRD$ = new BehaviorSubject(createSuccessfulRemoteDataObject(createPaginatedList([]))); + this.entriesRD$ = new BehaviorSubject(createSuccessfulRemoteDataObject(new PaginatedList(new PageInfo(), []))); this.isLoading$ = new BehaviorSubject(false); combineLatest( [ From c25085b299258bec0d66bac11873188b0ab304da Mon Sep 17 00:00:00 2001 From: Matteo Perelli Date: Wed, 24 Jun 2020 11:52:34 +0200 Subject: [PATCH 012/170] Lint errors fixed --- src/app/shared/mocks/external-source.service.mock.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/app/shared/mocks/external-source.service.mock.ts b/src/app/shared/mocks/external-source.service.mock.ts index 4edf9efb14..3e96eb508e 100644 --- a/src/app/shared/mocks/external-source.service.mock.ts +++ b/src/app/shared/mocks/external-source.service.mock.ts @@ -9,10 +9,10 @@ export const externalSourceOrcid: ExternalSource = { hierarchical: false, _links: { entries: { - href: "https://dspace7.4science.cloud/server/api/integration/externalsources/orcid/entries" + href: 'https://dspace7.4science.cloud/server/api/integration/externalsources/orcid/entries' }, self: { - href: "https://dspace7.4science.cloud/server/api/integration/externalsources/orcid" + href: 'https://dspace7.4science.cloud/server/api/integration/externalsources/orcid' } } }; @@ -24,10 +24,10 @@ export const externalSourceCiencia: ExternalSource = { hierarchical: false, _links: { entries: { - href: "https://dspace7.4science.cloud/server/api/integration/externalsources/ciencia/entries" + href: 'https://dspace7.4science.cloud/server/api/integration/externalsources/ciencia/entries' }, self: { - href: "https://dspace7.4science.cloud/server/api/integration/externalsources/ciencia" + href: 'https://dspace7.4science.cloud/server/api/integration/externalsources/ciencia' } } }; @@ -39,10 +39,10 @@ export const externalSourceMyStaffDb: ExternalSource = { hierarchical: false, _links: { entries: { - href: "https://dspace7.4science.cloud/server/api/integration/externalsources/my_staff_db/entries" + href: 'https://dspace7.4science.cloud/server/api/integration/externalsources/my_staff_db/entries' }, self: { - href: "https://dspace7.4science.cloud/server/api/integration/externalsources/my_staff_db" + href: 'https://dspace7.4science.cloud/server/api/integration/externalsources/my_staff_db' } } }; From c7cf11f4214a42d0c6994967f2d97aee0dfb96db Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Wed, 24 Jun 2020 12:52:16 +0200 Subject: [PATCH 013/170] [CST-3088] Improved VocabularyFindOptions --- .../models/vocabulary-find-options.model.ts | 45 +++++++++++++++++++ ...y-entries-response-parsing.service.spec.ts | 2 +- .../vocabularies/vocabulary.service.spec.ts | 10 +++-- .../vocabularies/vocabulary.service.ts | 27 +++-------- 4 files changed, 58 insertions(+), 26 deletions(-) create mode 100644 src/app/core/submission/vocabularies/models/vocabulary-find-options.model.ts diff --git a/src/app/core/submission/vocabularies/models/vocabulary-find-options.model.ts b/src/app/core/submission/vocabularies/models/vocabulary-find-options.model.ts new file mode 100644 index 0000000000..18309ed1fe --- /dev/null +++ b/src/app/core/submission/vocabularies/models/vocabulary-find-options.model.ts @@ -0,0 +1,45 @@ +import { SortOptions } from '../../../cache/models/sort-options.model'; +import { FindListOptions } from '../../../data/request.models'; +import { RequestParam } from '../../../cache/models/request-param.model'; +import { isNotEmpty } from '../../../../shared/empty.util'; + +/** + * Representing properties used to build a vocabulary find request + */ +export class VocabularyFindOptions extends FindListOptions { + + constructor(public collection: string = '', + public name: string = '', + public metadata: string = '', + public query: string = '', + public elementsPerPage?: number, + public currentPage?: number, + public sort?: SortOptions, + public filter?: string, + public exact?: string, + public entryID?: string, + ) { + super(); + + const searchParams = []; + if (isNotEmpty(metadata)) { + searchParams.push(new RequestParam('metadata', metadata)) + } + if (isNotEmpty(collection)) { + searchParams.push(new RequestParam('collection', collection)) + } + if (isNotEmpty(query)) { + searchParams.push(new RequestParam('query', query)) + } + if (isNotEmpty(filter)) { + searchParams.push(new RequestParam('filter', filter)) + } + if (isNotEmpty(exact)) { + searchParams.push(new RequestParam('exact', exact)) + } + if (isNotEmpty(entryID)) { + searchParams.push(new RequestParam('entryID', entryID)) + } + this.searchParams = searchParams; + } +} diff --git a/src/app/core/submission/vocabularies/vocabulary-entries-response-parsing.service.spec.ts b/src/app/core/submission/vocabularies/vocabulary-entries-response-parsing.service.spec.ts index 592ed234a7..9f28ccea17 100644 --- a/src/app/core/submission/vocabularies/vocabulary-entries-response-parsing.service.spec.ts +++ b/src/app/core/submission/vocabularies/vocabulary-entries-response-parsing.service.spec.ts @@ -4,7 +4,7 @@ import { DSpaceRESTV2Response } from '../../dspace-rest-v2/dspace-rest-v2-respon import { VocabularyEntriesResponseParsingService } from './vocabulary-entries-response-parsing.service'; import { VocabularyEntriesRequest } from '../../data/request.models'; -fdescribe('VocabularyEntriesResponseParsingService', () => { +describe('VocabularyEntriesResponseParsingService', () => { let service: VocabularyEntriesResponseParsingService; const metadata = 'dc.type'; const collectionUUID = '8b39g7ya-5a4b-438b-851f-be1d5b4a1c5a'; diff --git a/src/app/core/submission/vocabularies/vocabulary.service.spec.ts b/src/app/core/submission/vocabularies/vocabulary.service.spec.ts index 2596e368b5..5323c29f30 100644 --- a/src/app/core/submission/vocabularies/vocabulary.service.spec.ts +++ b/src/app/core/submission/vocabularies/vocabulary.service.spec.ts @@ -19,6 +19,7 @@ import { RestResponse } from '../../cache/response.models'; import { VocabularyService } from './vocabulary.service'; import { getMockRequestService } from '../../../shared/mocks/request.service.mock'; import { getMockRemoteDataBuildService } from '../../../shared/mocks/remote-data-build.service.mock'; +import { VocabularyFindOptions } from './models/vocabulary-find-options.model'; describe('VocabularyService', () => { let scheduler: TestScheduler; @@ -95,6 +96,7 @@ describe('VocabularyService', () => { const vocabularyId = 'types'; const metadata = 'dc.type'; const collectionUUID = '8b39g7ya-5a4b-438b-851f-be1d5b4a1c5a'; + const vocabularyOptions = new VocabularyFindOptions(collectionUUID, vocabularyId, metadata); const searchRequestURL = `https://rest.api/rest/api/submission/vocabularies/search/byMetadataAndCollection?metadata=${metadata}&collection=${collectionUUID}`; const entriesRequestURL = `https://rest.api/rest/api/submission/vocabularies/${vocabulary.id}/entries?metadata=${metadata}&collection=${collectionUUID}`; @@ -223,14 +225,14 @@ describe('VocabularyService', () => { new RequestParam('metadata', metadata), new RequestParam('collection', collectionUUID) ]; - scheduler.schedule(() => service.searchByMetadataAndCollection(metadata, collectionUUID).subscribe()); + scheduler.schedule(() => service.searchByMetadataAndCollection(vocabularyOptions).subscribe()); scheduler.flush(); expect((service as any).dataService.findByHref).toHaveBeenCalledWith(searchRequestURL); }); it('should return a RemoteData for the search', () => { - const result = service.searchByMetadataAndCollection(metadata, collectionUUID); + const result = service.searchByMetadataAndCollection(vocabularyOptions); const expected = cold('a|', { a: vocabularyRD }); @@ -251,14 +253,14 @@ describe('VocabularyService', () => { it('should configure a new VocabularyEntriesRequest', () => { const expected = new VocabularyEntriesRequest(requestService.generateRequestId(), entriesRequestURL); - scheduler.schedule(() => service.getVocabularyEntries(vocabularyId, metadata, collectionUUID).subscribe()); + scheduler.schedule(() => service.getVocabularyEntries(vocabularyOptions).subscribe()); scheduler.flush(); expect(requestService.configure).toHaveBeenCalledWith(expected); }); it('should call RemoteDataBuildService to create the RemoteData Observable', () => { - service.getVocabularyEntries(vocabularyId, metadata, collectionUUID); + service.getVocabularyEntries(vocabularyOptions); expect(rdbService.toRemoteDataObservable).toHaveBeenCalled(); diff --git a/src/app/core/submission/vocabularies/vocabulary.service.ts b/src/app/core/submission/vocabularies/vocabulary.service.ts index cfb795c942..094f87544f 100644 --- a/src/app/core/submission/vocabularies/vocabulary.service.ts +++ b/src/app/core/submission/vocabularies/vocabulary.service.ts @@ -19,13 +19,13 @@ import { NotificationsService } from '../../../shared/notifications/notification import { ChangeAnalyzer } from '../../data/change-analyzer'; import { DefaultChangeAnalyzer } from '../../data/default-change-analyzer.service'; import { PaginatedList } from '../../data/paginated-list'; -import { RequestParam } from '../../cache/models/request-param.model'; import { Vocabulary } from './models/vocabulary.model'; import { VOCABULARY } from './models/vocabularies.resource-type'; import { VocabularyEntry } from './models/vocabulary-entry.model'; import { hasValue, isNotEmptyOperator } from '../../../shared/empty.util'; import { configureRequest, filterSuccessfulResponses, getRequestFromRequestHref } from '../../shared/operators'; import { GenericSuccessResponse } from '../../cache/response.models'; +import { VocabularyFindOptions } from './models/vocabulary-find-options.model'; /* tslint:disable:max-classes-per-file */ @@ -111,22 +111,13 @@ export class VocabularyService { /** * Return the {@link VocabularyEntry} list for a given {@link Vocabulary} * - * @param id The vocabulary id to retrieve the entries for - * @param metadata The metadata name - * @param collectionUUID The collection UUID - * @param options The {@link FindListOptions} for the request + * @param options The {@link VocabularyFindOptions} for the request * @return {Observable>>} * Return an observable that emits object list */ - getVocabularyEntries(id: string, metadata: string, collectionUUID: string, options: FindListOptions = {}): Observable>> { - options = Object.assign({}, options, { - searchParams: [ - new RequestParam('metadata', metadata), - new RequestParam('collection', collectionUUID) - ] - }); + getVocabularyEntries(options: VocabularyFindOptions): Observable>> { - return this.dataService.getFindAllHref(options, `${id}/entries`).pipe( + return this.dataService.getFindAllHref(options, `${options.name}/entries`).pipe( isNotEmptyOperator(), distinctUntilChanged(), getVocabularyEntriesFor(this.requestService, this.rdbService) @@ -136,18 +127,12 @@ export class VocabularyService { /** * Return the controlled {@link Vocabulary} configured for the specified metadata and collection if any. * - * @param metadata The metadata name - * @param collectionUUID The collection UUID + * @param options The {@link VocabularyFindOptions} for the request * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved * @return {Observable>>} * Return an observable that emits object list */ - searchByMetadataAndCollection(metadata: string, collectionUUID: string, ...linksToFollow: Array>): Observable> { - const options = new FindListOptions(); - options.searchParams = [ - new RequestParam('metadata', metadata), - new RequestParam('collection', collectionUUID) - ]; + searchByMetadataAndCollection(options: VocabularyFindOptions, ...linksToFollow: Array>): Observable> { return this.dataService.getSearchByHref(this.searchByMetadataAndCollectionMethod, options).pipe( first((href: string) => hasValue(href)), From ba46f243c8dd68b3ab41b8b23bf964d2a2d114ab Mon Sep 17 00:00:00 2001 From: Matteo Perelli Date: Wed, 24 Jun 2020 15:38:45 +0200 Subject: [PATCH 014/170] Test fix for CI --- ...ion-import-external-preview.component.html | 2 +- ...-import-external-preview.component.spec.ts | 5 ++-- src/assets/i18n/en.json5 | 25 ++++++++++++++++++- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.html b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.html index 0f155286ce..83c1ed82b6 100644 --- a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.html +++ b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.html @@ -19,7 +19,7 @@
- {{metadata.key}} + {{'item.preview.' + metadata.key | translate}}

{{metadata.value.value}}

diff --git a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts index 66dfc72e6b..71360b9cc3 100644 --- a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts +++ b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts @@ -48,8 +48,8 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { { provide: Router, useValue: new RouterStub() }, { provide: SubmissionService, useValue: new SubmissionServiceStub() }, { provide: NotificationsService, useValue: new NotificationsServiceStub() }, - NgbModal, - NgbActiveModal, + { provide: NgbModal, useValue: { open: () => {/*comment*/} } }, + { provide: NgbActiveModal, useValue: { dismiss: () => {/*comment*/} } }, SubmissionImportExternalPreviewComponent ], schemas: [NO_ERRORS_SCHEMA] @@ -97,7 +97,6 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { const expected = [ { key: 'dc.identifier.uri', value: Metadata.first(comp.externalSourceEntry.metadata, 'dc.identifier.uri') } ]; - comp.ngOnInit(); fixture.detectChanges(); expect(comp.metadataList).toEqual(expected); diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index d5c761dae1..cb5a5b956a 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1425,6 +1425,28 @@ "item.page.uri": "URI", + "item.preview.dc.identifier.uri": "Identifier:", + + "item.preview.dc.contributor.author": "Authors:", + + "item.preview.dc.date.issued": "Published date:", + + "item.preview.dc.description.abstract": "Abstract:", + + "item.preview.dc.identifier.other": "Other identifier:", + + "item.preview.dc.language.iso": "Language:", + + "item.preview.dc.subject": "Subjects:", + + "item.preview.dc.title": "Title:", + + "item.preview.person.familyName": "Surname:", + + "item.preview.person.givenName": "Name:", + + "item.preview.person.identifier.orcid": "ORCID:", + "item.select.confirm": "Confirm selected", @@ -2440,7 +2462,6 @@ "submission.import-external.preview.error.import.body": "An error occurs during the external source entry import process.", - "submission.sections.describe.relationship-lookup.close": "Close", "submission.sections.describe.relationship-lookup.external-source.added": "Successfully added local entry to the selection", @@ -2575,6 +2596,8 @@ "submission.sections.describe.relationship-lookup.selection-tab.title.lcname": "Search Results", + "submission.sections.describe.relationship-lookup.selection-tab.title.pubmed": "Search Results", + "submission.sections.describe.relationship-lookup.name-variant.notification.content": "Would you like to save \"{{ value }}\" as a name variant for this person so you and others can reuse it for future submissions? If you don\'t you can still use it for this submission.", "submission.sections.describe.relationship-lookup.name-variant.notification.confirm": "Save a new name variant", From 3117916d5b127da82e1740d8c8529dd7d549f37e Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Wed, 24 Jun 2020 19:00:13 +0200 Subject: [PATCH 015/170] [CST-3088] Added vocabularyEntryDetails's methods to VocabularyService --- .../models/vocabularies.resource-type.ts | 1 + .../models/vocabulary-entry-detail.model.ts | 33 ++ .../models/vocabulary-entry.model.ts | 4 +- .../models/vocabulary-options.model.ts | 35 ++ .../vocabularies/vocabulary.service.spec.ts | 419 ++++++++++++------ .../vocabularies/vocabulary.service.ts | 91 +++- 6 files changed, 433 insertions(+), 150 deletions(-) create mode 100644 src/app/core/submission/vocabularies/models/vocabulary-entry-detail.model.ts create mode 100644 src/app/core/submission/vocabularies/models/vocabulary-options.model.ts diff --git a/src/app/core/submission/vocabularies/models/vocabularies.resource-type.ts b/src/app/core/submission/vocabularies/models/vocabularies.resource-type.ts index 4d49abd823..5902fe4e17 100644 --- a/src/app/core/submission/vocabularies/models/vocabularies.resource-type.ts +++ b/src/app/core/submission/vocabularies/models/vocabularies.resource-type.ts @@ -9,3 +9,4 @@ import { ResourceType } from '../../../shared/resource-type'; export const VOCABULARY = new ResourceType('vocabulary'); export const VOCABULARY_ENTRY = new ResourceType('vocabularyEntry'); +export const VOCABULARY_ENTRY_DETAIL = new ResourceType('vocabularyEntryDetail'); diff --git a/src/app/core/submission/vocabularies/models/vocabulary-entry-detail.model.ts b/src/app/core/submission/vocabularies/models/vocabulary-entry-detail.model.ts new file mode 100644 index 0000000000..e8d0fc835a --- /dev/null +++ b/src/app/core/submission/vocabularies/models/vocabulary-entry-detail.model.ts @@ -0,0 +1,33 @@ +import { autoserialize, deserialize, inheritSerialization } from 'cerialize'; + +import { HALLink } from '../../../shared/hal-link.model'; +import { VOCABULARY_ENTRY_DETAIL } from './vocabularies.resource-type'; +import { typedObject } from '../../../cache/builders/build-decorators'; +import { VocabularyEntry } from './vocabulary-entry.model'; + +/** + * Model class for a VocabularyEntryDetail + */ +@typedObject +@inheritSerialization(VocabularyEntry) +export class VocabularyEntryDetail extends VocabularyEntry { + static type = VOCABULARY_ENTRY_DETAIL; + + /** + * In an hierarchical vocabulary representing if entry is selectable as value + */ + @autoserialize + selectable: boolean; + + /** + * The {@link HALLink}s for this ExternalSourceEntry + */ + @deserialize + _links: { + self: HALLink; + vocabulary: HALLink; + parent: HALLink; + children + }; + +} diff --git a/src/app/core/submission/vocabularies/models/vocabulary-entry.model.ts b/src/app/core/submission/vocabularies/models/vocabulary-entry.model.ts index 5fe951c8aa..5ef61eba2e 100644 --- a/src/app/core/submission/vocabularies/models/vocabulary-entry.model.ts +++ b/src/app/core/submission/vocabularies/models/vocabulary-entry.model.ts @@ -11,7 +11,7 @@ import { ListableObject } from '../../../../shared/object-collection/shared/list import { GenericConstructor } from '../../../shared/generic-constructor'; /** - * Model class for a Vocabulary + * Model class for a VocabularyEntry */ @typedObject export class VocabularyEntry extends ListableObject { @@ -54,7 +54,7 @@ export class VocabularyEntry extends ListableObject { @deserialize _links: { self: HALLink; - vocabularyEntryDetail: HALLink; + vocabularyEntryDetail?: HALLink; }; /** diff --git a/src/app/core/submission/vocabularies/models/vocabulary-options.model.ts b/src/app/core/submission/vocabularies/models/vocabulary-options.model.ts new file mode 100644 index 0000000000..c28d8504bd --- /dev/null +++ b/src/app/core/submission/vocabularies/models/vocabulary-options.model.ts @@ -0,0 +1,35 @@ +/** + * Representing vocabulary properties + */ +export class VocabularyOptions { + + /** + * The name of the vocabulary + */ + name: string; + + /** + * The metadata field name (e.g. "dc.type") for which the vocabulary is used: + */ + metadata: string; + + /** + * The uuid of the collection where the item is being submitted + */ + scope: string; + + /** + * A boolean representing if value is closely related to a vocabulary entry or not + */ + closed: boolean; + + constructor(name: string, + metadata: string, + scope: string, + closed: boolean = false) { + this.name = name; + this.metadata = metadata; + this.scope = scope; + this.closed = closed; + } +} diff --git a/src/app/core/submission/vocabularies/vocabulary.service.spec.ts b/src/app/core/submission/vocabularies/vocabulary.service.spec.ts index 5323c29f30..da496899d1 100644 --- a/src/app/core/submission/vocabularies/vocabulary.service.spec.ts +++ b/src/app/core/submission/vocabularies/vocabulary.service.spec.ts @@ -9,7 +9,7 @@ import { RemoteDataBuildService } from '../../cache/builders/remote-data-build.s import { ObjectCacheService } from '../../cache/object-cache.service'; import { HALEndpointService } from '../../shared/hal-endpoint.service'; import { RequestService } from '../../data/request.service'; -import { FindListOptions, VocabularyEntriesRequest } from '../../data/request.models'; +import { VocabularyEntriesRequest } from '../../data/request.models'; import { RequestParam } from '../../cache/models/request-param.model'; import { PageInfo } from '../../shared/page-info.model'; import { PaginatedList } from '../../data/paginated-list'; @@ -48,7 +48,7 @@ describe('VocabularyService', () => { } }; - const anotherVocabulary: any = { + const hierarchicalVocabulary: any = { id: 'srsc', name: 'srsc', scrollable: false, @@ -90,8 +90,55 @@ describe('VocabularyService', () => { } } }; + + const vocabularyEntryDetail: any = { + authority: 'authorityId1', + display: 'testValue1', + value: 'testValue1', + otherInformation: { + id: 'VR131402', + parent: 'Research Subject Categories::SOCIAL SCIENCES::Social sciences::Social work', + hasChildren: 'true', + note: 'Familjeforskning' + }, + type: 'vocabularyEntryDetail', + _links: { + self: { + href: 'https://rest.api/rest/api/submission/vocabularyEntryDetails/srsc:VR131402' + }, + parent: { + href: 'https://rest.api/rest/api/submission/vocabularyEntryDetails/srsc:parent' + }, + children: { + href: 'https://rest.api/rest/api/submission/vocabularyEntryDetails/srsc:children' + } + } + }; + + const anotherVocabularyEntryDetail: any = { + authority: 'authorityId1', + display: 'children', + value: 'children', + otherInformation: { + id: 'VR131402', + parent: 'Research Subject Categories::SOCIAL SCIENCES::Social sciences::Social work', + hasChildren: 'false', + note: 'Familjeforskning' + }, + type: 'vocabularyEntryDetail', + _links: { + self: { + href: 'https://rest.api/rest/api/submission/vocabularyEntryDetails/srsc:children' + }, + parent: { + href: 'https://rest.api/rest/api/submission/vocabularyEntryDetails/srsc:testValue1' + } + } + }; + const endpointURL = `https://rest.api/rest/api/submission/vocabularies`; const requestURL = `https://rest.api/rest/api/submission/vocabularies/${vocabulary.id}`; + const entryDetailRequestURL = `https://rest.api/rest/api/submission/vocabularyEntryDetails/srsc:SCB110/${hierarchicalVocabulary.id}:testValue`; const requestUUID = '8b3c613a-5a4b-438b-9686-be1d5b4a1c5a'; const vocabularyId = 'types'; const metadata = 'dc.type'; @@ -101,10 +148,14 @@ describe('VocabularyService', () => { const entriesRequestURL = `https://rest.api/rest/api/submission/vocabularies/${vocabulary.id}/entries?metadata=${metadata}&collection=${collectionUUID}`; const pageInfo = new PageInfo(); - const array = [vocabulary, anotherVocabulary]; + const array = [vocabulary, hierarchicalVocabulary]; + const arrayEntries = [vocabularyEntryDetail, anotherVocabularyEntryDetail]; const paginatedList = new PaginatedList(pageInfo, array); + const entriesPaginatedList = new PaginatedList(pageInfo, arrayEntries); const vocabularyRD = createSuccessfulRemoteDataObject(vocabulary); + const vocabularyEntryDetailRD = createSuccessfulRemoteDataObject(vocabularyEntryDetail); const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); + const entriesPaginatedListRD = createSuccessfulRemoteDataObject(entriesPaginatedList); const getRequestEntry$ = (successful: boolean) => { return observableOf({ response: { isSuccessful: successful, payload: vocabulary } as any @@ -114,6 +165,7 @@ describe('VocabularyService', () => { const notificationsService = {} as NotificationsService; const http = {} as HttpClient; const comparator = {} as any; + const comparatorEntry = {} as any; function initTestService() { return new VocabularyService( @@ -123,149 +175,248 @@ describe('VocabularyService', () => { halService, notificationsService, http, - comparator + comparator, + comparatorEntry ); } - beforeEach(() => { - scheduler = getTestScheduler(); - - halService = jasmine.createSpyObj('halService', { - getEndpoint: cold('a', { a: endpointURL }) - }); - - responseCacheEntry = new RequestEntry(); - responseCacheEntry.response = new RestResponse(true, 200, 'Success'); - - requestService = jasmine.createSpyObj('requestService', { - generateRequestId: requestUUID, - configure: true, - removeByHrefSubstring: {}, - getByHref: observableOf(responseCacheEntry), - getByUUID: observableOf(responseCacheEntry), - }); - rdbService = jasmine.createSpyObj('rdbService', { - buildSingle: hot('a|', { - a: vocabularyRD - }), - buildList: hot('a|', { - a: paginatedListRD - }), - }); - - service = initTestService(); - - spyOn((service as any).dataService, 'findById').and.callThrough(); - spyOn((service as any).dataService, 'findAll').and.callThrough(); - spyOn((service as any).dataService, 'findByHref').and.callThrough(); - spyOn((service as any).dataService, 'searchBy').and.callThrough(); - spyOn((service as any).dataService, 'getSearchByHref').and.returnValue(observableOf(searchRequestURL)); - spyOn((service as any).dataService, 'getFindAllHref').and.returnValue(observableOf(entriesRequestURL)); - }); - - afterEach(() => { - service = null; - }); - - describe('findById', () => { - it('should proxy the call to dataservice.findById', () => { - scheduler.schedule(() => service.findById(vocabularyId)); - scheduler.flush(); - - expect((service as any).dataService.findById).toHaveBeenCalledWith(vocabularyId); - }); - - it('should return a RemoteData for the object with the given id', () => { - const result = service.findById(vocabularyId); - const expected = cold('a|', { - a: vocabularyRD - }); - expect(result).toBeObservable(expected); - }); - }); - - describe('findByHref', () => { - it('should proxy the call to dataservice.findByHref', () => { - scheduler.schedule(() => service.findByHref(requestURL)); - scheduler.flush(); - - expect((service as any).dataService.findByHref).toHaveBeenCalledWith(requestURL); - }); - - it('should return a RemoteData for the object with the given URL', () => { - const result = service.findByHref(requestURL); - const expected = cold('a|', { - a: vocabularyRD - }); - expect(result).toBeObservable(expected); - }); - }); - - describe('findAll', () => { - it('should proxy the call to dataservice.findAll', () => { - scheduler.schedule(() => service.findAll()); - scheduler.flush(); - - expect((service as any).dataService.findAll).toHaveBeenCalled(); - }); - - it('should return a RemoteData>', () => { - const result = service.findAll(); - const expected = cold('a|', { - a: paginatedListRD - }); - expect(result).toBeObservable(expected); - }); - }); - - describe('searchByMetadataAndCollection', () => { - it('should proxy the call to dataservice.findByHref', () => { - const options = new FindListOptions(); - options.searchParams = [ - new RequestParam('metadata', metadata), - new RequestParam('collection', collectionUUID) - ]; - scheduler.schedule(() => service.searchByMetadataAndCollection(vocabularyOptions).subscribe()); - scheduler.flush(); - - expect((service as any).dataService.findByHref).toHaveBeenCalledWith(searchRequestURL); - }); - - it('should return a RemoteData for the search', () => { - const result = service.searchByMetadataAndCollection(vocabularyOptions); - const expected = cold('a|', { - a: vocabularyRD - }); - expect(result).toBeObservable(expected); - }); - - }); - - describe('getVocabularyEntries', () => { - + describe('vocabularies endpoint', () => { beforeEach(() => { - requestService = getMockRequestService(getRequestEntry$(true)); - rdbService = getMockRemoteDataBuildService(); - spyOn(rdbService, 'toRemoteDataObservable').and.callThrough(); + scheduler = getTestScheduler(); + + halService = jasmine.createSpyObj('halService', { + getEndpoint: cold('a', { a: endpointURL }) + }); + + responseCacheEntry = new RequestEntry(); + responseCacheEntry.response = new RestResponse(true, 200, 'Success'); + + requestService = jasmine.createSpyObj('requestService', { + generateRequestId: requestUUID, + configure: true, + removeByHrefSubstring: {}, + getByHref: observableOf(responseCacheEntry), + getByUUID: observableOf(responseCacheEntry), + }); + rdbService = jasmine.createSpyObj('rdbService', { + buildSingle: hot('a|', { + a: vocabularyRD + }), + buildList: hot('a|', { + a: paginatedListRD + }), + }); + service = initTestService(); + + spyOn((service as any).vocabularyDataService, 'findById').and.callThrough(); + spyOn((service as any).vocabularyDataService, 'findAll').and.callThrough(); + spyOn((service as any).vocabularyDataService, 'findByHref').and.callThrough(); + spyOn((service as any).vocabularyDataService, 'searchBy').and.callThrough(); + spyOn((service as any).vocabularyDataService, 'getSearchByHref').and.returnValue(observableOf(searchRequestURL)); + spyOn((service as any).vocabularyDataService, 'getFindAllHref').and.returnValue(observableOf(entriesRequestURL)); }); - it('should configure a new VocabularyEntriesRequest', () => { - const expected = new VocabularyEntriesRequest(requestService.generateRequestId(), entriesRequestURL); - - scheduler.schedule(() => service.getVocabularyEntries(vocabularyOptions).subscribe()); - scheduler.flush(); - - expect(requestService.configure).toHaveBeenCalledWith(expected); + afterEach(() => { + service = null; }); - it('should call RemoteDataBuildService to create the RemoteData Observable', () => { - service.getVocabularyEntries(vocabularyOptions); + describe('findVocabularyById', () => { + it('should proxy the call to vocabularyDataService.findVocabularyById', () => { + scheduler.schedule(() => service.findVocabularyById(vocabularyId)); + scheduler.flush(); - expect(rdbService.toRemoteDataObservable).toHaveBeenCalled(); + expect((service as any).vocabularyDataService.findById).toHaveBeenCalledWith(vocabularyId); + }); + + it('should return a RemoteData for the object with the given id', () => { + const result = service.findVocabularyById(vocabularyId); + const expected = cold('a|', { + a: vocabularyRD + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('findVocabularyByHref', () => { + it('should proxy the call to vocabularyDataService.findVocabularyByHref', () => { + scheduler.schedule(() => service.findVocabularyByHref(requestURL)); + scheduler.flush(); + + expect((service as any).vocabularyDataService.findByHref).toHaveBeenCalledWith(requestURL); + }); + + it('should return a RemoteData for the object with the given URL', () => { + const result = service.findVocabularyByHref(requestURL); + const expected = cold('a|', { + a: vocabularyRD + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('findAllVocabularies', () => { + it('should proxy the call to vocabularyDataService.findAllVocabularies', () => { + scheduler.schedule(() => service.findAllVocabularies()); + scheduler.flush(); + + expect((service as any).vocabularyDataService.findAll).toHaveBeenCalled(); + }); + + it('should return a RemoteData>', () => { + const result = service.findAllVocabularies(); + const expected = cold('a|', { + a: paginatedListRD + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('searchVocabularyByMetadataAndCollection', () => { + it('should proxy the call to vocabularyDataService.findVocabularyByHref', () => { + const options = new VocabularyFindOptions(); + options.searchParams = [ + new RequestParam('metadata', metadata), + new RequestParam('collection', collectionUUID) + ]; + scheduler.schedule(() => service.searchVocabularyByMetadataAndCollection(vocabularyOptions).subscribe()); + scheduler.flush(); + + expect((service as any).vocabularyDataService.findByHref).toHaveBeenCalledWith(searchRequestURL); + }); + + it('should return a RemoteData for the search', () => { + const result = service.searchVocabularyByMetadataAndCollection(vocabularyOptions); + const expected = cold('a|', { + a: vocabularyRD + }); + expect(result).toBeObservable(expected); + }); + + }); + + describe('getVocabularyEntries', () => { + + beforeEach(() => { + requestService = getMockRequestService(getRequestEntry$(true)); + rdbService = getMockRemoteDataBuildService(); + spyOn(rdbService, 'toRemoteDataObservable').and.callThrough(); + service = initTestService(); + }); + + it('should configure a new VocabularyEntriesRequest', () => { + const expected = new VocabularyEntriesRequest(requestService.generateRequestId(), entriesRequestURL); + + scheduler.schedule(() => service.getVocabularyEntries(vocabularyOptions).subscribe()); + scheduler.flush(); + + expect(requestService.configure).toHaveBeenCalledWith(expected); + }); + + it('should call RemoteDataBuildService to create the RemoteData Observable', () => { + service.getVocabularyEntries(vocabularyOptions); + + expect(rdbService.toRemoteDataObservable).toHaveBeenCalled(); + + }); + + }); + }); + + describe('vocabularyEntryDetails endpoint', () => { + beforeEach(() => { + scheduler = getTestScheduler(); + + halService = jasmine.createSpyObj('halService', { + getEndpoint: cold('a', { a: endpointURL }) + }); + + responseCacheEntry = new RequestEntry(); + responseCacheEntry.response = new RestResponse(true, 200, 'Success'); + + requestService = jasmine.createSpyObj('requestService', { + generateRequestId: requestUUID, + configure: true, + removeByHrefSubstring: {}, + getByHref: observableOf(responseCacheEntry), + getByUUID: observableOf(responseCacheEntry), + }); + rdbService = jasmine.createSpyObj('rdbService', { + buildSingle: hot('a|', { + a: vocabularyEntryDetailRD + }), + buildList: hot('a|', { + a: entriesPaginatedListRD + }), + }); + + service = initTestService(); + + spyOn((service as any).vocabularyEntryDetailDataService, 'findById').and.callThrough(); + spyOn((service as any).vocabularyEntryDetailDataService, 'findAll').and.callThrough(); + spyOn((service as any).vocabularyEntryDetailDataService, 'findByHref').and.callThrough(); + spyOn((service as any).vocabularyEntryDetailDataService, 'searchBy').and.callThrough(); + spyOn((service as any).vocabularyEntryDetailDataService, 'getSearchByHref').and.returnValue(observableOf(searchRequestURL)); + spyOn((service as any).vocabularyEntryDetailDataService, 'getFindAllHref').and.returnValue(observableOf(entriesRequestURL)); + }); + + afterEach(() => { + service = null; + }); + + describe('findEntryDetailByHref', () => { + it('should proxy the call to vocabularyDataService.findVocabularyByHref', () => { + scheduler.schedule(() => service.findEntryDetailByHref(entryDetailRequestURL)); + scheduler.flush(); + + expect((service as any).vocabularyEntryDetailDataService.findByHref).toHaveBeenCalledWith(entryDetailRequestURL); + }); + + it('should return a RemoteData for the object with the given URL', () => { + const result = service.findEntryDetailByHref(entryDetailRequestURL); + const expected = cold('a|', { + a: vocabularyEntryDetailRD + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('findEntryDetailByValue', () => { + it('should proxy the call to vocabularyDataService.findVocabularyById', () => { + scheduler.schedule(() => service.findEntryDetailByValue('testValue', hierarchicalVocabulary.id)); + scheduler.flush(); + const expectedId = `${hierarchicalVocabulary.id}:testValue` + expect((service as any).vocabularyEntryDetailDataService.findById).toHaveBeenCalledWith(expectedId); + }); + + it('should return a RemoteData for the object with the given id', () => { + const result = service.findEntryDetailByValue('testValue', hierarchicalVocabulary.id); + const expected = cold('a|', { + a: vocabularyEntryDetailRD + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('searchByGroup', () => { + it('should proxy the call to vocabularyEntryDetailDataService.searchBy', () => { + const options = new VocabularyFindOptions(); + options.searchParams.push(new RequestParam('vocabulary', 'srsc')); + scheduler.schedule(() => service.searchTopEntries('srsc', new VocabularyFindOptions())); + scheduler.flush(); + + expect((service as any).vocabularyEntryDetailDataService.searchBy).toHaveBeenCalledWith((service as any).searchTopMethod, options); + }); + + it('should return a RemoteData) for the search', () => { + const result = service.searchTopEntries('srsc', new VocabularyFindOptions()); + const expected = cold('a|', { + a: entriesPaginatedListRD + }); + expect(result).toBeObservable(expected); + }); }); }); - }); diff --git a/src/app/core/submission/vocabularies/vocabulary.service.ts b/src/app/core/submission/vocabularies/vocabulary.service.ts index 094f87544f..13929525d4 100644 --- a/src/app/core/submission/vocabularies/vocabulary.service.ts +++ b/src/app/core/submission/vocabularies/vocabulary.service.ts @@ -26,13 +26,15 @@ import { hasValue, isNotEmptyOperator } from '../../../shared/empty.util'; import { configureRequest, filterSuccessfulResponses, getRequestFromRequestHref } from '../../shared/operators'; import { GenericSuccessResponse } from '../../cache/response.models'; import { VocabularyFindOptions } from './models/vocabulary-find-options.model'; +import { VocabularyEntryDetail } from './models/vocabulary-entry-detail.model'; +import { RequestParam } from '../../cache/models/request-param.model'; /* tslint:disable:max-classes-per-file */ /** * A private DataService implementation to delegate specific methods to. */ -class DataServiceImpl extends DataService { +class VocabularyDataServiceImpl extends DataService { protected linkPath = 'vocabularies'; constructor( @@ -49,6 +51,26 @@ class DataServiceImpl extends DataService { } +/** + * A private DataService implementation to delegate specific methods to. + */ +class VocabularyEntryDetailDataServiceImpl extends DataService { + protected linkPath = 'vocabularyEntryDetails'; + + constructor( + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected store: Store, + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected notificationsService: NotificationsService, + protected http: HttpClient, + protected comparator: ChangeAnalyzer) { + super(); + } + +} + /** * A service responsible for fetching/sending data from/to the REST API on the vocabularies endpoint */ @@ -58,7 +80,9 @@ class DataServiceImpl extends DataService { @dataService(VOCABULARY) export class VocabularyService { protected searchByMetadataAndCollectionMethod = 'byMetadataAndCollection'; - private dataService: DataServiceImpl; + protected searchTopMethod = 'top'; + private vocabularyDataService: VocabularyDataServiceImpl; + private vocabularyEntryDetailDataService: VocabularyEntryDetailDataServiceImpl; constructor( protected requestService: RequestService, @@ -67,8 +91,10 @@ export class VocabularyService { protected halService: HALEndpointService, protected notificationsService: NotificationsService, protected http: HttpClient, - protected comparator: DefaultChangeAnalyzer) { - this.dataService = new DataServiceImpl(requestService, rdbService, null, objectCache, halService, notificationsService, http, comparator); + protected comparatorVocabulary: DefaultChangeAnalyzer, + protected comparatorEntry: DefaultChangeAnalyzer) { + this.vocabularyDataService = new VocabularyDataServiceImpl(requestService, rdbService, null, objectCache, halService, notificationsService, http, comparatorVocabulary); + this.vocabularyEntryDetailDataService = new VocabularyEntryDetailDataServiceImpl(requestService, rdbService, null, objectCache, halService, notificationsService, http, comparatorEntry); } /** @@ -79,8 +105,8 @@ export class VocabularyService { * @return {Observable>} * Return an observable that emits vocabulary object */ - findByHref(href: string, ...linksToFollow: Array>): Observable> { - return this.dataService.findByHref(href, ...linksToFollow); + findVocabularyByHref(href: string, ...linksToFollow: Array>): Observable> { + return this.vocabularyDataService.findByHref(href, ...linksToFollow); } /** @@ -91,8 +117,8 @@ export class VocabularyService { * @return {Observable>} * Return an observable that emits vocabulary object */ - findById(id: string, ...linksToFollow: Array>): Observable> { - return this.dataService.findById(id, ...linksToFollow); + findVocabularyById(id: string, ...linksToFollow: Array>): Observable> { + return this.vocabularyDataService.findById(id, ...linksToFollow); } /** @@ -104,8 +130,8 @@ export class VocabularyService { * @return {Observable>>} * Return an observable that emits object list */ - findAll(options: FindListOptions = {}, ...linksToFollow: Array>): Observable>> { - return this.dataService.findAll(options, ...linksToFollow); + findAllVocabularies(options: FindListOptions = {}, ...linksToFollow: Array>): Observable>> { + return this.vocabularyDataService.findAll(options, ...linksToFollow); } /** @@ -117,7 +143,7 @@ export class VocabularyService { */ getVocabularyEntries(options: VocabularyFindOptions): Observable>> { - return this.dataService.getFindAllHref(options, `${options.name}/entries`).pipe( + return this.vocabularyDataService.getFindAllHref(options, `${options.name}/entries`).pipe( isNotEmptyOperator(), distinctUntilChanged(), getVocabularyEntriesFor(this.requestService, this.rdbService) @@ -132,14 +158,51 @@ export class VocabularyService { * @return {Observable>>} * Return an observable that emits object list */ - searchByMetadataAndCollection(options: VocabularyFindOptions, ...linksToFollow: Array>): Observable> { + searchVocabularyByMetadataAndCollection(options: VocabularyFindOptions, ...linksToFollow: Array>): Observable> { - return this.dataService.getSearchByHref(this.searchByMetadataAndCollectionMethod, options).pipe( + return this.vocabularyDataService.getSearchByHref(this.searchByMetadataAndCollectionMethod, options).pipe( first((href: string) => hasValue(href)), - flatMap((href: string) => this.dataService.findByHref(href)) + flatMap((href: string) => this.vocabularyDataService.findByHref(href)) ) } + /** + * Returns an observable of {@link RemoteData} of a {@link VocabularyEntryDetail}, based on an href, with a list of {@link FollowLinkConfig}, + * to automatically resolve {@link HALLink}s of the {@link VocabularyEntryDetail} + * @param href The url of {@link VocabularyEntryDetail} we want to retrieve + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved + * @return {Observable>} + * Return an observable that emits vocabulary object + */ + findEntryDetailByHref(href: string, ...linksToFollow: Array>): Observable> { + return this.vocabularyEntryDetailDataService.findByHref(href, ...linksToFollow); + } + + /** + * Returns an observable of {@link RemoteData} of a {@link VocabularyEntryDetail}, based on its ID, with a list of {@link FollowLinkConfig}, + * to automatically resolve {@link HALLink}s of the object + * @param value The entry value for which to provide detailed information. + * @param name The name of {@link Vocabulary} to which the entry belongs + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved + * @return {Observable>} + * Return an observable that emits VocabularyEntryDetail object + */ + findEntryDetailByValue(value: string, name: string, ...linksToFollow: Array>): Observable> { + const id = `${name}:${value}`; + return this.vocabularyEntryDetailDataService.findById(id, ...linksToFollow); + } + + /** + * Return the top level {@link VocabularyEntryDetail} list for a given hierarchical vocabulary + * + * @param name The name of hierarchical {@link Vocabulary} to which the entries belongs + * @param options The {@link VocabularyFindOptions} for the request + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved + */ + searchTopEntries(name: string, options: VocabularyFindOptions, ...linksToFollow: Array>): Observable>> { + options.searchParams.push(new RequestParam('vocabulary', name)); + return this.vocabularyEntryDetailDataService.searchBy(this.searchTopMethod, options, ...linksToFollow) + } } /** From 63cca76b49a5e5ed21cb7064904b01043910a189 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 25 Jun 2020 15:21:44 +0200 Subject: [PATCH 016/170] [CST-3088] Replace use of AuthorityService with new VocabularyService --- src/app/core/core.module.ts | 12 +- .../builder/json-patch-operations-builder.ts | 8 +- .../models => shared}/confidence-type.ts | 0 .../vocabularies/vocabulary.service.ts | 4 +- .../authority-confidence-state.directive.ts | 11 +- src/app/shared/chips/chips.component.spec.ts | 2 +- .../shared/chips/models/chips-item.model.ts | 2 +- src/app/shared/chips/models/chips.model.ts | 4 +- ...c-form-control-container.component.spec.ts | 10 +- .../date-picker/date-picker.component.spec.ts | 10 +- .../date-picker/date-picker.component.ts | 6 +- .../models/ds-dynamic-input.model.ts | 12 +- .../list/dynamic-list-checkbox-group.model.ts | 30 +- .../list/dynamic-list-radio-group.model.ts | 10 +- .../list/dynamic-list.component.spec.ts | 84 ++--- .../models/list/dynamic-list.component.ts | 59 ++-- .../lookup/dynamic-lookup.component.spec.ts | 71 ++-- .../models/lookup/dynamic-lookup.component.ts | 312 +++++++++--------- .../dynamic-relation-group.component.spec.ts | 17 +- .../dynamic-relation-group.components.ts | 52 ++- ...amic-scrollable-dropdown.component.spec.ts | 38 +-- .../dynamic-scrollable-dropdown.component.ts | 68 ++-- .../dynamic-scrollable-dropdown.model.ts | 6 +- .../models/tag/dynamic-tag.component.spec.ts | 33 +- .../models/tag/dynamic-tag.component.ts | 65 ++-- .../dynamic-typeahead.component.spec.ts | 38 +-- .../typeahead/dynamic-typeahead.component.ts | 61 ++-- .../form/builder/form-builder.service.spec.ts | 18 +- .../models/form-field-metadata-value.model.ts | 10 +- .../form/builder/models/form-field.model.ts | 75 ++++- .../builder/parsers/date-field-parser.spec.ts | 2 +- .../parsers/disabled-field-parser.spec.ts | 2 +- .../parsers/dropdown-field-parser.spec.ts | 6 +- .../builder/parsers/dropdown-field-parser.ts | 6 +- .../form/builder/parsers/field-parser.ts | 113 +++---- .../builder/parsers/list-field-parser.spec.ts | 4 +- .../form/builder/parsers/list-field-parser.ts | 10 +- .../parsers/lookup-field-parser.spec.ts | 4 +- .../builder/parsers/lookup-field-parser.ts | 4 +- .../parsers/lookup-name-field-parser.spec.ts | 4 +- .../parsers/lookup-name-field-parser.ts | 4 +- .../builder/parsers/name-field-parser.spec.ts | 2 +- .../parsers/onebox-field-parser.spec.ts | 4 +- .../builder/parsers/onebox-field-parser.ts | 4 +- .../form/builder/parsers/parser-options.ts | 2 +- .../relation-group-field-parser.spec.ts | 2 +- .../parsers/relation-group-field-parser.ts | 2 +- .../form/builder/parsers/row-parser.spec.ts | 16 +- .../shared/form/builder/parsers/row-parser.ts | 6 +- .../parsers/series-field-parser.spec.ts | 2 +- .../builder/parsers/tag-field-parser.spec.ts | 4 +- .../form/builder/parsers/tag-field-parser.ts | 6 +- .../parsers/textarea-field-parser.spec.ts | 2 +- src/app/shared/mocks/form-models.mock.ts | 37 ++- src/app/shared/mocks/submission.mock.ts | 4 +- .../shared/testing/authority-service.stub.ts | 21 -- .../shared/testing/vocabulary-service.stub.ts | 29 ++ .../section-form-operations.service.spec.ts | 6 +- .../form/section-form-operations.service.ts | 10 +- 59 files changed, 740 insertions(+), 706 deletions(-) rename src/app/core/{integration/models => shared}/confidence-type.ts (100%) delete mode 100644 src/app/shared/testing/authority-service.stub.ts create mode 100644 src/app/shared/testing/vocabulary-service.stub.ts diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index a92b52b339..704f6c9e62 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -86,9 +86,6 @@ import { EPersonDataService } from './eperson/eperson-data.service'; import { EpersonResponseParsingService } from './eperson/eperson-response-parsing.service'; import { EPerson } from './eperson/models/eperson.model'; import { Group } from './eperson/models/group.model'; -import { AuthorityService } from './integration/authority.service'; -import { IntegrationResponseParsingService } from './integration/integration-response-parsing.service'; -import { AuthorityValue } from './integration/models/authority.value'; import { JsonPatchOperationsBuilder } from './json-patch/builder/json-patch-operations-builder'; import { MetadataField } from './metadata/metadata-field.model'; import { MetadataSchema } from './metadata/metadata-schema.model'; @@ -148,6 +145,8 @@ import { WorkflowAction } from './tasks/models/workflow-action-object.model'; import { VocabularyEntry } from './submission/vocabularies/models/vocabulary-entry.model'; import { Vocabulary } from './submission/vocabularies/models/vocabulary.model'; import { VocabularyEntriesResponseParsingService } from './submission/vocabularies/vocabulary-entries-response-parsing.service'; +import { VocabularyEntryDetail } from './submission/vocabularies/models/vocabulary-entry-detail.model'; +import { VocabularyService } from './submission/vocabularies/vocabulary.service'; /** * When not in production, endpoint responses can be mocked for testing purposes @@ -224,8 +223,6 @@ const PROVIDERS = [ SubmissionResponseParsingService, SubmissionJsonPatchOperationsService, JsonPatchOperationsBuilder, - AuthorityService, - IntegrationResponseParsingService, MetadataschemaParsingService, MetadatafieldParsingService, UploaderService, @@ -276,6 +273,7 @@ const PROVIDERS = [ NotificationsService, FilteredDiscoveryPageResponseParsingService, { provide: NativeWindowService, useFactory: NativeWindowFactory }, + VocabularyService, VocabularyEntriesResponseParsingService ]; @@ -305,7 +303,6 @@ export const models = SubmissionSectionModel, SubmissionUploadsModel, AuthStatus, - AuthorityValue, BrowseEntry, BrowseDefinition, ClaimedTask, @@ -320,7 +317,8 @@ export const models = VersionHistory, WorkflowAction, Vocabulary, - VocabularyEntry + VocabularyEntry, + VocabularyEntryDetail ]; @NgModule({ diff --git a/src/app/core/json-patch/builder/json-patch-operations-builder.ts b/src/app/core/json-patch/builder/json-patch-operations-builder.ts index c45183b4ef..36c82db283 100644 --- a/src/app/core/json-patch/builder/json-patch-operations-builder.ts +++ b/src/app/core/json-patch/builder/json-patch-operations-builder.ts @@ -9,7 +9,7 @@ import { JsonPatchOperationPathObject } from './json-patch-operation-path-combin import { Injectable } from '@angular/core'; import { isEmpty, isNotEmpty } from '../../../shared/empty.util'; import { dateToISOFormat } from '../../../shared/date.util'; -import { AuthorityValue } from '../../integration/models/authority.value'; +import { VocabularyEntry } from '../../submission/vocabularies/models/vocabulary-entry.model'; import { FormFieldMetadataValueObject } from '../../../shared/form/builder/models/form-field-metadata-value.model'; import { FormFieldLanguageValueObject } from '../../../shared/form/builder/models/form-field-language-value.model'; @@ -106,7 +106,7 @@ export class JsonPatchOperationsBuilder { operationValue = value; } else if (value instanceof Date) { operationValue = new FormFieldMetadataValueObject(dateToISOFormat(value)); - } else if (value instanceof AuthorityValue) { + } else if (value instanceof VocabularyEntry) { operationValue = this.prepareAuthorityValue(value); } else if (value instanceof FormFieldLanguageValueObject) { operationValue = new FormFieldMetadataValueObject(value.value, value.language); @@ -127,8 +127,8 @@ export class JsonPatchOperationsBuilder { protected prepareAuthorityValue(value: any) { let operationValue: any = null; - if (isNotEmpty(value.id)) { - operationValue = new FormFieldMetadataValueObject(value.value, value.language, value.id); + if (isNotEmpty(value.authority)) { + operationValue = new FormFieldMetadataValueObject(value.value, value.language, value.authority); } else { operationValue = new FormFieldMetadataValueObject(value.value, value.language); } diff --git a/src/app/core/integration/models/confidence-type.ts b/src/app/core/shared/confidence-type.ts similarity index 100% rename from src/app/core/integration/models/confidence-type.ts rename to src/app/core/shared/confidence-type.ts diff --git a/src/app/core/submission/vocabularies/vocabulary.service.ts b/src/app/core/submission/vocabularies/vocabulary.service.ts index 13929525d4..bd5c5b6c48 100644 --- a/src/app/core/submission/vocabularies/vocabulary.service.ts +++ b/src/app/core/submission/vocabularies/vocabulary.service.ts @@ -74,9 +74,7 @@ class VocabularyEntryDetailDataServiceImpl extends DataService; @@ -102,7 +102,7 @@ export class Chips { private getChipsIcons(item) { const icons = []; - if (typeof item === 'string' || item instanceof FormFieldMetadataValueObject || item instanceof AuthorityValue) { + if (typeof item === 'string' || item instanceof FormFieldMetadataValueObject || item instanceof VocabularyEntry) { return icons; } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.spec.ts index 4dee6905d2..171ad69f64 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.spec.ts @@ -44,7 +44,7 @@ import { SharedModule } from '../../../shared.module'; import { DynamicDsDatePickerModel } from './models/date-picker/date-picker.model'; import { DynamicRelationGroupModel } from './models/relation-group/dynamic-relation-group.model'; import { DynamicListCheckboxGroupModel } from './models/list/dynamic-list-checkbox-group.model'; -import { AuthorityOptions } from '../../../../core/integration/models/authority-options.model'; +import { VocabularyOptions } from '../../../../core/submission/vocabularies/models/vocabulary-options.model'; import { DynamicListRadioGroupModel } from './models/list/dynamic-list-radio-group.model'; import { DynamicLookupModel } from './models/lookup/dynamic-lookup.model'; import { DynamicScrollableDropdownModel } from './models/scrollable-dropdown/dynamic-scrollable-dropdown.model'; @@ -74,7 +74,7 @@ import { createSuccessfulRemoteDataObject } from '../../../remote-data.utils'; describe('DsDynamicFormControlContainerComponent test suite', () => { - const authorityOptions: AuthorityOptions = { + const vocabularyOptions: VocabularyOptions = { closed: false, metadata: 'list', name: 'type_programme', @@ -104,7 +104,7 @@ describe('DsDynamicFormControlContainerComponent test suite', () => { new DynamicTypeaheadModel({ id: 'typeahead', metadataFields: [], repeatable: false, submissionId: '1234' }), new DynamicScrollableDropdownModel({ id: 'scrollableDropdown', - authorityOptions: authorityOptions, + vocabularyOptions: vocabularyOptions, metadataFields: [], repeatable: false, submissionId: '1234' @@ -112,12 +112,12 @@ describe('DsDynamicFormControlContainerComponent test suite', () => { new DynamicTagModel({ id: 'tag', metadataFields: [], repeatable: false, submissionId: '1234' }), new DynamicListCheckboxGroupModel({ id: 'checkboxList', - authorityOptions: authorityOptions, + vocabularyOptions: vocabularyOptions, repeatable: true }), new DynamicListRadioGroupModel({ id: 'radioList', - authorityOptions: authorityOptions, + vocabularyOptions: vocabularyOptions, repeatable: false }), new DynamicRelationGroupModel({ diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.spec.ts index 78c2d5d217..e08116e5fa 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.spec.ts @@ -8,10 +8,6 @@ import { DynamicFormLayoutService, DynamicFormValidationService } from '@ng-dyna import { DsDatePickerComponent } from './date-picker.component'; import { DynamicDsDatePickerModel } from './date-picker.model'; -import { FormBuilderService } from '../../../form-builder.service'; - -import { FormComponent } from '../../../../form.component'; -import { FormService } from '../../../../form.service'; import { createTestComponent } from '../../../../../testing/utils.test'; export const DATE_TEST_GROUP = new FormGroup({ @@ -20,7 +16,7 @@ export const DATE_TEST_GROUP = new FormGroup({ export const DATE_TEST_MODEL_CONFIG = { disabled: false, - errorMessages: {required: 'You must enter at least the year.'}, + errorMessages: { required: 'You must enter at least the year.' }, id: 'date', label: 'Date', name: 'date', @@ -52,8 +48,8 @@ describe('DsDatePickerComponent test suite', () => { providers: [ ChangeDetectorRef, DsDatePickerComponent, - {provide: DynamicFormLayoutService, useValue: {}}, - {provide: DynamicFormValidationService, useValue: {}} + { provide: DynamicFormLayoutService, useValue: {} }, + { provide: DynamicFormValidationService, useValue: {} } ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.ts index 2e22f314ed..8523c60cf0 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.ts @@ -20,10 +20,6 @@ export class DsDatePickerComponent extends DynamicFormControlComponent implement @Input() bindId = true; @Input() group: FormGroup; @Input() model: DynamicDsDatePickerModel; - // @Input() - // minDate; - // @Input() - // maxDate; @Output() selected = new EventEmitter(); @Output() remove = new EventEmitter(); @@ -65,7 +61,7 @@ export class DsDatePickerComponent extends DynamicFormControlComponent implement this.initialMonth = now.getMonth() + 1; this.initialDay = now.getDate(); - if (this.model.value && this.model.value !== null) { + if (this.model && this.model.value !== null) { const values = this.model.value.toString().split(DS_DATE_PICKER_SEPARATOR); if (values.length > 0) { this.initialYear = parseInt(values[0], 10); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model.ts index 3827df7be6..b723f7aa40 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model.ts @@ -2,13 +2,13 @@ import { DynamicFormControlLayout, DynamicInputModel, DynamicInputModelConfig, s import { Subject } from 'rxjs'; import { LanguageCode } from '../../models/form-field-language-value.model'; -import { AuthorityOptions } from '../../../../../core/integration/models/authority-options.model'; +import { VocabularyOptions } from '../../../../../core/submission/vocabularies/models/vocabulary-options.model'; import { hasValue } from '../../../../empty.util'; import { FormFieldMetadataValueObject } from '../../models/form-field-metadata-value.model'; import { RelationshipOptions } from '../../models/relationship-options.model'; export interface DsDynamicInputModelConfig extends DynamicInputModelConfig { - authorityOptions?: AuthorityOptions; + vocabularyOptions?: VocabularyOptions; languageCodes?: LanguageCode[]; language?: string; value?: any; @@ -20,7 +20,7 @@ export interface DsDynamicInputModelConfig extends DynamicInputModelConfig { export class DsDynamicInputModel extends DynamicInputModel { - @serializable() authorityOptions: AuthorityOptions; + @serializable() vocabularyOptions: VocabularyOptions; @serializable() private _languageCodes: LanguageCode[]; @serializable() private _language: string; @serializable() languageUpdates: Subject; @@ -58,11 +58,11 @@ export class DsDynamicInputModel extends DynamicInputModel { this.language = lang; }); - this.authorityOptions = config.authorityOptions; + this.vocabularyOptions = config.vocabularyOptions; } get hasAuthority(): boolean { - return this.authorityOptions && hasValue(this.authorityOptions.name); + return this.vocabularyOptions && hasValue(this.vocabularyOptions.name); } get hasLanguages(): boolean { @@ -83,7 +83,7 @@ export class DsDynamicInputModel extends DynamicInputModel { set languageCodes(languageCodes: LanguageCode[]) { this._languageCodes = languageCodes; - if (!this.language || this.language === null || this.language === '') { + if (!this.language || this.language === '') { this.language = this.languageCodes ? this.languageCodes[0].code : null; } } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list-checkbox-group.model.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list-checkbox-group.model.ts index f6b58c1504..fab371483c 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list-checkbox-group.model.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list-checkbox-group.model.ts @@ -1,16 +1,17 @@ import { Subject } from 'rxjs'; - import { - DynamicCheckboxGroupModel, DynamicFormControlLayout, + DynamicCheckboxGroupModel, + DynamicFormControlLayout, DynamicFormGroupModelConfig, serializable } from '@ng-dynamic-forms/core'; -import { AuthorityValue } from '../../../../../../core/integration/models/authority.value'; -import { AuthorityOptions } from '../../../../../../core/integration/models/authority-options.model'; + +import { VocabularyEntry } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry.model'; +import { VocabularyOptions } from '../../../../../../core/submission/vocabularies/models/vocabulary-options.model'; import { hasValue } from '../../../../../empty.util'; export interface DynamicListCheckboxGroupModelConfig extends DynamicFormGroupModelConfig { - authorityOptions: AuthorityOptions; + vocabularyOptions: VocabularyOptions; groupLength?: number; repeatable: boolean; value?: any; @@ -18,43 +19,44 @@ export interface DynamicListCheckboxGroupModelConfig extends DynamicFormGroupMod export class DynamicListCheckboxGroupModel extends DynamicCheckboxGroupModel { - @serializable() authorityOptions: AuthorityOptions; + @serializable() vocabularyOptions: VocabularyOptions; @serializable() repeatable: boolean; @serializable() groupLength: number; - @serializable() _value: AuthorityValue[]; isListGroup = true; valueUpdates: Subject; constructor(config: DynamicListCheckboxGroupModelConfig, layout?: DynamicFormControlLayout) { super(config, layout); - this.authorityOptions = config.authorityOptions; + this.vocabularyOptions = config.vocabularyOptions; this.groupLength = config.groupLength || 5; this._value = []; this.repeatable = config.repeatable; this.valueUpdates = new Subject(); - this.valueUpdates.subscribe((value: AuthorityValue | AuthorityValue[]) => this.value = value); + this.valueUpdates.subscribe((value: VocabularyEntry | VocabularyEntry[]) => this.value = value); this.valueUpdates.next(config.value); } - get hasAuthority(): boolean { - return this.authorityOptions && hasValue(this.authorityOptions.name); - } + @serializable() _value: VocabularyEntry[]; get value() { return this._value; } - set value(value: AuthorityValue | AuthorityValue[]) { + set value(value: VocabularyEntry | VocabularyEntry[]) { if (value) { if (Array.isArray(value)) { this._value = value; } else { // _value is non extendible so assign it a new array - const newValue = (this.value as AuthorityValue[]).concat([value]); + const newValue = (this.value as VocabularyEntry[]).concat([value]); this._value = newValue } } } + + get hasAuthority(): boolean { + return this.vocabularyOptions && hasValue(this.vocabularyOptions.name); + } } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list-radio-group.model.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list-radio-group.model.ts index 287c10f3fe..a4a0fb7749 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list-radio-group.model.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list-radio-group.model.ts @@ -4,11 +4,11 @@ import { DynamicRadioGroupModelConfig, serializable } from '@ng-dynamic-forms/core'; -import { AuthorityOptions } from '../../../../../../core/integration/models/authority-options.model'; +import { VocabularyOptions } from '../../../../../../core/submission/vocabularies/models/vocabulary-options.model'; import { hasValue } from '../../../../../empty.util'; export interface DynamicListModelConfig extends DynamicRadioGroupModelConfig { - authorityOptions: AuthorityOptions; + vocabularyOptions: VocabularyOptions; groupLength?: number; repeatable: boolean; value?: any; @@ -16,7 +16,7 @@ export interface DynamicListModelConfig extends DynamicRadioGroupModelConfig { - @serializable() authorityOptions: AuthorityOptions; + @serializable() vocabularyOptions: VocabularyOptions; @serializable() repeatable: boolean; @serializable() groupLength: number; isListGroup = true; @@ -24,13 +24,13 @@ export class DynamicListRadioGroupModel extends DynamicRadioGroupModel { constructor(config: DynamicListModelConfig, layout?: DynamicFormControlLayout) { super(config, layout); - this.authorityOptions = config.authorityOptions; + this.vocabularyOptions = config.vocabularyOptions; this.groupLength = config.groupLength || 5; this.repeatable = config.repeatable; this.valueUpdates.next(config.value); } get hasAuthority(): boolean { - return this.authorityOptions && hasValue(this.authorityOptions.name); + return this.vocabularyOptions && hasValue(this.vocabularyOptions.name); } } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.spec.ts index 63ae56e59a..b35ee10e8a 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.spec.ts @@ -2,25 +2,25 @@ import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { async, ComponentFixture, inject, TestBed, } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; - -import { DsDynamicListComponent } from './dynamic-list.component'; -import { DynamicListCheckboxGroupModel } from './dynamic-list-checkbox-group.model'; -import { AuthorityOptions } from '../../../../../../core/integration/models/authority-options.model'; -import { FormBuilderService } from '../../../form-builder.service'; +import { DynamicFormsNGBootstrapUIModule } from '@ng-dynamic-forms/ui-ng-bootstrap'; import { DynamicFormControlLayout, DynamicFormLayoutService, DynamicFormsCoreModule, DynamicFormValidationService } from '@ng-dynamic-forms/core'; -import { DynamicFormsNGBootstrapUIModule } from '@ng-dynamic-forms/ui-ng-bootstrap'; -import { AuthorityService } from '../../../../../../core/integration/authority.service'; -import { AuthorityServiceStub } from '../../../../../testing/authority-service.stub'; + +import { DsDynamicListComponent } from './dynamic-list.component'; +import { DynamicListCheckboxGroupModel } from './dynamic-list-checkbox-group.model'; +import { VocabularyOptions } from '../../../../../../core/submission/vocabularies/models/vocabulary-options.model'; +import { FormBuilderService } from '../../../form-builder.service'; +import { VocabularyService } from '../../../../../../core/submission/vocabularies/vocabulary.service'; +import { VocabularyServiceStub } from '../../../../../testing/vocabulary-service.stub'; import { DynamicListRadioGroupModel } from './dynamic-list-radio-group.model'; -import { By } from '@angular/platform-browser'; -import { AuthorityValue } from '../../../../../../core/integration/models/authority.value'; +import { VocabularyEntry } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry.model'; import { createTestComponent } from '../../../../../testing/utils.test'; export const LAYOUT_TEST = { @@ -35,12 +35,12 @@ export const LIST_TEST_GROUP = new FormGroup({ }); export const LIST_CHECKBOX_TEST_MODEL_CONFIG = { - authorityOptions: { + vocabularyOptions: { closed: false, metadata: 'listCheckbox', name: 'type_programme', scope: 'c1c16450-d56f-41bc-bb81-27f1d1eb5c23' - } as AuthorityOptions, + } as VocabularyOptions, disabled: false, id: 'listCheckbox', label: 'Programme', @@ -52,12 +52,12 @@ export const LIST_CHECKBOX_TEST_MODEL_CONFIG = { }; export const LIST_RADIO_TEST_MODEL_CONFIG = { - authorityOptions: { + vocabularyOptions: { closed: false, metadata: 'listRadio', name: 'type_programme', scope: 'c1c16450-d56f-41bc-bb81-27f1d1eb5c23' - } as AuthorityOptions, + } as VocabularyOptions, disabled: false, id: 'listRadio', label: 'Programme', @@ -77,7 +77,7 @@ describe('DsDynamicListComponent test suite', () => { let html; let modelValue; - const authorityServiceStub = new AuthorityServiceStub(); + const vocabularyServiceStub = new VocabularyServiceStub(); // async beforeEach beforeEach(async(() => { @@ -99,9 +99,9 @@ describe('DsDynamicListComponent test suite', () => { DsDynamicListComponent, DynamicFormValidationService, FormBuilderService, - {provide: AuthorityService, useValue: authorityServiceStub}, - {provide: DynamicFormLayoutService, useValue: {}}, - {provide: DynamicFormValidationService, useValue: {}} + { provide: VocabularyService, useValue: vocabularyServiceStub }, + { provide: DynamicFormLayoutService, useValue: {} }, + { provide: DynamicFormValidationService, useValue: {} } ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }); @@ -147,20 +147,16 @@ describe('DsDynamicListComponent test suite', () => { }); it('should init component properly', () => { - const results$ = authorityServiceStub.getEntriesByName({} as any); - - results$.subscribe((results) => { - expect((listComp as any).optionsList).toEqual(results.payload); - expect(listComp.items.length).toBe(1); - expect(listComp.items[0].length).toBe(2); - }) + expect((listComp as any).optionsList).toEqual(vocabularyServiceStub.getList()); + expect(listComp.items.length).toBe(1); + expect(listComp.items[0].length).toBe(2); }); it('should set model value properly when a checkbox option is selected', () => { const de = listFixture.debugElement.queryAll(By.css('div.custom-checkbox')); const items = de[0].queryAll(By.css('input.custom-control-input')); const item = items[0]; - modelValue = [Object.assign(new AuthorityValue(), {id: 1, display: 'one', value: 1})]; + modelValue = [Object.assign(new VocabularyEntry(), { authority: 1, display: 'one', value: 1 })]; item.nativeElement.click(); @@ -187,7 +183,7 @@ describe('DsDynamicListComponent test suite', () => { listComp = listFixture.componentInstance; // FormComponent test instance listComp.group = LIST_TEST_GROUP; listComp.model = new DynamicListCheckboxGroupModel(LIST_CHECKBOX_TEST_MODEL_CONFIG, LAYOUT_TEST); - modelValue = [Object.assign(new AuthorityValue(), {id: 1, display: 'one', value: 1})]; + modelValue = [Object.assign(new VocabularyEntry(), { authority: 1, display: 'one', value: 1 })]; listComp.model.value = modelValue; listFixture.detectChanges(); }); @@ -198,13 +194,9 @@ describe('DsDynamicListComponent test suite', () => { }); it('should init component properly', () => { - const results$ = authorityServiceStub.getEntriesByName({} as any); - - results$.subscribe((results) => { - expect((listComp as any).optionsList).toEqual(results.payload); - expect(listComp.model.value).toEqual(modelValue); - expect((listComp.model as DynamicListCheckboxGroupModel).group[0].value).toBeTruthy(); - }) + expect((listComp as any).optionsList).toEqual(vocabularyServiceStub.getList()); + expect(listComp.model.value).toEqual(modelValue); + expect((listComp.model as DynamicListCheckboxGroupModel).group[0].value).toBeTruthy(); }); it('should set model value properly when a checkbox option is deselected', () => { @@ -237,20 +229,16 @@ describe('DsDynamicListComponent test suite', () => { }); it('should init component properly', () => { - const results$ = authorityServiceStub.getEntriesByName({} as any); - - results$.subscribe((results) => { - expect((listComp as any).optionsList).toEqual(results.payload); - expect(listComp.items.length).toBe(1); - expect(listComp.items[0].length).toBe(2); - }) + expect((listComp as any).optionsList).toEqual(vocabularyServiceStub.getList()); + expect(listComp.items.length).toBe(1); + expect(listComp.items[0].length).toBe(2); }); it('should set model value when a radio option is selected', () => { const de = listFixture.debugElement.queryAll(By.css('div.custom-radio')); const items = de[0].queryAll(By.css('input.custom-control-input')); const item = items[0]; - modelValue = Object.assign(new AuthorityValue(), {id: 1, display: 'one', value: 1}); + modelValue = Object.assign(new VocabularyEntry(), { authority: 1, display: 'one', value: 1 }); item.nativeElement.click(); @@ -265,7 +253,7 @@ describe('DsDynamicListComponent test suite', () => { listComp = listFixture.componentInstance; // FormComponent test instance listComp.group = LIST_TEST_GROUP; listComp.model = new DynamicListRadioGroupModel(LIST_RADIO_TEST_MODEL_CONFIG, LAYOUT_TEST); - modelValue = Object.assign(new AuthorityValue(), {id: 1, display: 'one', value: 1}); + modelValue = Object.assign(new VocabularyEntry(), { authority: 1, display: 'one', value: 1 }); listComp.model.value = modelValue; listFixture.detectChanges(); }); @@ -276,13 +264,9 @@ describe('DsDynamicListComponent test suite', () => { }); it('should init component properly', () => { - const results$ = authorityServiceStub.getEntriesByName({} as any); - - results$.subscribe((results) => { - expect((listComp as any).optionsList).toEqual(results.payload); - expect(listComp.model.value).toEqual(modelValue); - expect((listComp.model as DynamicListRadioGroupModel).options[0].value).toBeTruthy(); - }) + expect((listComp as any).optionsList).toEqual(vocabularyServiceStub.getList()); + expect(listComp.model.value).toEqual(modelValue); + expect((listComp.model as DynamicListRadioGroupModel).options[0].value).toBeTruthy(); }); }); }); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.ts index d023f1c583..3c5a86f362 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.ts @@ -1,20 +1,23 @@ import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { FormGroup } from '@angular/forms'; + +import { + DynamicCheckboxModel, + DynamicFormControlComponent, + DynamicFormLayoutService, + DynamicFormValidationService +} from '@ng-dynamic-forms/core'; import { findKey } from 'lodash'; -import { AuthorityService } from '../../../../../../core/integration/authority.service'; -import { IntegrationSearchOptions } from '../../../../../../core/integration/models/integration-options.model'; +import { VocabularyFindOptions } from '../../../../../../core/submission/vocabularies/models/vocabulary-find-options.model'; import { hasValue, isNotEmpty } from '../../../../../empty.util'; import { DynamicListCheckboxGroupModel } from './dynamic-list-checkbox-group.model'; import { FormBuilderService } from '../../../form-builder.service'; -import { - DynamicCheckboxModel, - DynamicFormControlComponent, DynamicFormLayoutService, - DynamicFormValidationService -} from '@ng-dynamic-forms/core'; -import { AuthorityValue } from '../../../../../../core/integration/models/authority.value'; import { DynamicListRadioGroupModel } from './dynamic-list-radio-group.model'; -import { IntegrationData } from '../../../../../../core/integration/integration-data'; +import { VocabularyService } from '../../../../../../core/submission/vocabularies/vocabulary.service'; +import { getFirstSucceededRemoteDataPayload } from '../../../../../../core/shared/operators'; +import { PaginatedList } from '../../../../../../core/data/paginated-list'; +import { VocabularyEntry } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry.model'; export interface ListItem { id: string, @@ -39,10 +42,10 @@ export class DsDynamicListComponent extends DynamicFormControlComponent implemen @Output() focus: EventEmitter = new EventEmitter(); public items: ListItem[][] = []; - protected optionsList: AuthorityValue[]; - protected searchOptions: IntegrationSearchOptions; + protected optionsList: VocabularyEntry[]; + protected searchOptions: VocabularyFindOptions; - constructor(private authorityService: AuthorityService, + constructor(private vocabularyService: VocabularyService, private cdr: ChangeDetectorRef, private formBuilderService: FormBuilderService, protected layoutService: DynamicFormLayoutService, @@ -54,10 +57,10 @@ export class DsDynamicListComponent extends DynamicFormControlComponent implemen ngOnInit() { if (this.hasAuthorityOptions()) { // TODO Replace max elements 1000 with a paginated request when pagination bug is resolved - this.searchOptions = new IntegrationSearchOptions( - this.model.authorityOptions.scope, - this.model.authorityOptions.name, - this.model.authorityOptions.metadata, + this.searchOptions = new VocabularyFindOptions( + this.model.vocabularyOptions.scope, + this.model.vocabularyOptions.name, + this.model.vocabularyOptions.metadata, '', 1000, // Max elements 1);// Current Page @@ -77,13 +80,13 @@ export class DsDynamicListComponent extends DynamicFormControlComponent implemen const target = event.target as any; if (this.model.repeatable) { // Target tabindex coincide with the array index of the value into the authority list - const authorityValue: AuthorityValue = this.optionsList[target.tabIndex]; + const entry: VocabularyEntry = this.optionsList[target.tabIndex]; if (target.checked) { - this.model.valueUpdates.next(authorityValue); + this.model.valueUpdates.next(entry); } else { const newValue = []; this.model.value - .filter((item) => item.value !== authorityValue.value) + .filter((item) => item.value !== entry.value) .forEach((item) => newValue.push(item)); this.model.valueUpdates.next(newValue); } @@ -94,16 +97,18 @@ export class DsDynamicListComponent extends DynamicFormControlComponent implemen } protected setOptionsFromAuthority() { - if (this.model.authorityOptions.name && this.model.authorityOptions.name.length > 0) { + if (this.model.vocabularyOptions.name && this.model.vocabularyOptions.name.length > 0) { const listGroup = this.group.controls[this.model.id] as FormGroup; - this.authorityService.getEntriesByName(this.searchOptions).subscribe((authorities: IntegrationData) => { + this.vocabularyService.getVocabularyEntries(this.searchOptions).pipe( + getFirstSucceededRemoteDataPayload() + ).subscribe((entries: PaginatedList) => { let groupCounter = 0; let itemsPerGroup = 0; let tempList: ListItem[] = []; - this.optionsList = authorities.payload as AuthorityValue[]; + this.optionsList = entries.page; // Make a list of available options (checkbox/radio) and split in groups of 'model.groupLength' - (authorities.payload as AuthorityValue[]).forEach((option, key) => { - const value = option.id || option.value; + entries.page.forEach((option, key) => { + const value = option.authority || option.value; const checked: boolean = isNotEmpty(findKey( this.model.value, (v) => v.value === option.value)); @@ -138,8 +143,8 @@ export class DsDynamicListComponent extends DynamicFormControlComponent implemen } protected hasAuthorityOptions() { - return (hasValue(this.model.authorityOptions.scope) - && hasValue(this.model.authorityOptions.name) - && hasValue(this.model.authorityOptions.metadata)); + return (hasValue(this.model.vocabularyOptions.scope) + && hasValue(this.model.vocabularyOptions.name) + && hasValue(this.model.vocabularyOptions.metadata)); } } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts index c77aabfeed..ce45e113a0 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts @@ -2,33 +2,33 @@ import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { async, ComponentFixture, fakeAsync, inject, TestBed, tick, } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; - -import { AuthorityOptions } from '../../../../../../core/integration/models/authority-options.model'; -import { DynamicFormLayoutService, DynamicFormsCoreModule, DynamicFormValidationService } from '@ng-dynamic-forms/core'; +import { TranslateModule } from '@ngx-translate/core'; +import { InfiniteScrollModule } from 'ngx-infinite-scroll'; import { DynamicFormsNGBootstrapUIModule } from '@ng-dynamic-forms/ui-ng-bootstrap'; -import { AuthorityService } from '../../../../../../core/integration/authority.service'; -import { AuthorityServiceStub } from '../../../../../testing/authority-service.stub'; +import { DynamicFormLayoutService, DynamicFormsCoreModule, DynamicFormValidationService } from '@ng-dynamic-forms/core'; + +import { VocabularyOptions } from '../../../../../../core/submission/vocabularies/models/vocabulary-options.model'; +import { VocabularyService } from '../../../../../../core/submission/vocabularies/vocabulary.service'; +import { VocabularyServiceStub } from '../../../../../testing/vocabulary-service.stub'; import { DsDynamicLookupComponent } from './dynamic-lookup.component'; import { DynamicLookupModel } from './dynamic-lookup.model'; -import { InfiniteScrollModule } from 'ngx-infinite-scroll'; -import { TranslateModule } from '@ngx-translate/core'; import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model'; -import { By } from '@angular/platform-browser'; -import { AuthorityValue } from '../../../../../../core/integration/models/authority.value'; +import { VocabularyEntry } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry.model'; import { createTestComponent } from '../../../../../testing/utils.test'; import { DynamicLookupNameModel } from './dynamic-lookup-name.model'; import { AuthorityConfidenceStateDirective } from '../../../../../authority-confidence/authority-confidence-state.directive'; import { ObjNgFor } from '../../../../../utils/object-ngfor.pipe'; let LOOKUP_TEST_MODEL_CONFIG = { - authorityOptions: { + vocabularyOptions: { closed: false, metadata: 'lookup', name: 'RPAuthority', scope: 'c1c16450-d56f-41bc-bb81-27f1d1eb5c23' - } as AuthorityOptions, + } as VocabularyOptions, disabled: false, errorMessages: { required: 'Required field.' }, id: 'lookup', @@ -47,12 +47,12 @@ let LOOKUP_TEST_MODEL_CONFIG = { }; let LOOKUP_NAME_TEST_MODEL_CONFIG = { - authorityOptions: { + vocabularyOptions: { closed: false, metadata: 'lookup-name', name: 'RPAuthority', scope: 'c1c16450-d56f-41bc-bb81-27f1d1eb5c23' - } as AuthorityOptions, + } as VocabularyOptions, disabled: false, errorMessages: { required: 'Required field.' }, id: 'lookupName', @@ -78,12 +78,12 @@ let LOOKUP_TEST_GROUP = new FormGroup({ describe('Dynamic Lookup component', () => { function init() { LOOKUP_TEST_MODEL_CONFIG = { - authorityOptions: { + vocabularyOptions: { closed: false, metadata: 'lookup', name: 'RPAuthority', scope: 'c1c16450-d56f-41bc-bb81-27f1d1eb5c23' - } as AuthorityOptions, + } as VocabularyOptions, disabled: false, errorMessages: { required: 'Required field.' }, id: 'lookup', @@ -102,12 +102,12 @@ describe('Dynamic Lookup component', () => { }; LOOKUP_NAME_TEST_MODEL_CONFIG = { - authorityOptions: { + vocabularyOptions: { closed: false, metadata: 'lookup-name', name: 'RPAuthority', scope: 'c1c16450-d56f-41bc-bb81-27f1d1eb5c23' - } as AuthorityOptions, + } as VocabularyOptions, disabled: false, errorMessages: { required: 'Required field.' }, id: 'lookupName', @@ -137,12 +137,11 @@ describe('Dynamic Lookup component', () => { let testFixture: ComponentFixture; let lookupFixture: ComponentFixture; let html; + let vocabularyServiceStub: VocabularyServiceStub; - let authorityServiceStub; // async beforeEach beforeEach(async(() => { - const authorityService = new AuthorityServiceStub(); - authorityServiceStub = authorityService; + vocabularyServiceStub = new VocabularyServiceStub(); TestBed.configureTestingModule({ imports: [ DynamicFormsCoreModule, @@ -162,7 +161,7 @@ describe('Dynamic Lookup component', () => { providers: [ ChangeDetectorRef, DsDynamicLookupComponent, - { provide: AuthorityService, useValue: authorityService }, + { provide: VocabularyService, useValue: vocabularyServiceStub }, { provide: DynamicFormLayoutService, useValue: {} }, { provide: DynamicFormValidationService, useValue: {} } ], @@ -247,7 +246,7 @@ describe('Dynamic Lookup component', () => { it('should return search results', fakeAsync(() => { const de = lookupFixture.debugElement.queryAll(By.css('button')); const btnEl = de[0].nativeElement; - const results$ = authorityServiceStub.getEntriesByName({} as any); + const results = vocabularyServiceStub.getList(); lookupComp.firstInputValue = 'test'; lookupFixture.detectChanges(); @@ -255,17 +254,15 @@ describe('Dynamic Lookup component', () => { btnEl.click(); tick(); lookupFixture.detectChanges(); - results$.subscribe((results) => { - expect(lookupComp.optionsList).toEqual(results.payload); - }); + expect(lookupComp.optionsList).toEqual(results); })); it('should select a results entry properly', fakeAsync(() => { let de = lookupFixture.debugElement.queryAll(By.css('button')); const btnEl = de[0].nativeElement; - const selectedValue = Object.assign(new AuthorityValue(), { - id: 1, + const selectedValue = Object.assign(new VocabularyEntry(), { + authority: 1, display: 'one', value: 1 }); @@ -284,7 +281,7 @@ describe('Dynamic Lookup component', () => { expect(lookupComp.change.emit).toHaveBeenCalled(); })); - it('should set model.value on input type when AuthorityOptions.closed is false', fakeAsync(() => { + it('should set model.value on input type when VocabularyOptions.closed is false', fakeAsync(() => { lookupComp.firstInputValue = 'test'; lookupFixture.detectChanges(); @@ -293,8 +290,8 @@ describe('Dynamic Lookup component', () => { })); - it('should not set model.value on input type when AuthorityOptions.closed is true', () => { - lookupComp.model.authorityOptions.closed = true; + it('should not set model.value on input type when VocabularyOptions.closed is true', () => { + lookupComp.model.vocabularyOptions.closed = true; lookupComp.firstInputValue = 'test'; lookupFixture.detectChanges(); @@ -389,26 +386,26 @@ describe('Dynamic Lookup component', () => { it('should select a results entry properly', fakeAsync(() => { const payload = [ - Object.assign(new AuthorityValue(), { - id: 1, + Object.assign(new VocabularyEntry(), { + authority: 1, display: 'Name, Lastname', value: 1 }), - Object.assign(new AuthorityValue(), { - id: 2, + Object.assign(new VocabularyEntry(), { + authority: 2, display: 'NameTwo, LastnameTwo', value: 2 }), ]; let de = lookupFixture.debugElement.queryAll(By.css('button')); const btnEl = de[0].nativeElement; - const selectedValue = Object.assign(new AuthorityValue(), { - id: 1, + const selectedValue = Object.assign(new VocabularyEntry(), { + authority: 1, display: 'Name, Lastname', value: 1 }); spyOn(lookupComp.change, 'emit'); - authorityServiceStub.setNewPayload(payload); + vocabularyServiceStub.setNewPayload(payload); lookupComp.firstInputValue = 'test'; lookupFixture.detectChanges(); btnEl.click(); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts index d5516df6d9..24422e891a 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts @@ -1,8 +1,7 @@ import { ChangeDetectorRef, Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'; import { FormGroup } from '@angular/forms'; -import { Subscription } from 'rxjs'; -import { of as observableOf } from 'rxjs'; +import { of as observableOf, Subscription } from 'rxjs'; import { catchError, distinctUntilChanged } from 'rxjs/operators'; import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap'; import { @@ -11,16 +10,16 @@ import { DynamicFormValidationService } from '@ng-dynamic-forms/core'; -import { AuthorityService } from '../../../../../../core/integration/authority.service'; -import { DynamicLookupModel } from './dynamic-lookup.model'; -import { IntegrationSearchOptions } from '../../../../../../core/integration/models/integration-options.model'; +import { VocabularyService } from '../../../../../../core/submission/vocabularies/vocabulary.service'; +import { VocabularyFindOptions } from '../../../../../../core/submission/vocabularies/models/vocabulary-find-options.model'; import { hasValue, isEmpty, isNotEmpty, isNull, isUndefined } from '../../../../../empty.util'; -import { IntegrationData } from '../../../../../../core/integration/integration-data'; import { PageInfo } from '../../../../../../core/shared/page-info.model'; import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model'; -import { AuthorityValue } from '../../../../../../core/integration/models/authority.value'; +import { VocabularyEntry } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry.model'; import { DynamicLookupNameModel } from './dynamic-lookup-name.model'; -import { ConfidenceType } from '../../../../../../core/integration/models/confidence-type'; +import { ConfidenceType } from '../../../../../../core/shared/confidence-type'; +import { PaginatedList } from '../../../../../../core/data/paginated-list'; +import { getFirstSucceededRemoteDataPayload } from '../../../../../../core/shared/operators'; @Component({ selector: 'ds-dynamic-lookup', @@ -43,10 +42,10 @@ export class DsDynamicLookupComponent extends DynamicFormControlComponent implem public pageInfo: PageInfo; public optionsList: any; - protected searchOptions: IntegrationSearchOptions; + protected searchOptions: VocabularyFindOptions; protected subs: Subscription[] = []; - constructor(private authorityService: AuthorityService, + constructor(private vocabularyService: VocabularyService, private cdr: ChangeDetectorRef, protected layoutService: DynamicFormLayoutService, protected validationService: DynamicFormValidationService @@ -59,10 +58,10 @@ export class DsDynamicLookupComponent extends DynamicFormControlComponent implem }; ngOnInit() { - this.searchOptions = new IntegrationSearchOptions( - this.model.authorityOptions.scope, - this.model.authorityOptions.name, - this.model.authorityOptions.metadata, + this.searchOptions = new VocabularyFindOptions( + this.model.vocabularyOptions.scope, + this.model.vocabularyOptions.name, + this.model.vocabularyOptions.metadata, '', this.model.maxOptions, 1); @@ -79,6 +78,148 @@ export class DsDynamicLookupComponent extends DynamicFormControlComponent implem })); } + public formatItemForInput(item: any, field: number): string { + if (isUndefined(item) || isNull(item)) { + return ''; + } + return (typeof item === 'string') ? item : this.inputFormatter(item, field); + } + + public hasAuthorityValue() { + return hasValue(this.model.value) + && this.model.value.hasAuthority(); + } + + public hasEmptyValue() { + return isNotEmpty(this.getCurrentValue()); + } + + public clearFields() { + // Clear inputs whether there is no results and authority is closed + if (this.model.vocabularyOptions.closed) { + this.resetFields(); + } + } + + public isEditDisabled() { + return !this.hasAuthorityValue(); + } + + public isInputDisabled() { + return (this.model.vocabularyOptions.closed && this.hasAuthorityValue() && !this.editMode); + } + + public isLookupName() { + return (this.model instanceof DynamicLookupNameModel); + } + + public isSearchDisabled() { + return isEmpty(this.firstInputValue) || this.editMode; + } + + public onBlurEvent(event: Event) { + this.blur.emit(event); + } + + public onFocusEvent(event) { + this.focus.emit(event); + } + + public onChange(event) { + event.preventDefault(); + if (!this.model.vocabularyOptions.closed) { + if (isNotEmpty(this.getCurrentValue())) { + const currentValue = new FormFieldMetadataValueObject(this.getCurrentValue()); + if (!this.editMode) { + this.updateModel(currentValue); + } + } else { + this.remove(); + } + } + } + + public onScroll() { + if (!this.loading && this.pageInfo.currentPage <= this.pageInfo.totalPages) { + this.searchOptions.currentPage++; + this.search(); + } + } + + public onSelect(event) { + this.updateModel(event); + } + + public openChange(isOpened: boolean) { + if (!isOpened) { + if (this.model.vocabularyOptions.closed && !this.hasAuthorityValue()) { + this.setInputsValue(''); + } + } + } + + public remove() { + this.group.markAsPristine(); + this.model.valueUpdates.next(null); + this.change.emit(null); + } + + public saveChanges() { + if (isNotEmpty(this.getCurrentValue())) { + const newValue = Object.assign(new VocabularyEntry(), this.model.value, { + display: this.getCurrentValue(), + value: this.getCurrentValue() + }); + this.updateModel(newValue); + } else { + this.remove(); + } + this.switchEditMode(); + } + + public search() { + this.optionsList = null; + this.pageInfo = null; + + // Query + this.searchOptions.query = this.getCurrentValue(); + + this.loading = true; + this.subs.push(this.vocabularyService.getVocabularyEntries(this.searchOptions).pipe( + getFirstSucceededRemoteDataPayload(), + catchError(() => + observableOf(new PaginatedList( + new PageInfo(), + [] + )) + ), + distinctUntilChanged()) + .subscribe((list: PaginatedList) => { + console.log(list); + this.optionsList = list.page; + this.pageInfo = list.pageInfo; + this.loading = false; + this.cdr.detectChanges(); + })); + } + + public switchEditMode() { + this.editMode = !this.editMode; + } + + public whenClickOnConfidenceNotAccepted(sdRef: NgbDropdown, confidence: ConfidenceType) { + if (!this.model.readOnly) { + sdRef.open(); + this.search(); + } + } + + ngOnDestroy() { + this.subs + .filter((sub) => hasValue(sub)) + .forEach((sub) => sub.unsubscribe()); + } + protected getCurrentValue(): string { let result = ''; if (!this.isLookupName()) { @@ -106,7 +247,7 @@ export class DsDynamicLookupComponent extends DynamicFormControlComponent implem protected setInputsValue(value) { if (hasValue(value)) { let displayValue = value; - if (value instanceof FormFieldMetadataValueObject || value instanceof AuthorityValue) { + if (value instanceof FormFieldMetadataValueObject || value instanceof VocabularyEntry) { displayValue = value.display; } @@ -131,145 +272,4 @@ export class DsDynamicLookupComponent extends DynamicFormControlComponent implem this.optionsList = null; this.pageInfo = null; } - - public formatItemForInput(item: any, field: number): string { - if (isUndefined(item) || isNull(item)) { - return ''; - } - return (typeof item === 'string') ? item : this.inputFormatter(item, field); - } - - public hasAuthorityValue() { - return hasValue(this.model.value) - && this.model.value.hasAuthority(); - } - - public hasEmptyValue() { - return isNotEmpty(this.getCurrentValue()); - } - - public clearFields() { - // Clear inputs whether there is no results and authority is closed - if (this.model.authorityOptions.closed) { - this.resetFields(); - } - } - - public isEditDisabled() { - return !this.hasAuthorityValue(); - } - - public isInputDisabled() { - return (this.model.authorityOptions.closed && this.hasAuthorityValue() && !this.editMode); - } - - public isLookupName() { - return (this.model instanceof DynamicLookupNameModel); - } - - public isSearchDisabled() { - return isEmpty(this.firstInputValue) || this.editMode; - } - - public onBlurEvent(event: Event) { - this.blur.emit(event); - } - - public onFocusEvent(event) { - this.focus.emit(event); - } - - public onChange(event) { - event.preventDefault(); - if (!this.model.authorityOptions.closed) { - if (isNotEmpty(this.getCurrentValue())) { - const currentValue = new FormFieldMetadataValueObject(this.getCurrentValue()); - if (!this.editMode) { - this.updateModel(currentValue); - } - } else { - this.remove(); - } - } - } - - public onScroll() { - if (!this.loading && this.pageInfo.currentPage <= this.pageInfo.totalPages) { - this.searchOptions.currentPage++; - this.search(); - } - } - - public onSelect(event) { - this.updateModel(event); - } - - public openChange(isOpened: boolean) { - if (!isOpened) { - if (this.model.authorityOptions.closed && !this.hasAuthorityValue()) { - this.setInputsValue(''); - } - } - } - - public remove() { - this.group.markAsPristine(); - this.model.valueUpdates.next(null); - this.change.emit(null); - } - - public saveChanges() { - if (isNotEmpty(this.getCurrentValue())) { - const newValue = Object.assign(new AuthorityValue(), this.model.value, { - display: this.getCurrentValue(), - value: this.getCurrentValue() - }); - this.updateModel(newValue); - } else { - this.remove(); - } - this.switchEditMode(); - } - - public search() { - this.optionsList = null; - this.pageInfo = null; - - // Query - this.searchOptions.query = this.getCurrentValue(); - - this.loading = true; - this.subs.push(this.authorityService.getEntriesByName(this.searchOptions).pipe( - catchError(() => { - const emptyResult = new IntegrationData( - new PageInfo(), - [] - ); - return observableOf(emptyResult); - }), - distinctUntilChanged()) - .subscribe((object: IntegrationData) => { - this.optionsList = object.payload; - this.pageInfo = object.pageInfo; - this.loading = false; - this.cdr.detectChanges(); - })); - } - - public switchEditMode() { - this.editMode = !this.editMode; - } - - public whenClickOnConfidenceNotAccepted(sdRef: NgbDropdown, confidence: ConfidenceType) { - if (!this.model.readOnly) { - sdRef.open(); - this.search(); - } - } - - ngOnDestroy() { - this.subs - .filter((sub) => hasValue(sub)) - .forEach((sub) => sub.unsubscribe()); - } } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.component.spec.ts index bcddb52123..64cf658d47 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.component.spec.ts @@ -2,9 +2,12 @@ import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { async, ComponentFixture, inject, TestBed, } from '@angular/core/testing'; import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { Store, StoreModule } from '@ngrx/store'; import { TranslateModule } from '@ngx-translate/core'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { DynamicFormLayoutService, DynamicFormValidationService } from '@ng-dynamic-forms/core'; import { DsDynamicRelationGroupComponent } from './dynamic-relation-group.components'; import { DynamicRelationGroupModel, DynamicRelationGroupModelConfig } from './dynamic-relation-group.model'; @@ -13,18 +16,14 @@ import { FormFieldModel } from '../../../models/form-field.model'; import { FormBuilderService } from '../../../form-builder.service'; import { FormService } from '../../../../form.service'; import { FormComponent } from '../../../../form.component'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { Chips } from '../../../../../chips/models/chips.model'; import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model'; import { DsDynamicInputModel } from '../ds-dynamic-input.model'; import { createTestComponent } from '../../../../../testing/utils.test'; -import { DynamicFormLayoutService, DynamicFormValidationService } from '@ng-dynamic-forms/core'; -import { AuthorityService } from '../../../../../../core/integration/authority.service'; -import { AuthorityServiceStub } from '../../../../../testing/authority-service.stub'; -import { Store, StoreModule } from '@ngrx/store'; +import { VocabularyService } from '../../../../../../core/submission/vocabularies/vocabulary.service'; +import { VocabularyServiceStub } from '../../../../../testing/vocabulary-service.stub'; import { StoreMock } from '../../../../../testing/store.mock'; import { FormRowModel } from '../../../../../../core/config/models/config-submission-form.model'; -import { GlobalConfig } from '../../../../../../../config/global-config.interface'; import { storeModuleConfig } from '../../../../../../app.reducer'; export let FORM_GROUP_TEST_MODEL_CONFIG; @@ -47,7 +46,7 @@ function init() { mandatoryMessage: 'Required field!', repeatable: false, selectableMetadata: [{ - authority: 'RPAuthority', + controlledVocabulary: 'RPAuthority', closed: false, metadata: 'dc.contributor.author' }], @@ -61,7 +60,7 @@ function init() { mandatory: 'false', repeatable: false, selectableMetadata: [{ - authority: 'OUAuthority', + controlledVocabulary: 'OUAuthority', closed: false, metadata: 'local.contributor.affiliation' }] @@ -128,7 +127,7 @@ describe('DsDynamicRelationGroupComponent test suite', () => { FormBuilderService, FormComponent, FormService, - { provide: AuthorityService, useValue: new AuthorityServiceStub() }, + { provide: VocabularyService, useValue: new VocabularyServiceStub() }, { provide: Store, useClass: StoreMock } ], schemas: [CUSTOM_ELEMENTS_SCHEMA] diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.components.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.components.ts index 11085a1bc3..21606d7abc 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.components.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.components.ts @@ -1,14 +1,4 @@ -import { - ChangeDetectorRef, - Component, - EventEmitter, - Inject, - Input, - OnDestroy, - OnInit, - Output, - ViewChild -} from '@angular/core'; +import { ChangeDetectorRef, Component, EventEmitter, Input, OnDestroy, OnInit, Output, ViewChild } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { combineLatest, Observable, of as observableOf, Subscription } from 'rxjs'; @@ -33,12 +23,12 @@ import { hasValue, isEmpty, isNotEmpty, isNotNull } from '../../../../../empty.u import { shrinkInOut } from '../../../../../animations/shrink'; import { ChipsItem } from '../../../../../chips/models/chips-item.model'; import { hasOnlyEmptyProperties } from '../../../../../object.util'; -import { IntegrationSearchOptions } from '../../../../../../core/integration/models/integration-options.model'; -import { AuthorityService } from '../../../../../../core/integration/authority.service'; -import { IntegrationData } from '../../../../../../core/integration/integration-data'; +import { VocabularyFindOptions } from '../../../../../../core/submission/vocabularies/models/vocabulary-find-options.model'; +import { VocabularyService } from '../../../../../../core/submission/vocabularies/vocabulary.service'; import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model'; -import { AuthorityValue } from '../../../../../../core/integration/models/authority.value'; import { environment } from '../../../../../../../environments/environment'; +import { getFirstSucceededRemoteDataPayload } from '../../../../../../core/shared/operators'; +import { VocabularyEntryDetail } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry-detail.model'; @Component({ selector: 'ds-dynamic-relation-group', @@ -64,9 +54,9 @@ export class DsDynamicRelationGroupComponent extends DynamicFormControlComponent private selectedChipItem: ChipsItem; private subs: Subscription[] = []; - @ViewChild('formRef', {static: false}) private formRef: FormComponent; + @ViewChild('formRef', { static: false }) private formRef: FormComponent; - constructor(private authorityService: AuthorityService, + constructor(private vocabularyService: VocabularyService, private formBuilderService: FormBuilderService, private formService: FormService, private cdr: ChangeDetectorRef, @@ -177,6 +167,12 @@ export class DsDynamicRelationGroupComponent extends DynamicFormControlComponent this.clear(); } + ngOnDestroy(): void { + this.subs + .filter((sub) => hasValue(sub)) + .forEach((sub) => sub.unsubscribe()); + } + private addToChips() { if (!this.formRef.formGroup.valid) { this.formService.validateAllFormFields(this.formRef.formGroup); @@ -235,20 +231,16 @@ export class DsDynamicRelationGroupComponent extends DynamicFormControlComponent if (isObject(valueObj[fieldName]) && valueObj[fieldName].hasAuthority() && isNotEmpty(valueObj[fieldName].authority)) { const fieldId = fieldName.replace(/\./g, '_'); const model = this.formBuilderService.findById(fieldId, this.formModel); - const searchOptions: IntegrationSearchOptions = new IntegrationSearchOptions( - (model as any).authorityOptions.scope, - (model as any).authorityOptions.name, - (model as any).authorityOptions.metadata, + return$ = this.vocabularyService.findEntryDetailByValue( valueObj[fieldName].authority, - (model as any).maxOptions, - 1); - - return$ = this.authorityService.getEntryByValue(searchOptions).pipe( - map((result: IntegrationData) => Object.assign( + (model as any).vocabularyOptions.name + ).pipe( + getFirstSucceededRemoteDataPayload(), + map((entryDetail: VocabularyEntryDetail) => Object.assign( new FormFieldMetadataValueObject(), valueObj[fieldName], { - otherInformation: (result.payload[0] as AuthorityValue).otherInformation + otherInformation: entryDetail.otherInformation }) )); } else { @@ -315,10 +307,4 @@ export class DsDynamicRelationGroupComponent extends DynamicFormControlComponent } } - ngOnDestroy(): void { - this.subs - .filter((sub) => hasValue(sub)) - .forEach((sub) => sub.unsubscribe()); - } - } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.spec.ts index 6086444264..c06908bdc5 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.spec.ts @@ -9,12 +9,12 @@ import { InfiniteScrollModule } from 'ngx-infinite-scroll'; import { DynamicFormLayoutService, DynamicFormsCoreModule, DynamicFormValidationService } from '@ng-dynamic-forms/core'; import { DynamicFormsNGBootstrapUIModule } from '@ng-dynamic-forms/ui-ng-bootstrap'; -import { AuthorityOptions } from '../../../../../../core/integration/models/authority-options.model'; -import { AuthorityService } from '../../../../../../core/integration/authority.service'; -import { AuthorityServiceStub } from '../../../../../testing/authority-service.stub'; +import { VocabularyOptions } from '../../../../../../core/submission/vocabularies/models/vocabulary-options.model'; +import { VocabularyService } from '../../../../../../core/submission/vocabularies/vocabulary.service'; +import { VocabularyServiceStub } from '../../../../../testing/vocabulary-service.stub'; import { DsDynamicScrollableDropdownComponent } from './dynamic-scrollable-dropdown.component'; import { DynamicScrollableDropdownModel } from './dynamic-scrollable-dropdown.model'; -import { AuthorityValue } from '../../../../../../core/integration/models/authority.value'; +import { VocabularyEntry } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry.model'; import { createTestComponent, hasClass } from '../../../../../testing/utils.test'; export const SD_TEST_GROUP = new FormGroup({ @@ -22,14 +22,14 @@ export const SD_TEST_GROUP = new FormGroup({ }); export const SD_TEST_MODEL_CONFIG = { - authorityOptions: { + vocabularyOptions: { closed: false, metadata: 'dropdown', name: 'common_iso_languages', scope: 'c1c16450-d56f-41bc-bb81-27f1d1eb5c23' - } as AuthorityOptions, + } as VocabularyOptions, disabled: false, - errorMessages: {required: 'Required field.'}, + errorMessages: { required: 'Required field.' }, id: 'dropdown', label: 'Language', maxOptions: 10, @@ -52,7 +52,7 @@ describe('Dynamic Dynamic Scrollable Dropdown component', () => { let html; let modelValue; - const authorityServiceStub = new AuthorityServiceStub(); + const vocabularyServiceStub = new VocabularyServiceStub(); // async beforeEach beforeEach(async(() => { @@ -74,9 +74,9 @@ describe('Dynamic Dynamic Scrollable Dropdown component', () => { providers: [ ChangeDetectorRef, DsDynamicScrollableDropdownComponent, - {provide: AuthorityService, useValue: authorityServiceStub}, - {provide: DynamicFormLayoutService, useValue: {}}, - {provide: DynamicFormValidationService, useValue: {}} + { provide: VocabularyService, useValue: vocabularyServiceStub }, + { provide: DynamicFormLayoutService, useValue: {} }, + { provide: DynamicFormValidationService, useValue: {} } ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }); @@ -121,11 +121,8 @@ describe('Dynamic Dynamic Scrollable Dropdown component', () => { }); it('should init component properly', () => { - const results$ = authorityServiceStub.getEntriesByName({} as any); expect(scrollableDropdownComp.optionsList).toBeDefined(); - results$.subscribe((results) => { - expect(scrollableDropdownComp.optionsList).toEqual(results.payload); - }) + expect(scrollableDropdownComp.optionsList).toEqual(vocabularyServiceStub.getList()); }); it('should display dropdown menu entries', () => { @@ -154,7 +151,7 @@ describe('Dynamic Dynamic Scrollable Dropdown component', () => { })); it('should select a results entry properly', fakeAsync(() => { - const selectedValue = Object.assign(new AuthorityValue(), {id: 1, display: 'one', value: 1}); + const selectedValue = Object.assign(new VocabularyEntry(), { authority: 1, display: 'one', value: 1 }); let de: any = scrollableDropdownFixture.debugElement.query(By.css('button.ds-form-input-btn')); let btnEl = de.nativeElement; @@ -192,7 +189,7 @@ describe('Dynamic Dynamic Scrollable Dropdown component', () => { scrollableDropdownFixture = TestBed.createComponent(DsDynamicScrollableDropdownComponent); scrollableDropdownComp = scrollableDropdownFixture.componentInstance; // FormComponent test instance scrollableDropdownComp.group = SD_TEST_GROUP; - modelValue = Object.assign(new AuthorityValue(), {id: 1, display: 'one', value: 1}); + modelValue = Object.assign(new VocabularyEntry(), { authority: 1, display: 'one', value: 1 }); scrollableDropdownComp.model = new DynamicScrollableDropdownModel(SD_TEST_MODEL_CONFIG); scrollableDropdownComp.model.value = modelValue; scrollableDropdownFixture.detectChanges(); @@ -204,12 +201,9 @@ describe('Dynamic Dynamic Scrollable Dropdown component', () => { }); it('should init component properly', () => { - const results$ = authorityServiceStub.getEntriesByName({} as any); expect(scrollableDropdownComp.optionsList).toBeDefined(); - results$.subscribe((results) => { - expect(scrollableDropdownComp.optionsList).toEqual(results.payload); - expect(scrollableDropdownComp.model.value).toEqual(modelValue); - }) + expect(scrollableDropdownComp.optionsList).toEqual(vocabularyServiceStub.getList()); + expect(scrollableDropdownComp.model.value).toEqual(modelValue); }); }); }); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.ts index 5eda1372eb..f6442407c4 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.ts @@ -2,7 +2,7 @@ import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } fro import { FormGroup } from '@angular/forms'; import { Observable, of as observableOf } from 'rxjs'; -import { catchError, distinctUntilChanged, first, tap } from 'rxjs/operators'; +import { catchError, distinctUntilChanged, tap } from 'rxjs/operators'; import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap'; import { DynamicFormControlComponent, @@ -10,13 +10,14 @@ import { DynamicFormValidationService } from '@ng-dynamic-forms/core'; -import { AuthorityValue } from '../../../../../../core/integration/models/authority.value'; +import { VocabularyEntry } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry.model'; import { DynamicScrollableDropdownModel } from './dynamic-scrollable-dropdown.model'; import { PageInfo } from '../../../../../../core/shared/page-info.model'; import { isNull, isUndefined } from '../../../../../empty.util'; -import { AuthorityService } from '../../../../../../core/integration/authority.service'; -import { IntegrationSearchOptions } from '../../../../../../core/integration/models/integration-options.model'; -import { IntegrationData } from '../../../../../../core/integration/integration-data'; +import { VocabularyService } from '../../../../../../core/submission/vocabularies/vocabulary.service'; +import { VocabularyFindOptions } from '../../../../../../core/submission/vocabularies/models/vocabulary-find-options.model'; +import { getFirstSucceededRemoteDataPayload } from '../../../../../../core/shared/operators'; +import { PaginatedList } from '../../../../../../core/data/paginated-list'; @Component({ selector: 'ds-dynamic-scrollable-dropdown', @@ -37,9 +38,9 @@ export class DsDynamicScrollableDropdownComponent extends DynamicFormControlComp public pageInfo: PageInfo; public optionsList: any; - protected searchOptions: IntegrationSearchOptions; + protected searchOptions: VocabularyFindOptions; - constructor(private authorityService: AuthorityService, + constructor(private vocabularyService: VocabularyService, private cdr: ChangeDetectorRef, protected layoutService: DynamicFormLayoutService, protected validationService: DynamicFormValidationService @@ -48,28 +49,26 @@ export class DsDynamicScrollableDropdownComponent extends DynamicFormControlComp } ngOnInit() { - this.searchOptions = new IntegrationSearchOptions( - this.model.authorityOptions.scope, - this.model.authorityOptions.name, - this.model.authorityOptions.metadata, + this.searchOptions = new VocabularyFindOptions( + this.model.vocabularyOptions.scope, + this.model.vocabularyOptions.name, + this.model.vocabularyOptions.metadata, '', this.model.maxOptions, 1); - this.authorityService.getEntriesByName(this.searchOptions).pipe( - catchError(() => { - const emptyResult = new IntegrationData( - new PageInfo(), - [] - ); - return observableOf(emptyResult); - }), - first()) - .subscribe((object: IntegrationData) => { - this.optionsList = object.payload; + this.vocabularyService.getVocabularyEntries(this.searchOptions).pipe( + getFirstSucceededRemoteDataPayload(), + catchError(() => observableOf(new PaginatedList( + new PageInfo(), + [] + )) + )) + .subscribe((list: PaginatedList) => { + this.optionsList = list.page; if (this.model.value) { this.setCurrentValue(this.model.value); } - this.pageInfo = object.pageInfo; + this.pageInfo = list.pageInfo; this.cdr.detectChanges(); }); @@ -80,7 +79,7 @@ export class DsDynamicScrollableDropdownComponent extends DynamicFormControlComp } - inputFormatter = (x: AuthorityValue): string => x.display || x.value; + inputFormatter = (x: VocabularyEntry): string => x.display || x.value; openDropdown(sdRef: NgbDropdown) { if (!this.model.readOnly) { @@ -92,18 +91,17 @@ export class DsDynamicScrollableDropdownComponent extends DynamicFormControlComp if (!this.loading && this.pageInfo.currentPage <= this.pageInfo.totalPages) { this.loading = true; this.searchOptions.currentPage++; - this.authorityService.getEntriesByName(this.searchOptions).pipe( - catchError(() => { - const emptyResult = new IntegrationData( - new PageInfo(), - [] - ); - return observableOf(emptyResult); - }), + this.vocabularyService.getVocabularyEntries(this.searchOptions).pipe( + getFirstSucceededRemoteDataPayload(), + catchError(() => observableOf(new PaginatedList( + new PageInfo(), + [] + )) + ), tap(() => this.loading = false)) - .subscribe((object: IntegrationData) => { - this.optionsList = this.optionsList.concat(object.payload); - this.pageInfo = object.pageInfo; + .subscribe((list: PaginatedList) => { + this.optionsList = this.optionsList.concat(list.page); + this.pageInfo = list.pageInfo; this.cdr.detectChanges(); }) } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.model.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.model.ts index 8ab497ec6e..a9974717e4 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.model.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.model.ts @@ -1,11 +1,11 @@ import { AUTOCOMPLETE_OFF, DynamicFormControlLayout, serializable } from '@ng-dynamic-forms/core'; import { DsDynamicInputModel, DsDynamicInputModelConfig } from '../ds-dynamic-input.model'; -import { AuthorityOptions } from '../../../../../../core/integration/models/authority-options.model'; +import { VocabularyOptions } from '../../../../../../core/submission/vocabularies/models/vocabulary-options.model'; export const DYNAMIC_FORM_CONTROL_TYPE_SCROLLABLE_DROPDOWN = 'SCROLLABLE_DROPDOWN'; export interface DynamicScrollableDropdownModelConfig extends DsDynamicInputModelConfig { - authorityOptions: AuthorityOptions; + vocabularyOptions: VocabularyOptions; maxOptions?: number; value?: any; } @@ -20,7 +20,7 @@ export class DynamicScrollableDropdownModel extends DsDynamicInputModel { super(config, layout); this.autoComplete = AUTOCOMPLETE_OFF; - this.authorityOptions = config.authorityOptions; + this.vocabularyOptions = config.vocabularyOptions; this.maxOptions = config.maxOptions || 10; } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.spec.ts index 79d652623f..a85c215b5f 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.spec.ts @@ -12,15 +12,14 @@ import { import { DynamicFormsNGBootstrapUIModule } from '@ng-dynamic-forms/ui-ng-bootstrap'; import { NgbModule, NgbTypeaheadSelectItemEvent } from '@ng-bootstrap/ng-bootstrap'; -import { AuthorityOptions } from '../../../../../../core/integration/models/authority-options.model'; -import { AuthorityService } from '../../../../../../core/integration/authority.service'; -import { AuthorityServiceStub } from '../../../../../testing/authority-service.stub'; +import { VocabularyOptions } from '../../../../../../core/submission/vocabularies/models/vocabulary-options.model'; +import { VocabularyService } from '../../../../../../core/submission/vocabularies/vocabulary.service'; +import { VocabularyServiceStub } from '../../../../../testing/vocabulary-service.stub'; import { DsDynamicTagComponent } from './dynamic-tag.component'; import { DynamicTagModel } from './dynamic-tag.model'; -import { GlobalConfig } from '../../../../../../../config/global-config.interface'; import { Chips } from '../../../../../chips/models/chips.model'; import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model'; -import { AuthorityValue } from '../../../../../../core/integration/models/authority.value'; +import { VocabularyEntry } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry.model'; import { createTestComponent } from '../../../../../testing/utils.test'; function createKeyUpEvent(key: number) { @@ -45,12 +44,12 @@ function init() { }); TAG_TEST_MODEL_CONFIG = { - authorityOptions: { + vocabularyOptions: { closed: false, metadata: 'tag', name: 'common_iso_languages', scope: 'c1c16450-d56f-41bc-bb81-27f1d1eb5c23' - } as AuthorityOptions, + } as VocabularyOptions, disabled: false, id: 'tag', label: 'Keywords', @@ -75,7 +74,7 @@ describe('DsDynamicTagComponent test suite', () => { // async beforeEach beforeEach(async(() => { - const authorityServiceStub = new AuthorityServiceStub(); + const vocabularyServiceStub = new VocabularyServiceStub(); init(); TestBed.configureTestingModule({ imports: [ @@ -92,7 +91,7 @@ describe('DsDynamicTagComponent test suite', () => { providers: [ ChangeDetectorRef, DsDynamicTagComponent, - { provide: AuthorityService, useValue: authorityServiceStub }, + { provide: VocabularyService, useValue: vocabularyServiceStub }, { provide: DynamicFormLayoutService, useValue: {} }, { provide: DynamicFormValidationService, useValue: {} } ], @@ -124,7 +123,7 @@ describe('DsDynamicTagComponent test suite', () => { })); }); - describe('when authorityOptions are set', () => { + describe('when vocabularyOptions are set', () => { describe('and init model value is empty', () => { beforeEach(() => { @@ -148,20 +147,20 @@ describe('DsDynamicTagComponent test suite', () => { }); it('should search when 3+ characters typed', fakeAsync(() => { - spyOn((tagComp as any).authorityService, 'getEntriesByName').and.callThrough(); + spyOn((tagComp as any).vocabularyService, 'getVocabularyEntries').and.callThrough(); tagComp.search(observableOf('test')).subscribe(() => { - expect((tagComp as any).authorityService.getEntriesByName).toHaveBeenCalled(); + expect((tagComp as any).vocabularyService.getVocabularyEntries).toHaveBeenCalled(); }); })); it('should select a results entry properly', fakeAsync(() => { modelValue = [ - Object.assign(new AuthorityValue(), { id: 1, display: 'Name, Lastname', value: 1 }) + Object.assign(new VocabularyEntry(), { authority: 1, display: 'Name, Lastname', value: 1 }) ]; const event: NgbTypeaheadSelectItemEvent = { - item: Object.assign(new AuthorityValue(), { - id: 1, + item: Object.assign(new VocabularyEntry(), { + authority: 1, display: 'Name, Lastname', value: 1 }), @@ -239,7 +238,7 @@ describe('DsDynamicTagComponent test suite', () => { }); - describe('when authorityOptions are not set', () => { + describe('when vocabularyOptions are not set', () => { describe('and init model value is empty', () => { beforeEach(() => { @@ -247,7 +246,7 @@ describe('DsDynamicTagComponent test suite', () => { tagComp = tagFixture.componentInstance; // FormComponent test instance tagComp.group = TAG_TEST_GROUP; const config = TAG_TEST_MODEL_CONFIG; - config.authorityOptions = null; + config.vocabularyOptions = null; tagComp.model = new DynamicTagModel(config); tagFixture.detectChanges(); }); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.ts index 69a7a5a8c2..85d791da6d 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectorRef, Component, EventEmitter, Inject, Input, OnInit, Output, ViewChild } from '@angular/core'; +import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { @@ -6,17 +6,21 @@ import { DynamicFormLayoutService, DynamicFormValidationService } from '@ng-dynamic-forms/core'; -import { of as observableOf, Observable } from 'rxjs'; -import { catchError, debounceTime, distinctUntilChanged, tap, switchMap, map, merge } from 'rxjs/operators'; +import { Observable, of as observableOf } from 'rxjs'; +import { catchError, debounceTime, distinctUntilChanged, map, merge, switchMap, tap } from 'rxjs/operators'; import { NgbTypeahead, NgbTypeaheadSelectItemEvent } from '@ng-bootstrap/ng-bootstrap'; import { isEqual } from 'lodash'; -import { AuthorityService } from '../../../../../../core/integration/authority.service'; +import { VocabularyService } from '../../../../../../core/submission/vocabularies/vocabulary.service'; import { DynamicTagModel } from './dynamic-tag.model'; -import { IntegrationSearchOptions } from '../../../../../../core/integration/models/integration-options.model'; +import { VocabularyFindOptions } from '../../../../../../core/submission/vocabularies/models/vocabulary-find-options.model'; import { Chips } from '../../../../../chips/models/chips.model'; import { hasValue, isNotEmpty } from '../../../../../empty.util'; import { environment } from '../../../../../../../environments/environment'; +import { getFirstSucceededRemoteDataPayload } from '../../../../../../core/shared/operators'; +import { PaginatedList } from '../../../../../../core/data/paginated-list'; +import { VocabularyEntry } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry.model'; +import { PageInfo } from '../../../../../../core/shared/page-info.model'; @Component({ selector: 'ds-dynamic-tag', @@ -32,17 +36,25 @@ export class DsDynamicTagComponent extends DynamicFormControlComponent implement @Output() change: EventEmitter = new EventEmitter(); @Output() focus: EventEmitter = new EventEmitter(); - @ViewChild('instance', {static: false}) instance: NgbTypeahead; + @ViewChild('instance', { static: false }) instance: NgbTypeahead; chips: Chips; hasAuthority: boolean; searching = false; - searchOptions: IntegrationSearchOptions; + searchOptions: VocabularyFindOptions; searchFailed = false; hideSearchingWhenUnsubscribed = new Observable(() => () => this.changeSearchingStatus(false)); currentValue: any; + constructor(private vocabularyService: VocabularyService, + private cdr: ChangeDetectorRef, + protected layoutService: DynamicFormLayoutService, + protected validationService: DynamicFormValidationService + ) { + super(layoutService, validationService); + } + formatter = (x: { display: string }) => x.display; search = (text$: Observable) => @@ -52,44 +64,33 @@ export class DsDynamicTagComponent extends DynamicFormControlComponent implement tap(() => this.changeSearchingStatus(true)), switchMap((term) => { if (term === '' || term.length < this.model.minChars) { - return observableOf({list: []}); + return observableOf({ list: [] }); } else { this.searchOptions.query = term; - return this.authorityService.getEntriesByName(this.searchOptions).pipe( - map((authorities) => { - // @TODO Pagination for authority is not working, to refactor when it will be fixed - return { - list: authorities.payload, - pageInfo: authorities.pageInfo - }; - }), + return this.vocabularyService.getVocabularyEntries(this.searchOptions).pipe( + getFirstSucceededRemoteDataPayload(), tap(() => this.searchFailed = false), catchError(() => { this.searchFailed = true; - return observableOf({list: []}); + return observableOf(new PaginatedList( + new PageInfo(), + [] + )); })); } }), - map((results) => results.list), + map((list: PaginatedList) => list.page), tap(() => this.changeSearchingStatus(false)), merge(this.hideSearchingWhenUnsubscribed)); - constructor(private authorityService: AuthorityService, - private cdr: ChangeDetectorRef, - protected layoutService: DynamicFormLayoutService, - protected validationService: DynamicFormValidationService - ) { - super(layoutService, validationService); - } - ngOnInit() { - this.hasAuthority = this.model.authorityOptions && hasValue(this.model.authorityOptions.name); + this.hasAuthority = this.model.vocabularyOptions && hasValue(this.model.vocabularyOptions.name); if (this.hasAuthority) { - this.searchOptions = new IntegrationSearchOptions( - this.model.authorityOptions.scope, - this.model.authorityOptions.name, - this.model.authorityOptions.metadata); + this.searchOptions = new VocabularyFindOptions( + this.model.vocabularyOptions.scope, + this.model.vocabularyOptions.name, + this.model.vocabularyOptions.metadata); } this.chips = new Chips( @@ -166,7 +167,7 @@ export class DsDynamicTagComponent extends DynamicFormControlComponent implement } private addTagsToChips() { - if (hasValue(this.currentValue) && (!this.hasAuthority || !this.model.authorityOptions.closed)) { + if (hasValue(this.currentValue) && (!this.hasAuthority || !this.model.vocabularyOptions.closed)) { let res: string[] = []; res = this.currentValue.split(','); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.spec.ts index f31f0eeff9..48456230bf 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.spec.ts @@ -10,10 +10,9 @@ import { DynamicFormLayoutService, DynamicFormsCoreModule, DynamicFormValidation import { DynamicFormsNGBootstrapUIModule } from '@ng-dynamic-forms/ui-ng-bootstrap'; import { TranslateModule } from '@ngx-translate/core'; -import { AuthorityOptions } from '../../../../../../core/integration/models/authority-options.model'; -import { AuthorityService } from '../../../../../../core/integration/authority.service'; -import { AuthorityServiceStub } from '../../../../../testing/authority-service.stub'; -import { GlobalConfig } from '../../../../../../../config/global-config.interface'; +import { VocabularyOptions } from '../../../../../../core/submission/vocabularies/models/vocabulary-options.model'; +import { VocabularyService } from '../../../../../../core/submission/vocabularies/vocabulary.service'; +import { VocabularyServiceStub } from '../../../../../testing/vocabulary-service.stub'; import { DsDynamicTypeaheadComponent } from './dynamic-typeahead.component'; import { DynamicTypeaheadModel } from './dynamic-typeahead.model'; import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model'; @@ -31,12 +30,12 @@ function init() { }); TYPEAHEAD_TEST_MODEL_CONFIG = { - authorityOptions: { + vocabularyOptions: { closed: false, metadata: 'typeahead', name: 'EVENTAuthority', scope: 'c1c16450-d56f-41bc-bb81-27f1d1eb5c23' - } as AuthorityOptions, + } as VocabularyOptions, disabled: false, id: 'typeahead', label: 'Conference', @@ -49,6 +48,7 @@ function init() { value: undefined }; } + describe('DsDynamicTypeaheadComponent test suite', () => { let testComp: TestComponent; @@ -59,7 +59,7 @@ describe('DsDynamicTypeaheadComponent test suite', () => { // async beforeEach beforeEach(async(() => { - const authorityServiceStub = new AuthorityServiceStub(); + const vocabularyServiceStub = new VocabularyServiceStub(); init(); TestBed.configureTestingModule({ imports: [ @@ -79,7 +79,7 @@ describe('DsDynamicTypeaheadComponent test suite', () => { providers: [ ChangeDetectorRef, DsDynamicTypeaheadComponent, - { provide: AuthorityService, useValue: authorityServiceStub }, + { provide: VocabularyService, useValue: vocabularyServiceStub }, { provide: DynamicFormLayoutService, useValue: {} }, { provide: DynamicFormValidationService, useValue: {} } ], @@ -134,17 +134,17 @@ describe('DsDynamicTypeaheadComponent test suite', () => { it('should search when 3+ characters typed', fakeAsync(() => { - spyOn((typeaheadComp as any).authorityService, 'getEntriesByName').and.callThrough(); + spyOn((typeaheadComp as any).vocabularyService, 'getVocabularyEntries').and.callThrough(); typeaheadComp.search(observableOf('test')).subscribe(); tick(300); typeaheadFixture.detectChanges(); - expect((typeaheadComp as any).authorityService.getEntriesByName).toHaveBeenCalled(); + expect((typeaheadComp as any).vocabularyService.getVocabularyEntries).toHaveBeenCalled(); })); - it('should set model.value on input type when AuthorityOptions.closed is false', () => { + it('should set model.value on input type when VocabularyOptions.closed is false', () => { const inputDe = typeaheadFixture.debugElement.query(By.css('input.form-control')); const inputElement = inputDe.nativeElement; @@ -155,8 +155,8 @@ describe('DsDynamicTypeaheadComponent test suite', () => { }); - it('should not set model.value on input type when AuthorityOptions.closed is true', () => { - typeaheadComp.model.authorityOptions.closed = true; + it('should not set model.value on input type when VocabularyOptions.closed is true', () => { + typeaheadComp.model.vocabularyOptions.closed = true; typeaheadFixture.detectChanges(); const inputDe = typeaheadFixture.debugElement.query(By.css('input.form-control')); const inputElement = inputDe.nativeElement; @@ -184,18 +184,18 @@ describe('DsDynamicTypeaheadComponent test suite', () => { expect(typeaheadComp.blur.emit).not.toHaveBeenCalled(); }); - it('should emit change Event onBlur when AuthorityOptions.closed is false and inputValue is changed', () => { + it('should emit change Event onBlur when VocabularyOptions.closed is false and inputValue is changed', () => { typeaheadComp.inputValue = 'test value'; typeaheadFixture.detectChanges(); spyOn(typeaheadComp.blur, 'emit'); spyOn(typeaheadComp.change, 'emit'); spyOn(typeaheadComp.instance, 'isPopupOpen').and.returnValue(false); - typeaheadComp.onBlur(new Event('blur', )); + typeaheadComp.onBlur(new Event('blur',)); expect(typeaheadComp.change.emit).toHaveBeenCalled(); expect(typeaheadComp.blur.emit).toHaveBeenCalled(); }); - it('should not emit change Event onBlur when AuthorityOptions.closed is false and inputValue is not changed', () => { + it('should not emit change Event onBlur when VocabularyOptions.closed is false and inputValue is not changed', () => { typeaheadComp.inputValue = 'test value'; typeaheadComp.model = new DynamicTypeaheadModel(TYPEAHEAD_TEST_MODEL_CONFIG); (typeaheadComp.model as any).value = 'test value'; @@ -203,12 +203,12 @@ describe('DsDynamicTypeaheadComponent test suite', () => { spyOn(typeaheadComp.blur, 'emit'); spyOn(typeaheadComp.change, 'emit'); spyOn(typeaheadComp.instance, 'isPopupOpen').and.returnValue(false); - typeaheadComp.onBlur(new Event('blur', )); + typeaheadComp.onBlur(new Event('blur',)); expect(typeaheadComp.change.emit).not.toHaveBeenCalled(); expect(typeaheadComp.blur.emit).toHaveBeenCalled(); }); - it('should not emit change Event onBlur when AuthorityOptions.closed is false and inputValue is null', () => { + it('should not emit change Event onBlur when VocabularyOptions.closed is false and inputValue is null', () => { typeaheadComp.inputValue = null; typeaheadComp.model = new DynamicTypeaheadModel(TYPEAHEAD_TEST_MODEL_CONFIG); (typeaheadComp.model as any).value = 'test value'; @@ -216,7 +216,7 @@ describe('DsDynamicTypeaheadComponent test suite', () => { spyOn(typeaheadComp.blur, 'emit'); spyOn(typeaheadComp.change, 'emit'); spyOn(typeaheadComp.instance, 'isPopupOpen').and.returnValue(false); - typeaheadComp.onBlur(new Event('blur', )); + typeaheadComp.onBlur(new Event('blur',)); expect(typeaheadComp.change.emit).not.toHaveBeenCalled(); expect(typeaheadComp.blur.emit).toHaveBeenCalled(); }); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.ts index 791704a7ca..67030682a5 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.ts @@ -10,12 +10,16 @@ import { catchError, debounceTime, distinctUntilChanged, filter, map, merge, swi import { Observable, of as observableOf, Subject } from 'rxjs'; import { NgbTypeahead, NgbTypeaheadSelectItemEvent } from '@ng-bootstrap/ng-bootstrap'; -import { AuthorityService } from '../../../../../../core/integration/authority.service'; +import { VocabularyService } from '../../../../../../core/submission/vocabularies/vocabulary.service'; import { DynamicTypeaheadModel } from './dynamic-typeahead.model'; -import { IntegrationSearchOptions } from '../../../../../../core/integration/models/integration-options.model'; +import { VocabularyFindOptions } from '../../../../../../core/submission/vocabularies/models/vocabulary-find-options.model'; import { isEmpty, isNotEmpty, isNotNull } from '../../../../../empty.util'; import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model'; -import { ConfidenceType } from '../../../../../../core/integration/models/confidence-type'; +import { ConfidenceType } from '../../../../../../core/shared/confidence-type'; +import { getFirstSucceededRemoteDataPayload } from '../../../../../../core/shared/operators'; +import { PaginatedList } from '../../../../../../core/data/paginated-list'; +import { VocabularyEntry } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry.model'; +import { PageInfo } from '../../../../../../core/shared/page-info.model'; @Component({ selector: 'ds-dynamic-typeahead', @@ -31,16 +35,24 @@ export class DsDynamicTypeaheadComponent extends DynamicFormControlComponent imp @Output() change: EventEmitter = new EventEmitter(); @Output() focus: EventEmitter = new EventEmitter(); - @ViewChild('instance', {static: false}) instance: NgbTypeahead; + @ViewChild('instance', { static: false }) instance: NgbTypeahead; searching = false; - searchOptions: IntegrationSearchOptions; + searchOptions: VocabularyFindOptions; searchFailed = false; hideSearchingWhenUnsubscribed$ = new Observable(() => () => this.changeSearchingStatus(false)); click$ = new Subject(); currentValue: any; inputValue: any; + constructor(private vocabularyService: VocabularyService, + private cdr: ChangeDetectorRef, + protected layoutService: DynamicFormLayoutService, + protected validationService: DynamicFormValidationService + ) { + super(layoutService, validationService); + } + formatter = (x: { display: string }) => { return (typeof x === 'object') ? x.display : x }; @@ -53,44 +65,33 @@ export class DsDynamicTypeaheadComponent extends DynamicFormControlComponent imp tap(() => this.changeSearchingStatus(true)), switchMap((term) => { if (term === '' || term.length < this.model.minChars) { - return observableOf({list: []}); + return observableOf({ list: [] }); } else { this.searchOptions.query = term; - return this.authorityService.getEntriesByName(this.searchOptions).pipe( - map((authorities) => { - // @TODO Pagination for authority is not working, to refactor when it will be fixed - return { - list: authorities.payload, - pageInfo: authorities.pageInfo - }; - }), + return this.vocabularyService.getVocabularyEntries(this.searchOptions).pipe( + getFirstSucceededRemoteDataPayload(), tap(() => this.searchFailed = false), catchError(() => { this.searchFailed = true; - return observableOf({list: []}); + return observableOf(new PaginatedList( + new PageInfo(), + [] + )); })); } }), - map((results) => results.list), + map((list: PaginatedList) => list.page), tap(() => this.changeSearchingStatus(false)), merge(this.hideSearchingWhenUnsubscribed$) ) }; - constructor(private authorityService: AuthorityService, - private cdr: ChangeDetectorRef, - protected layoutService: DynamicFormLayoutService, - protected validationService: DynamicFormValidationService - ) { - super(layoutService, validationService); - } - ngOnInit() { this.currentValue = this.model.value; - this.searchOptions = new IntegrationSearchOptions( - this.model.authorityOptions.scope, - this.model.authorityOptions.name, - this.model.authorityOptions.metadata); + this.searchOptions = new VocabularyFindOptions( + this.model.vocabularyOptions.scope, + this.model.vocabularyOptions.name, + this.model.vocabularyOptions.metadata); this.group.get(this.model.id).valueChanges.pipe( filter((value) => this.currentValue !== value)) .subscribe((value) => { @@ -104,14 +105,14 @@ export class DsDynamicTypeaheadComponent extends DynamicFormControlComponent imp } onInput(event) { - if (!this.model.authorityOptions.closed && isNotEmpty(event.target.value)) { + if (!this.model.vocabularyOptions.closed && isNotEmpty(event.target.value)) { this.inputValue = new FormFieldMetadataValueObject(event.target.value); } } onBlur(event: Event) { if (!this.instance.isPopupOpen()) { - if (!this.model.authorityOptions.closed && isNotEmpty(this.inputValue)) { + if (!this.model.vocabularyOptions.closed && isNotEmpty(this.inputValue)) { if (isNotNull(this.inputValue) && this.model.value !== this.inputValue) { this.model.valueUpdates.next(this.inputValue); this.change.emit(this.inputValue); diff --git a/src/app/shared/form/builder/form-builder.service.spec.ts b/src/app/shared/form/builder/form-builder.service.spec.ts index 972abb68b5..434fe6a2e1 100644 --- a/src/app/shared/form/builder/form-builder.service.spec.ts +++ b/src/app/shared/form/builder/form-builder.service.spec.ts @@ -36,7 +36,7 @@ import { DynamicLookupModel } from './ds-dynamic-form-ui/models/lookup/dynamic-l import { DynamicDsDatePickerModel } from './ds-dynamic-form-ui/models/date-picker/date-picker.model'; import { DynamicTypeaheadModel } from './ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.model'; import { DynamicListRadioGroupModel } from './ds-dynamic-form-ui/models/list/dynamic-list-radio-group.model'; -import { AuthorityOptions } from '../../../core/integration/models/authority-options.model'; +import { VocabularyOptions } from '../../../core/submission/vocabularies/models/vocabulary-options.model'; import { FormFieldModel } from './models/form-field.model'; import { SubmissionFormsModel @@ -78,7 +78,7 @@ describe('FormBuilderService test suite', () => { ] }); - const authorityOptions: AuthorityOptions = { + const vocabularyOptions: VocabularyOptions = { closed: false, metadata: 'list', name: 'type_programme', @@ -197,13 +197,13 @@ describe('FormBuilderService test suite', () => { new DynamicTypeaheadModel({id: 'testTypeahead', repeatable: false, metadataFields: [], submissionId: '1234'}), - new DynamicScrollableDropdownModel({id: 'testScrollableDropdown', authorityOptions: authorityOptions, repeatable: false, metadataFields: [], submissionId: '1234'}), + new DynamicScrollableDropdownModel({id: 'testScrollableDropdown', vocabularyOptions: vocabularyOptions, repeatable: false, metadataFields: [], submissionId: '1234'}), new DynamicTagModel({id: 'testTag', repeatable: false, metadataFields: [], submissionId: '1234'}), - new DynamicListCheckboxGroupModel({id: 'testCheckboxList', authorityOptions: authorityOptions, repeatable: true}), + new DynamicListCheckboxGroupModel({id: 'testCheckboxList', vocabularyOptions: vocabularyOptions, repeatable: true}), - new DynamicListRadioGroupModel({id: 'testRadioList', authorityOptions: authorityOptions, repeatable: false}), + new DynamicListRadioGroupModel({id: 'testRadioList', vocabularyOptions: vocabularyOptions, repeatable: false}), new DynamicRelationGroupModel({ submissionId, @@ -218,7 +218,7 @@ describe('FormBuilderService test suite', () => { mandatoryMessage: 'Required field!', repeatable: false, selectableMetadata: [{ - authority: 'RPAuthority', + controlledVocabulary: 'RPAuthority', closed: false, metadata: 'dc.contributor.author' }], @@ -232,7 +232,7 @@ describe('FormBuilderService test suite', () => { mandatory: 'false', repeatable: false, selectableMetadata: [{ - authority: 'OUAuthority', + controlledVocabulary: 'OUAuthority', closed: false, metadata: 'local.contributor.affiliation' }] @@ -284,7 +284,7 @@ describe('FormBuilderService test suite', () => { selectableMetadata: [ { metadata: 'journal', - authority: 'JOURNALAuthority', + controlledVocabulary: 'JOURNALAuthority', closed: false } ], @@ -364,7 +364,7 @@ describe('FormBuilderService test suite', () => { selectableMetadata: [ { metadata: 'conference', - authority: 'EVENTAuthority', + controlledVocabulary: 'EVENTAuthority', closed: false } ], diff --git a/src/app/shared/form/builder/models/form-field-metadata-value.model.ts b/src/app/shared/form/builder/models/form-field-metadata-value.model.ts index 45489e3618..ff0afe97fd 100644 --- a/src/app/shared/form/builder/models/form-field-metadata-value.model.ts +++ b/src/app/shared/form/builder/models/form-field-metadata-value.model.ts @@ -1,5 +1,5 @@ import { isEmpty, isNotEmpty, isNotNull } from '../../../empty.util'; -import { ConfidenceType } from '../../../../core/integration/models/confidence-type'; +import { ConfidenceType } from '../../../../core/shared/confidence-type'; import { PLACEHOLDER_PARENT_METADATA } from '../ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.model'; import { MetadataValueInterface } from '../../../../core/shared/metadata.models'; @@ -7,15 +7,16 @@ export interface OtherInformation { [name: string]: string } +/** + * A class representing a specific input-form field's value + */ export class FormFieldMetadataValueObject implements MetadataValueInterface { - metadata?: string; value: any; display: string; language: any; authority: string; confidence: ConfidenceType; place: number; - closed: boolean; label: string; otherInformation: OtherInformation; @@ -42,9 +43,6 @@ export class FormFieldMetadataValueObject implements MetadataValueInterface { } this.place = place; - if (isNotEmpty(metadata)) { - this.metadata = metadata; - } this.otherInformation = otherInformation; } diff --git a/src/app/shared/form/builder/models/form-field.model.ts b/src/app/shared/form/builder/models/form-field.model.ts index 718b3f4f0d..95ee980aeb 100644 --- a/src/app/shared/form/builder/models/form-field.model.ts +++ b/src/app/shared/form/builder/models/form-field.model.ts @@ -1,50 +1,121 @@ import { autoserialize } from 'cerialize'; + import { LanguageCode } from './form-field-language-value.model'; -import { FormFieldMetadataValueObject } from './form-field-metadata-value.model'; import { RelationshipOptions } from './relationship-options.model'; import { FormRowModel } from '../../../../core/config/models/config-submission-form.model'; +/** + * Representing SelectableMetadata properties + */ +export interface SelectableMetadata { + /** + * The key of the metadata field to use to store the input + */ + metadata: string; + + /** + * The label of the metadata field to use to store the input + */ + label: string; + + /** + * The name of the controlled vocabulary used to retrieve value for the input see controlled vocabularies + */ + controlledVocabulary: string; + + /** + * A boolean representing if value is closely related to the controlled vocabulary entry or not + */ + closed: boolean; +} + +/** + * A class representing a specific input-form field + */ export class FormFieldModel { + /** + * The hints for this metadata field to display on form + */ @autoserialize hints: string; + /** + * The label for this metadata field to display on form + */ @autoserialize label: string; + /** + * The languages available for this metadata field to display on form + */ @autoserialize languageCodes: LanguageCode[]; + /** + * The error message for this metadata field to display on form in case of field is required + */ @autoserialize mandatoryMessage: string; + /** + * Representing if this metadata field is mandatory or not + */ @autoserialize mandatory: string; + /** + * Representing if this metadata field is repeatable or not + */ @autoserialize repeatable: boolean; + /** + * Containing additional properties for this metadata field + */ @autoserialize input: { + /** + * Representing the type for this metadata field + */ type: string; + + /** + * Containing regex to use for field validation + */ regex?: string; }; + /** + * Representing additional vocabulary configuration for this metadata field + */ @autoserialize - selectableMetadata: FormFieldMetadataValueObject[]; + selectableMetadata: SelectableMetadata[]; + /** + * Representing additional relationship configuration for this metadata field + */ @autoserialize selectableRelationship: RelationshipOptions; @autoserialize rows: FormRowModel[]; + /** + * Representing the scope for this metadata field + */ @autoserialize scope: string; + /** + * Containing additional css classes for this metadata field to use on form + */ @autoserialize style: string; + /** + * Containing the value for this metadata field + */ @autoserialize value: any; } diff --git a/src/app/shared/form/builder/parsers/date-field-parser.spec.ts b/src/app/shared/form/builder/parsers/date-field-parser.spec.ts index efa4f3cdb5..b9adf3ed65 100644 --- a/src/app/shared/form/builder/parsers/date-field-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/date-field-parser.spec.ts @@ -12,7 +12,7 @@ describe('DateFieldParser test suite', () => { const parserOptions: ParserOptions = { readOnly: false, submissionScope: null, - authorityUuid: null + collectionUUID: null }; beforeEach(() => { diff --git a/src/app/shared/form/builder/parsers/disabled-field-parser.spec.ts b/src/app/shared/form/builder/parsers/disabled-field-parser.spec.ts index c885b737c2..e7e64feb7b 100644 --- a/src/app/shared/form/builder/parsers/disabled-field-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/disabled-field-parser.spec.ts @@ -12,7 +12,7 @@ describe('DisabledFieldParser test suite', () => { const parserOptions: ParserOptions = { readOnly: false, submissionScope: null, - authorityUuid: null + collectionUUID: null }; beforeEach(() => { diff --git a/src/app/shared/form/builder/parsers/dropdown-field-parser.spec.ts b/src/app/shared/form/builder/parsers/dropdown-field-parser.spec.ts index 8dbd68e05a..82d2aeac63 100644 --- a/src/app/shared/form/builder/parsers/dropdown-field-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/dropdown-field-parser.spec.ts @@ -11,7 +11,7 @@ describe('DropdownFieldParser test suite', () => { const parserOptions: ParserOptions = { readOnly: false, submissionScope: 'testScopeUUID', - authorityUuid: null + collectionUUID: null }; beforeEach(() => { @@ -26,7 +26,7 @@ describe('DropdownFieldParser test suite', () => { selectableMetadata: [ { metadata: 'type', - authority: 'common_types_dataset', + controlledVocabulary: 'common_types_dataset', closed: false } ], @@ -50,7 +50,7 @@ describe('DropdownFieldParser test suite', () => { }); it('should throw when authority is not passed', () => { - field.selectableMetadata[0].authority = null; + field.selectableMetadata[0].controlledVocabulary = null; const parser = new DropdownFieldParser(submissionId, field, initFormValues, parserOptions); expect(() => parser.parse()) diff --git a/src/app/shared/form/builder/parsers/dropdown-field-parser.ts b/src/app/shared/form/builder/parsers/dropdown-field-parser.ts index 4816a2a073..7fb5fb206c 100644 --- a/src/app/shared/form/builder/parsers/dropdown-field-parser.ts +++ b/src/app/shared/form/builder/parsers/dropdown-field-parser.ts @@ -31,8 +31,8 @@ export class DropdownFieldParser extends FieldParser { const dropdownModelConfig: DynamicScrollableDropdownModelConfig = this.initModel(null, label); let layout: DynamicFormControlLayout; - if (isNotEmpty(this.configData.selectableMetadata[0].authority)) { - this.setAuthorityOptions(dropdownModelConfig, this.parserOptions.authorityUuid); + if (isNotEmpty(this.configData.selectableMetadata[0].controlledVocabulary)) { + this.setVocabularyOptions(dropdownModelConfig, this.parserOptions.collectionUUID); if (isNotEmpty(fieldValue)) { dropdownModelConfig.value = fieldValue; } @@ -47,7 +47,7 @@ export class DropdownFieldParser extends FieldParser { const dropdownModel = new DynamicScrollableDropdownModel(dropdownModelConfig, layout); return dropdownModel; } else { - throw Error(`Authority name is not available. Please check the form configuration file.`); + throw Error(`Controlled Vocabulary name is not available. Please check the form configuration file.`); } } } diff --git a/src/app/shared/form/builder/parsers/field-parser.ts b/src/app/shared/form/builder/parsers/field-parser.ts index f218d442e1..540c9c7b4e 100644 --- a/src/app/shared/form/builder/parsers/field-parser.ts +++ b/src/app/shared/form/builder/parsers/field-parser.ts @@ -1,19 +1,20 @@ import { Inject, InjectionToken } from '@angular/core'; -import { hasValue, isNotEmpty, isNotNull, isNotUndefined, isEmpty } from '../../../empty.util'; -import { FormFieldModel } from '../models/form-field.model'; import { uniqueId } from 'lodash'; +import { DynamicFormControlLayout } from '@ng-dynamic-forms/core'; + +import { hasValue, isEmpty, isNotEmpty, isNotNull, isNotUndefined } from '../../../empty.util'; +import { FormFieldModel } from '../models/form-field.model'; import { FormFieldMetadataValueObject } from '../models/form-field-metadata-value.model'; import { DynamicRowArrayModel, DynamicRowArrayModelConfig } from '../ds-dynamic-form-ui/models/ds-dynamic-row-array-model'; import { DsDynamicInputModel, DsDynamicInputModelConfig } from '../ds-dynamic-form-ui/models/ds-dynamic-input.model'; -import { DynamicFormControlLayout } from '@ng-dynamic-forms/core'; import { setLayout } from './parser.utils'; -import { AuthorityOptions } from '../../../../core/integration/models/authority-options.model'; import { ParserOptions } from './parser-options'; import { RelationshipOptions } from '../models/relationship-options.model'; +import { VocabularyOptions } from '../../../../core/submission/vocabularies/models/vocabulary-options.model'; export const SUBMISSION_ID: InjectionToken = new InjectionToken('submissionId'); export const CONFIG_DATA: InjectionToken = new InjectionToken('configData'); @@ -49,7 +50,7 @@ export abstract class FieldParser { label: this.configData.label, initialCount: this.getInitArrayIndex(), notRepeatable: !this.configData.repeatable, - required: JSON.parse( this.configData.mandatory), + required: JSON.parse(this.configData.mandatory), groupFactory: () => { let model; if ((arrayCounter === 0)) { @@ -92,6 +93,52 @@ export abstract class FieldParser { } } + public setVocabularyOptions(controlModel, scope) { + if (isNotEmpty(this.configData.selectableMetadata) && isNotEmpty(this.configData.selectableMetadata[0].controlledVocabulary)) { + controlModel.vocabularyOptions = new VocabularyOptions( + this.configData.selectableMetadata[0].controlledVocabulary, + this.configData.selectableMetadata[0].metadata, + scope, + this.configData.selectableMetadata[0].closed + ) + } + } + + public setValues(modelConfig: DsDynamicInputModelConfig, fieldValue: any, forceValueAsObj: boolean = false, groupModel?: boolean) { + if (isNotEmpty(fieldValue)) { + if (groupModel) { + // Array, values is an array + modelConfig.value = this.getInitGroupValues(); + if (Array.isArray(modelConfig.value) && modelConfig.value.length > 0 && modelConfig.value[0].language) { + // Array Item has language, ex. AuthorityModel + modelConfig.language = modelConfig.value[0].language; + } + return; + } + + if (typeof fieldValue === 'object') { + modelConfig.language = fieldValue.language; + if (forceValueAsObj) { + modelConfig.value = fieldValue; + } else { + modelConfig.value = fieldValue.value; + } + } else { + if (forceValueAsObj) { + // If value isn't an instance of FormFieldMetadataValueObject instantiate it + modelConfig.value = new FormFieldMetadataValueObject(fieldValue); + } else { + if (typeof fieldValue === 'string') { + // Case only string + modelConfig.value = fieldValue; + } + } + } + } + + return modelConfig; + } + protected getInitValueCount(index = 0, fieldId?): number { const fieldIds = fieldId || this.getAllFieldIds(); if (isNotEmpty(this.initFormValues) && isNotNull(fieldIds) && fieldIds.length === 1 && this.initFormValues.hasOwnProperty(fieldIds[0])) { @@ -135,7 +182,7 @@ export abstract class FieldParser { fieldIds.forEach((id) => { if (this.initFormValues.hasOwnProperty(id)) { const valueObj: FormFieldMetadataValueObject = Object.assign(new FormFieldMetadataValueObject(), this.initFormValues[id][innerIndex]); - valueObj.metadata = id; + // valueObj.metadata = id; // valueObj.value = this.initFormValues[id][innerIndex]; values.push(valueObj); } @@ -224,14 +271,6 @@ export abstract class FieldParser { if (this.configData.languageCodes && this.configData.languageCodes.length > 0) { (controlModel as DsDynamicInputModel).languageCodes = this.configData.languageCodes; } - /* (controlModel as DsDynamicInputModel).languageCodes = [{ - display: 'English', - code: 'en_US' - }, - { - display: 'Italian', - code: 'it_IT' - }];*/ return controlModel; } @@ -278,50 +317,4 @@ export abstract class FieldParser { } } - public setAuthorityOptions(controlModel, authorityUuid) { - if (isNotEmpty(this.configData.selectableMetadata) && isNotEmpty(this.configData.selectableMetadata[0].authority)) { - controlModel.authorityOptions = new AuthorityOptions( - this.configData.selectableMetadata[0].authority, - this.configData.selectableMetadata[0].metadata, - authorityUuid, - this.configData.selectableMetadata[0].closed - ) - } - } - - public setValues(modelConfig: DsDynamicInputModelConfig, fieldValue: any, forceValueAsObj: boolean = false, groupModel?: boolean) { - if (isNotEmpty(fieldValue)) { - if (groupModel) { - // Array, values is an array - modelConfig.value = this.getInitGroupValues(); - if (Array.isArray(modelConfig.value) && modelConfig.value.length > 0 && modelConfig.value[0].language) { - // Array Item has language, ex. AuthorityModel - modelConfig.language = modelConfig.value[0].language; - } - return; - } - - if (typeof fieldValue === 'object') { - modelConfig.language = fieldValue.language; - if (forceValueAsObj) { - modelConfig.value = fieldValue; - } else { - modelConfig.value = fieldValue.value; - } - } else { - if (forceValueAsObj) { - // If value isn't an instance of FormFieldMetadataValueObject instantiate it - modelConfig.value = new FormFieldMetadataValueObject(fieldValue); - } else { - if (typeof fieldValue === 'string') { - // Case only string - modelConfig.value = fieldValue; - } - } - } - } - - return modelConfig; - } - } diff --git a/src/app/shared/form/builder/parsers/list-field-parser.spec.ts b/src/app/shared/form/builder/parsers/list-field-parser.spec.ts index fab5ec3888..8a05b169fd 100644 --- a/src/app/shared/form/builder/parsers/list-field-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/list-field-parser.spec.ts @@ -13,7 +13,7 @@ describe('ListFieldParser test suite', () => { const parserOptions: ParserOptions = { readOnly: false, submissionScope: 'testScopeUUID', - authorityUuid: null + collectionUUID: null }; beforeEach(() => { @@ -28,7 +28,7 @@ describe('ListFieldParser test suite', () => { selectableMetadata: [ { metadata: 'type', - authority: 'type_programme', + controlledVocabulary: 'type_programme', closed: false } ], diff --git a/src/app/shared/form/builder/parsers/list-field-parser.ts b/src/app/shared/form/builder/parsers/list-field-parser.ts index 273c9d1665..d3c158f4b8 100644 --- a/src/app/shared/form/builder/parsers/list-field-parser.ts +++ b/src/app/shared/form/builder/parsers/list-field-parser.ts @@ -1,19 +1,19 @@ import { FieldParser } from './field-parser'; import { isNotEmpty } from '../../../empty.util'; -import { IntegrationSearchOptions } from '../../../../core/integration/models/integration-options.model'; +import { VocabularyFindOptions } from '../../../../core/submission/vocabularies/models/vocabulary-find-options.model'; import { FormFieldMetadataValueObject } from '../models/form-field-metadata-value.model'; import { DynamicListCheckboxGroupModel } from '../ds-dynamic-form-ui/models/list/dynamic-list-checkbox-group.model'; import { DynamicListRadioGroupModel } from '../ds-dynamic-form-ui/models/list/dynamic-list-radio-group.model'; export class ListFieldParser extends FieldParser { - searchOptions: IntegrationSearchOptions; + searchOptions: VocabularyFindOptions; public modelFactory(fieldValue?: FormFieldMetadataValueObject | any, label?: boolean): any { const listModelConfig = this.initModel(null, label); listModelConfig.repeatable = this.configData.repeatable; - if (this.configData.selectableMetadata[0].authority - && this.configData.selectableMetadata[0].authority.length > 0) { + if (this.configData.selectableMetadata[0].controlledVocabulary + && this.configData.selectableMetadata[0].controlledVocabulary.length > 0) { if (isNotEmpty(this.getInitGroupValues())) { listModelConfig.value = []; @@ -26,7 +26,7 @@ export class ListFieldParser extends FieldParser { } }); } - this.setAuthorityOptions(listModelConfig, this.parserOptions.authorityUuid); + this.setVocabularyOptions(listModelConfig, this.parserOptions.collectionUUID); } let listModel; diff --git a/src/app/shared/form/builder/parsers/lookup-field-parser.spec.ts b/src/app/shared/form/builder/parsers/lookup-field-parser.spec.ts index 5e14e0c013..87cee9d950 100644 --- a/src/app/shared/form/builder/parsers/lookup-field-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/lookup-field-parser.spec.ts @@ -12,7 +12,7 @@ describe('LookupFieldParser test suite', () => { const parserOptions: ParserOptions = { readOnly: false, submissionScope: 'testScopeUUID', - authorityUuid: null + collectionUUID: null }; beforeEach(() => { @@ -27,7 +27,7 @@ describe('LookupFieldParser test suite', () => { selectableMetadata: [ { metadata: 'journal', - authority: 'JOURNALAuthority', + controlledVocabulary: 'JOURNALAuthority', closed: false } ], diff --git a/src/app/shared/form/builder/parsers/lookup-field-parser.ts b/src/app/shared/form/builder/parsers/lookup-field-parser.ts index 9e9c434c4f..6e28194dad 100644 --- a/src/app/shared/form/builder/parsers/lookup-field-parser.ts +++ b/src/app/shared/form/builder/parsers/lookup-field-parser.ts @@ -5,10 +5,10 @@ import { FormFieldMetadataValueObject } from '../models/form-field-metadata-valu export class LookupFieldParser extends FieldParser { public modelFactory(fieldValue?: FormFieldMetadataValueObject | any, label?: boolean): any { - if (this.configData.selectableMetadata[0].authority) { + if (this.configData.selectableMetadata[0].controlledVocabulary) { const lookupModelConfig: DynamicLookupModelConfig = this.initModel(null, label); - this.setAuthorityOptions(lookupModelConfig, this.parserOptions.authorityUuid); + this.setVocabularyOptions(lookupModelConfig, this.parserOptions.collectionUUID); this.setValues(lookupModelConfig, fieldValue, true); diff --git a/src/app/shared/form/builder/parsers/lookup-name-field-parser.spec.ts b/src/app/shared/form/builder/parsers/lookup-name-field-parser.spec.ts index adc1e90166..3d02b6952e 100644 --- a/src/app/shared/form/builder/parsers/lookup-name-field-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/lookup-name-field-parser.spec.ts @@ -12,7 +12,7 @@ describe('LookupNameFieldParser test suite', () => { const parserOptions: ParserOptions = { readOnly: false, submissionScope: 'testScopeUUID', - authorityUuid: null + collectionUUID: null }; beforeEach(() => { @@ -27,7 +27,7 @@ describe('LookupNameFieldParser test suite', () => { selectableMetadata: [ { metadata: 'author', - authority: 'RPAuthority', + controlledVocabulary: 'RPAuthority', closed: false } ], diff --git a/src/app/shared/form/builder/parsers/lookup-name-field-parser.ts b/src/app/shared/form/builder/parsers/lookup-name-field-parser.ts index 684e06bcb6..26806742c8 100644 --- a/src/app/shared/form/builder/parsers/lookup-name-field-parser.ts +++ b/src/app/shared/form/builder/parsers/lookup-name-field-parser.ts @@ -8,10 +8,10 @@ import { FormFieldMetadataValueObject } from '../models/form-field-metadata-valu export class LookupNameFieldParser extends FieldParser { public modelFactory(fieldValue?: FormFieldMetadataValueObject | any, label?: boolean): any { - if (this.configData.selectableMetadata[0].authority) { + if (this.configData.selectableMetadata[0].controlledVocabulary) { const lookupModelConfig: DynamicLookupNameModelConfig = this.initModel(null, label); - this.setAuthorityOptions(lookupModelConfig, this.parserOptions.authorityUuid); + this.setVocabularyOptions(lookupModelConfig, this.parserOptions.collectionUUID); this.setValues(lookupModelConfig, fieldValue, true); diff --git a/src/app/shared/form/builder/parsers/name-field-parser.spec.ts b/src/app/shared/form/builder/parsers/name-field-parser.spec.ts index 1b0c637030..363ff40926 100644 --- a/src/app/shared/form/builder/parsers/name-field-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/name-field-parser.spec.ts @@ -14,7 +14,7 @@ describe('NameFieldParser test suite', () => { const parserOptions: ParserOptions = { readOnly: false, submissionScope: 'testScopeUUID', - authorityUuid: null + collectionUUID: null }; beforeEach(() => { diff --git a/src/app/shared/form/builder/parsers/onebox-field-parser.spec.ts b/src/app/shared/form/builder/parsers/onebox-field-parser.spec.ts index 4668b3017d..c2d1b6f565 100644 --- a/src/app/shared/form/builder/parsers/onebox-field-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/onebox-field-parser.spec.ts @@ -15,7 +15,7 @@ describe('OneboxFieldParser test suite', () => { const parserOptions: ParserOptions = { readOnly: false, submissionScope: 'testScopeUUID', - authorityUuid: null + collectionUUID: null }; beforeEach(() => { @@ -28,7 +28,7 @@ describe('OneboxFieldParser test suite', () => { selectableMetadata: [ { metadata: 'title', - authority: 'EVENTAuthority', + controlledVocabulary: 'EVENTAuthority', closed: false } ], diff --git a/src/app/shared/form/builder/parsers/onebox-field-parser.ts b/src/app/shared/form/builder/parsers/onebox-field-parser.ts index d69c9d4677..598918ac2e 100644 --- a/src/app/shared/form/builder/parsers/onebox-field-parser.ts +++ b/src/app/shared/form/builder/parsers/onebox-field-parser.ts @@ -75,9 +75,9 @@ export class OneboxFieldParser extends FieldParser { inputSelectGroup.group.push(new DsDynamicInputModel(inputModelConfig, clsInput)); return new DynamicQualdropModel(inputSelectGroup, clsGroup); - } else if (this.configData.selectableMetadata[0].authority) { + } else if (this.configData.selectableMetadata[0].controlledVocabulary) { const typeaheadModelConfig: DsDynamicTypeaheadModelConfig = this.initModel(null, label); - this.setAuthorityOptions(typeaheadModelConfig, this.parserOptions.authorityUuid); + this.setVocabularyOptions(typeaheadModelConfig, this.parserOptions.collectionUUID); this.setValues(typeaheadModelConfig, fieldValue, true); return new DynamicTypeaheadModel(typeaheadModelConfig); diff --git a/src/app/shared/form/builder/parsers/parser-options.ts b/src/app/shared/form/builder/parsers/parser-options.ts index f96ce0f2f3..e8ac4b49cd 100644 --- a/src/app/shared/form/builder/parsers/parser-options.ts +++ b/src/app/shared/form/builder/parsers/parser-options.ts @@ -1,5 +1,5 @@ export interface ParserOptions { readOnly: boolean; submissionScope: string; - authorityUuid: string + collectionUUID: string } diff --git a/src/app/shared/form/builder/parsers/relation-group-field-parser.spec.ts b/src/app/shared/form/builder/parsers/relation-group-field-parser.spec.ts index 84f3df0365..111193a637 100644 --- a/src/app/shared/form/builder/parsers/relation-group-field-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/relation-group-field-parser.spec.ts @@ -12,7 +12,7 @@ describe('RelationGroupFieldParser test suite', () => { const parserOptions: ParserOptions = { readOnly: false, submissionScope: 'testScopeUUID', - authorityUuid: 'WORKSPACE' + collectionUUID: 'WORKSPACE' }; beforeEach(() => { diff --git a/src/app/shared/form/builder/parsers/relation-group-field-parser.ts b/src/app/shared/form/builder/parsers/relation-group-field-parser.ts index 01699d9e78..99dfcf777a 100644 --- a/src/app/shared/form/builder/parsers/relation-group-field-parser.ts +++ b/src/app/shared/form/builder/parsers/relation-group-field-parser.ts @@ -16,7 +16,7 @@ export class RelationGroupFieldParser extends FieldParser { const modelConfiguration: DynamicRelationGroupModelConfig = this.initModel(null, label); modelConfiguration.submissionId = this.submissionId; - modelConfiguration.scopeUUID = this.parserOptions.authorityUuid; + modelConfiguration.scopeUUID = this.parserOptions.collectionUUID; modelConfiguration.submissionScope = this.parserOptions.submissionScope; if (this.configData && this.configData.rows && this.configData.rows.length > 0) { modelConfiguration.formConfiguration = this.configData.rows; diff --git a/src/app/shared/form/builder/parsers/row-parser.spec.ts b/src/app/shared/form/builder/parsers/row-parser.spec.ts index 435c6a6426..63f343e60d 100644 --- a/src/app/shared/form/builder/parsers/row-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/row-parser.spec.ts @@ -35,7 +35,7 @@ describe('RowParser test suite', () => { selectableMetadata: [ { metadata: 'journal', - authority: 'JOURNALAuthority', + controlledVocabulary: 'JOURNALAuthority', closed: false } ], @@ -83,7 +83,7 @@ describe('RowParser test suite', () => { selectableMetadata: [ { metadata: 'title', - authority: 'EVENTAuthority', + controlledVocabulary: 'EVENTAuthority', closed: false } ], @@ -103,7 +103,7 @@ describe('RowParser test suite', () => { selectableMetadata: [ { metadata: 'title', - authority: 'EVENTAuthority', + controlledVocabulary: 'EVENTAuthority', closed: false } ], @@ -119,7 +119,7 @@ describe('RowParser test suite', () => { selectableMetadata: [ { metadata: 'otherTitle', - authority: 'EVENTAuthority', + controlledVocabulary: 'EVENTAuthority', closed: false } ], @@ -141,7 +141,7 @@ describe('RowParser test suite', () => { selectableMetadata: [ { metadata: 'type', - authority: 'common_types_dataset', + controlledVocabulary: 'common_types_dataset', closed: false } ], @@ -176,7 +176,7 @@ describe('RowParser test suite', () => { selectableMetadata: [ { metadata: 'author', - authority: 'RPAuthority', + controlledVocabulary: 'RPAuthority', closed: false } ], @@ -198,7 +198,7 @@ describe('RowParser test suite', () => { selectableMetadata: [ { metadata: 'type', - authority: 'type_programme', + controlledVocabulary: 'type_programme', closed: false } ], @@ -241,7 +241,7 @@ describe('RowParser test suite', () => { selectableMetadata: [ { metadata: 'subject', - authority: 'JOURNALAuthority', + controlledVocabulary: 'JOURNALAuthority', closed: false } ], diff --git a/src/app/shared/form/builder/parsers/row-parser.ts b/src/app/shared/form/builder/parsers/row-parser.ts index 4938b9859e..a7ea023569 100644 --- a/src/app/shared/form/builder/parsers/row-parser.ts +++ b/src/app/shared/form/builder/parsers/row-parser.ts @@ -5,7 +5,7 @@ import { } from '@ng-dynamic-forms/core'; import { uniqueId } from 'lodash'; -import { IntegrationSearchOptions } from '../../../../core/integration/models/integration-options.model'; +import { VocabularyFindOptions } from '../../../../core/submission/vocabularies/models/vocabulary-find-options.model'; import { isEmpty } from '../../../empty.util'; import { DynamicRowGroupModel } from '../ds-dynamic-form-ui/models/ds-dynamic-row-group-model'; import { DYNAMIC_FORM_CONTROL_TYPE_RELATION_GROUP } from '../ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.model'; @@ -48,7 +48,7 @@ export class RowParser { group: [], }; - const authorityOptions = new IntegrationSearchOptions(scopeUUID); + const vocabularyOptions = new VocabularyFindOptions(scopeUUID); const scopedFields: FormFieldModel[] = this.filterScopedFields(rowData.fields, submissionScope); @@ -58,7 +58,7 @@ export class RowParser { const parserOptions: ParserOptions = { readOnly: readOnly, submissionScope: submissionScope, - authorityUuid: authorityOptions.uuid + collectionUUID: vocabularyOptions.collection }; // Iterate over row's fields diff --git a/src/app/shared/form/builder/parsers/series-field-parser.spec.ts b/src/app/shared/form/builder/parsers/series-field-parser.spec.ts index ceb4e96320..ca58dfb50a 100644 --- a/src/app/shared/form/builder/parsers/series-field-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/series-field-parser.spec.ts @@ -12,7 +12,7 @@ describe('SeriesFieldParser test suite', () => { const parserOptions: ParserOptions = { readOnly: false, submissionScope: 'testScopeUUID', - authorityUuid: null + collectionUUID: null }; beforeEach(() => { diff --git a/src/app/shared/form/builder/parsers/tag-field-parser.spec.ts b/src/app/shared/form/builder/parsers/tag-field-parser.spec.ts index 90449e62e5..7c63235f67 100644 --- a/src/app/shared/form/builder/parsers/tag-field-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/tag-field-parser.spec.ts @@ -12,7 +12,7 @@ describe('TagFieldParser test suite', () => { const parserOptions: ParserOptions = { readOnly: false, submissionScope: 'testScopeUUID', - authorityUuid: null + collectionUUID: null }; beforeEach(() => { @@ -27,7 +27,7 @@ describe('TagFieldParser test suite', () => { selectableMetadata: [ { metadata: 'subject', - authority: 'JOURNALAuthority', + controlledVocabulary: 'JOURNALAuthority', closed: false } ], diff --git a/src/app/shared/form/builder/parsers/tag-field-parser.ts b/src/app/shared/form/builder/parsers/tag-field-parser.ts index c1c39feb2b..08685e0e35 100644 --- a/src/app/shared/form/builder/parsers/tag-field-parser.ts +++ b/src/app/shared/form/builder/parsers/tag-field-parser.ts @@ -6,9 +6,9 @@ export class TagFieldParser extends FieldParser { public modelFactory(fieldValue?: FormFieldMetadataValueObject | any, label?: boolean): any { const tagModelConfig: DynamicTagModelConfig = this.initModel(null, label); - if (this.configData.selectableMetadata[0].authority - && this.configData.selectableMetadata[0].authority.length > 0) { - this.setAuthorityOptions(tagModelConfig, this.parserOptions.authorityUuid); + if (this.configData.selectableMetadata[0].controlledVocabulary + && this.configData.selectableMetadata[0].controlledVocabulary.length > 0) { + this.setVocabularyOptions(tagModelConfig, this.parserOptions.collectionUUID); } this.setValues(tagModelConfig, fieldValue, null, true); diff --git a/src/app/shared/form/builder/parsers/textarea-field-parser.spec.ts b/src/app/shared/form/builder/parsers/textarea-field-parser.spec.ts index 167f126cf2..84acc9f239 100644 --- a/src/app/shared/form/builder/parsers/textarea-field-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/textarea-field-parser.spec.ts @@ -12,7 +12,7 @@ describe('TextareaFieldParser test suite', () => { const parserOptions: ParserOptions = { readOnly: false, submissionScope: null, - authorityUuid: null + collectionUUID: null }; beforeEach(() => { diff --git a/src/app/shared/mocks/form-models.mock.ts b/src/app/shared/mocks/form-models.mock.ts index e4f9ec3131..1965f8d709 100644 --- a/src/app/shared/mocks/form-models.mock.ts +++ b/src/app/shared/mocks/form-models.mock.ts @@ -1,16 +1,19 @@ +import { DynamicSelectModel } from '@ng-dynamic-forms/core'; + import { DsDynamicInputModel } from '../form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model'; import { DynamicQualdropModel } from '../form/builder/ds-dynamic-form-ui/models/ds-dynamic-qualdrop.model'; -import { DynamicRowArrayModel, DynamicRowArrayModelConfig } from '../form/builder/ds-dynamic-form-ui/models/ds-dynamic-row-array-model'; -import { DynamicSelectModel } from '@ng-dynamic-forms/core'; +import { + DynamicRowArrayModel, + DynamicRowArrayModelConfig +} from '../form/builder/ds-dynamic-form-ui/models/ds-dynamic-row-array-model'; import { SubmissionScopeType } from '../../core/submission/submission-scope-type'; import { DynamicRelationGroupModel } from '../form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.model'; import { FormFieldModel } from '../form/builder/models/form-field.model'; -import { AuthorityOptions } from '../../core/integration/models/authority-options.model'; -import { AuthorityValue } from '../../core/integration/models/authority.value'; +import { VocabularyOptions } from '../../core/submission/vocabularies/models/vocabulary-options.model'; +import { VocabularyEntry } from '../../core/submission/vocabularies/models/vocabulary-entry.model'; import { FormFieldMetadataValueObject } from '../form/builder/models/form-field-metadata-value.model'; import { DynamicRowGroupModel } from '../form/builder/ds-dynamic-form-ui/models/ds-dynamic-row-group-model'; import { FormRowModel } from '../../core/config/models/config-submission-form.model'; -import { WorkspaceItem } from '../../core/submission/models/workspaceitem.model'; export const qualdropSelectConfig = { name: 'dc.identifier_QUALDROP_METADATA', @@ -87,7 +90,7 @@ export const MockRowArrayQualdropModel: DynamicRowArrayModel = new DynamicRowArr const mockFormRowModel = { fields: [ { - input: {type: 'lookup'}, + input: { type: 'lookup' }, label: 'Journal', mandatory: 'false', repeatable: false, @@ -95,14 +98,14 @@ const mockFormRowModel = { selectableMetadata: [ { metadata: 'journal', - authority: 'JOURNALAuthority', + controlledVocabulary: 'JOURNALAuthority', closed: false } ], languageCodes: [] } as FormFieldModel, { - input: {type: 'onebox'}, + input: { type: 'onebox' }, label: 'Issue', mandatory: 'false', repeatable: false, @@ -142,7 +145,7 @@ const relationGroupConfig = { export const MockRelationModel: DynamicRelationGroupModel = new DynamicRelationGroupModel(relationGroupConfig); export const inputWithLanguageAndAuthorityConfig = { - authorityOptions: new AuthorityOptions('testAuthority', 'testWithAuthority', 'scope'), + vocabularyOptions: new VocabularyOptions('testAuthority', 'testWithAuthority', 'scope'), languageCodes: [ { display: 'English', @@ -159,10 +162,10 @@ export const inputWithLanguageAndAuthorityConfig = { readOnly: false, disabled: false, repeatable: false, - value: { + value: { value: 'testWithLanguageAndAuthority', display: 'testWithLanguageAndAuthority', - id: 'testWithLanguageAndAuthority', + authority: 'testWithLanguageAndAuthority', }, submissionId: '1234', metadataFields: [] @@ -195,7 +198,7 @@ export const inputWithLanguageConfig = { export const mockInputWithLanguageModel = new DsDynamicInputModel(inputWithLanguageConfig); export const inputWithLanguageAndAuthorityArrayConfig = { - authorityOptions: new AuthorityOptions('testAuthority', 'testWithAuthority', 'scope'), + vocabularyOptions: new VocabularyOptions('testAuthority', 'testWithAuthority', 'scope'), languageCodes: [ { display: 'English', @@ -215,7 +218,7 @@ export const inputWithLanguageAndAuthorityArrayConfig = { value: [{ value: 'testLanguageAndAuthorityArray', display: 'testLanguageAndAuthorityArray', - id: 'testLanguageAndAuthorityArray', + authority: 'testLanguageAndAuthorityArray', }], submissionId: '1234', metadataFields: [] @@ -242,7 +245,11 @@ export const inputWithAuthorityValueConfig = { readOnly: false, disabled: false, repeatable: false, - value: Object.assign({}, new AuthorityValue(), { value: 'testWithAuthorityValue', id: 'testWithAuthorityValue', display: 'testWithAuthorityValue' }), + value: Object.assign({}, new VocabularyEntry(), { + value: 'testWithAuthorityValue', + authority: 'testWithAuthorityValue', + display: 'testWithAuthorityValue' + }), submissionId: '1234', metadataFields: [] }; @@ -255,7 +262,7 @@ export const inputWithObjectValueConfig = { readOnly: false, disabled: false, repeatable: false, - value: { value: 'testWithObjectValue', id: 'testWithObjectValue', display: 'testWithObjectValue' }, + value: { value: 'testWithObjectValue', authority: 'testWithObjectValue', display: 'testWithObjectValue' }, submissionId: '1234', metadataFields: [] }; diff --git a/src/app/shared/mocks/submission.mock.ts b/src/app/shared/mocks/submission.mock.ts index 082eec4c71..8965a17eef 100644 --- a/src/app/shared/mocks/submission.mock.ts +++ b/src/app/shared/mocks/submission.mock.ts @@ -1254,7 +1254,7 @@ export const mockUploadConfigResponse = { { metadata: 'dc.title', label: null, - authority: null, + controlledVocabulary: null, closed: null } ], @@ -1276,7 +1276,7 @@ export const mockUploadConfigResponse = { { metadata: 'dc.description', label: null, - authority: null, + controlledVocabulary: null, closed: null } ], diff --git a/src/app/shared/testing/authority-service.stub.ts b/src/app/shared/testing/authority-service.stub.ts deleted file mode 100644 index 3a5d31ab0d..0000000000 --- a/src/app/shared/testing/authority-service.stub.ts +++ /dev/null @@ -1,21 +0,0 @@ -import {of as observableOf, Observable } from 'rxjs'; -import { IntegrationSearchOptions } from '../../core/integration/models/integration-options.model'; -import { IntegrationData } from '../../core/integration/integration-data'; -import { PageInfo } from '../../core/shared/page-info.model'; -import { AuthorityValue } from '../../core/integration/models/authority.value'; - -export class AuthorityServiceStub { - - private _payload = [ - Object.assign(new AuthorityValue(),{id: 1, display: 'one', value: 1}), - Object.assign(new AuthorityValue(),{id: 2, display: 'two', value: 2}), - ]; - - setNewPayload(payload) { - this._payload = payload; - } - - getEntriesByName(options: IntegrationSearchOptions) { - return observableOf(new IntegrationData(new PageInfo(), this._payload)); - } -} diff --git a/src/app/shared/testing/vocabulary-service.stub.ts b/src/app/shared/testing/vocabulary-service.stub.ts new file mode 100644 index 0000000000..15528653c2 --- /dev/null +++ b/src/app/shared/testing/vocabulary-service.stub.ts @@ -0,0 +1,29 @@ +import { Observable } from 'rxjs'; + +import { VocabularyFindOptions } from '../../core/submission/vocabularies/models/vocabulary-find-options.model'; +import { PageInfo } from '../../core/shared/page-info.model'; +import { VocabularyEntry } from '../../core/submission/vocabularies/models/vocabulary-entry.model'; +import { PaginatedList } from '../../core/data/paginated-list'; +import { createSuccessfulRemoteDataObject$ } from '../remote-data.utils'; +import { RemoteData } from '../../core/data/remote-data'; + + +export class VocabularyServiceStub { + + private _payload = [ + Object.assign(new VocabularyEntry(),{authority: 1, display: 'one', value: 1}), + Object.assign(new VocabularyEntry(),{authority: 2, display: 'two', value: 2}), + ]; + + setNewPayload(payload) { + this._payload = payload; + } + + getList() { + return this._payload + } + + getVocabularyEntries(options: VocabularyFindOptions): Observable>> { + return createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), this._payload)); + } +} diff --git a/src/app/submission/sections/form/section-form-operations.service.spec.ts b/src/app/submission/sections/form/section-form-operations.service.spec.ts index de8e7da7f9..bc1c17ddbd 100644 --- a/src/app/submission/sections/form/section-form-operations.service.spec.ts +++ b/src/app/submission/sections/form/section-form-operations.service.spec.ts @@ -27,7 +27,7 @@ import { mockRowGroupModel } from '../../../shared/mocks/form-models.mock'; import { FormFieldMetadataValueObject } from '../../../shared/form/builder/models/form-field-metadata-value.model'; -import { AuthorityValue } from '../../../core/integration/models/authority.value'; +import { VocabularyEntry } from '../../../core/submission/vocabularies/models/vocabulary-entry.model'; describe('SectionFormOperationsService test suite', () => { let formBuilderService: any; @@ -365,7 +365,7 @@ describe('SectionFormOperationsService test suite', () => { event = Object.assign({}, dynamicFormControlChangeEvent, { model: mockInputWithLanguageAndAuthorityModel }); - expectedValue = Object.assign(new AuthorityValue(), mockInputWithLanguageAndAuthorityModel.value, {language: mockInputWithLanguageAndAuthorityModel.language}); + expectedValue = Object.assign(new VocabularyEntry(), mockInputWithLanguageAndAuthorityModel.value, {language: mockInputWithLanguageAndAuthorityModel.language}); expect(service.getFieldValueFromChangeEvent(event)).toEqual(expectedValue); @@ -373,7 +373,7 @@ describe('SectionFormOperationsService test suite', () => { model: mockInputWithLanguageAndAuthorityArrayModel }); expectedValue = [ - Object.assign(new AuthorityValue(), mockInputWithLanguageAndAuthorityArrayModel.value[0], + Object.assign(new VocabularyEntry(), mockInputWithLanguageAndAuthorityArrayModel.value[0], { language: mockInputWithLanguageAndAuthorityArrayModel.language } ) ]; diff --git a/src/app/submission/sections/form/section-form-operations.service.ts b/src/app/submission/sections/form/section-form-operations.service.ts index 2d6b1c5477..a28536a0a7 100644 --- a/src/app/submission/sections/form/section-form-operations.service.ts +++ b/src/app/submission/sections/form/section-form-operations.service.ts @@ -15,11 +15,12 @@ import { FormFieldPreviousValueObject } from '../../../shared/form/builder/model import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder'; import { FormFieldLanguageValueObject } from '../../../shared/form/builder/models/form-field-language-value.model'; import { DsDynamicInputModel } from '../../../shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model'; -import { AuthorityValue } from '../../../core/integration/models/authority.value'; +import { VocabularyEntry } from '../../../core/submission/vocabularies/models/vocabulary-entry.model'; import { FormBuilderService } from '../../../shared/form/builder/form-builder.service'; import { FormFieldMetadataValueObject } from '../../../shared/form/builder/models/form-field-metadata-value.model'; import { DynamicQualdropModel } from '../../../shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-qualdrop.model'; import { DynamicRelationGroupModel } from '../../../shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.model'; +import { VocabularyEntryDetail } from '../../../core/submission/vocabularies/models/vocabulary-entry-detail.model'; /** * The service handling all form section operations @@ -221,18 +222,19 @@ export class SectionFormOperationsService { if ((event.model as DsDynamicInputModel).hasAuthority) { if (Array.isArray(value)) { value.forEach((authority, index) => { - authority = Object.assign(new AuthorityValue(), authority, { language }); + authority = Object.assign(new VocabularyEntry(), authority, { language }); value[index] = authority; }); fieldValue = value; } else { - fieldValue = Object.assign(new AuthorityValue(), value, { language }); + fieldValue = Object.assign(new VocabularyEntry(), value, { language }); } } else { // Language without Authority (input, textArea) fieldValue = new FormFieldMetadataValueObject(value, language); } - } else if (value instanceof FormFieldLanguageValueObject || value instanceof AuthorityValue || isObject(value)) { + } else if (value instanceof FormFieldLanguageValueObject || value instanceof VocabularyEntry + || value instanceof VocabularyEntryDetail || isObject(value)) { fieldValue = value; } else { fieldValue = new FormFieldMetadataValueObject(value); From f71fd5737a82be56dcbf8cd8929e47073a166224 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 25 Jun 2020 15:22:20 +0200 Subject: [PATCH 017/170] [CST-3088] Removed authority and integration services --- src/app/core/cache/response.models.ts | 14 +- src/app/core/data/request.models.ts | 38 ++- src/app/core/integration/authority.service.ts | 21 -- src/app/core/integration/integration-data.ts | 12 - ...tegration-response-parsing.service.spec.ts | 221 ------------------ .../integration-response-parsing.service.ts | 50 ---- .../integration/integration.service.spec.ts | 96 -------- .../core/integration/integration.service.ts | 121 ---------- .../models/authority-options.model.ts | 16 -- .../models/authority.resource-type.ts | 10 - .../integration/models/authority.value.ts | 92 -------- .../models/integration-options.model.ts | 14 -- .../integration/models/integration.model.ts | 22 -- 13 files changed, 16 insertions(+), 711 deletions(-) delete mode 100644 src/app/core/integration/authority.service.ts delete mode 100644 src/app/core/integration/integration-data.ts delete mode 100644 src/app/core/integration/integration-response-parsing.service.spec.ts delete mode 100644 src/app/core/integration/integration-response-parsing.service.ts delete mode 100644 src/app/core/integration/integration.service.spec.ts delete mode 100644 src/app/core/integration/integration.service.ts delete mode 100644 src/app/core/integration/models/authority-options.model.ts delete mode 100644 src/app/core/integration/models/authority.resource-type.ts delete mode 100644 src/app/core/integration/models/authority.value.ts delete mode 100644 src/app/core/integration/models/integration-options.model.ts delete mode 100644 src/app/core/integration/models/integration.model.ts diff --git a/src/app/core/cache/response.models.ts b/src/app/core/cache/response.models.ts index 3f46ecf647..00f1bffdeb 100644 --- a/src/app/core/cache/response.models.ts +++ b/src/app/core/cache/response.models.ts @@ -5,11 +5,9 @@ import { PageInfo } from '../shared/page-info.model'; import { ConfigObject } from '../config/models/config.model'; import { FacetValue } from '../../shared/search/facet-value.model'; import { SearchFilterConfig } from '../../shared/search/search-filter-config.model'; -import { IntegrationModel } from '../integration/models/integration.model'; import { RegistryMetadataschemasResponse } from '../registry/registry-metadataschemas-response.model'; import { RegistryMetadatafieldsResponse } from '../registry/registry-metadatafields-response.model'; import { RegistryBitstreamformatsResponse } from '../registry/registry-bitstreamformats-response.model'; -import { PaginatedList } from '../data/paginated-list'; import { SubmissionObject } from '../submission/models/submission-object.model'; import { DSpaceObject } from '../shared/dspace-object.model'; import { MetadataSchema } from '../metadata/metadata-schema.model'; @@ -211,17 +209,6 @@ export class AuthStatusResponse extends RestResponse { } } -export class IntegrationSuccessResponse extends RestResponse { - constructor( - public dataDefinition: PaginatedList, - public statusCode: number, - public statusText: string, - public pageInfo?: PageInfo - ) { - super(true, statusCode, statusText); - } -} - export class PostPatchSuccessResponse extends RestResponse { constructor( public dataDefinition: any, @@ -302,4 +289,5 @@ export class ContentSourceSuccessResponse extends RestResponse { super(true, statusCode, statusText); } } + /* tslint:enable:max-classes-per-file */ diff --git a/src/app/core/data/request.models.ts b/src/app/core/data/request.models.ts index c9fe1fe0ce..a1f77d9cbb 100644 --- a/src/app/core/data/request.models.ts +++ b/src/app/core/data/request.models.ts @@ -9,7 +9,6 @@ import { ConfigResponseParsingService } from '../config/config-response-parsing. import { AuthResponseParsingService } from '../auth/auth-response-parsing.service'; import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; import { SubmissionResponseParsingService } from '../submission/submission-response-parsing.service'; -import { IntegrationResponseParsingService } from '../integration/integration-response-parsing.service'; import { RestRequestMethod } from './rest-request-method'; import { RequestParam } from '../cache/models/request-param.model'; import { EpersonResponseParsingService } from '../eperson/eperson-response-parsing.service'; @@ -26,13 +25,14 @@ import { VocabularyEntriesResponseParsingService } from '../submission/vocabular // uuid and handle requests have separate endpoints export enum IdentifierType { - UUID ='uuid', + UUID = 'uuid', HANDLE = 'handle' } export abstract class RestRequest { public responseMsToLive = 10 * 1000; public forceBypassCache = false; + constructor( public uuid: string, public href: string, @@ -42,13 +42,13 @@ export abstract class RestRequest { ) { } - getResponseParser(): GenericConstructor { - return DSOResponseParsingService; - } - get toCache(): boolean { return this.responseMsToLive > 0; } + + getResponseParser(): GenericConstructor { + return DSOResponseParsingService; + } } export class GetRequest extends RestRequest { @@ -59,7 +59,7 @@ export class GetRequest extends RestRequest { public href: string, public body?: any, public options?: HttpOptions - ) { + ) { super(uuid, href, RestRequestMethod.GET, body, options) } } @@ -70,7 +70,7 @@ export class PostRequest extends RestRequest { public href: string, public body?: any, public options?: HttpOptions - ) { + ) { super(uuid, href, RestRequestMethod.POST, body) } } @@ -81,7 +81,7 @@ export class PutRequest extends RestRequest { public href: string, public body?: any, public options?: HttpOptions - ) { + ) { super(uuid, href, RestRequestMethod.PUT, body) } } @@ -92,7 +92,7 @@ export class DeleteRequest extends RestRequest { public href: string, public body?: any, public options?: HttpOptions - ) { + ) { super(uuid, href, RestRequestMethod.DELETE, body) } } @@ -103,7 +103,7 @@ export class OptionsRequest extends RestRequest { public href: string, public body?: any, public options?: HttpOptions - ) { + ) { super(uuid, href, RestRequestMethod.OPTIONS, body) } } @@ -114,7 +114,7 @@ export class HeadRequest extends RestRequest { public href: string, public body?: any, public options?: HttpOptions - ) { + ) { super(uuid, href, RestRequestMethod.HEAD, body) } } @@ -127,7 +127,7 @@ export class PatchRequest extends RestRequest { public href: string, public body?: any, public options?: HttpOptions - ) { + ) { super(uuid, href, RestRequestMethod.PATCH, body) } } @@ -242,16 +242,6 @@ export class AuthGetRequest extends GetRequest { } } -export class IntegrationRequest extends GetRequest { - constructor(uuid: string, href: string) { - super(uuid, href); - } - - getResponseParser(): GenericConstructor { - return IntegrationResponseParsingService; - } -} - /** * Request to create a MetadataSchema */ @@ -309,6 +299,7 @@ export class UpdateMetadataFieldRequest extends PutRequest { */ export class SubmissionRequest extends GetRequest { forceBypassCache = true; + constructor(uuid: string, href: string) { super(uuid, href); } @@ -456,4 +447,5 @@ export class RequestError extends Error { statusCode: number; statusText: string; } + /* tslint:enable:max-classes-per-file */ diff --git a/src/app/core/integration/authority.service.ts b/src/app/core/integration/authority.service.ts deleted file mode 100644 index f0a1759be6..0000000000 --- a/src/app/core/integration/authority.service.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Injectable } from '@angular/core'; - -import { RequestService } from '../data/request.service'; -import { IntegrationService } from './integration.service'; -import { HALEndpointService } from '../shared/hal-endpoint.service'; -import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; - -@Injectable() -export class AuthorityService extends IntegrationService { - protected linkPath = 'authorities'; - protected entriesEndpoint = 'entries'; - protected entryValueEndpoint = 'entryValues'; - - constructor( - protected requestService: RequestService, - protected rdbService: RemoteDataBuildService, - protected halService: HALEndpointService) { - super(); - } - -} diff --git a/src/app/core/integration/integration-data.ts b/src/app/core/integration/integration-data.ts deleted file mode 100644 index b93ce36dad..0000000000 --- a/src/app/core/integration/integration-data.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { PageInfo } from '../shared/page-info.model'; -import { IntegrationModel } from './models/integration.model'; - -/** - * A class to represent the data retrieved by an Integration service - */ -export class IntegrationData { - constructor( - public pageInfo: PageInfo, - public payload: IntegrationModel[] - ) { } -} diff --git a/src/app/core/integration/integration-response-parsing.service.spec.ts b/src/app/core/integration/integration-response-parsing.service.spec.ts deleted file mode 100644 index b5cb8c4dc4..0000000000 --- a/src/app/core/integration/integration-response-parsing.service.spec.ts +++ /dev/null @@ -1,221 +0,0 @@ -import { Store } from '@ngrx/store'; - -import { ObjectCacheService } from '../cache/object-cache.service'; -import { ErrorResponse, IntegrationSuccessResponse } from '../cache/response.models'; -import { CoreState } from '../core.reducers'; -import { PaginatedList } from '../data/paginated-list'; -import { IntegrationRequest } from '../data/request.models'; -import { PageInfo } from '../shared/page-info.model'; -import { IntegrationResponseParsingService } from './integration-response-parsing.service'; -import { AuthorityValue } from './models/authority.value'; - -describe('IntegrationResponseParsingService', () => { - let service: IntegrationResponseParsingService; - - const store = {} as Store; - const objectCacheService = new ObjectCacheService(store, undefined); - const name = 'type'; - const metadata = 'dc.type'; - const query = ''; - const uuid = 'd9d30c0c-69b7-4369-8397-ca67c888974d'; - const integrationEndpoint = 'https://rest.api/integration/authorities'; - const entriesEndpoint = `${integrationEndpoint}/${name}/entries?query=${query}&metadata=${metadata}&uuid=${uuid}`; - let validRequest; - - let validResponse; - - let invalidResponse1; - let invalidResponse2; - let pageInfo; - let definitions; - - function initVars() { - pageInfo = Object.assign(new PageInfo(), { - elementsPerPage: 5, - totalElements: 5, - totalPages: 1, - currentPage: 1, - _links: { - self: { href: 'https://rest.api/integration/authorities/type/entries' } - } - }); - definitions = new PaginatedList(pageInfo, [ - Object.assign(new AuthorityValue(), { - type: 'authority', - display: 'One', - id: 'One', - otherInformation: undefined, - value: 'One' - }), - Object.assign(new AuthorityValue(), { - type: 'authority', - display: 'Two', - id: 'Two', - otherInformation: undefined, - value: 'Two' - }), - Object.assign(new AuthorityValue(), { - type: 'authority', - display: 'Three', - id: 'Three', - otherInformation: undefined, - value: 'Three' - }), - Object.assign(new AuthorityValue(), { - type: 'authority', - display: 'Four', - id: 'Four', - otherInformation: undefined, - value: 'Four' - }), - Object.assign(new AuthorityValue(), { - type: 'authority', - display: 'Five', - id: 'Five', - otherInformation: undefined, - value: 'Five' - }) - ]); - validRequest = new IntegrationRequest('69f375b5-19f4-4453-8c7a-7dc5c55aafbb', entriesEndpoint); - - validResponse = { - payload: { - page: { - number: 0, - size: 5, - totalElements: 5, - totalPages: 1 - }, - _embedded: { - authorityEntries: [ - { - display: 'One', - id: 'One', - otherInformation: {}, - type: 'authority', - value: 'One' - }, - { - display: 'Two', - id: 'Two', - otherInformation: {}, - type: 'authority', - value: 'Two' - }, - { - display: 'Three', - id: 'Three', - otherInformation: {}, - type: 'authority', - value: 'Three' - }, - { - display: 'Four', - id: 'Four', - otherInformation: {}, - type: 'authority', - value: 'Four' - }, - { - display: 'Five', - id: 'Five', - otherInformation: {}, - type: 'authority', - value: 'Five' - }, - ], - - }, - _links: { - self: { href: 'https://rest.api/integration/authorities/type/entries' } - } - }, - statusCode: 200, - statusText: 'OK' - }; - - invalidResponse1 = { - payload: {}, - statusCode: 400, - statusText: 'Bad Request' - }; - - invalidResponse2 = { - payload: { - page: { - number: 0, - size: 5, - totalElements: 5, - totalPages: 1 - }, - _embedded: { - authorityEntries: [ - { - display: 'One', - id: 'One', - otherInformation: {}, - type: 'authority', - value: 'One' - }, - { - display: 'Two', - id: 'Two', - otherInformation: {}, - type: 'authority', - value: 'Two' - }, - { - display: 'Three', - id: 'Three', - otherInformation: {}, - type: 'authority', - value: 'Three' - }, - { - display: 'Four', - id: 'Four', - otherInformation: {}, - type: 'authority', - value: 'Four' - }, - { - display: 'Five', - id: 'Five', - otherInformation: {}, - type: 'authority', - value: 'Five' - }, - ], - - }, - _links: {} - }, - statusCode: 500, - statusText: 'Internal Server Error' - }; - } - beforeEach(() => { - initVars(); - service = new IntegrationResponseParsingService(objectCacheService); - }); - - describe('parse', () => { - it('should return a IntegrationSuccessResponse if data contains a valid endpoint response', () => { - const response = service.parse(validRequest, validResponse); - expect(response.constructor).toBe(IntegrationSuccessResponse); - }); - - it('should return an ErrorResponse if data contains an invalid config endpoint response', () => { - const response1 = service.parse(validRequest, invalidResponse1); - const response2 = service.parse(validRequest, invalidResponse2); - expect(response1.constructor).toBe(ErrorResponse); - expect(response2.constructor).toBe(ErrorResponse); - }); - - it('should return a IntegrationSuccessResponse with data definition', () => { - const response = service.parse(validRequest, validResponse); - expect((response as any).dataDefinition).toEqual(definitions); - }); - - }); -}); diff --git a/src/app/core/integration/integration-response-parsing.service.ts b/src/app/core/integration/integration-response-parsing.service.ts deleted file mode 100644 index 2719669bae..0000000000 --- a/src/app/core/integration/integration-response-parsing.service.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { Inject, Injectable } from '@angular/core'; -import { RestRequest } from '../data/request.models'; -import { ResponseParsingService } from '../data/parsing.service'; -import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; -import { ErrorResponse, IntegrationSuccessResponse, RestResponse } from '../cache/response.models'; -import { isNotEmpty } from '../../shared/empty.util'; - -import { BaseResponseParsingService } from '../data/base-response-parsing.service'; -import { ObjectCacheService } from '../cache/object-cache.service'; -import { IntegrationModel } from './models/integration.model'; -import { AuthorityValue } from './models/authority.value'; -import { PaginatedList } from '../data/paginated-list'; - -@Injectable() -export class IntegrationResponseParsingService extends BaseResponseParsingService implements ResponseParsingService { - - protected toCache = true; - - constructor( - protected objectCache: ObjectCacheService, - ) { - super(); - } - - parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { - if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links)) { - const dataDefinition = this.process(data.payload, request); - return new IntegrationSuccessResponse(this.processResponse(dataDefinition), data.statusCode, data.statusText, this.processPageInfo(data.payload)); - } else { - return new ErrorResponse( - Object.assign( - new Error('Unexpected response from Integration endpoint'), - {statusCode: data.statusCode, statusText: data.statusText} - ) - ); - } - } - - protected processResponse(data: PaginatedList): any { - const returnList = Array.of(); - data.page.forEach((item, index) => { - if (item.type === AuthorityValue.type.value) { - data.page[index] = Object.assign(new AuthorityValue(), item); - } - }); - - return data; - } - -} diff --git a/src/app/core/integration/integration.service.spec.ts b/src/app/core/integration/integration.service.spec.ts deleted file mode 100644 index 148a5df7b8..0000000000 --- a/src/app/core/integration/integration.service.spec.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { cold, getTestScheduler } from 'jasmine-marbles'; -import { TestScheduler } from 'rxjs/testing'; -import { getMockRequestService } from '../../shared/mocks/request.service.mock'; - -import { RequestService } from '../data/request.service'; -import { IntegrationRequest } from '../data/request.models'; -import { HALEndpointService } from '../shared/hal-endpoint.service'; -import { HALEndpointServiceStub } from '../../shared/testing/hal-endpoint-service.stub'; -import { IntegrationService } from './integration.service'; -import { IntegrationSearchOptions } from './models/integration-options.model'; -import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; -import { getMockRemoteDataBuildService } from '../../shared/mocks/remote-data-build.service.mock'; - -const LINK_NAME = 'authorities'; -const ENTRIES = 'entries'; -const ENTRY_VALUE = 'entryValue'; - -class TestService extends IntegrationService { - protected linkPath = LINK_NAME; - protected entriesEndpoint = ENTRIES; - protected entryValueEndpoint = ENTRY_VALUE; - - constructor( - protected requestService: RequestService, - protected rdbService: RemoteDataBuildService, - protected halService: HALEndpointService) { - super(); - } -} - -describe('IntegrationService', () => { - let scheduler: TestScheduler; - let service: TestService; - let requestService: RequestService; - let rdbService: RemoteDataBuildService; - let halService: any; - let findOptions: IntegrationSearchOptions; - - const name = 'type'; - const metadata = 'dc.type'; - const query = ''; - const value = 'test'; - const uuid = 'd9d30c0c-69b7-4369-8397-ca67c888974d'; - const integrationEndpoint = 'https://rest.api/integration'; - const serviceEndpoint = `${integrationEndpoint}/${LINK_NAME}`; - const entriesEndpoint = `${serviceEndpoint}/${name}/entries?query=${query}&metadata=${metadata}&uuid=${uuid}`; - const entryValueEndpoint = `${serviceEndpoint}/${name}/entryValue/${value}?metadata=${metadata}`; - - findOptions = new IntegrationSearchOptions(uuid, name, metadata); - - function initTestService(): TestService { - return new TestService( - requestService, - rdbService, - halService - ); - } - - beforeEach(() => { - requestService = getMockRequestService(); - rdbService = getMockRemoteDataBuildService(); - scheduler = getTestScheduler(); - halService = new HALEndpointServiceStub(integrationEndpoint); - findOptions = new IntegrationSearchOptions(uuid, name, metadata, query); - service = initTestService(); - - }); - - describe('getEntriesByName', () => { - - it('should configure a new IntegrationRequest', () => { - const expected = new IntegrationRequest(requestService.generateRequestId(), entriesEndpoint); - scheduler.schedule(() => service.getEntriesByName(findOptions).subscribe()); - scheduler.flush(); - - expect(requestService.configure).toHaveBeenCalledWith(expected); - }); - }); - - describe('getEntryByValue', () => { - - it('should configure a new IntegrationRequest', () => { - findOptions = new IntegrationSearchOptions( - null, - name, - metadata, - value); - - const expected = new IntegrationRequest(requestService.generateRequestId(), entryValueEndpoint); - scheduler.schedule(() => service.getEntryByValue(findOptions).subscribe()); - scheduler.flush(); - - expect(requestService.configure).toHaveBeenCalledWith(expected); - }); - }); -}); diff --git a/src/app/core/integration/integration.service.ts b/src/app/core/integration/integration.service.ts deleted file mode 100644 index 5826f4646d..0000000000 --- a/src/app/core/integration/integration.service.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { Observable, of as observableOf, throwError as observableThrowError } from 'rxjs'; -import { distinctUntilChanged, filter, map, mergeMap, tap } from 'rxjs/operators'; -import { RequestService } from '../data/request.service'; -import { IntegrationSuccessResponse } from '../cache/response.models'; -import { GetRequest, IntegrationRequest } from '../data/request.models'; -import { hasValue, isNotEmpty } from '../../shared/empty.util'; -import { HALEndpointService } from '../shared/hal-endpoint.service'; -import { IntegrationData } from './integration-data'; -import { IntegrationSearchOptions } from './models/integration-options.model'; -import { getResponseFromEntry } from '../shared/operators'; - -export abstract class IntegrationService { - protected request: IntegrationRequest; - protected abstract requestService: RequestService; - protected abstract linkPath: string; - protected abstract entriesEndpoint: string; - protected abstract entryValueEndpoint: string; - protected abstract halService: HALEndpointService; - - protected getData(request: GetRequest): Observable { - return this.requestService.getByHref(request.href).pipe( - getResponseFromEntry(), - mergeMap((response: IntegrationSuccessResponse) => { - if (response.isSuccessful && isNotEmpty(response)) { - return observableOf(new IntegrationData( - response.pageInfo, - (response.dataDefinition) ? response.dataDefinition.page : [] - )); - } else if (!response.isSuccessful) { - return observableThrowError(new Error(`Couldn't retrieve the integration data`)); - } - }), - distinctUntilChanged() - ); - } - - protected getEntriesHref(endpoint, options: IntegrationSearchOptions = new IntegrationSearchOptions()): string { - let result; - const args = []; - - if (hasValue(options.name)) { - result = `${endpoint}/${options.name}/${this.entriesEndpoint}`; - } else { - result = endpoint; - } - - if (hasValue(options.query)) { - args.push(`query=${options.query}`); - } - - if (hasValue(options.metadata)) { - args.push(`metadata=${options.metadata}`); - } - - if (hasValue(options.uuid)) { - args.push(`uuid=${options.uuid}`); - } - - if (hasValue(options.currentPage) && typeof options.currentPage === 'number') { - /* TODO: this is a temporary fix for the pagination start index (0 or 1) discrepancy between the rest and the frontend respectively */ - args.push(`page=${options.currentPage - 1}`); - } - - if (hasValue(options.elementsPerPage)) { - args.push(`size=${options.elementsPerPage}`); - } - - if (hasValue(options.sort)) { - args.push(`sort=${options.sort.field},${options.sort.direction}`); - } - - if (isNotEmpty(args)) { - result = `${result}?${args.join('&')}`; - } - return result; - } - - protected getEntryValueHref(endpoint, options: IntegrationSearchOptions = new IntegrationSearchOptions()): string { - let result; - const args = []; - - if (hasValue(options.name) && hasValue(options.query)) { - result = `${endpoint}/${options.name}/${this.entryValueEndpoint}/${options.query}`; - } else { - result = endpoint; - } - - if (hasValue(options.metadata)) { - args.push(`metadata=${options.metadata}`); - } - - if (isNotEmpty(args)) { - result = `${result}?${args.join('&')}`; - } - - return result; - } - - public getEntriesByName(options: IntegrationSearchOptions): Observable { - return this.halService.getEndpoint(this.linkPath).pipe( - map((endpoint: string) => this.getEntriesHref(endpoint, options)), - filter((href: string) => isNotEmpty(href)), - distinctUntilChanged(), - map((endpointURL: string) => new IntegrationRequest(this.requestService.generateRequestId(), endpointURL)), - tap((request: GetRequest) => this.requestService.configure(request)), - mergeMap((request: GetRequest) => this.getData(request)), - distinctUntilChanged()); - } - - public getEntryByValue(options: IntegrationSearchOptions): Observable { - return this.halService.getEndpoint(this.linkPath).pipe( - map((endpoint: string) => this.getEntryValueHref(endpoint, options)), - filter((href: string) => isNotEmpty(href)), - distinctUntilChanged(), - map((endpointURL: string) => new IntegrationRequest(this.requestService.generateRequestId(), endpointURL)), - tap((request: GetRequest) => this.requestService.configure(request)), - mergeMap((request: GetRequest) => this.getData(request)), - distinctUntilChanged()); - } - -} diff --git a/src/app/core/integration/models/authority-options.model.ts b/src/app/core/integration/models/authority-options.model.ts deleted file mode 100644 index 0b826f7f9c..0000000000 --- a/src/app/core/integration/models/authority-options.model.ts +++ /dev/null @@ -1,16 +0,0 @@ -export class AuthorityOptions { - name: string; - metadata: string; - scope: string; - closed: boolean; - - constructor(name: string, - metadata: string, - scope: string, - closed: boolean = false) { - this.name = name; - this.metadata = metadata; - this.scope = scope; - this.closed = closed; - } -} diff --git a/src/app/core/integration/models/authority.resource-type.ts b/src/app/core/integration/models/authority.resource-type.ts deleted file mode 100644 index ec87ddc85f..0000000000 --- a/src/app/core/integration/models/authority.resource-type.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { ResourceType } from '../../shared/resource-type'; - -/** - * The resource type for AuthorityValue - * - * Needs to be in a separate file to prevent circular - * dependencies in webpack. - */ - -export const AUTHORITY_VALUE = new ResourceType('authority'); diff --git a/src/app/core/integration/models/authority.value.ts b/src/app/core/integration/models/authority.value.ts deleted file mode 100644 index 4e0183603b..0000000000 --- a/src/app/core/integration/models/authority.value.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { autoserialize, deserialize, inheritSerialization } from 'cerialize'; -import { isNotEmpty } from '../../../shared/empty.util'; -import { PLACEHOLDER_PARENT_METADATA } from '../../../shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.model'; -import { OtherInformation } from '../../../shared/form/builder/models/form-field-metadata-value.model'; -import { typedObject } from '../../cache/builders/build-decorators'; -import { HALLink } from '../../shared/hal-link.model'; -import { MetadataValueInterface } from '../../shared/metadata.models'; -import { AUTHORITY_VALUE } from './authority.resource-type'; -import { IntegrationModel } from './integration.model'; - -/** - * Class representing an authority object - */ -@typedObject -@inheritSerialization(IntegrationModel) -export class AuthorityValue extends IntegrationModel implements MetadataValueInterface { - static type = AUTHORITY_VALUE; - - /** - * The identifier of this authority - */ - @autoserialize - id: string; - - /** - * The display value of this authority - */ - @autoserialize - display: string; - - /** - * The value of this authority - */ - @autoserialize - value: string; - - /** - * An object containing additional information related to this authority - */ - @autoserialize - otherInformation: OtherInformation; - - /** - * The language code of this authority value - */ - @autoserialize - language: string; - - /** - * The {@link HALLink}s for this AuthorityValue - */ - @deserialize - _links: { - self: HALLink, - }; - - /** - * This method checks if authority has an identifier value - * - * @return boolean - */ - hasAuthority(): boolean { - return isNotEmpty(this.id); - } - - /** - * This method checks if authority has a value - * - * @return boolean - */ - hasValue(): boolean { - return isNotEmpty(this.value); - } - - /** - * This method checks if authority has related information object - * - * @return boolean - */ - hasOtherInformation(): boolean { - return isNotEmpty(this.otherInformation); - } - - /** - * This method checks if authority has a placeholder as value - * - * @return boolean - */ - hasPlaceholder(): boolean { - return this.hasValue() && this.value === PLACEHOLDER_PARENT_METADATA; - } -} diff --git a/src/app/core/integration/models/integration-options.model.ts b/src/app/core/integration/models/integration-options.model.ts deleted file mode 100644 index 5f158bd47c..0000000000 --- a/src/app/core/integration/models/integration-options.model.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { SortOptions } from '../../cache/models/sort-options.model'; - -export class IntegrationSearchOptions { - - constructor(public uuid: string = '', - public name: string = '', - public metadata: string = '', - public query: string = '', - public elementsPerPage?: number, - public currentPage?: number, - public sort?: SortOptions) { - - } -} diff --git a/src/app/core/integration/models/integration.model.ts b/src/app/core/integration/models/integration.model.ts deleted file mode 100644 index d2f21a70c0..0000000000 --- a/src/app/core/integration/models/integration.model.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { autoserialize, deserialize } from 'cerialize'; -import { CacheableObject } from '../../cache/object-cache.reducer'; -import { HALLink } from '../../shared/hal-link.model'; - -export abstract class IntegrationModel implements CacheableObject { - - @autoserialize - self: string; - - @autoserialize - uuid: string; - - @autoserialize - public type: any; - - @deserialize - public _links: { - self: HALLink, - [name: string]: HALLink - } - -} From 9ada61db2874730bc94fa7da7305e7b055975b6b Mon Sep 17 00:00:00 2001 From: Matteo Perelli Date: Thu, 25 Jun 2020 16:58:43 +0200 Subject: [PATCH 018/170] Multiple call to external source service fix --- .../import-external/submission-import-external.component.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/app/submission/import-external/submission-import-external.component.ts b/src/app/submission/import-external/submission-import-external.component.ts index 9988f098c9..e23dce9719 100644 --- a/src/app/submission/import-external/submission-import-external.component.ts +++ b/src/app/submission/import-external/submission-import-external.component.ts @@ -7,7 +7,7 @@ import { RemoteData } from '../../core/data/remote-data'; import { PaginatedList } from '../../core/data/paginated-list'; import { ExternalSourceEntry } from '../../core/shared/external-source-entry.model'; import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service'; -import { switchMap, filter } from 'rxjs/operators'; +import { switchMap, filter, take } from 'rxjs/operators'; import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; import { Context } from '../../core/shared/context.model'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; @@ -116,7 +116,8 @@ export class SubmissionImportExternalComponent implements OnInit { return this.searchConfigService.paginatedSearchOptions.pipe( switchMap((searchOptions: PaginatedSearchOptions) => { return this.externalService.getExternalSourceEntries(this.routeData.sourceId, searchOptions); - }) + }), + take(1) ) }), ).subscribe((rdData) => { From 59564eb44d1b8bc56bbfedc601693a556181eb80 Mon Sep 17 00:00:00 2001 From: Danilo Di Nuzzo Date: Fri, 26 Jun 2020 09:25:22 +0200 Subject: [PATCH 019/170] [CST-3091] add comp collection-selector, fix issue --- .../collection-selector.component.html | 11 +++++ .../collection-selector.component.scss | 0 .../collection-selector.component.spec.ts | 25 +++++++++++ .../collection-selector.component.ts | 35 ++++++++++++++++ .../my-dspace-new-submission.component.html | 3 +- .../my-dspace-new-submission.component.ts | 41 +++++++++++++++++-- .../+my-dspace-page/my-dspace-page.module.ts | 7 +++- .../shared/uploader/uploader-error.model.ts | 9 ++++ .../shared/uploader/uploader-options.model.ts | 5 +++ src/app/shared/uploader/uploader.component.ts | 13 +++++- src/assets/i18n/en.json5 | 4 ++ 11 files changed, 145 insertions(+), 8 deletions(-) create mode 100644 src/app/+my-dspace-page/collection-selector/collection-selector.component.html create mode 100644 src/app/+my-dspace-page/collection-selector/collection-selector.component.scss create mode 100644 src/app/+my-dspace-page/collection-selector/collection-selector.component.spec.ts create mode 100644 src/app/+my-dspace-page/collection-selector/collection-selector.component.ts create mode 100644 src/app/shared/uploader/uploader-error.model.ts diff --git a/src/app/+my-dspace-page/collection-selector/collection-selector.component.html b/src/app/+my-dspace-page/collection-selector/collection-selector.component.html new file mode 100644 index 0000000000..ef8865ad87 --- /dev/null +++ b/src/app/+my-dspace-page/collection-selector/collection-selector.component.html @@ -0,0 +1,11 @@ +
+ + +
diff --git a/src/app/+my-dspace-page/collection-selector/collection-selector.component.scss b/src/app/+my-dspace-page/collection-selector/collection-selector.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/+my-dspace-page/collection-selector/collection-selector.component.spec.ts b/src/app/+my-dspace-page/collection-selector/collection-selector.component.spec.ts new file mode 100644 index 0000000000..8cfc6e6361 --- /dev/null +++ b/src/app/+my-dspace-page/collection-selector/collection-selector.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CollectionSelectorComponent } from './collection-selector.component'; + +describe('CollectionSelectorComponent', () => { + let component: CollectionSelectorComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ CollectionSelectorComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(CollectionSelectorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/+my-dspace-page/collection-selector/collection-selector.component.ts b/src/app/+my-dspace-page/collection-selector/collection-selector.component.ts new file mode 100644 index 0000000000..e1a5a887d3 --- /dev/null +++ b/src/app/+my-dspace-page/collection-selector/collection-selector.component.ts @@ -0,0 +1,35 @@ +import { Component, OnInit } from '@angular/core'; +import { DSOSelectorModalWrapperComponent, SelectorActionType } from 'src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component'; +import { DSpaceObject } from '../../core/shared/dspace-object.model'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { ActivatedRoute, Router } from '@angular/router'; +import { DSpaceObjectType } from 'src/app/core/shared/dspace-object-type.model'; + +@Component({ + selector: 'ds-collection-selector', + templateUrl: './collection-selector.component.html', + styleUrls: ['./collection-selector.component.scss'] +}) +export class CollectionSelectorComponent extends DSOSelectorModalWrapperComponent { + objectType = DSpaceObjectType.ITEM; + selectorType = DSpaceObjectType.COLLECTION; + action = SelectorActionType.CREATE; + + navigate(dso: DSpaceObject) { + throw new Error('Method not implemented.'); + } + + constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) { + super(activeModal, route); + } + + /** + * Method called when an element has been selected from collection list. + * Its close the active modal and send selected value to the component container + * @param dso The selected DSpaceObject + */ + selectObject(dso: DSpaceObject) { + this.activeModal.close(dso); + } + +} diff --git a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html index 4809f206ae..a3181f3dfe 100644 --- a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html +++ b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html @@ -3,7 +3,8 @@ + (onUploadError)="onUploadError($event)" + (onFileSelected)="uploadDialogForFileUpload($event)">
diff --git a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts index 8d20a5736a..d68502a476 100644 --- a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts +++ b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectorRef, Component, EventEmitter, OnDestroy, OnInit, Output } from '@angular/core'; +import { ChangeDetectorRef, Component, EventEmitter, OnDestroy, OnInit, Output, ViewChild } from '@angular/core'; import { Subscription } from 'rxjs'; import { first } from 'rxjs/operators'; @@ -18,6 +18,9 @@ import { SearchResult } from '../../shared/search/search-result.model'; import { Router } from '@angular/router'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { CreateItemParentSelectorComponent } from 'src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component'; +import { CollectionSelectorComponent } from '../collection-selector/collection-selector.component'; +import { UploaderComponent } from 'src/app/shared/uploader/uploader.component'; +import { UploaderError } from 'src/app/shared/uploader/uploader-error.model'; /** * This component represents the whole mydspace page header @@ -43,6 +46,11 @@ export class MyDSpaceNewSubmissionComponent implements OnDestroy, OnInit { */ private sub: Subscription; + /** + * Reference to uploaderComponent + */ + @ViewChild(UploaderComponent, { static: false }) uploaderComponent: UploaderComponent; + /** * Initialize instance variables * @@ -67,6 +75,7 @@ export class MyDSpaceNewSubmissionComponent implements OnDestroy, OnInit { * Initialize url and Bearer token */ ngOnInit() { + this.uploadFilesOptions.autoUpload = false; this.sub = this.halService.getEndpoint('workspaceitems').pipe(first()).subscribe((url) => { this.uploadFilesOptions.url = url; this.uploadFilesOptions.authToken = this.authService.buildAuthHeader(); @@ -106,8 +115,12 @@ export class MyDSpaceNewSubmissionComponent implements OnDestroy, OnInit { /** * Method called on file upload error */ - public onUploadError() { - this.notificationsService.error(null, this.translate.get('mydspace.upload.upload-failed')); + public onUploadError(error: UploaderError) { + let errorMessageKey = 'mydspace.upload.upload-failed'; + if (hasValue(error.status) && error.status === 422) { + errorMessageKey = 'mydspace.upload.upload-failed-manyentries'; + } + this.notificationsService.error(null, this.translate.get(errorMessageKey)); } /** @@ -118,6 +131,28 @@ export class MyDSpaceNewSubmissionComponent implements OnDestroy, OnInit { this.modalService.open(CreateItemParentSelectorComponent); } + /** + * Method for open dialog after submission file selection + */ + uploadDialogForFileUpload(items) { + const uploader = this.uploaderComponent.uploader; + if (hasValue(items) && items.length > 1) { + this.notificationsService.error(null, this.translate.get('mydspace.upload.upload-failed-moreonefile')); + uploader.clearQueue(); + this.changeDetectorRef.detectChanges(); + } else { + const modalRef = this.modalService.open(CollectionSelectorComponent); + // When the dialog are closes its takes the collection selected and + // uploads choosed file after adds owningCollection parameter + modalRef.result.then( (result) => { + uploader.onBuildItemForm = (fileItem: any, form: any) => { + form.append('owningCollection', result.uuid); + }; + uploader.uploadAll(); + }); + } + } + /** * Unsubscribe from the subscription */ diff --git a/src/app/+my-dspace-page/my-dspace-page.module.ts b/src/app/+my-dspace-page/my-dspace-page.module.ts index 1cf30c4ec9..49570fec6d 100644 --- a/src/app/+my-dspace-page/my-dspace-page.module.ts +++ b/src/app/+my-dspace-page/my-dspace-page.module.ts @@ -20,6 +20,7 @@ import { SearchResultListElementComponent } from '../shared/object-list/search-r import { ItemSearchResultListElementSubmissionComponent } from '../shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component'; import { WorkflowItemSearchResultListElementComponent } from '../shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component'; import { PoolSearchResultDetailElementComponent } from '../shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component'; +import { CollectionSelectorComponent } from './collection-selector/collection-selector.component'; @NgModule({ imports: [ @@ -40,7 +41,8 @@ import { PoolSearchResultDetailElementComponent } from '../shared/object-detail/ ClaimedTaskSearchResultDetailElementComponent, PoolSearchResultDetailElementComponent, MyDSpaceNewSubmissionComponent, - ItemSearchResultListElementSubmissionComponent + ItemSearchResultListElementSubmissionComponent, + CollectionSelectorComponent ], providers: [ MyDSpaceGuard, @@ -57,7 +59,8 @@ import { PoolSearchResultDetailElementComponent } from '../shared/object-detail/ WorkflowItemSearchResultDetailElementComponent, ClaimedTaskSearchResultDetailElementComponent, PoolSearchResultDetailElementComponent, - ItemSearchResultListElementSubmissionComponent + ItemSearchResultListElementSubmissionComponent, + CollectionSelectorComponent ] }) diff --git a/src/app/shared/uploader/uploader-error.model.ts b/src/app/shared/uploader/uploader-error.model.ts new file mode 100644 index 0000000000..9238a0df36 --- /dev/null +++ b/src/app/shared/uploader/uploader-error.model.ts @@ -0,0 +1,9 @@ +/** + * An interface that represents the upload error values + */ +export interface UploaderError { + item?: any; + response?: any; + status?: any; + headers?: any; +} diff --git a/src/app/shared/uploader/uploader-options.model.ts b/src/app/shared/uploader/uploader-options.model.ts index f195b0930e..959e5c3295 100644 --- a/src/app/shared/uploader/uploader-options.model.ts +++ b/src/app/shared/uploader/uploader-options.model.ts @@ -17,6 +17,11 @@ export class UploaderOptions { */ autoUpload = true; + /** + * Set the max number of files that can be loaded + */ + maxFileNumber: number; + /** * The request method to use for the file upload request */ diff --git a/src/app/shared/uploader/uploader.component.ts b/src/app/shared/uploader/uploader.component.ts index 72a38d1eb1..07f4245954 100644 --- a/src/app/shared/uploader/uploader.component.ts +++ b/src/app/shared/uploader/uploader.component.ts @@ -69,6 +69,11 @@ export class UploaderComponent { */ @Output() onUploadError: EventEmitter = new EventEmitter(); + /** + * The function to call when a file is selected + */ + @Output() onFileSelected: EventEmitter = new EventEmitter(); + public uploader: FileUploader; public uploaderId: string; public isOverBaseDropZone = observableOf(false); @@ -102,7 +107,8 @@ export class UploaderComponent { itemAlias: this.uploadFilesOptions.itemAlias, removeAfterUpload: true, autoUpload: this.uploadFilesOptions.autoUpload, - method: this.uploadFilesOptions.method + method: this.uploadFilesOptions.method, + queueLimit: this.uploadFilesOptions.maxFileNumber }); if (isUndefined(this.enableDragOverDocument)) { @@ -121,6 +127,9 @@ export class UploaderComponent { this.uploader.onAfterAddingFile = ((item) => { item.withCredentials = false; }); + this.uploader.onAfterAddingAll = ((items) => { + this.onFileSelected.emit(items); + }); if (isUndefined(this.onBeforeUpload)) { this.onBeforeUpload = () => {return}; } @@ -149,7 +158,7 @@ export class UploaderComponent { } }; this.uploader.onErrorItem = (item: any, response: any, status: any, headers: any) => { - this.onUploadError.emit(null); + this.onUploadError.emit({ item: item, response: response, status: status, headers: headers }); this.uploader.cancelAll(); }; this.uploader.onProgressAll = () => this.onProgress(); diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 4173fa1cf2..e7cfdb9e4d 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1803,6 +1803,10 @@ "mydspace.upload.upload-failed": "Error creating new workspace. Please verify the content uploaded before retry.", + "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", + + "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", + "mydspace.upload.upload-multiple-successful": "{{qty}} new workspace items created.", "mydspace.upload.upload-successful": "New workspace item created. Click {{here}} for edit it.", From 97b4b905857c885f65d1171c090c7954784add4c Mon Sep 17 00:00:00 2001 From: Matteo Perelli Date: Fri, 26 Jun 2020 09:29:11 +0200 Subject: [PATCH 020/170] Additional fix for CI tests --- src/app/core/data/external-source.service.ts | 2 +- .../submission-import-external-preview.component.spec.ts | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/app/core/data/external-source.service.ts b/src/app/core/data/external-source.service.ts index eda0440b4a..0d84639a40 100644 --- a/src/app/core/data/external-source.service.ts +++ b/src/app/core/data/external-source.service.ts @@ -11,7 +11,7 @@ import { NotificationsService } from '../../shared/notifications/notifications.s import { HttpClient } from '@angular/common/http'; import { FindListOptions, GetRequest } from './request.models'; import { Observable } from 'rxjs/internal/Observable'; -import { distinctUntilChanged, map, switchMap, take, flatMap, catchError } from 'rxjs/operators'; +import { distinctUntilChanged, map, switchMap } from 'rxjs/operators'; import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; import { hasValue, isNotEmptyOperator } from '../../shared/empty.util'; import { configureRequest } from '../shared/operators'; diff --git a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts index 71360b9cc3..2060594de4 100644 --- a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts +++ b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts @@ -21,6 +21,7 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { let compAsAny: any; let fixture: ComponentFixture; let submissionServiceStub: SubmissionServiceStub; + const modal = jasmine.createSpyObj('modal', ['close', 'dismiss']); const externalEntry = Object.assign(new ExternalSourceEntry(), { id: '0001-0001-0001-0001', display: 'John Doe', @@ -49,7 +50,7 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { { provide: SubmissionService, useValue: new SubmissionServiceStub() }, { provide: NotificationsService, useValue: new NotificationsServiceStub() }, { provide: NgbModal, useValue: { open: () => {/*comment*/} } }, - { provide: NgbActiveModal, useValue: { dismiss: () => {/*comment*/} } }, + { provide: NgbActiveModal, useValue: modal }, SubmissionImportExternalPreviewComponent ], schemas: [NO_ERRORS_SCHEMA] @@ -103,7 +104,7 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { }); it('Should close the modal calling \'activeModal.dismiss\'', () => { - spyOn(compAsAny.activeModal, 'dismiss'); + comp.modalRef = jasmine.createSpyObj('modal', ['close', 'dismiss']); comp.closeMetadataModal(); expect(compAsAny.activeModal.dismiss).toHaveBeenCalled(); From e094663a774e973e1334ef78e9f5faf72f0d490c Mon Sep 17 00:00:00 2001 From: Matteo Perelli Date: Fri, 26 Jun 2020 11:19:44 +0200 Subject: [PATCH 021/170] Additional fix for CI tests --- .../submission-import-external-preview.component.spec.ts | 9 +++++---- .../submission-import-external.component.spec.ts | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts index 2060594de4..3bb6a19645 100644 --- a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts +++ b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts @@ -21,7 +21,8 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { let compAsAny: any; let fixture: ComponentFixture; let submissionServiceStub: SubmissionServiceStub; - const modal = jasmine.createSpyObj('modal', ['close', 'dismiss']); + const ngbActiveModal = jasmine.createSpyObj('modal', ['close', 'dismiss']); + const ngbModal = jasmine.createSpyObj('modal', ['open']); const externalEntry = Object.assign(new ExternalSourceEntry(), { id: '0001-0001-0001-0001', display: 'John Doe', @@ -49,8 +50,8 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { { provide: Router, useValue: new RouterStub() }, { provide: SubmissionService, useValue: new SubmissionServiceStub() }, { provide: NotificationsService, useValue: new NotificationsServiceStub() }, - { provide: NgbModal, useValue: { open: () => {/*comment*/} } }, - { provide: NgbActiveModal, useValue: modal }, + { provide: NgbModal, useValue: ngbModal }, + { provide: NgbActiveModal, useValue: ngbActiveModal }, SubmissionImportExternalPreviewComponent ], schemas: [NO_ERRORS_SCHEMA] @@ -129,7 +130,7 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { { id: 'jk11k13o-9v4z-632i-sr88-wq071n0h1d47' } ]; comp.externalSourceEntry = externalEntry; - spyOn(compAsAny.modalService, 'open').and.returnValue({componentInstance: { selectedEvent: observableOf(emittedEvent)}}); + ngbModal.open.and.returnValue({componentInstance: { selectedEvent: observableOf(emittedEvent)}}); spyOn(comp, 'closeMetadataModal'); submissionServiceStub.createSubmissionFromExternalSource.and.returnValue(observableOf(submissionObjects)); spyOn(compAsAny.router, 'navigateByUrl'); diff --git a/src/app/submission/import-external/submission-import-external.component.spec.ts b/src/app/submission/import-external/submission-import-external.component.spec.ts index 6b5ec05171..923d431923 100644 --- a/src/app/submission/import-external/submission-import-external.component.spec.ts +++ b/src/app/submission/import-external/submission-import-external.component.spec.ts @@ -23,6 +23,7 @@ describe('SubmissionImportExternalComponent test suite', () => { let comp: SubmissionImportExternalComponent; let compAsAny: any; let fixture: ComponentFixture; + const ngbModal = jasmine.createSpyObj('modal', ['open']); const mockSearchOptions = of(new PaginatedSearchOptions({ pagination: Object.assign(new PaginationComponentOptions(), { pageSize: 10, @@ -48,7 +49,7 @@ describe('SubmissionImportExternalComponent test suite', () => { { provide: SearchConfigurationService, useValue: searchConfigServiceStub }, { provide: RouteService, useValue: routeServiceStub }, { provide: Router, useValue: new RouterStub() }, - NgbModal, + { provide: NgbModal, useValue: ngbModal }, SubmissionImportExternalComponent ], schemas: [NO_ERRORS_SCHEMA] @@ -93,7 +94,6 @@ describe('SubmissionImportExternalComponent test suite', () => { it('Should init component properly (without route data)', () => { const expectedEntries = createSuccessfulRemoteDataObject(createPaginatedList([])); spyOn(compAsAny.routeService, 'getQueryParameterValue').and.returnValue(observableOf('')); - comp.ngOnInit(); fixture.detectChanges(); expect(comp.routeData).toEqual({ sourceId: '', query: '' }); @@ -139,7 +139,7 @@ describe('SubmissionImportExternalComponent test suite', () => { ] } }); - spyOn(compAsAny.modalService, 'open').and.returnValue({componentInstance: { externalSourceEntry: null}}); + ngbModal.open.and.returnValue({componentInstance: { externalSourceEntry: null}}); comp.import(entry); expect(compAsAny.modalService.open).toHaveBeenCalledWith(SubmissionImportExternalPreviewComponent, { size: 'lg' }); From 0ca1798537d976338fedbb47890216c648c0e9d4 Mon Sep 17 00:00:00 2001 From: Danilo Di Nuzzo Date: Fri, 26 Jun 2020 15:25:58 +0200 Subject: [PATCH 022/170] [CST-3091] fix tests and add new labels --- .../collection-selector.component.html | 2 +- .../collection-selector.component.spec.ts | 138 +- .../collection-selector.component.ts | 18 +- .../my-dspace-new-submission.component.html | 2 +- ...my-dspace-new-submission.component.spec.ts | 38 +- .../my-dspace-new-submission.component.ts | 10 +- src/assets/i18n/ar.json5 | 556 ++- src/assets/i18n/cs.json5 | 556 ++- src/assets/i18n/de.json5 | 552 ++- src/assets/i18n/en.json5 | 2 + src/assets/i18n/es.json5 | 3224 ++++++++++------- src/assets/i18n/fi.json5 | 554 ++- src/assets/i18n/fr.json5 | 552 ++- src/assets/i18n/ja.json5 | 556 ++- src/assets/i18n/lv.json5 | 524 ++- src/assets/i18n/nl.json5 | 553 ++- src/assets/i18n/pl.json5 | 556 ++- src/assets/i18n/pt.json5 | 552 ++- src/assets/i18n/sw.json5 | 556 ++- src/assets/i18n/tr.json5 | 556 ++- 20 files changed, 8607 insertions(+), 1450 deletions(-) diff --git a/src/app/+my-dspace-page/collection-selector/collection-selector.component.html b/src/app/+my-dspace-page/collection-selector/collection-selector.component.html index ef8865ad87..83cc4151a3 100644 --- a/src/app/+my-dspace-page/collection-selector/collection-selector.component.html +++ b/src/app/+my-dspace-page/collection-selector/collection-selector.component.html @@ -1,5 +1,5 @@
-
diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts index ce45e113a0..66eca2393b 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts @@ -4,6 +4,7 @@ import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angul import { async, ComponentFixture, fakeAsync, inject, TestBed, tick, } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; +import { of as observableOf } from 'rxjs'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { TranslateModule } from '@ngx-translate/core'; import { InfiniteScrollModule } from 'ngx-infinite-scroll'; @@ -309,7 +310,13 @@ describe('Dynamic Lookup component', () => { lookupComp = lookupFixture.componentInstance; // FormComponent test instance lookupComp.group = LOOKUP_TEST_GROUP; lookupComp.model = new DynamicLookupModel(LOOKUP_TEST_MODEL_CONFIG); - lookupComp.model.value = new FormFieldMetadataValueObject('test', null, 'test001'); + const entry = observableOf(Object.assign(new VocabularyEntry(), { + authority: null, + value: 'test', + display: 'testDisplay' + })); + spyOn((lookupComp as any).vocabularyService, 'getVocabularyEntryByValue').and.returnValue(entry); + (lookupComp.model as any).value = new FormFieldMetadataValueObject('test', null, null, 'testDisplay'); lookupFixture.detectChanges(); // spyOn(store, 'dispatch'); @@ -318,9 +325,52 @@ describe('Dynamic Lookup component', () => { lookupFixture.destroy(); lookupComp = null; }); - it('should init component properly', () => { - expect(lookupComp.firstInputValue).toBe('test'); + it('should init component properly', fakeAsync(() => { + tick(); + expect(lookupComp.firstInputValue).toBe('testDisplay'); + expect((lookupComp as any).vocabularyService.getVocabularyEntryByValue).toHaveBeenCalled(); + })); + + it('should have search button disabled on edit mode', () => { + lookupComp.editMode = true; + lookupFixture.detectChanges(); + + const de = lookupFixture.debugElement.queryAll(By.css('button')); + const searchBtnEl = de[0].nativeElement; + const saveBtnEl = de[1].nativeElement; + expect(searchBtnEl.disabled).toBe(true); + expect(saveBtnEl.disabled).toBe(false); + expect(saveBtnEl.textContent.trim()).toBe('form.save'); + }); + }); + describe('and init model value is not empty with authority', () => { + beforeEach(() => { + + lookupFixture = TestBed.createComponent(DsDynamicLookupComponent); + lookupComp = lookupFixture.componentInstance; // FormComponent test instance + lookupComp.group = LOOKUP_TEST_GROUP; + lookupComp.model = new DynamicLookupModel(LOOKUP_TEST_MODEL_CONFIG); + const entry = observableOf(Object.assign(new VocabularyEntry(), { + authority: 'test001', + value: 'test', + display: 'testDisplay' + })); + spyOn((lookupComp as any).vocabularyService, 'getVocabularyEntryByID').and.returnValue(entry); + lookupComp.model.value = new FormFieldMetadataValueObject('test', null, 'test001', 'testDisplay'); + lookupFixture.detectChanges(); + + // spyOn(store, 'dispatch'); + }); + afterEach(() => { + lookupFixture.destroy(); + lookupComp = null; + }); + it('should init component properly', fakeAsync(() => { + tick(); + expect(lookupComp.firstInputValue).toBe('testDisplay'); + expect((lookupComp as any).vocabularyService.getVocabularyEntryByID).toHaveBeenCalled(); + })); it('should have search button disabled on edit mode', () => { lookupComp.editMode = true; @@ -430,6 +480,13 @@ describe('Dynamic Lookup component', () => { lookupComp.group = LOOKUP_TEST_GROUP; lookupComp.model = new DynamicLookupNameModel(LOOKUP_NAME_TEST_MODEL_CONFIG); lookupComp.model.value = new FormFieldMetadataValueObject('Name, Lastname', null, 'test001'); + const entry = observableOf(Object.assign(new VocabularyEntry(), { + authority: null, + value: 'Name, Lastname', + display: 'Name, Lastname' + })); + spyOn((lookupComp as any).vocabularyService, 'getVocabularyEntryByValue').and.returnValue(entry); + (lookupComp.model as any).value = new FormFieldMetadataValueObject('Name, Lastname', null, null, 'Name, Lastname'); lookupFixture.detectChanges(); }); @@ -437,10 +494,55 @@ describe('Dynamic Lookup component', () => { lookupFixture.destroy(); lookupComp = null; }); - it('should init component properly', () => { + it('should init component properly', fakeAsync(() => { + tick(); expect(lookupComp.firstInputValue).toBe('Name'); expect(lookupComp.secondInputValue).toBe('Lastname'); + expect((lookupComp as any).vocabularyService.getVocabularyEntryByValue).toHaveBeenCalled(); + })); + + it('should have search button disabled on edit mode', () => { + lookupComp.editMode = true; + lookupFixture.detectChanges(); + + const de = lookupFixture.debugElement.queryAll(By.css('button')); + const searchBtnEl = de[0].nativeElement; + const saveBtnEl = de[1].nativeElement; + expect(searchBtnEl.disabled).toBe(true); + expect(saveBtnEl.disabled).toBe(false); + expect(saveBtnEl.textContent.trim()).toBe('form.save'); + }); + }); + + describe('and init model value is not empty with authority', () => { + beforeEach(() => { + + lookupFixture = TestBed.createComponent(DsDynamicLookupComponent); + lookupComp = lookupFixture.componentInstance; // FormComponent test instance + lookupComp.group = LOOKUP_TEST_GROUP; + lookupComp.model = new DynamicLookupNameModel(LOOKUP_NAME_TEST_MODEL_CONFIG); + lookupComp.model.value = new FormFieldMetadataValueObject('Name, Lastname', null, 'test001'); + const entry = observableOf(Object.assign(new VocabularyEntry(), { + authority: 'test001', + value: 'Name, Lastname', + display: 'Name, Lastname' + })); + spyOn((lookupComp as any).vocabularyService, 'getVocabularyEntryByID').and.returnValue(entry); + lookupComp.model.value = new FormFieldMetadataValueObject('Name, Lastname', null, 'test001', 'Name, Lastname'); + lookupFixture.detectChanges(); + + }); + afterEach(() => { + lookupFixture.destroy(); + lookupComp = null; + }); + it('should init component properly', fakeAsync(() => { + tick(); + expect(lookupComp.firstInputValue).toBe('Name'); + expect(lookupComp.secondInputValue).toBe('Lastname'); + expect((lookupComp as any).vocabularyService.getVocabularyEntryByID).toHaveBeenCalled(); + })); it('should have search button disabled on edit mode', () => { lookupComp.editMode = true; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts index 24422e891a..9ae4ad0737 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts @@ -4,15 +4,10 @@ import { FormGroup } from '@angular/forms'; import { of as observableOf, Subscription } from 'rxjs'; import { catchError, distinctUntilChanged } from 'rxjs/operators'; import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap'; -import { - DynamicFormControlComponent, - DynamicFormLayoutService, - DynamicFormValidationService -} from '@ng-dynamic-forms/core'; +import { DynamicFormLayoutService, DynamicFormValidationService } from '@ng-dynamic-forms/core'; import { VocabularyService } from '../../../../../../core/submission/vocabularies/vocabulary.service'; -import { VocabularyFindOptions } from '../../../../../../core/submission/vocabularies/models/vocabulary-find-options.model'; -import { hasValue, isEmpty, isNotEmpty, isNull, isUndefined } from '../../../../../empty.util'; +import { hasValue, isEmpty, isNotEmpty } from '../../../../../empty.util'; import { PageInfo } from '../../../../../../core/shared/page-info.model'; import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model'; import { VocabularyEntry } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry.model'; @@ -20,16 +15,21 @@ import { DynamicLookupNameModel } from './dynamic-lookup-name.model'; import { ConfidenceType } from '../../../../../../core/shared/confidence-type'; import { PaginatedList } from '../../../../../../core/data/paginated-list'; import { getFirstSucceededRemoteDataPayload } from '../../../../../../core/shared/operators'; +import { DsDynamicVocabularyComponent } from '../dynamic-vocabulary.component'; +import { DynamicLookupModel } from './dynamic-lookup.model'; +/** + * Component representing a lookup or lookup-name input field + */ @Component({ selector: 'ds-dynamic-lookup', styleUrls: ['./dynamic-lookup.component.scss'], templateUrl: './dynamic-lookup.component.html' }) -export class DsDynamicLookupComponent extends DynamicFormControlComponent implements OnDestroy, OnInit { +export class DsDynamicLookupComponent extends DsDynamicVocabularyComponent implements OnDestroy, OnInit { @Input() bindId = true; @Input() group: FormGroup; - @Input() model: any; + @Input() model: DynamicLookupModel | DynamicLookupNameModel; @Output() blur: EventEmitter = new EventEmitter(); @Output() change: EventEmitter = new EventEmitter(); @@ -42,89 +42,97 @@ export class DsDynamicLookupComponent extends DynamicFormControlComponent implem public pageInfo: PageInfo; public optionsList: any; - protected searchOptions: VocabularyFindOptions; protected subs: Subscription[] = []; - constructor(private vocabularyService: VocabularyService, + constructor(protected vocabularyService: VocabularyService, private cdr: ChangeDetectorRef, protected layoutService: DynamicFormLayoutService, protected validationService: DynamicFormValidationService ) { - super(layoutService, validationService); + super(vocabularyService, layoutService, validationService); } + /** + * Converts an item from the result list to a `string` to display in the `` field. + */ inputFormatter = (x: { display: string }, y: number) => { return y === 1 ? this.firstInputValue : this.secondInputValue; }; + /** + * Initialize the component, setting up the init form value + */ ngOnInit() { - this.searchOptions = new VocabularyFindOptions( - this.model.vocabularyOptions.scope, - this.model.vocabularyOptions.name, - this.model.vocabularyOptions.metadata, - '', - this.model.maxOptions, - 1); - - this.setInputsValue(this.model.value); + if (isNotEmpty(this.model.value)) { + this.setCurrentValue(this.model.value, true); + } this.subs.push(this.model.valueUpdates .subscribe((value) => { if (isEmpty(value)) { this.resetFields(); } else if (!this.editMode) { - this.setInputsValue(this.model.value); + this.setCurrentValue(this.model.value); } })); } - public formatItemForInput(item: any, field: number): string { - if (isUndefined(item) || isNull(item)) { - return ''; - } - return (typeof item === 'string') ? item : this.inputFormatter(item, field); - } - + /** + * Check if model value has an authority + */ public hasAuthorityValue() { return hasValue(this.model.value) && this.model.value.hasAuthority(); } + /** + * Check if current value has an authority + */ public hasEmptyValue() { return isNotEmpty(this.getCurrentValue()); } + /** + * Clear inputs whether there is no results and authority is closed + */ public clearFields() { - // Clear inputs whether there is no results and authority is closed if (this.model.vocabularyOptions.closed) { this.resetFields(); } } + /** + * Check if edit button is disabled + */ public isEditDisabled() { return !this.hasAuthorityValue(); } + /** + * Check if input is disabled + */ public isInputDisabled() { return (this.model.vocabularyOptions.closed && this.hasAuthorityValue() && !this.editMode); } + /** + * Check if model is instanceof DynamicLookupNameModel + */ public isLookupName() { return (this.model instanceof DynamicLookupNameModel); } + /** + * Check if search button is disabled + */ public isSearchDisabled() { return isEmpty(this.firstInputValue) || this.editMode; } - public onBlurEvent(event: Event) { - this.blur.emit(event); - } - - public onFocusEvent(event) { - this.focus.emit(event); - } - + /** + * Update model value with the typed text if vocabulary is not closed + * @param event the typed text + */ public onChange(event) { event.preventDefault(); if (!this.model.vocabularyOptions.closed) { @@ -139,31 +147,51 @@ export class DsDynamicLookupComponent extends DynamicFormControlComponent implem } } + /** + * Load more result entries + */ public onScroll() { if (!this.loading && this.pageInfo.currentPage <= this.pageInfo.totalPages) { - this.searchOptions.currentPage++; + this.updatePageInfo( + this.pageInfo.elementsPerPage, + this.pageInfo.currentPage + 1, + this.pageInfo.totalElements, + this.pageInfo.totalPages + ); this.search(); } } + /** + * Update model value with selected entry + * @param event the selected entry + */ public onSelect(event) { this.updateModel(event); } + /** + * Reset the current value when dropdown toggle + */ public openChange(isOpened: boolean) { if (!isOpened) { if (this.model.vocabularyOptions.closed && !this.hasAuthorityValue()) { - this.setInputsValue(''); + this.setCurrentValue(''); } } } + /** + * Reset the model value + */ public remove() { this.group.markAsPristine(); - this.model.valueUpdates.next(null); - this.change.emit(null); + this.dispatchUpdate(null) } + /** + * Saves all changes + */ public saveChanges() { if (isNotEmpty(this.getCurrentValue())) { const newValue = Object.assign(new VocabularyEntry(), this.model.value, { @@ -177,15 +205,21 @@ export class DsDynamicLookupComponent extends DynamicFormControlComponent implem this.switchEditMode(); } + /** + * Converts a stream of text values from the `` element to the stream of the array of items + * to display in the result list. + */ public search() { this.optionsList = null; - this.pageInfo = null; - - // Query - this.searchOptions.query = this.getCurrentValue(); - + this.updatePageInfo(this.model.maxOptions, 1); this.loading = true; - this.subs.push(this.vocabularyService.getVocabularyEntries(this.searchOptions).pipe( + + this.subs.push(this.vocabularyService.getVocabularyEntriesByValue( + this.getCurrentValue(), + false, + this.model.vocabularyOptions, + this.pageInfo + ).pipe( getFirstSucceededRemoteDataPayload(), catchError(() => observableOf(new PaginatedList( @@ -195,18 +229,28 @@ export class DsDynamicLookupComponent extends DynamicFormControlComponent implem ), distinctUntilChanged()) .subscribe((list: PaginatedList) => { - console.log(list); this.optionsList = list.page; - this.pageInfo = list.pageInfo; + this.updatePageInfo( + list.pageInfo.elementsPerPage, + list.pageInfo.currentPage, + list.pageInfo.totalElements, + list.pageInfo.totalPages + ); this.loading = false; this.cdr.detectChanges(); })); } + /** + * Changes the edit mode flag + */ public switchEditMode() { this.editMode = !this.editMode; } + /** + * Callback functions for whenClickOnConfidenceNotAccepted event + */ public whenClickOnConfidenceNotAccepted(sdRef: NgbDropdown, confidence: ConfidenceType) { if (!this.model.readOnly) { sdRef.open(); @@ -220,6 +264,38 @@ export class DsDynamicLookupComponent extends DynamicFormControlComponent implem .forEach((sub) => sub.unsubscribe()); } + /** + * Sets the current value with the given value. + * @param value The value to set. + * @param init Representing if is init value or not. + */ + public setCurrentValue(value: any, init = false) { + if (init) { + this.getInitValueFromModel() + .subscribe((value: FormFieldMetadataValueObject) => this.setDisplayInputValue(value.display)); + } else if (hasValue(value)) { + if (value instanceof FormFieldMetadataValueObject || value instanceof VocabularyEntry) { + this.setDisplayInputValue(value.display); + } + } + } + + protected setDisplayInputValue(displayValue: string) { + if (hasValue(displayValue)) { + if (this.isLookupName()) { + const values = displayValue.split((this.model as DynamicLookupNameModel).separator); + + this.firstInputValue = (values[0] || '').trim(); + this.secondInputValue = (values[1] || '').trim(); + } else { + this.firstInputValue = displayValue || ''; + } + } + } + + /** + * Gets the current text present in the input field(s) + */ protected getCurrentValue(): string { let result = ''; if (!this.isLookupName()) { @@ -237,6 +313,9 @@ export class DsDynamicLookupComponent extends DynamicFormControlComponent implem return result; } + /** + * Clear text present in the input field(s) + */ protected resetFields() { this.firstInputValue = ''; if (this.isLookupName()) { @@ -244,32 +323,12 @@ export class DsDynamicLookupComponent extends DynamicFormControlComponent implem } } - protected setInputsValue(value) { - if (hasValue(value)) { - let displayValue = value; - if (value instanceof FormFieldMetadataValueObject || value instanceof VocabularyEntry) { - displayValue = value.display; - } - - if (hasValue(displayValue)) { - if (this.isLookupName()) { - const values = displayValue.split((this.model as DynamicLookupNameModel).separator); - - this.firstInputValue = (values[0] || '').trim(); - this.secondInputValue = (values[1] || '').trim(); - } else { - this.firstInputValue = displayValue || ''; - } - } - } - } - protected updateModel(value) { this.group.markAsDirty(); - this.model.valueUpdates.next(value); - this.setInputsValue(value); - this.change.emit(value); + this.dispatchUpdate(value); + this.setCurrentValue(value); this.optionsList = null; this.pageInfo = null; } + } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.components.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.components.ts index 21606d7abc..51cf69d560 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.components.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.components.ts @@ -23,13 +23,15 @@ import { hasValue, isEmpty, isNotEmpty, isNotNull } from '../../../../../empty.u import { shrinkInOut } from '../../../../../animations/shrink'; import { ChipsItem } from '../../../../../chips/models/chips-item.model'; import { hasOnlyEmptyProperties } from '../../../../../object.util'; -import { VocabularyFindOptions } from '../../../../../../core/submission/vocabularies/models/vocabulary-find-options.model'; import { VocabularyService } from '../../../../../../core/submission/vocabularies/vocabulary.service'; import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model'; import { environment } from '../../../../../../../environments/environment'; import { getFirstSucceededRemoteDataPayload } from '../../../../../../core/shared/operators'; import { VocabularyEntryDetail } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry-detail.model'; +/** + * Component representing a group input field + */ @Component({ selector: 'ds-dynamic-relation-group', styleUrls: ['./dynamic-relation-group.component.scss'], diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.html index cfe50def98..7a35287a99 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.html @@ -1,5 +1,5 @@ -
- + -
- -

- {{'treeview.search.no-result' | translate}} + +

+ {{'vocabulary-treeview.search.no-result' | translate}}

@@ -62,13 +62,13 @@ diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.spec.ts b/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.spec.ts index 39f4274280..9af00b6be7 100644 --- a/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.spec.ts +++ b/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.spec.ts @@ -16,6 +16,7 @@ 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'; describe('VocabularyTreeviewComponent test suite', () => { @@ -37,7 +38,7 @@ describe('VocabularyTreeviewComponent test suite', () => { getData: jasmine.createSpy('getData'), loadMore: jasmine.createSpy('loadMore'), loadMoreRoot: jasmine.createSpy('loadMoreRoot'), - isSearching: jasmine.createSpy('isSearching'), + isLoading: jasmine.createSpy('isLoading'), searchByQuery: jasmine.createSpy('searchByQuery'), restoreNodes: jasmine.createSpy('restoreNodes'), cleanTree: jasmine.createSpy('cleanTree'), @@ -100,7 +101,7 @@ describe('VocabularyTreeviewComponent test suite', () => { comp = fixture.componentInstance; compAsAny = comp; vocabularyTreeviewServiceStub.getData.and.returnValue(observableOf([])); - vocabularyTreeviewServiceStub.isSearching.and.returnValue(observableOf(false)); + vocabularyTreeviewServiceStub.isLoading.and.returnValue(observableOf(false)); comp.vocabularyOptions = vocabularyOptions; comp.selectedItem = null; }); @@ -118,19 +119,27 @@ describe('VocabularyTreeviewComponent test suite', () => { }); it('should should init component properly with init value as FormFieldMetadataValueObject', () => { - comp.selectedItem = new FormFieldMetadataValueObject('test', null, 'auth001'); + const currentValue = new FormFieldMetadataValueObject(); + currentValue.value = 'testValue'; + currentValue.otherInformation = { + id: 'entryID' + }; + comp.selectedItem = currentValue; fixture.detectChanges(); expect(comp.dataSource.data).toEqual([]); - expect(vocabularyTreeviewServiceStub.initialize).toHaveBeenCalledWith(comp.vocabularyOptions, new PageInfo(), 'auth001'); + expect(vocabularyTreeviewServiceStub.initialize).toHaveBeenCalledWith(comp.vocabularyOptions, new PageInfo(), 'entryID'); }); - it('should should init component properly with init value as AuthorityEntry', () => { - const authority = new VocabularyEntryDetail(); - authority.id = 'auth001'; - comp.selectedItem = authority; + it('should should init component properly with init value as VocabularyEntry', () => { + const currentValue = new VocabularyEntry(); + currentValue.value = 'testValue'; + currentValue.otherInformation = { + id: 'entryID' + }; + comp.selectedItem = currentValue; fixture.detectChanges(); expect(comp.dataSource.data).toEqual([]); - expect(vocabularyTreeviewServiceStub.initialize).toHaveBeenCalledWith(comp.vocabularyOptions, new PageInfo(), 'auth001'); + expect(vocabularyTreeviewServiceStub.initialize).toHaveBeenCalledWith(comp.vocabularyOptions, new PageInfo(), 'entryID'); }); it('should call loadMore function', () => { diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts b/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts index 34c9a52c60..8c7543849d 100644 --- a/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts +++ b/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts @@ -16,6 +16,7 @@ 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'; /** * Component that show a hierarchical vocabulary in a tree view @@ -78,9 +79,9 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit { searchText: string; /** - * A boolean representing if a search operation is pending + * A boolean representing if tree is loading */ - searching: Observable; + loading: Observable; /** * An event fired when a vocabulary entry is selected. @@ -198,7 +199,7 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit { }) ); - const descriptionLabel = 'tree.description.' + this.vocabularyOptions.name; + const descriptionLabel = 'vocabulary-treeview.tree.description.' + this.vocabularyOptions.name; this.description = this.translate.get(descriptionLabel).pipe( filter((msg) => msg !== descriptionLabel), startWith('') @@ -207,13 +208,13 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit { // set isAuthenticated this.isAuthenticated = this.store.pipe(select(isAuthenticated)); - this.searching = this.vocabularyTreeviewService.isSearching(); + this.loading = this.vocabularyTreeviewService.isLoading(); this.isAuthenticated.pipe( find((isAuth) => isAuth) ).subscribe(() => { - const valueId: string = (this.selectedItem) ? (this.selectedItem.authority || this.selectedItem.id) : null; - this.vocabularyTreeviewService.initialize(this.vocabularyOptions, new PageInfo(), valueId); + const entryId: string = (this.selectedItem) ? this.getEntryId(this.selectedItem) : null; + this.vocabularyTreeviewService.initialize(this.vocabularyOptions, new PageInfo(), entryId); }); } @@ -292,4 +293,11 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit { .filter((sub) => hasValue(sub)) .forEach((sub) => sub.unsubscribe()); } + + /** + * Return an id for a given {@link VocabularyEntry} + */ + private getEntryId(entry: VocabularyEntry): string { + return entry.authority || entry.otherInformation.id || undefined; + } } diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.spec.ts b/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.spec.ts index 32ef635792..2f03549898 100644 --- a/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.spec.ts +++ b/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.spec.ts @@ -50,39 +50,47 @@ describe('VocabularyTreeviewService test suite', () => { let nodeMapWithChildren: Map; let searchNodeMap: Map; let vocabularyOptions; + let pageInfo: PageInfo; const vocabularyServiceStub = jasmine.createSpyObj('VocabularyService', { getVocabularyEntriesByValue: jasmine.createSpy('getVocabularyEntriesByValue'), getEntryDetailParent: jasmine.createSpy('getEntryDetailParent'), findEntryDetailByValue: jasmine.createSpy('findEntryDetailByValue'), searchTopEntries: jasmine.createSpy('searchTopEntries'), - getEntryDetailChildren: jasmine.createSpy('getEntryDetailChildren') + getEntryDetailChildren: jasmine.createSpy('getEntryDetailChildren'), + clearSearchTopRequests: jasmine.createSpy('clearSearchTopRequests') }); function init() { + pageInfo = Object.assign(new PageInfo(), { + elementsPerPage: 1, + totalElements: 3, + totalPages: 1, + currentPage: 1 + }); loadMoreNode = new TreeviewNode(LOAD_MORE_NODE, false, new PageInfo(), item); loadMoreRootNode = new TreeviewNode(LOAD_MORE_ROOT_NODE, false, new PageInfo(), null); loadMoreRootFlatNode = new TreeviewFlatNode(LOAD_MORE_ROOT_NODE, 1, false, new PageInfo(), null); item = new VocabularyEntryDetail(); item.id = item.value = item.display = 'root1'; - item.otherInformation = { children: 'root1-child1::root1-child2', id: 'root1' }; - itemNode = new TreeviewNode(item, true); + item.otherInformation = { hasChildren: 'true', id: 'root1' }; + itemNode = new TreeviewNode(item, true, pageInfo); searchItemNode = new TreeviewNode(item, true, new PageInfo(), null, true); item2 = new VocabularyEntryDetail(); item2.id = item2.value = item2.display = 'root2'; item2.otherInformation = { id: 'root2' }; - itemNode2 = new TreeviewNode(item2); + itemNode2 = new TreeviewNode(item2, false, pageInfo); item3 = new VocabularyEntryDetail(); item3.id = item3.value = item3.display = 'root3'; item3.otherInformation = { id: 'root3' }; - itemNode3 = new TreeviewNode(item3); + itemNode3 = new TreeviewNode(item3, false, pageInfo); child = new VocabularyEntryDetail(); child.id = child.value = child.display = 'root1-child1'; - child.otherInformation = { parent: 'root1', children: 'root1-child1-child1', id: 'root1-child1' }; + child.otherInformation = { parent: 'root1', hasChildren: 'true', id: 'root1-child1' }; childNode = new TreeviewNode(child); searchChildNode = new TreeviewNode(child, true, new PageInfo(), item, true); @@ -167,12 +175,6 @@ describe('VocabularyTreeviewService test suite', () => { describe('initialize', () => { it('should set vocabularyName and call retrieveTopNodes method', () => { - const pageInfo = Object.assign(new PageInfo(), { - elementsPerPage: 1, - totalElements: 3, - totalPages: 1, - currentPage: 1 - }); serviceAsAny.vocabularyService.searchTopEntries.and.returnValue(hot('-a', { a: createSuccessfulRemoteDataObject(new PaginatedList(pageInfo, [item, item2, item3])) })); @@ -181,16 +183,12 @@ describe('VocabularyTreeviewService test suite', () => { scheduler.flush(); expect(serviceAsAny.vocabularyName).toEqual(vocabularyOptions.name); + expect(serviceAsAny.pageInfo).toEqual(pageInfo); + console.log(serviceAsAny.dataChange.value[0].pageInfo, itemNode.pageInfo); expect(serviceAsAny.dataChange.value).toEqual([itemNode, itemNode2, itemNode3]); }); it('should set initValueHierarchy', () => { - const pageInfo = Object.assign(new PageInfo(), { - elementsPerPage: 1, - totalElements: 3, - totalPages: 1, - currentPage: 1 - }); serviceAsAny.vocabularyService.searchTopEntries.and.returnValue(hot('-c', { a: createSuccessfulRemoteDataObject(new PaginatedList(pageInfo, [item, item2, item3])) })); @@ -239,7 +237,7 @@ describe('VocabularyTreeviewService test suite', () => { }); it('should add children nodes properly', () => { - const pageInfo = Object.assign(new PageInfo(), { + pageInfo = Object.assign(new PageInfo(), { elementsPerPage: 1, totalElements: 2, totalPages: 2, @@ -260,7 +258,7 @@ describe('VocabularyTreeviewService test suite', () => { }); it('should add loadMore node properly', () => { - const pageInfo = Object.assign(new PageInfo(), { + pageInfo = Object.assign(new PageInfo(), { elementsPerPage: 1, totalElements: 2, totalPages: 2, @@ -285,7 +283,7 @@ describe('VocabularyTreeviewService test suite', () => { describe('searchByQuery', () => { it('should set tree data properly after a search', () => { - const pageInfo = Object.assign(new PageInfo(), { + pageInfo = Object.assign(new PageInfo(), { elementsPerPage: 1, totalElements: 1, totalPages: 1, diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.ts b/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.ts index bfaddf414e..8beead5419 100644 --- a/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.ts +++ b/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { BehaviorSubject, Observable, of as observableOf } from 'rxjs'; -import { flatMap, map, merge, scan, take, tap } from 'rxjs/operators'; +import { flatMap, map, merge, scan } from 'rxjs/operators'; import { findIndex } from 'lodash'; import { LOAD_MORE_NODE, LOAD_MORE_ROOT_NODE, TreeviewFlatNode, TreeviewNode } from './vocabulary-treeview-node.model'; @@ -56,14 +56,18 @@ export class VocabularyTreeviewService { private initValueHierarchy: string[] = []; /** - * A boolean representing if a search operation is pending + * A boolean representing if any operation is pending */ - private searching = new BehaviorSubject(false); + private loading = new BehaviorSubject(false); /** - * An observable to change the searching status + * The {@link PageInfo} object */ - private hideSearchingWhenUnsubscribed$ = new Observable(() => () => this.searching.next(false)); + private pageInfo: PageInfo; + /** + * An observable to change the loading status + */ + private hideSearchingWhenUnsubscribed$ = new Observable(() => () => this.loading.next(false)); /** * Initialize instance variables @@ -92,8 +96,10 @@ export class VocabularyTreeviewService { * @param initValueId The entry id of the node to mark as selected, if any */ initialize(options: VocabularyOptions, pageInfo: PageInfo, initValueId?: string): void { + this.loading.next(true); this.vocabularyOptions = options; this.vocabularyName = options.name; + this.pageInfo = pageInfo; if (isNotEmpty(initValueId)) { this.getNodeHierarchyById(initValueId) .subscribe((hierarchy: string[]) => { @@ -160,17 +166,17 @@ export class VocabularyTreeviewService { } /** - * Check if a search operation is pending + * Check if any operation is pending */ - isSearching(): Observable { - return this.searching; + isLoading(): Observable { + return this.loading; } /** * Perform a search operation by query */ searchByQuery(query: string) { - this.searching.next(true); + this.loading.next(true); if (isEmpty(this.storedNodes)) { this.storedNodes = this.dataChange.value; this.storedNodeMap = this.nodeMap; @@ -192,7 +198,7 @@ export class VocabularyTreeviewService { merge(this.hideSearchingWhenUnsubscribed$) ).subscribe((nodes: TreeviewNode[]) => { this.dataChange.next(nodes); - this.searching.next(false); + this.loading.next(false); }) } @@ -200,7 +206,7 @@ export class VocabularyTreeviewService { * Reset tree state with the one before the search */ restoreNodes() { - this.searching.next(false); + this.loading.next(false); this.dataChange.next(this.storedNodes); this.nodeMap = this.storedNodeMap; @@ -224,8 +230,8 @@ export class VocabularyTreeviewService { const entryDetail: VocabularyEntryDetail = Object.assign(new VocabularyEntryDetail(), entry, { id: entryId }); - const hasChildren = entry.hasOtherInformation() && isNotEmpty((entry.otherInformation as any).children); - const pageInfo: PageInfo = new PageInfo(); + const hasChildren = entry.hasOtherInformation() && (entry.otherInformation as any)!.hasChildren == 'true'; + const pageInfo: PageInfo = this.pageInfo; const isInInitValueHierarchy = this.initValueHierarchy.includes(entryId); const result = new TreeviewNode( entryDetail, @@ -295,8 +301,10 @@ export class VocabularyTreeviewService { this.vocabularyService.searchTopEntries(this.vocabularyName, pageInfo).pipe( getFirstSucceededRemoteDataPayload() ).subscribe((list: PaginatedList) => { - const newNodes: TreeviewNode[] = list.page.map((entry: VocabularyEntryDetail) => this._generateNode(entry)) + this.vocabularyService.clearSearchTopRequests(); + const newNodes: TreeviewNode[] = list.page.map((entry: VocabularyEntryDetail) => this._generateNode(entry)); nodes.push(...newNodes); + if ((list.pageInfo.currentPage + 1) <= list.pageInfo.totalPages) { // Need a new load more node const newPageInfo: PageInfo = Object.assign(new PageInfo(), list.pageInfo, { @@ -306,6 +314,7 @@ export class VocabularyTreeviewService { loadMoreNode.updatePageInfo(newPageInfo); nodes.push(loadMoreNode); } + this.loading.next(false); // Notify the change. this.dataChange.next(nodes); }); @@ -328,8 +337,7 @@ export class VocabularyTreeviewService { if (isNotEmpty(children)) { const newChildren = children .filter((entry: TreeviewNode) => { - const ii = findIndex(node.children, (nodeEntry) => nodeEntry.item.id === entry.item.id); - return ii === -1; + return findIndex(node.children, (nodeEntry) => nodeEntry.item.id === entry.item.id) === -1; }); newChildren.forEach((entry: TreeviewNode) => { entry.loadMoreParentItem = node.item diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 3a79984ec3..26c4829e4c 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -2712,6 +2712,24 @@ "title": "DSpace", + + + "vocabulary-treeview.header": "Hierarchical tree view", + + "vocabulary-treeview.load-more": "Load more", + + "vocabulary-treeview.search.form.reset": "Reset", + + "vocabulary-treeview.search.form.search": "Search", + + "vocabulary-treeview.search.no-result": "There were no items to show", + + "vocabulary-treeview.tree.description.nsi": "The Norwegian Science Index", + + "vocabulary-treeview.tree.description.srsc": "Research Subject Categories", + + + "administrativeView.search.results.head": "Administrative Search", "menu.section.admin_search": "Admin Search", From e8237f196f796e365eacb9a6b3945ca0cbcc3a14 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 2 Jul 2020 11:42:30 +0200 Subject: [PATCH 033/170] [CST-3088] added test for hierarchical vocabulary --- .../models/dynamic-vocabulary.component.ts | 2 +- .../dynamic-typeahead.component.spec.ts | 112 ++++++++++++++++-- .../typeahead/dynamic-typeahead.component.ts | 4 + 3 files changed, 106 insertions(+), 12 deletions(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-vocabulary.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-vocabulary.component.ts index 14ae2128b5..5e6acf8581 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-vocabulary.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-vocabulary.component.ts @@ -64,7 +64,7 @@ export abstract class DsDynamicVocabularyComponent extends DynamicFormControlCom value: initEntry.value, authority: initEntry.authority, display: initEntry.display, - otherInformation: initEntry.otherInformation + otherInformation: initEntry.otherInformation || null }); } else { return this.model.value as any; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.spec.ts index 72fc7fcba0..d837af5402 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.spec.ts @@ -5,7 +5,7 @@ import { async, ComponentFixture, fakeAsync, inject, TestBed, tick, } from '@ang import { By } from '@angular/platform-browser'; import { of as observableOf } from 'rxjs'; -import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { NgbModal, NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { DynamicFormLayoutService, DynamicFormsCoreModule, DynamicFormValidationService } from '@ng-dynamic-forms/core'; import { DynamicFormsNGBootstrapUIModule } from '@ng-dynamic-forms/ui-ng-bootstrap'; import { TranslateModule } from '@ngx-translate/core'; @@ -21,6 +21,10 @@ import { AuthorityConfidenceStateDirective } from '../../../../../authority-conf import { ObjNgFor } from '../../../../../utils/object-ngfor.pipe'; import { VocabularyEntry } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry.model'; import { createSuccessfulRemoteDataObject$ } from '../../../../../remote-data.utils'; +import { VocabularyTreeviewComponent } from '../../../../../vocabulary-treeview/vocabulary-treeview.component'; +import { CdkTreeModule } from '@angular/cdk/tree'; +import { TestScheduler } from 'rxjs/testing'; +import { getTestScheduler } from 'jasmine-marbles'; export let TYPEAHEAD_TEST_GROUP; @@ -51,14 +55,16 @@ function init() { }; } -fdescribe('DsDynamicTypeaheadComponent test suite', () => { +describe('DsDynamicTypeaheadComponent test suite', () => { + let scheduler: TestScheduler; let testComp: TestComponent; let typeaheadComp: DsDynamicTypeaheadComponent; let testFixture: ComponentFixture; let typeaheadFixture: ComponentFixture; - let service: any; + let vocabularyServiceStub: any; let html; + let modal; let vocabulary = { id: 'vocabulary', name: 'vocabulary', @@ -95,7 +101,15 @@ fdescribe('DsDynamicTypeaheadComponent test suite', () => { // async beforeEach beforeEach(async(() => { - const vocabularyServiceStub = new VocabularyServiceStub(); + vocabularyServiceStub = new VocabularyServiceStub(); + modal = jasmine.createSpyObj('modal', ['open', 'close', 'dismiss']); +/* jasmine.createSpyObj('modal', + { + open: jasmine.createSpy('open'), + close: jasmine.createSpy('close'), + dismiss: jasmine.createSpy('dismiss'), + } + );*/ init(); TestBed.configureTestingModule({ imports: [ @@ -104,20 +118,23 @@ fdescribe('DsDynamicTypeaheadComponent test suite', () => { FormsModule, NgbModule, ReactiveFormsModule, - TranslateModule.forRoot() + TranslateModule.forRoot(), + CdkTreeModule ], declarations: [ DsDynamicTypeaheadComponent, TestComponent, AuthorityConfidenceStateDirective, - ObjNgFor + ObjNgFor, + VocabularyTreeviewComponent ], // declare the test component providers: [ ChangeDetectorRef, DsDynamicTypeaheadComponent, { provide: VocabularyService, useValue: vocabularyServiceStub }, { provide: DynamicFormLayoutService, useValue: {} }, - { provide: DynamicFormValidationService, useValue: {} } + { provide: DynamicFormValidationService, useValue: {} }, + { provide: NgbModal, useValue: modal } ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }); @@ -135,6 +152,7 @@ fdescribe('DsDynamicTypeaheadComponent test suite', () => { (change)="onValueChange($event)" (focus)="onFocus($event)">`; + spyOn(vocabularyServiceStub, 'findVocabularyById').and.returnValue(createSuccessfulRemoteDataObject$(vocabulary)); testFixture = createTestComponent(html, TestComponent) as ComponentFixture; testComp = testFixture.componentInstance; }); @@ -143,12 +161,15 @@ fdescribe('DsDynamicTypeaheadComponent test suite', () => { testFixture.destroy(); }); it('should create DsDynamicTypeaheadComponent', inject([DsDynamicTypeaheadComponent], (app: DsDynamicTypeaheadComponent) => { - expect(app).toBeDefined(); })); }); - describe('not hiearchical', () => { + describe('Has not hierarchical vocabulary', () => { + beforeEach(() => { + spyOn(vocabularyServiceStub, 'findVocabularyById').and.returnValue(createSuccessfulRemoteDataObject$(vocabulary)); + }); + describe('when init model value is empty', () => { beforeEach(() => { @@ -156,8 +177,6 @@ fdescribe('DsDynamicTypeaheadComponent test suite', () => { typeaheadComp = typeaheadFixture.componentInstance; // FormComponent test instance typeaheadComp.group = TYPEAHEAD_TEST_GROUP; typeaheadComp.model = new DynamicTypeaheadModel(TYPEAHEAD_TEST_MODEL_CONFIG); - service = (typeaheadComp as any).vocabularyService; - spyOn(service, 'findVocabularyById').and.returnValue(createSuccessfulRemoteDataObject$(vocabulary)); typeaheadFixture.detectChanges(); }); @@ -341,6 +360,77 @@ fdescribe('DsDynamicTypeaheadComponent test suite', () => { }); }); }); + + describe('Has hierarchical vocabulary', () => { + beforeEach(() => { + scheduler = getTestScheduler(); + spyOn(vocabularyServiceStub, 'findVocabularyById').and.returnValue(createSuccessfulRemoteDataObject$(hierarchicalVocabulary)); + }); + + describe('when init model value is empty', () => { + beforeEach(() => { + + typeaheadFixture = TestBed.createComponent(DsDynamicTypeaheadComponent); + typeaheadComp = typeaheadFixture.componentInstance; // FormComponent test instance + typeaheadComp.group = TYPEAHEAD_TEST_GROUP; + typeaheadComp.model = new DynamicTypeaheadModel(TYPEAHEAD_TEST_MODEL_CONFIG); + typeaheadFixture.detectChanges(); + }); + + afterEach(() => { + typeaheadFixture.destroy(); + typeaheadComp = null; + }); + + it('should init component properly', () => { + expect(typeaheadComp.currentValue).not.toBeDefined(); + }); + + it('should open tree properly', () => { + scheduler.schedule(() => typeaheadComp.openTree(new Event('click'))); + scheduler.flush(); + + expect((typeaheadComp as any).modalService.open).toHaveBeenCalled(); + }); + }); + + describe('when init model value is not empty', () => { + beforeEach(() => { + typeaheadFixture = TestBed.createComponent(DsDynamicTypeaheadComponent); + typeaheadComp = typeaheadFixture.componentInstance; // FormComponent test instance + typeaheadComp.group = TYPEAHEAD_TEST_GROUP; + typeaheadComp.model = new DynamicTypeaheadModel(TYPEAHEAD_TEST_MODEL_CONFIG); + const entry = observableOf(Object.assign(new VocabularyEntry(), { + authority: null, + value: 'test', + display: 'testDisplay' + })); + spyOn((typeaheadComp as any).vocabularyService, 'getVocabularyEntryByValue').and.returnValue(entry); + spyOn((typeaheadComp as any).vocabularyService, 'getVocabularyEntryByID').and.returnValue(entry); + (typeaheadComp.model as any).value = new FormFieldMetadataValueObject('test', null, null, 'testDisplay'); + typeaheadFixture.detectChanges(); + }); + + afterEach(() => { + typeaheadFixture.destroy(); + typeaheadComp = null; + }); + + it('should init component properly', fakeAsync(() => { + tick(); + expect(typeaheadComp.currentValue).toEqual(new FormFieldMetadataValueObject('test', null, null, 'testDisplay')); + expect((typeaheadComp as any).vocabularyService.getVocabularyEntryByValue).toHaveBeenCalled(); + })); + + it('should open tree properly', () => { + scheduler.schedule(() => typeaheadComp.openTree(new Event('click'))); + scheduler.flush(); + + expect((typeaheadComp as any).modalService.open).toHaveBeenCalled(); + }); + }); + + }); }); // declare a test component diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.ts index 93e5b228e7..5d7413e4dd 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.ts @@ -201,6 +201,10 @@ export class DsDynamicTypeaheadComponent extends DsDynamicVocabularyComponent im this.dispatchUpdate(event.item); } + /** + * Open modal to show tree for hierarchical vocabulary + * @param event The click event fired + */ openTree(event) { event.preventDefault(); event.stopImmediatePropagation(); From e36cb83622ec106dc64c4f597f8f388580f8a605 Mon Sep 17 00:00:00 2001 From: Matteo Perelli Date: Thu, 2 Jul 2020 11:50:39 +0200 Subject: [PATCH 034/170] Additional fix for CI tests --- .../submission-import-external-searchbar.component.spec.ts | 2 -- .../submission-import-external.component.spec.ts | 1 - 2 files changed, 3 deletions(-) diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.spec.ts b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.spec.ts index 1f77374932..285581560b 100644 --- a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.spec.ts +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.spec.ts @@ -84,7 +84,6 @@ describe('SubmissionImportExternalSearchbarComponent test suite', () => { it('Should init component properly (without initExternalSourceData)', () => { comp.initExternalSourceData = { sourceId: '', query: '' }; - comp.ngOnInit(); fixture.detectChanges(); expect(comp.selectedElement).toEqual(sourceList[0]); @@ -94,7 +93,6 @@ describe('SubmissionImportExternalSearchbarComponent test suite', () => { it('Should init component properly (with initExternalSourceData populated)', () => { comp.initExternalSourceData = { query: 'dummy', sourceId: 'ciencia' }; - comp.ngOnInit(); fixture.detectChanges(); expect(comp.selectedElement).toEqual(sourceList[1]); diff --git a/src/app/submission/import-external/submission-import-external.component.spec.ts b/src/app/submission/import-external/submission-import-external.component.spec.ts index 923d431923..4cbe204a91 100644 --- a/src/app/submission/import-external/submission-import-external.component.spec.ts +++ b/src/app/submission/import-external/submission-import-external.component.spec.ts @@ -110,7 +110,6 @@ describe('SubmissionImportExternalComponent test suite', () => { }) }); spyOn(compAsAny.routeService, 'getQueryParameterValue').and.returnValue(observableOf('dummy')); - comp.ngOnInit(); fixture.detectChanges(); expect(comp.routeData).toEqual({ sourceId: 'dummy', query: 'dummy' }); From 30d53c5954832b2d1948f5bb1b0b420c71fb51ac Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 2 Jul 2020 12:12:56 +0200 Subject: [PATCH 035/170] [CST-3088] Renamed DsDynamicTypeaheadComponent to DsDynamicOneboxComponent --- ...c-form-control-container.component.spec.ts | 8 +- ...ynamic-form-control-container.component.ts | 25 +- .../models/ds-dynamic-input.model.ts | 2 +- .../dynamic-onebox.component.html} | 0 .../dynamic-onebox.component.scss} | 0 .../dynamic-onebox.component.spec.ts} | 270 +++++++++--------- .../dynamic-onebox.component.ts} | 14 +- .../dynamic-onebox.model.ts} | 10 +- .../form/builder/form-builder.service.spec.ts | 14 +- .../parsers/onebox-field-parser.spec.ts | 6 +- .../builder/parsers/onebox-field-parser.ts | 14 +- src/app/shared/shared.module.ts | 6 +- 12 files changed, 188 insertions(+), 181 deletions(-) rename src/app/shared/form/builder/ds-dynamic-form-ui/models/{typeahead/dynamic-typeahead.component.html => onebox/dynamic-onebox.component.html} (100%) rename src/app/shared/form/builder/ds-dynamic-form-ui/models/{typeahead/dynamic-typeahead.component.scss => onebox/dynamic-onebox.component.scss} (100%) rename src/app/shared/form/builder/ds-dynamic-form-ui/models/{typeahead/dynamic-typeahead.component.spec.ts => onebox/dynamic-onebox.component.spec.ts} (50%) rename src/app/shared/form/builder/ds-dynamic-form-ui/models/{typeahead/dynamic-typeahead.component.ts => onebox/dynamic-onebox.component.ts} (95%) rename src/app/shared/form/builder/ds-dynamic-form-ui/models/{typeahead/dynamic-typeahead.model.ts => onebox/dynamic-onebox.model.ts} (58%) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.spec.ts index 171ad69f64..e4e6ac6e90 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.spec.ts @@ -49,10 +49,10 @@ import { DynamicListRadioGroupModel } from './models/list/dynamic-list-radio-gro import { DynamicLookupModel } from './models/lookup/dynamic-lookup.model'; import { DynamicScrollableDropdownModel } from './models/scrollable-dropdown/dynamic-scrollable-dropdown.model'; import { DynamicTagModel } from './models/tag/dynamic-tag.model'; -import { DynamicTypeaheadModel } from './models/typeahead/dynamic-typeahead.model'; +import { DynamicOneboxModel } from './models/onebox/dynamic-onebox.model'; import { DynamicQualdropModel } from './models/ds-dynamic-qualdrop.model'; import { DynamicLookupNameModel } from './models/lookup/dynamic-lookup-name.model'; -import { DsDynamicTypeaheadComponent } from './models/typeahead/dynamic-typeahead.component'; +import { DsDynamicOneboxComponent } from './models/onebox/dynamic-onebox.component'; import { DsDynamicScrollableDropdownComponent } from './models/scrollable-dropdown/dynamic-scrollable-dropdown.component'; import { DsDynamicTagComponent } from './models/tag/dynamic-tag.component'; import { DsDynamicListComponent } from './models/list/dynamic-list.component'; @@ -101,7 +101,7 @@ describe('DsDynamicFormControlContainerComponent test suite', () => { new DynamicSwitchModel({ id: 'switch' }), new DynamicTextAreaModel({ id: 'textarea' }), new DynamicTimePickerModel({ id: 'timepicker' }), - new DynamicTypeaheadModel({ id: 'typeahead', metadataFields: [], repeatable: false, submissionId: '1234' }), + new DynamicOneboxModel({ id: 'onebox', metadataFields: [], repeatable: false, submissionId: '1234' }), new DynamicScrollableDropdownModel({ id: 'scrollableDropdown', vocabularyOptions: vocabularyOptions, @@ -312,7 +312,7 @@ describe('DsDynamicFormControlContainerComponent test suite', () => { expect(testFn(formModel[13])).toBeNull(); expect(testFn(formModel[14])).toEqual(DynamicNGBootstrapTextAreaComponent); expect(testFn(formModel[15])).toEqual(DynamicNGBootstrapTimePickerComponent); - expect(testFn(formModel[16])).toEqual(DsDynamicTypeaheadComponent); + expect(testFn(formModel[16])).toEqual(DsDynamicOneboxComponent); expect(testFn(formModel[17])).toEqual(DsDynamicScrollableDropdownComponent); expect(testFn(formModel[18])).toEqual(DsDynamicTagComponent); expect(testFn(formModel[19])).toEqual(DsDynamicListComponent); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts index 2089ce8bca..3eaca6a67a 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts @@ -1,5 +1,6 @@ import { - ChangeDetectionStrategy, ChangeDetectorRef, + ChangeDetectionStrategy, + ChangeDetectorRef, Component, ComponentFactoryResolver, ContentChildren, @@ -29,13 +30,15 @@ import { DYNAMIC_FORM_CONTROL_TYPE_SELECT, DYNAMIC_FORM_CONTROL_TYPE_TEXTAREA, DYNAMIC_FORM_CONTROL_TYPE_TIMEPICKER, - DynamicDatePickerModel, DynamicFormComponentService, + DynamicDatePickerModel, + DynamicFormComponentService, DynamicFormControl, DynamicFormControlContainerComponent, DynamicFormControlEvent, DynamicFormControlModel, DynamicFormLayout, - DynamicFormLayoutService, DynamicFormRelationService, + DynamicFormLayoutService, + DynamicFormRelationService, DynamicFormValidationService, DynamicTemplateDirective, } from '@ng-dynamic-forms/core'; @@ -56,7 +59,7 @@ import { ReorderableRelationship } from './existing-metadata-list-element/existing-metadata-list-element.component'; -import { DYNAMIC_FORM_CONTROL_TYPE_TYPEAHEAD } from './models/typeahead/dynamic-typeahead.model'; +import { DYNAMIC_FORM_CONTROL_TYPE_ONEBOX } from './models/onebox/dynamic-onebox.model'; import { DYNAMIC_FORM_CONTROL_TYPE_SCROLLABLE_DROPDOWN } from './models/scrollable-dropdown/dynamic-scrollable-dropdown.model'; import { DYNAMIC_FORM_CONTROL_TYPE_TAG } from './models/tag/dynamic-tag.model'; import { DYNAMIC_FORM_CONTROL_TYPE_DSDATEPICKER } from './models/date-picker/date-picker.model'; @@ -68,7 +71,7 @@ import { DYNAMIC_FORM_CONTROL_TYPE_LOOKUP_NAME } from './models/lookup/dynamic-l import { DsDynamicTagComponent } from './models/tag/dynamic-tag.component'; import { DsDatePickerComponent } from './models/date-picker/date-picker.component'; import { DsDynamicListComponent } from './models/list/dynamic-list.component'; -import { DsDynamicTypeaheadComponent } from './models/typeahead/dynamic-typeahead.component'; +import { DsDynamicOneboxComponent } from './models/onebox/dynamic-onebox.component'; import { DsDynamicScrollableDropdownComponent } from './models/scrollable-dropdown/dynamic-scrollable-dropdown.component'; import { DsDynamicLookupComponent } from './models/lookup/dynamic-lookup.component'; import { DsDynamicFormGroupComponent } from './models/form-group/dynamic-form-group.component'; @@ -78,7 +81,7 @@ import { DYNAMIC_FORM_CONTROL_TYPE_RELATION_GROUP } from './models/relation-grou import { DsDatePickerInlineComponent } from './models/date-picker-inline/dynamic-date-picker-inline.component'; import { DYNAMIC_FORM_CONTROL_TYPE_CUSTOM_SWITCH } from './models/custom-switch/custom-switch.model'; import { CustomSwitchComponent } from './models/custom-switch/custom-switch.component'; -import { map, startWith, switchMap, find } from 'rxjs/operators'; +import { map, startWith, switchMap } from 'rxjs/operators'; import { combineLatest as observableCombineLatest, Observable, of as observableOf, Subscription } from 'rxjs'; import { SearchResult } from '../../../search/search-result.model'; import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; @@ -88,7 +91,11 @@ import { SelectableListService } from '../../../object-list/selectable-list/sele import { DsDynamicDisabledComponent } from './models/disabled/dynamic-disabled.component'; import { DYNAMIC_FORM_CONTROL_TYPE_DISABLED } from './models/disabled/dynamic-disabled.model'; import { DsDynamicLookupRelationModalComponent } from './relation-lookup-modal/dynamic-lookup-relation-modal.component'; -import { getAllSucceededRemoteData, getRemoteDataPayload, getSucceededRemoteData } from '../../../../core/shared/operators'; +import { + getAllSucceededRemoteData, + getRemoteDataPayload, + getSucceededRemoteData +} from '../../../../core/shared/operators'; import { RemoteData } from '../../../../core/data/remote-data'; import { Item } from '../../../../core/shared/item.model'; import { ItemDataService } from '../../../../core/data/item-data.service'; @@ -136,8 +143,8 @@ export function dsDynamicFormControlMapFn(model: DynamicFormControlModel): Type< case DYNAMIC_FORM_CONTROL_TYPE_TIMEPICKER: return DynamicNGBootstrapTimePickerComponent; - case DYNAMIC_FORM_CONTROL_TYPE_TYPEAHEAD: - return DsDynamicTypeaheadComponent; + case DYNAMIC_FORM_CONTROL_TYPE_ONEBOX: + return DsDynamicOneboxComponent; case DYNAMIC_FORM_CONTROL_TYPE_SCROLLABLE_DROPDOWN: return DsDynamicScrollableDropdownComponent; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model.ts index b723f7aa40..90c26b69cf 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model.ts @@ -41,7 +41,7 @@ export class DsDynamicInputModel extends DynamicInputModel { this.language = config.language; if (!this.language) { - // TypeAhead + // Onebox if (config.value instanceof FormFieldMetadataValueObject) { this.language = config.value.language; } else if (Array.isArray(config.value)) { diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.html similarity index 100% rename from src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.html rename to src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.html diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.scss b/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.scss similarity index 100% rename from src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.scss rename to src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.scss diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.spec.ts similarity index 50% rename from src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.spec.ts rename to src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.spec.ts index d837af5402..3982f659af 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.spec.ts @@ -13,8 +13,8 @@ import { TranslateModule } from '@ngx-translate/core'; import { VocabularyOptions } from '../../../../../../core/submission/vocabularies/models/vocabulary-options.model'; import { VocabularyService } from '../../../../../../core/submission/vocabularies/vocabulary.service'; import { VocabularyServiceStub } from '../../../../../testing/vocabulary-service.stub'; -import { DsDynamicTypeaheadComponent } from './dynamic-typeahead.component'; -import { DynamicTypeaheadModel } from './dynamic-typeahead.model'; +import { DsDynamicOneboxComponent } from './dynamic-onebox.component'; +import { DynamicOneboxModel } from './dynamic-onebox.model'; import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model'; import { createTestComponent } from '../../../../../testing/utils.test'; import { AuthorityConfidenceStateDirective } from '../../../../../authority-confidence/authority-confidence-state.directive'; @@ -26,27 +26,27 @@ import { CdkTreeModule } from '@angular/cdk/tree'; import { TestScheduler } from 'rxjs/testing'; import { getTestScheduler } from 'jasmine-marbles'; -export let TYPEAHEAD_TEST_GROUP; +export let ONEBOX_TEST_GROUP; -export let TYPEAHEAD_TEST_MODEL_CONFIG; +export let ONEBOX_TEST_MODEL_CONFIG; function init() { - TYPEAHEAD_TEST_GROUP = new FormGroup({ - typeahead: new FormControl(), + ONEBOX_TEST_GROUP = new FormGroup({ + onebox: new FormControl(), }); - TYPEAHEAD_TEST_MODEL_CONFIG = { + ONEBOX_TEST_MODEL_CONFIG = { vocabularyOptions: { closed: false, - metadata: 'typeahead', + metadata: 'onebox', name: 'vocabulary', scope: 'c1c16450-d56f-41bc-bb81-27f1d1eb5c23' } as VocabularyOptions, disabled: false, - id: 'typeahead', + id: 'onebox', label: 'Conference', minChars: 3, - name: 'typeahead', + name: 'onebox', placeholder: 'Conference', readOnly: false, required: false, @@ -55,13 +55,13 @@ function init() { }; } -describe('DsDynamicTypeaheadComponent test suite', () => { +describe('DsDynamicOneboxComponent test suite', () => { let scheduler: TestScheduler; let testComp: TestComponent; - let typeaheadComp: DsDynamicTypeaheadComponent; + let oneboxComponent: DsDynamicOneboxComponent; let testFixture: ComponentFixture; - let typeaheadFixture: ComponentFixture; + let oneboxCompFixture: ComponentFixture; let vocabularyServiceStub: any; let html; let modal; @@ -122,7 +122,7 @@ describe('DsDynamicTypeaheadComponent test suite', () => { CdkTreeModule ], declarations: [ - DsDynamicTypeaheadComponent, + DsDynamicOneboxComponent, TestComponent, AuthorityConfidenceStateDirective, ObjNgFor, @@ -130,7 +130,7 @@ describe('DsDynamicTypeaheadComponent test suite', () => { ], // declare the test component providers: [ ChangeDetectorRef, - DsDynamicTypeaheadComponent, + DsDynamicOneboxComponent, { provide: VocabularyService, useValue: vocabularyServiceStub }, { provide: DynamicFormLayoutService, useValue: {} }, { provide: DynamicFormValidationService, useValue: {} }, @@ -145,12 +145,12 @@ describe('DsDynamicTypeaheadComponent test suite', () => { // synchronous beforeEach beforeEach(() => { html = ` - `; + (focus)="onFocus($event)">`; spyOn(vocabularyServiceStub, 'findVocabularyById').and.returnValue(createSuccessfulRemoteDataObject$(vocabulary)); testFixture = createTestComponent(html, TestComponent) as ComponentFixture; @@ -160,7 +160,7 @@ describe('DsDynamicTypeaheadComponent test suite', () => { afterEach(() => { testFixture.destroy(); }); - it('should create DsDynamicTypeaheadComponent', inject([DsDynamicTypeaheadComponent], (app: DsDynamicTypeaheadComponent) => { + it('should create DsDynamicOneboxComponent', inject([DsDynamicOneboxComponent], (app: DsDynamicOneboxComponent) => { expect(app).toBeDefined(); })); }); @@ -173,190 +173,190 @@ describe('DsDynamicTypeaheadComponent test suite', () => { describe('when init model value is empty', () => { beforeEach(() => { - typeaheadFixture = TestBed.createComponent(DsDynamicTypeaheadComponent); - typeaheadComp = typeaheadFixture.componentInstance; // FormComponent test instance - typeaheadComp.group = TYPEAHEAD_TEST_GROUP; - typeaheadComp.model = new DynamicTypeaheadModel(TYPEAHEAD_TEST_MODEL_CONFIG); - typeaheadFixture.detectChanges(); + oneboxCompFixture = TestBed.createComponent(DsDynamicOneboxComponent); + oneboxComponent = oneboxCompFixture.componentInstance; // FormComponent test instance + oneboxComponent.group = ONEBOX_TEST_GROUP; + oneboxComponent.model = new DynamicOneboxModel(ONEBOX_TEST_MODEL_CONFIG); + oneboxCompFixture.detectChanges(); }); afterEach(() => { - typeaheadFixture.destroy(); - typeaheadComp = null; + oneboxCompFixture.destroy(); + oneboxComponent = null; }); it('should init component properly', () => { - expect(typeaheadComp.currentValue).not.toBeDefined(); + expect(oneboxComponent.currentValue).not.toBeDefined(); }); it('should search when 3+ characters typed', fakeAsync(() => { - spyOn((typeaheadComp as any).vocabularyService, 'getVocabularyEntriesByValue').and.callThrough(); + spyOn((oneboxComponent as any).vocabularyService, 'getVocabularyEntriesByValue').and.callThrough(); - typeaheadComp.search(observableOf('test')).subscribe(); + oneboxComponent.search(observableOf('test')).subscribe(); tick(300); - typeaheadFixture.detectChanges(); + oneboxCompFixture.detectChanges(); - expect((typeaheadComp as any).vocabularyService.getVocabularyEntriesByValue).toHaveBeenCalled(); + expect((oneboxComponent as any).vocabularyService.getVocabularyEntriesByValue).toHaveBeenCalled(); })); it('should set model.value on input type when VocabularyOptions.closed is false', () => { - const inputDe = typeaheadFixture.debugElement.query(By.css('input.form-control')); + const inputDe = oneboxCompFixture.debugElement.query(By.css('input.form-control')); const inputElement = inputDe.nativeElement; inputElement.value = 'test value'; inputElement.dispatchEvent(new Event('input')); - expect(typeaheadComp.inputValue).toEqual(new FormFieldMetadataValueObject('test value')) + expect(oneboxComponent.inputValue).toEqual(new FormFieldMetadataValueObject('test value')) }); it('should not set model.value on input type when VocabularyOptions.closed is true', () => { - typeaheadComp.model.vocabularyOptions.closed = true; - typeaheadFixture.detectChanges(); - const inputDe = typeaheadFixture.debugElement.query(By.css('input.form-control')); + oneboxComponent.model.vocabularyOptions.closed = true; + oneboxCompFixture.detectChanges(); + const inputDe = oneboxCompFixture.debugElement.query(By.css('input.form-control')); const inputElement = inputDe.nativeElement; inputElement.value = 'test value'; inputElement.dispatchEvent(new Event('input')); - expect(typeaheadComp.model.value).not.toBeDefined(); + expect(oneboxComponent.model.value).not.toBeDefined(); }); it('should emit blur Event onBlur when popup is closed', () => { - spyOn(typeaheadComp.blur, 'emit'); - spyOn(typeaheadComp.instance, 'isPopupOpen').and.returnValue(false); - typeaheadComp.onBlur(new Event('blur')); - expect(typeaheadComp.blur.emit).toHaveBeenCalled(); + spyOn(oneboxComponent.blur, 'emit'); + spyOn(oneboxComponent.instance, 'isPopupOpen').and.returnValue(false); + oneboxComponent.onBlur(new Event('blur')); + expect(oneboxComponent.blur.emit).toHaveBeenCalled(); }); it('should not emit blur Event onBlur when popup is opened', () => { - spyOn(typeaheadComp.blur, 'emit'); - spyOn(typeaheadComp.instance, 'isPopupOpen').and.returnValue(true); - const input = typeaheadFixture.debugElement.query(By.css('input')); + spyOn(oneboxComponent.blur, 'emit'); + spyOn(oneboxComponent.instance, 'isPopupOpen').and.returnValue(true); + const input = oneboxCompFixture.debugElement.query(By.css('input')); input.nativeElement.blur(); - expect(typeaheadComp.blur.emit).not.toHaveBeenCalled(); + expect(oneboxComponent.blur.emit).not.toHaveBeenCalled(); }); it('should emit change Event onBlur when VocabularyOptions.closed is false and inputValue is changed', () => { - typeaheadComp.inputValue = 'test value'; - typeaheadFixture.detectChanges(); - spyOn(typeaheadComp.blur, 'emit'); - spyOn(typeaheadComp.change, 'emit'); - spyOn(typeaheadComp.instance, 'isPopupOpen').and.returnValue(false); - typeaheadComp.onBlur(new Event('blur',)); - expect(typeaheadComp.change.emit).toHaveBeenCalled(); - expect(typeaheadComp.blur.emit).toHaveBeenCalled(); + oneboxComponent.inputValue = 'test value'; + oneboxCompFixture.detectChanges(); + spyOn(oneboxComponent.blur, 'emit'); + spyOn(oneboxComponent.change, 'emit'); + spyOn(oneboxComponent.instance, 'isPopupOpen').and.returnValue(false); + oneboxComponent.onBlur(new Event('blur',)); + expect(oneboxComponent.change.emit).toHaveBeenCalled(); + expect(oneboxComponent.blur.emit).toHaveBeenCalled(); }); it('should not emit change Event onBlur when VocabularyOptions.closed is false and inputValue is not changed', () => { - typeaheadComp.inputValue = 'test value'; - typeaheadComp.model = new DynamicTypeaheadModel(TYPEAHEAD_TEST_MODEL_CONFIG); - (typeaheadComp.model as any).value = 'test value'; - typeaheadFixture.detectChanges(); - spyOn(typeaheadComp.blur, 'emit'); - spyOn(typeaheadComp.change, 'emit'); - spyOn(typeaheadComp.instance, 'isPopupOpen').and.returnValue(false); - typeaheadComp.onBlur(new Event('blur',)); - expect(typeaheadComp.change.emit).not.toHaveBeenCalled(); - expect(typeaheadComp.blur.emit).toHaveBeenCalled(); + oneboxComponent.inputValue = 'test value'; + oneboxComponent.model = new DynamicOneboxModel(ONEBOX_TEST_MODEL_CONFIG); + (oneboxComponent.model as any).value = 'test value'; + oneboxCompFixture.detectChanges(); + spyOn(oneboxComponent.blur, 'emit'); + spyOn(oneboxComponent.change, 'emit'); + spyOn(oneboxComponent.instance, 'isPopupOpen').and.returnValue(false); + oneboxComponent.onBlur(new Event('blur',)); + expect(oneboxComponent.change.emit).not.toHaveBeenCalled(); + expect(oneboxComponent.blur.emit).toHaveBeenCalled(); }); it('should not emit change Event onBlur when VocabularyOptions.closed is false and inputValue is null', () => { - typeaheadComp.inputValue = null; - typeaheadComp.model = new DynamicTypeaheadModel(TYPEAHEAD_TEST_MODEL_CONFIG); - (typeaheadComp.model as any).value = 'test value'; - typeaheadFixture.detectChanges(); - spyOn(typeaheadComp.blur, 'emit'); - spyOn(typeaheadComp.change, 'emit'); - spyOn(typeaheadComp.instance, 'isPopupOpen').and.returnValue(false); - typeaheadComp.onBlur(new Event('blur',)); - expect(typeaheadComp.change.emit).not.toHaveBeenCalled(); - expect(typeaheadComp.blur.emit).toHaveBeenCalled(); + oneboxComponent.inputValue = null; + oneboxComponent.model = new DynamicOneboxModel(ONEBOX_TEST_MODEL_CONFIG); + (oneboxComponent.model as any).value = 'test value'; + oneboxCompFixture.detectChanges(); + spyOn(oneboxComponent.blur, 'emit'); + spyOn(oneboxComponent.change, 'emit'); + spyOn(oneboxComponent.instance, 'isPopupOpen').and.returnValue(false); + oneboxComponent.onBlur(new Event('blur',)); + expect(oneboxComponent.change.emit).not.toHaveBeenCalled(); + expect(oneboxComponent.blur.emit).toHaveBeenCalled(); }); it('should emit focus Event onFocus', () => { - spyOn(typeaheadComp.focus, 'emit'); - typeaheadComp.onFocus(new Event('focus')); - expect(typeaheadComp.focus.emit).toHaveBeenCalled(); + spyOn(oneboxComponent.focus, 'emit'); + oneboxComponent.onFocus(new Event('focus')); + expect(oneboxComponent.focus.emit).toHaveBeenCalled(); }); }); describe('when init model value is not empty', () => { beforeEach(() => { - typeaheadFixture = TestBed.createComponent(DsDynamicTypeaheadComponent); - typeaheadComp = typeaheadFixture.componentInstance; // FormComponent test instance - typeaheadComp.group = TYPEAHEAD_TEST_GROUP; - typeaheadComp.model = new DynamicTypeaheadModel(TYPEAHEAD_TEST_MODEL_CONFIG); + oneboxCompFixture = TestBed.createComponent(DsDynamicOneboxComponent); + oneboxComponent = oneboxCompFixture.componentInstance; // FormComponent test instance + oneboxComponent.group = ONEBOX_TEST_GROUP; + oneboxComponent.model = new DynamicOneboxModel(ONEBOX_TEST_MODEL_CONFIG); const entry = observableOf(Object.assign(new VocabularyEntry(), { authority: null, value: 'test', display: 'testDisplay' })); - spyOn((typeaheadComp as any).vocabularyService, 'getVocabularyEntryByValue').and.returnValue(entry); - spyOn((typeaheadComp as any).vocabularyService, 'getVocabularyEntryByID').and.returnValue(entry); - (typeaheadComp.model as any).value = new FormFieldMetadataValueObject('test', null, null, 'testDisplay'); - typeaheadFixture.detectChanges(); + spyOn((oneboxComponent as any).vocabularyService, 'getVocabularyEntryByValue').and.returnValue(entry); + spyOn((oneboxComponent as any).vocabularyService, 'getVocabularyEntryByID').and.returnValue(entry); + (oneboxComponent.model as any).value = new FormFieldMetadataValueObject('test', null, null, 'testDisplay'); + oneboxCompFixture.detectChanges(); }); afterEach(() => { - typeaheadFixture.destroy(); - typeaheadComp = null; + oneboxCompFixture.destroy(); + oneboxComponent = null; }); it('should init component properly', fakeAsync(() => { tick(); - expect(typeaheadComp.currentValue).toEqual(new FormFieldMetadataValueObject('test', null, null, 'testDisplay')); - expect((typeaheadComp as any).vocabularyService.getVocabularyEntryByValue).toHaveBeenCalled(); + expect(oneboxComponent.currentValue).toEqual(new FormFieldMetadataValueObject('test', null, null, 'testDisplay')); + expect((oneboxComponent as any).vocabularyService.getVocabularyEntryByValue).toHaveBeenCalled(); })); it('should emit change Event onChange and currentValue is empty', () => { - typeaheadComp.currentValue = null; - spyOn(typeaheadComp.change, 'emit'); - typeaheadComp.onChange(new Event('change')); - expect(typeaheadComp.change.emit).toHaveBeenCalled(); - expect(typeaheadComp.model.value).toBeNull(); + oneboxComponent.currentValue = null; + spyOn(oneboxComponent.change, 'emit'); + oneboxComponent.onChange(new Event('change')); + expect(oneboxComponent.change.emit).toHaveBeenCalled(); + expect(oneboxComponent.model.value).toBeNull(); }); }); describe('when init model value is not empty and has authority', () => { beforeEach(() => { - typeaheadFixture = TestBed.createComponent(DsDynamicTypeaheadComponent); - typeaheadComp = typeaheadFixture.componentInstance; // FormComponent test instance - typeaheadComp.group = TYPEAHEAD_TEST_GROUP; - typeaheadComp.model = new DynamicTypeaheadModel(TYPEAHEAD_TEST_MODEL_CONFIG); + oneboxCompFixture = TestBed.createComponent(DsDynamicOneboxComponent); + oneboxComponent = oneboxCompFixture.componentInstance; // FormComponent test instance + oneboxComponent.group = ONEBOX_TEST_GROUP; + oneboxComponent.model = new DynamicOneboxModel(ONEBOX_TEST_MODEL_CONFIG); const entry = observableOf(Object.assign(new VocabularyEntry(), { authority: 'test001', value: 'test001', display: 'test' })); - spyOn((typeaheadComp as any).vocabularyService, 'getVocabularyEntryByValue').and.returnValue(entry); - spyOn((typeaheadComp as any).vocabularyService, 'getVocabularyEntryByID').and.returnValue(entry); - (typeaheadComp.model as any).value = new FormFieldMetadataValueObject('test', null, 'test001'); - typeaheadFixture.detectChanges(); + spyOn((oneboxComponent as any).vocabularyService, 'getVocabularyEntryByValue').and.returnValue(entry); + spyOn((oneboxComponent as any).vocabularyService, 'getVocabularyEntryByID').and.returnValue(entry); + (oneboxComponent.model as any).value = new FormFieldMetadataValueObject('test', null, 'test001'); + oneboxCompFixture.detectChanges(); }); afterEach(() => { - typeaheadFixture.destroy(); - typeaheadComp = null; + oneboxCompFixture.destroy(); + oneboxComponent = null; }); it('should init component properly', fakeAsync(() => { tick(); - expect(typeaheadComp.currentValue).toEqual(new FormFieldMetadataValueObject('test001', null, 'test001', 'test')); - expect((typeaheadComp as any).vocabularyService.getVocabularyEntryByID).toHaveBeenCalled(); + expect(oneboxComponent.currentValue).toEqual(new FormFieldMetadataValueObject('test001', null, 'test001', 'test')); + expect((oneboxComponent as any).vocabularyService.getVocabularyEntryByID).toHaveBeenCalled(); })); it('should emit change Event onChange and currentValue is empty', () => { - typeaheadComp.currentValue = null; - spyOn(typeaheadComp.change, 'emit'); - typeaheadComp.onChange(new Event('change')); - expect(typeaheadComp.change.emit).toHaveBeenCalled(); - expect(typeaheadComp.model.value).toBeNull(); + oneboxComponent.currentValue = null; + spyOn(oneboxComponent.change, 'emit'); + oneboxComponent.onChange(new Event('change')); + expect(oneboxComponent.change.emit).toHaveBeenCalled(); + expect(oneboxComponent.model.value).toBeNull(); }); }); }); @@ -370,63 +370,63 @@ describe('DsDynamicTypeaheadComponent test suite', () => { describe('when init model value is empty', () => { beforeEach(() => { - typeaheadFixture = TestBed.createComponent(DsDynamicTypeaheadComponent); - typeaheadComp = typeaheadFixture.componentInstance; // FormComponent test instance - typeaheadComp.group = TYPEAHEAD_TEST_GROUP; - typeaheadComp.model = new DynamicTypeaheadModel(TYPEAHEAD_TEST_MODEL_CONFIG); - typeaheadFixture.detectChanges(); + oneboxCompFixture = TestBed.createComponent(DsDynamicOneboxComponent); + oneboxComponent = oneboxCompFixture.componentInstance; // FormComponent test instance + oneboxComponent.group = ONEBOX_TEST_GROUP; + oneboxComponent.model = new DynamicOneboxModel(ONEBOX_TEST_MODEL_CONFIG); + oneboxCompFixture.detectChanges(); }); afterEach(() => { - typeaheadFixture.destroy(); - typeaheadComp = null; + oneboxCompFixture.destroy(); + oneboxComponent = null; }); it('should init component properly', () => { - expect(typeaheadComp.currentValue).not.toBeDefined(); + expect(oneboxComponent.currentValue).not.toBeDefined(); }); it('should open tree properly', () => { - scheduler.schedule(() => typeaheadComp.openTree(new Event('click'))); + scheduler.schedule(() => oneboxComponent.openTree(new Event('click'))); scheduler.flush(); - expect((typeaheadComp as any).modalService.open).toHaveBeenCalled(); + expect((oneboxComponent as any).modalService.open).toHaveBeenCalled(); }); }); describe('when init model value is not empty', () => { beforeEach(() => { - typeaheadFixture = TestBed.createComponent(DsDynamicTypeaheadComponent); - typeaheadComp = typeaheadFixture.componentInstance; // FormComponent test instance - typeaheadComp.group = TYPEAHEAD_TEST_GROUP; - typeaheadComp.model = new DynamicTypeaheadModel(TYPEAHEAD_TEST_MODEL_CONFIG); + oneboxCompFixture = TestBed.createComponent(DsDynamicOneboxComponent); + oneboxComponent = oneboxCompFixture.componentInstance; // FormComponent test instance + oneboxComponent.group = ONEBOX_TEST_GROUP; + oneboxComponent.model = new DynamicOneboxModel(ONEBOX_TEST_MODEL_CONFIG); const entry = observableOf(Object.assign(new VocabularyEntry(), { authority: null, value: 'test', display: 'testDisplay' })); - spyOn((typeaheadComp as any).vocabularyService, 'getVocabularyEntryByValue').and.returnValue(entry); - spyOn((typeaheadComp as any).vocabularyService, 'getVocabularyEntryByID').and.returnValue(entry); - (typeaheadComp.model as any).value = new FormFieldMetadataValueObject('test', null, null, 'testDisplay'); - typeaheadFixture.detectChanges(); + spyOn((oneboxComponent as any).vocabularyService, 'getVocabularyEntryByValue').and.returnValue(entry); + spyOn((oneboxComponent as any).vocabularyService, 'getVocabularyEntryByID').and.returnValue(entry); + (oneboxComponent.model as any).value = new FormFieldMetadataValueObject('test', null, null, 'testDisplay'); + oneboxCompFixture.detectChanges(); }); afterEach(() => { - typeaheadFixture.destroy(); - typeaheadComp = null; + oneboxCompFixture.destroy(); + oneboxComponent = null; }); it('should init component properly', fakeAsync(() => { tick(); - expect(typeaheadComp.currentValue).toEqual(new FormFieldMetadataValueObject('test', null, null, 'testDisplay')); - expect((typeaheadComp as any).vocabularyService.getVocabularyEntryByValue).toHaveBeenCalled(); + expect(oneboxComponent.currentValue).toEqual(new FormFieldMetadataValueObject('test', null, null, 'testDisplay')); + expect((oneboxComponent as any).vocabularyService.getVocabularyEntryByValue).toHaveBeenCalled(); })); it('should open tree properly', () => { - scheduler.schedule(() => typeaheadComp.openTree(new Event('click'))); + scheduler.schedule(() => oneboxComponent.openTree(new Event('click'))); scheduler.flush(); - expect((typeaheadComp as any).modalService.open).toHaveBeenCalled(); + expect((oneboxComponent as any).modalService.open).toHaveBeenCalled(); }); }); @@ -440,8 +440,8 @@ describe('DsDynamicTypeaheadComponent test suite', () => { }) class TestComponent { - group: FormGroup = TYPEAHEAD_TEST_GROUP; + group: FormGroup = ONEBOX_TEST_GROUP; - model = new DynamicTypeaheadModel(TYPEAHEAD_TEST_MODEL_CONFIG); + model = new DynamicOneboxModel(ONEBOX_TEST_MODEL_CONFIG); } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.ts similarity index 95% rename from src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.ts rename to src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.ts index 5d7413e4dd..fa9fe2103a 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.ts @@ -17,7 +17,7 @@ import { Observable, of as observableOf, Subject, Subscription } from 'rxjs'; import { NgbModal, NgbModalRef, NgbTypeahead, NgbTypeaheadSelectItemEvent } from '@ng-bootstrap/ng-bootstrap'; import { VocabularyService } from '../../../../../../core/submission/vocabularies/vocabulary.service'; -import { DynamicTypeaheadModel } from './dynamic-typeahead.model'; +import { DynamicOneboxModel } from './dynamic-onebox.model'; import { hasValue, isEmpty, isNotEmpty, isNotNull } from '../../../../../empty.util'; import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model'; import { ConfidenceType } from '../../../../../../core/shared/confidence-type'; @@ -31,14 +31,14 @@ import { VocabularyTreeviewComponent } from '../../../../../vocabulary-treeview/ import { VocabularyEntryDetail } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry-detail.model'; @Component({ - selector: 'ds-dynamic-typeahead', - styleUrls: ['./dynamic-typeahead.component.scss'], - templateUrl: './dynamic-typeahead.component.html' + selector: 'ds-dynamic-onebox', + styleUrls: ['./dynamic-onebox.component.scss'], + templateUrl: './dynamic-onebox.component.html' }) -export class DsDynamicTypeaheadComponent extends DsDynamicVocabularyComponent implements OnInit { +export class DsDynamicOneboxComponent extends DsDynamicVocabularyComponent implements OnInit { @Input() bindId = true; @Input() group: FormGroup; - @Input() model: DynamicTypeaheadModel; + @Input() model: DynamicOneboxModel; @Output() blur: EventEmitter = new EventEmitter(); @Output() change: EventEmitter = new EventEmitter(); @@ -76,7 +76,7 @@ export class DsDynamicTypeaheadComponent extends DsDynamicVocabularyComponent im /** * Converts a stream of text values from the `` element to the stream of the array of items - * to display in the typeahead popup. + * to display in the onebox popup. */ search = (text$: Observable) => { return text$.pipe( diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.model.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.model.ts similarity index 58% rename from src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.model.ts rename to src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.model.ts index 866055ed04..4b973e3058 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.model.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.model.ts @@ -1,19 +1,19 @@ import { AUTOCOMPLETE_OFF, DynamicFormControlLayout, serializable } from '@ng-dynamic-forms/core'; import { DsDynamicInputModel, DsDynamicInputModelConfig } from '../ds-dynamic-input.model'; -export const DYNAMIC_FORM_CONTROL_TYPE_TYPEAHEAD = 'TYPEAHEAD'; +export const DYNAMIC_FORM_CONTROL_TYPE_ONEBOX = 'ONEBOX'; -export interface DsDynamicTypeaheadModelConfig extends DsDynamicInputModelConfig { +export interface DsDynamicOneboxModelConfig extends DsDynamicInputModelConfig { minChars?: number; value?: any; } -export class DynamicTypeaheadModel extends DsDynamicInputModel { +export class DynamicOneboxModel extends DsDynamicInputModel { @serializable() minChars: number; - @serializable() readonly type: string = DYNAMIC_FORM_CONTROL_TYPE_TYPEAHEAD; + @serializable() readonly type: string = DYNAMIC_FORM_CONTROL_TYPE_ONEBOX; - constructor(config: DsDynamicTypeaheadModelConfig, layout?: DynamicFormControlLayout) { + constructor(config: DsDynamicOneboxModelConfig, layout?: DynamicFormControlLayout) { super(config, layout); diff --git a/src/app/shared/form/builder/form-builder.service.spec.ts b/src/app/shared/form/builder/form-builder.service.spec.ts index 434fe6a2e1..ae3aa782b9 100644 --- a/src/app/shared/form/builder/form-builder.service.spec.ts +++ b/src/app/shared/form/builder/form-builder.service.spec.ts @@ -34,7 +34,7 @@ import { DynamicScrollableDropdownModel } from './ds-dynamic-form-ui/models/scro import { DynamicRelationGroupModel } from './ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.model'; import { DynamicLookupModel } from './ds-dynamic-form-ui/models/lookup/dynamic-lookup.model'; import { DynamicDsDatePickerModel } from './ds-dynamic-form-ui/models/date-picker/date-picker.model'; -import { DynamicTypeaheadModel } from './ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.model'; +import { DynamicOneboxModel } from './ds-dynamic-form-ui/models/onebox/dynamic-onebox.model'; import { DynamicListRadioGroupModel } from './ds-dynamic-form-ui/models/list/dynamic-list-radio-group.model'; import { VocabularyOptions } from '../../../core/submission/vocabularies/models/vocabulary-options.model'; import { FormFieldModel } from './models/form-field.model'; @@ -195,7 +195,7 @@ describe('FormBuilderService test suite', () => { new DynamicColorPickerModel({id: 'testColorPicker'}), - new DynamicTypeaheadModel({id: 'testTypeahead', repeatable: false, metadataFields: [], submissionId: '1234'}), + new DynamicOneboxModel({id: 'testOnebox', repeatable: false, metadataFields: [], submissionId: '1234'}), new DynamicScrollableDropdownModel({id: 'testScrollableDropdown', vocabularyOptions: vocabularyOptions, repeatable: false, metadataFields: [], submissionId: '1234'}), @@ -433,7 +433,7 @@ describe('FormBuilderService test suite', () => { expect(formModel[2] instanceof DynamicRowGroupModel).toBe(true); expect((formModel[2] as DynamicRowGroupModel).group.length).toBe(1); - expect((formModel[2] as DynamicRowGroupModel).get(0) instanceof DynamicTypeaheadModel).toBe(true); + expect((formModel[2] as DynamicRowGroupModel).get(0) instanceof DynamicOneboxModel).toBe(true); }); it('should return form\'s fields value from form model', () => { @@ -449,7 +449,7 @@ describe('FormBuilderService test suite', () => { }; expect(service.getValueFromModel(formModel)).toEqual(value); - ((formModel[2] as DynamicRowGroupModel).get(0) as DynamicTypeaheadModel).valueUpdates.next('test one'); + ((formModel[2] as DynamicRowGroupModel).get(0) as DynamicOneboxModel).valueUpdates.next('test one'); value = { issue: [new FormFieldMetadataValueObject('test')], conference: [new FormFieldMetadataValueObject('test one')] @@ -462,11 +462,11 @@ describe('FormBuilderService test suite', () => { const value = {} as any; ((formModel[0] as DynamicRowGroupModel).get(1) as DsDynamicInputModel).valueUpdates.next('test'); - ((formModel[2] as DynamicRowGroupModel).get(0) as DynamicTypeaheadModel).valueUpdates.next('test one'); + ((formModel[2] as DynamicRowGroupModel).get(0) as DynamicOneboxModel).valueUpdates.next('test one'); service.clearAllModelsValue(formModel); - expect(((formModel[0] as DynamicRowGroupModel).get(1) as DynamicTypeaheadModel).value).toEqual(undefined) - expect(((formModel[2] as DynamicRowGroupModel).get(0) as DynamicTypeaheadModel).value).toEqual(undefined) + expect(((formModel[0] as DynamicRowGroupModel).get(1) as DynamicOneboxModel).value).toEqual(undefined) + expect(((formModel[2] as DynamicRowGroupModel).get(0) as DynamicOneboxModel).value).toEqual(undefined) }); it('should return true when model has a custom group model as parent', () => { diff --git a/src/app/shared/form/builder/parsers/onebox-field-parser.spec.ts b/src/app/shared/form/builder/parsers/onebox-field-parser.spec.ts index c2d1b6f565..e6a99d8e74 100644 --- a/src/app/shared/form/builder/parsers/onebox-field-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/onebox-field-parser.spec.ts @@ -1,7 +1,7 @@ import { FormFieldModel } from '../models/form-field.model'; import { OneboxFieldParser } from './onebox-field-parser'; import { DynamicQualdropModel } from '../ds-dynamic-form-ui/models/ds-dynamic-qualdrop.model'; -import { DynamicTypeaheadModel } from '../ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.model'; +import { DynamicOneboxModel } from '../ds-dynamic-form-ui/models/onebox/dynamic-onebox.model'; import { DsDynamicInputModel } from '../ds-dynamic-form-ui/models/ds-dynamic-input.model'; import { ParserOptions } from './parser-options'; @@ -92,12 +92,12 @@ describe('OneboxFieldParser test suite', () => { expect(fieldModel instanceof DsDynamicInputModel).toBe(true); }); - it('should return a DynamicTypeaheadModel object when selectableMetadata has authority', () => { + it('should return a DynamicOneboxModel object when selectableMetadata has authority', () => { const parser = new OneboxFieldParser(submissionId, field1, initFormValues, parserOptions); const fieldModel = parser.parse(); - expect(fieldModel instanceof DynamicTypeaheadModel).toBe(true); + expect(fieldModel instanceof DynamicOneboxModel).toBe(true); }); }); diff --git a/src/app/shared/form/builder/parsers/onebox-field-parser.ts b/src/app/shared/form/builder/parsers/onebox-field-parser.ts index 598918ac2e..3eb5764a37 100644 --- a/src/app/shared/form/builder/parsers/onebox-field-parser.ts +++ b/src/app/shared/form/builder/parsers/onebox-field-parser.ts @@ -12,9 +12,9 @@ import { FormFieldMetadataValueObject } from '../models/form-field-metadata-valu import { isNotEmpty } from '../../../empty.util'; import { DsDynamicInputModel, DsDynamicInputModelConfig } from '../ds-dynamic-form-ui/models/ds-dynamic-input.model'; import { - DsDynamicTypeaheadModelConfig, - DynamicTypeaheadModel -} from '../ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.model'; + DsDynamicOneboxModelConfig, + DynamicOneboxModel +} from '../ds-dynamic-form-ui/models/onebox/dynamic-onebox.model'; export class OneboxFieldParser extends FieldParser { @@ -76,11 +76,11 @@ export class OneboxFieldParser extends FieldParser { return new DynamicQualdropModel(inputSelectGroup, clsGroup); } else if (this.configData.selectableMetadata[0].controlledVocabulary) { - const typeaheadModelConfig: DsDynamicTypeaheadModelConfig = this.initModel(null, label); - this.setVocabularyOptions(typeaheadModelConfig, this.parserOptions.collectionUUID); - this.setValues(typeaheadModelConfig, fieldValue, true); + const oneboxModelConfig: DsDynamicOneboxModelConfig = this.initModel(null, label); + this.setVocabularyOptions(oneboxModelConfig, this.parserOptions.collectionUUID); + this.setValues(oneboxModelConfig, fieldValue, true); - return new DynamicTypeaheadModel(typeaheadModelConfig); + return new DynamicOneboxModel(oneboxModelConfig); } else { const inputModelConfig: DsDynamicInputModelConfig = this.initModel(null, label); this.setValues(inputModelConfig, fieldValue); diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 38bb9afd5d..7790698059 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -48,7 +48,7 @@ import { VarDirective } from './utils/var.directive'; import { AuthNavMenuComponent } from './auth-nav-menu/auth-nav-menu.component'; import { LogOutComponent } from './log-out/log-out.component'; import { FormComponent } from './form/form.component'; -import { DsDynamicTypeaheadComponent } from './form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component'; +import { DsDynamicOneboxComponent } from './form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component'; import { DsDynamicScrollableDropdownComponent } from './form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component'; import { DsDynamicFormControlContainerComponent, @@ -271,7 +271,7 @@ const COMPONENTS = [ DsDynamicLookupRelationModalComponent, DsDynamicScrollableDropdownComponent, DsDynamicTagComponent, - DsDynamicTypeaheadComponent, + DsDynamicOneboxComponent, DsDynamicRelationGroupComponent, DsDatePickerComponent, DsDynamicFormGroupComponent, @@ -415,7 +415,7 @@ const ENTRY_COMPONENTS = [ DsDynamicLookupRelationModalComponent, DsDynamicScrollableDropdownComponent, DsDynamicTagComponent, - DsDynamicTypeaheadComponent, + DsDynamicOneboxComponent, DsDynamicRelationGroupComponent, DsDatePickerComponent, DsDynamicFormGroupComponent, From 3f0ab2cf1310f5f8bd29040a502466e553742f17 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 2 Jul 2020 14:15:16 +0200 Subject: [PATCH 036/170] [CST-3088] Fixed lint errors --- .../core/submission/vocabularies/vocabulary.service.spec.ts | 1 - .../models/onebox/dynamic-onebox.component.spec.ts | 4 ++-- .../shared/vocabulary-treeview/vocabulary-treeview.service.ts | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/app/core/submission/vocabularies/vocabulary.service.spec.ts b/src/app/core/submission/vocabularies/vocabulary.service.spec.ts index 94ac30ab56..962507ad94 100644 --- a/src/app/core/submission/vocabularies/vocabulary.service.spec.ts +++ b/src/app/core/submission/vocabularies/vocabulary.service.spec.ts @@ -607,7 +607,6 @@ describe('VocabularyService', () => { }); }); - describe('searchByTop', () => { it('should proxy the call to vocabularyEntryDetailDataService.searchBy', () => { const options: VocabularyFindOptions = new VocabularyFindOptions( diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.spec.ts index 3982f659af..f43d779ae3 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.spec.ts @@ -65,7 +65,7 @@ describe('DsDynamicOneboxComponent test suite', () => { let vocabularyServiceStub: any; let html; let modal; - let vocabulary = { + const vocabulary = { id: 'vocabulary', name: 'vocabulary', scrollable: true, @@ -82,7 +82,7 @@ describe('DsDynamicOneboxComponent test suite', () => { } } - let hierarchicalVocabulary = { + const hierarchicalVocabulary = { id: 'hierarchicalVocabulary', name: 'hierarchicalVocabulary', scrollable: true, diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.ts b/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.ts index 8beead5419..836ce7672a 100644 --- a/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.ts +++ b/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.ts @@ -230,7 +230,7 @@ export class VocabularyTreeviewService { const entryDetail: VocabularyEntryDetail = Object.assign(new VocabularyEntryDetail(), entry, { id: entryId }); - const hasChildren = entry.hasOtherInformation() && (entry.otherInformation as any)!.hasChildren == 'true'; + const hasChildren = entry.hasOtherInformation() && (entry.otherInformation as any)!.hasChildren === 'true'; const pageInfo: PageInfo = this.pageInfo; const isInInitValueHierarchy = this.initValueHierarchy.includes(entryId); const result = new TreeviewNode( From 599ddf465305fb1df3b1c2813d944afa358b0ef2 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 2 Jul 2020 14:28:12 +0200 Subject: [PATCH 037/170] [CST-3088] Renamed browseEntries variable to entries --- src/app/core/data/entries-response-parsing.service.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/core/data/entries-response-parsing.service.ts b/src/app/core/data/entries-response-parsing.service.ts index 2f49eb3871..ed13c3f228 100644 --- a/src/app/core/data/entries-response-parsing.service.ts +++ b/src/app/core/data/entries-response-parsing.service.ts @@ -23,12 +23,12 @@ export abstract class EntriesResponseParsingService e parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { if (isNotEmpty(data.payload)) { - let browseEntries = []; + let entries = []; if (isNotEmpty(data.payload._embedded) && Array.isArray(data.payload._embedded[Object.keys(data.payload._embedded)[0]])) { const serializer = new DSpaceSerializer(this.getSerializerModel()); - browseEntries = serializer.deserializeArray(data.payload._embedded[Object.keys(data.payload._embedded)[0]]); + entries = serializer.deserializeArray(data.payload._embedded[Object.keys(data.payload._embedded)[0]]); } - return new GenericSuccessResponse(browseEntries, data.statusCode, data.statusText, this.processPageInfo(data.payload)); + return new GenericSuccessResponse(entries, data.statusCode, data.statusText, this.processPageInfo(data.payload)); } else { return new ErrorResponse( Object.assign( From e46ee579a39818f8c637e306593cec99a670a895 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 2 Jul 2020 16:33:16 +0200 Subject: [PATCH 038/170] reverted i18n files to master version --- src/assets/i18n/ar.json5 | 556 +------ src/assets/i18n/cs.json5 | 556 +------ src/assets/i18n/de.json5 | 552 +------ src/assets/i18n/es.json5 | 3224 ++++++++++++++++---------------------- src/assets/i18n/fi.json5 | 554 +------ src/assets/i18n/fr.json5 | 552 +------ src/assets/i18n/ja.json5 | 556 +------ src/assets/i18n/lv.json5 | 524 +------ src/assets/i18n/nl.json5 | 553 +------ src/assets/i18n/pl.json5 | 556 +------ src/assets/i18n/pt.json5 | 552 +------ src/assets/i18n/sw.json5 | 556 +------ src/assets/i18n/tr.json5 | 556 +------ 13 files changed, 1414 insertions(+), 8433 deletions(-) diff --git a/src/assets/i18n/ar.json5 b/src/assets/i18n/ar.json5 index 64a775dee8..d7afa97f08 100644 --- a/src/assets/i18n/ar.json5 +++ b/src/assets/i18n/ar.json5 @@ -332,22 +332,6 @@ - // "admin.access-control.epeople.actions.delete": "Delete EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.delete": "Delete EPerson", - - // "admin.access-control.epeople.actions.impersonate": "Impersonate EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.impersonate": "Impersonate EPerson", - - // "admin.access-control.epeople.actions.reset": "Reset password", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.reset": "Reset password", - - // "admin.access-control.epeople.actions.stop-impersonating": "Stop impersonating EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.stop-impersonating": "Stop impersonating EPerson", - // "admin.access-control.epeople.title": "DSpace Angular :: EPeople", // TODO New key - Add a translation "admin.access-control.epeople.title": "DSpace Angular :: EPeople", @@ -799,30 +783,6 @@ - - // "admin.workflow.breadcrumbs": "Administer Workflow", - // TODO New key - Add a translation - "admin.workflow.breadcrumbs": "Administer Workflow", - - // "admin.workflow.title": "Administer Workflow", - // TODO New key - Add a translation - "admin.workflow.title": "Administer Workflow", - - // "admin.workflow.item.workflow": "Workflow", - // TODO New key - Add a translation - "admin.workflow.item.workflow": "Workflow", - - // "admin.workflow.item.delete": "Delete", - // TODO New key - Add a translation - "admin.workflow.item.delete": "Delete", - - // "admin.workflow.item.send-back": "Send back", - // TODO New key - Add a translation - "admin.workflow.item.send-back": "Send back", - - - - // "auth.errors.invalid-user": "Invalid email address or password.", // TODO New key - Add a translation "auth.errors.invalid-user": "Invalid email address or password.", @@ -1515,104 +1475,6 @@ - // "comcol-role.edit.no-group": "None", - // TODO New key - Add a translation - "comcol-role.edit.no-group": "None", - - // "comcol-role.edit.create": "Create", - // TODO New key - Add a translation - "comcol-role.edit.create": "Create", - - // "comcol-role.edit.restrict": "Restrict", - // TODO New key - Add a translation - "comcol-role.edit.restrict": "Restrict", - - // "comcol-role.edit.delete": "Delete", - // TODO New key - Add a translation - "comcol-role.edit.delete": "Delete", - - - // "comcol-role.edit.community-admin.name": "Administrators", - // TODO New key - Add a translation - "comcol-role.edit.community-admin.name": "Administrators", - - // "comcol-role.edit.collection-admin.name": "Administrators", - // TODO New key - Add a translation - "comcol-role.edit.collection-admin.name": "Administrators", - - - // "comcol-role.edit.community-admin.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - // TODO New key - Add a translation - "comcol-role.edit.community-admin.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - - // "comcol-role.edit.collection-admin.description": "Collection administrators decide who can submit items to the collection, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization for that collection).", - // TODO New key - Add a translation - "comcol-role.edit.collection-admin.description": "Collection administrators decide who can submit items to the collection, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization for that collection).", - - - // "comcol-role.edit.submitters.name": "Submitters", - // TODO New key - Add a translation - "comcol-role.edit.submitters.name": "Submitters", - - // "comcol-role.edit.submitters.description": "The E-People and Groups that have permission to submit new items to this collection.", - // TODO New key - Add a translation - "comcol-role.edit.submitters.description": "The E-People and Groups that have permission to submit new items to this collection.", - - - // "comcol-role.edit.item_read.name": "Default item read access", - // TODO New key - Add a translation - "comcol-role.edit.item_read.name": "Default item read access", - - // "comcol-role.edit.item_read.description": "E-People and Groups that can read new items submitted to this collection. Changes to this role are not retroactive. Existing items in the system will still be viewable by those who had read access at the time of their addition.", - // TODO New key - Add a translation - "comcol-role.edit.item_read.description": "E-People and Groups that can read new items submitted to this collection. Changes to this role are not retroactive. Existing items in the system will still be viewable by those who had read access at the time of their addition.", - - // "comcol-role.edit.item_read.anonymous-group": "Default read for incoming items is currently set to Anonymous.", - // TODO New key - Add a translation - "comcol-role.edit.item_read.anonymous-group": "Default read for incoming items is currently set to Anonymous.", - - - // "comcol-role.edit.bitstream_read.name": "Default bitstream read access", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.name": "Default bitstream read access", - - // "comcol-role.edit.bitstream_read.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - - // "comcol-role.edit.bitstream_read.anonymous-group": "Default read for incoming bitstreams is currently set to Anonymous.", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.anonymous-group": "Default read for incoming bitstreams is currently set to Anonymous.", - - - // "comcol-role.edit.editor.name": "Editors", - // TODO New key - Add a translation - "comcol-role.edit.editor.name": "Editors", - - // "comcol-role.edit.editor.description": "Editors are able to edit the metadata of incoming submissions, and then accept or reject them.", - // TODO New key - Add a translation - "comcol-role.edit.editor.description": "Editors are able to edit the metadata of incoming submissions, and then accept or reject them.", - - - // "comcol-role.edit.finaleditor.name": "Final editors", - // TODO New key - Add a translation - "comcol-role.edit.finaleditor.name": "Final editors", - - // "comcol-role.edit.finaleditor.description": "Final editors are able to edit the metadata of incoming submissions, but will not be able to reject them.", - // TODO New key - Add a translation - "comcol-role.edit.finaleditor.description": "Final editors are able to edit the metadata of incoming submissions, but will not be able to reject them.", - - - // "comcol-role.edit.reviewer.name": "Reviewers", - // TODO New key - Add a translation - "comcol-role.edit.reviewer.name": "Reviewers", - - // "comcol-role.edit.reviewer.description": "Reviewers are able to accept or reject incoming submissions. However, they are not able to edit the submission's metadata.", - // TODO New key - Add a translation - "comcol-role.edit.reviewer.description": "Reviewers are able to accept or reject incoming submissions. However, they are not able to edit the submission's metadata.", - - - // "community.form.abstract": "Short Description", // TODO New key - Add a translation "community.form.abstract": "Short Description", @@ -1683,10 +1545,6 @@ // TODO New key - Add a translation "dso-selector.create.item.head": "New item", - // "dso-selector.create.submission.head": "New submission", - // TODO New key - Add a translation - "dso-selector.create.submission.head": "New submission", - // "dso-selector.edit.collection.head": "Edit collection", // TODO New key - Add a translation "dso-selector.edit.collection.head": "Edit collection", @@ -1892,9 +1750,9 @@ // TODO New key - Add a translation "form.search": "Search", - // "form.search-help": "Click here to look for an existing correspondence", + // "form.search-help": "Click here to looking for an existing correspondence", // TODO New key - Add a translation - "form.search-help": "Click here to look for an existing correspondence", + "form.search-help": "Click here to looking for an existing correspondence", // "form.submit": "Submit", // TODO New key - Add a translation @@ -1920,15 +1778,6 @@ - // "item.edit.authorizations.heading": "With this editor you can view and alter the policies of an item, plus alter policies of individual item components: bundles and bitstreams. Briefly, an item is a container of bundles, and bundles are containers of bitstreams. Containers usually have ADD/REMOVE/READ/WRITE policies, while bitstreams only have READ/WRITE policies.", - // TODO New key - Add a translation - "item.edit.authorizations.heading": "With this editor you can view and alter the policies of an item, plus alter policies of individual item components: bundles and bitstreams. Briefly, an item is a container of bundles, and bundles are containers of bitstreams. Containers usually have ADD/REMOVE/READ/WRITE policies, while bitstreams only have READ/WRITE policies.", - - // "item.edit.authorizations.title": "Edit item's Policies", - // TODO New key - Add a translation - "item.edit.authorizations.title": "Edit item's Policies", - - // "item.bitstreams.upload.bundle": "Bundle", // TODO New key - Add a translation @@ -3318,18 +3167,14 @@ "menu.section.toggle.statistics_task": "Toggle Statistics Task section", - // "menu.section.workflow": "Administer Workflow", - // TODO New key - Add a translation - "menu.section.workflow": "Administer Workflow", - // "mydspace.description": "", // TODO New key - Add a translation "mydspace.description": "", - // "mydspace.general.text-here": "here", + // "mydspace.general.text-here": "HERE", // TODO New key - Add a translation - "mydspace.general.text-here": "here", + "mydspace.general.text-here": "HERE", // "mydspace.messages.controller-help": "Select this option to send a message to item's submitter.", // TODO New key - Add a translation @@ -3459,14 +3304,6 @@ // TODO New key - Add a translation "mydspace.upload.upload-failed": "Error creating new workspace. Please verify the content uploaded before retry.", - // "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", - // TODO New key - Add a translation - "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", - - // "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", - // TODO New key - Add a translation - "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", - // "mydspace.upload.upload-multiple-successful": "{{qty}} new workspace items created.", // TODO New key - Add a translation "mydspace.upload.upload-multiple-successful": "{{qty}} new workspace items created.", @@ -3517,10 +3354,6 @@ // TODO New key - Add a translation "nav.statistics.header": "Statistics", - // "nav.stop-impersonating": "Stop impersonating EPerson", - // TODO New key - Add a translation - "nav.stop-impersonating": "Stop impersonating EPerson", - // "orgunit.listelement.badge": "Organizational Unit", @@ -3735,120 +3568,6 @@ - // "profile.breadcrumbs": "Update Profile", - // TODO New key - Add a translation - "profile.breadcrumbs": "Update Profile", - - // "profile.card.identify": "Identify", - // TODO New key - Add a translation - "profile.card.identify": "Identify", - - // "profile.card.security": "Security", - // TODO New key - Add a translation - "profile.card.security": "Security", - - // "profile.form.submit": "Update Profile", - // TODO New key - Add a translation - "profile.form.submit": "Update Profile", - - // "profile.groups.head": "Authorization groups you belong to", - // TODO New key - Add a translation - "profile.groups.head": "Authorization groups you belong to", - - // "profile.head": "Update Profile", - // TODO New key - Add a translation - "profile.head": "Update Profile", - - // "profile.metadata.form.error.firstname.required": "First Name is required", - // TODO New key - Add a translation - "profile.metadata.form.error.firstname.required": "First Name is required", - - // "profile.metadata.form.error.lastname.required": "Last Name is required", - // TODO New key - Add a translation - "profile.metadata.form.error.lastname.required": "Last Name is required", - - // "profile.metadata.form.label.email": "Email Address", - // TODO New key - Add a translation - "profile.metadata.form.label.email": "Email Address", - - // "profile.metadata.form.label.firstname": "First Name", - // TODO New key - Add a translation - "profile.metadata.form.label.firstname": "First Name", - - // "profile.metadata.form.label.language": "Language", - // TODO New key - Add a translation - "profile.metadata.form.label.language": "Language", - - // "profile.metadata.form.label.lastname": "Last Name", - // TODO New key - Add a translation - "profile.metadata.form.label.lastname": "Last Name", - - // "profile.metadata.form.label.phone": "Contact Telephone", - // TODO New key - Add a translation - "profile.metadata.form.label.phone": "Contact Telephone", - - // "profile.metadata.form.notifications.success.content": "Your changes to the profile were saved.", - // TODO New key - Add a translation - "profile.metadata.form.notifications.success.content": "Your changes to the profile were saved.", - - // "profile.metadata.form.notifications.success.title": "Profile saved", - // TODO New key - Add a translation - "profile.metadata.form.notifications.success.title": "Profile saved", - - // "profile.notifications.warning.no-changes.content": "No changes were made to the Profile.", - // TODO New key - Add a translation - "profile.notifications.warning.no-changes.content": "No changes were made to the Profile.", - - // "profile.notifications.warning.no-changes.title": "No changes", - // TODO New key - Add a translation - "profile.notifications.warning.no-changes.title": "No changes", - - // "profile.security.form.error.matching-passwords": "The passwords do not match.", - // TODO New key - Add a translation - "profile.security.form.error.matching-passwords": "The passwords do not match.", - - // "profile.security.form.error.password-length": "The password should be at least 6 characters long.", - // TODO New key - Add a translation - "profile.security.form.error.password-length": "The password should be at least 6 characters long.", - - // "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.", - // TODO New key - Add a translation - "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.", - - // "profile.security.form.label.password": "Password", - // TODO New key - Add a translation - "profile.security.form.label.password": "Password", - - // "profile.security.form.label.passwordrepeat": "Retype to confirm", - // TODO New key - Add a translation - "profile.security.form.label.passwordrepeat": "Retype to confirm", - - // "profile.security.form.notifications.success.content": "Your changes to the password were saved.", - // TODO New key - Add a translation - "profile.security.form.notifications.success.content": "Your changes to the password were saved.", - - // "profile.security.form.notifications.success.title": "Password saved", - // TODO New key - Add a translation - "profile.security.form.notifications.success.title": "Password saved", - - // "profile.security.form.notifications.error.title": "Error changing passwords", - // TODO New key - Add a translation - "profile.security.form.notifications.error.title": "Error changing passwords", - - // "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", - // TODO New key - Add a translation - "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", - - // "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", - // TODO New key - Add a translation - "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", - - // "profile.title": "Update Profile", - // TODO New key - Add a translation - "profile.title": "Update Profile", - - - // "project.listelement.badge": "Research Project", // TODO New key - Add a translation "project.listelement.badge": "Research Project", @@ -3983,192 +3702,6 @@ - // "resource-policies.add.button": "Add", - // TODO New key - Add a translation - "resource-policies.add.button": "Add", - - // "resource-policies.add.for.": "Add a new policy", - // TODO New key - Add a translation - "resource-policies.add.for.": "Add a new policy", - - // "resource-policies.add.for.bitstream": "Add a new Bitstream policy", - // TODO New key - Add a translation - "resource-policies.add.for.bitstream": "Add a new Bitstream policy", - - // "resource-policies.add.for.bundle": "Add a new Bundle policy", - // TODO New key - Add a translation - "resource-policies.add.for.bundle": "Add a new Bundle policy", - - // "resource-policies.add.for.item": "Add a new Item policy", - // TODO New key - Add a translation - "resource-policies.add.for.item": "Add a new Item policy", - - // "resource-policies.create.page.heading": "Create new resource policy for ", - // TODO New key - Add a translation - "resource-policies.create.page.heading": "Create new resource policy for ", - - // "resource-policies.create.page.failure.content": "An error occurred while creating the resource policy.", - // TODO New key - Add a translation - "resource-policies.create.page.failure.content": "An error occurred while creating the resource policy.", - - // "resource-policies.create.page.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.create.page.success.content": "Operation successful", - - // "resource-policies.create.page.title": "Create new resource policy", - // TODO New key - Add a translation - "resource-policies.create.page.title": "Create new resource policy", - - // "resource-policies.delete.btn": "Delete selected", - // TODO New key - Add a translation - "resource-policies.delete.btn": "Delete selected", - - // "resource-policies.delete.btn.title": "Delete selected resource policies", - // TODO New key - Add a translation - "resource-policies.delete.btn.title": "Delete selected resource policies", - - // "resource-policies.delete.failure.content": "An error occurred while deleting selected resource policies.", - // TODO New key - Add a translation - "resource-policies.delete.failure.content": "An error occurred while deleting selected resource policies.", - - // "resource-policies.delete.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.delete.success.content": "Operation successful", - - // "resource-policies.edit.page.heading": "Edit resource policy ", - // TODO New key - Add a translation - "resource-policies.edit.page.heading": "Edit resource policy ", - - // "resource-policies.edit.page.failure.content": "An error occurred while editing the resource policy.", - // TODO New key - Add a translation - "resource-policies.edit.page.failure.content": "An error occurred while editing the resource policy.", - - // "resource-policies.edit.page.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.edit.page.success.content": "Operation successful", - - // "resource-policies.edit.page.title": "Edit resource policy", - // TODO New key - Add a translation - "resource-policies.edit.page.title": "Edit resource policy", - - // "resource-policies.form.action-type.label": "Select the action type", - // TODO New key - Add a translation - "resource-policies.form.action-type.label": "Select the action type", - - // "resource-policies.form.action-type.required": "You must select the resource policy action.", - // TODO New key - Add a translation - "resource-policies.form.action-type.required": "You must select the resource policy action.", - - // "resource-policies.form.eperson-group-list.label": "The eperson or group that will be grant of the permission", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.label": "The eperson or group that will be grant of the permission", - - // "resource-policies.form.eperson-group-list.select.btn": "Select", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.select.btn": "Select", - - // "resource-policies.form.eperson-group-list.tab.eperson": "Search for a ePerson", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.tab.eperson": "Search for a ePerson", - - // "resource-policies.form.eperson-group-list.tab.group": "Search for a group", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.tab.group": "Search for a group", - - // "resource-policies.form.eperson-group-list.table.headers.action": "Action", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.action": "Action", - - // "resource-policies.form.eperson-group-list.table.headers.id": "ID", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.id": "ID", - - // "resource-policies.form.eperson-group-list.table.headers.name": "Name", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.name": "Name", - - // "resource-policies.form.date.end.label": "End Date", - // TODO New key - Add a translation - "resource-policies.form.date.end.label": "End Date", - - // "resource-policies.form.date.start.label": "Start Date", - // TODO New key - Add a translation - "resource-policies.form.date.start.label": "Start Date", - - // "resource-policies.form.description.label": "Description", - // TODO New key - Add a translation - "resource-policies.form.description.label": "Description", - - // "resource-policies.form.name.label": "Name", - // TODO New key - Add a translation - "resource-policies.form.name.label": "Name", - - // "resource-policies.form.policy-type.label": "Select the policy type", - // TODO New key - Add a translation - "resource-policies.form.policy-type.label": "Select the policy type", - - // "resource-policies.form.policy-type.required": "You must select the resource policy type.", - // TODO New key - Add a translation - "resource-policies.form.policy-type.required": "You must select the resource policy type.", - - // "resource-policies.table.headers.action": "Action", - // TODO New key - Add a translation - "resource-policies.table.headers.action": "Action", - - // "resource-policies.table.headers.date.end": "End Date", - // TODO New key - Add a translation - "resource-policies.table.headers.date.end": "End Date", - - // "resource-policies.table.headers.date.start": "Start Date", - // TODO New key - Add a translation - "resource-policies.table.headers.date.start": "Start Date", - - // "resource-policies.table.headers.edit": "Edit", - // TODO New key - Add a translation - "resource-policies.table.headers.edit": "Edit", - - // "resource-policies.table.headers.edit.group": "Edit group", - // TODO New key - Add a translation - "resource-policies.table.headers.edit.group": "Edit group", - - // "resource-policies.table.headers.edit.policy": "Edit policy", - // TODO New key - Add a translation - "resource-policies.table.headers.edit.policy": "Edit policy", - - // "resource-policies.table.headers.eperson": "EPerson", - // TODO New key - Add a translation - "resource-policies.table.headers.eperson": "EPerson", - - // "resource-policies.table.headers.group": "Group", - // TODO New key - Add a translation - "resource-policies.table.headers.group": "Group", - - // "resource-policies.table.headers.id": "ID", - // TODO New key - Add a translation - "resource-policies.table.headers.id": "ID", - - // "resource-policies.table.headers.name": "Name", - // TODO New key - Add a translation - "resource-policies.table.headers.name": "Name", - - // "resource-policies.table.headers.policyType": "type", - // TODO New key - Add a translation - "resource-policies.table.headers.policyType": "type", - - // "resource-policies.table.headers.title.for.bitstream": "Policies for Bitstream", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.bitstream": "Policies for Bitstream", - - // "resource-policies.table.headers.title.for.bundle": "Policies for Bundle", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.bundle": "Policies for Bundle", - - // "resource-policies.table.headers.title.for.item": "Policies for Item", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.item": "Policies for Item", - - - // "search.description": "", // TODO New key - Add a translation "search.description": "", @@ -5013,9 +4546,9 @@ // TODO New key - Add a translation "submission.sections.upload.form.date-required": "Date is required.", - // "submission.sections.upload.form.from-label": "Grant access from", + // "submission.sections.upload.form.from-label": "Access grant from", // TODO New key - Add a translation - "submission.sections.upload.form.from-label": "Grant access from", + "submission.sections.upload.form.from-label": "Access grant from", // "submission.sections.upload.form.from-placeholder": "From", // TODO New key - Add a translation @@ -5029,9 +4562,9 @@ // TODO New key - Add a translation "submission.sections.upload.form.group-required": "Group is required.", - // "submission.sections.upload.form.until-label": "Grant access until", + // "submission.sections.upload.form.until-label": "Access grant until", // TODO New key - Add a translation - "submission.sections.upload.form.until-label": "Grant access until", + "submission.sections.upload.form.until-label": "Access grant until", // "submission.sections.upload.form.until-placeholder": "Until", // TODO New key - Add a translation @@ -5241,78 +4774,5 @@ "virtual-metadata.delete-relationship.modal-head": "Select the items for which you want to save the virtual metadata as real metadata", - - // "workflowAdmin.search.results.head": "Administer Workflow", - // TODO New key - Add a translation - "workflowAdmin.search.results.head": "Administer Workflow", - - - - // "workflow-item.delete.notification.success.title": "Deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.success.title": "Deleted", - - // "workflow-item.delete.notification.success.content": "This workflow item was successfully deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.success.content": "This workflow item was successfully deleted", - - // "workflow-item.delete.notification.error.title": "Something went wrong", - // TODO New key - Add a translation - "workflow-item.delete.notification.error.title": "Something went wrong", - - // "workflow-item.delete.notification.error.content": "The workflow item could not be deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.error.content": "The workflow item could not be deleted", - - // "workflow-item.delete.title": "Delete workflow item", - // TODO New key - Add a translation - "workflow-item.delete.title": "Delete workflow item", - - // "workflow-item.delete.header": "Delete workflow item", - // TODO New key - Add a translation - "workflow-item.delete.header": "Delete workflow item", - - // "workflow-item.delete.button.cancel": "Cancel", - // TODO New key - Add a translation - "workflow-item.delete.button.cancel": "Cancel", - - // "workflow-item.delete.button.confirm": "Delete", - // TODO New key - Add a translation - "workflow-item.delete.button.confirm": "Delete", - - - // "workflow-item.send-back.notification.success.title": "Sent back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.success.title": "Sent back to submitter", - - // "workflow-item.send-back.notification.success.content": "This workflow item was successfully sent back to the submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.success.content": "This workflow item was successfully sent back to the submitter", - - // "workflow-item.send-back.notification.error.title": "Something went wrong", - // TODO New key - Add a translation - "workflow-item.send-back.notification.error.title": "Something went wrong", - - // "workflow-item.send-back.notification.error.content": "The workflow item could not be sent back to the submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.error.content": "The workflow item could not be sent back to the submitter", - - // "workflow-item.send-back.title": "Send workflow item back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.title": "Send workflow item back to submitter", - - // "workflow-item.send-back.header": "Send workflow item back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.header": "Send workflow item back to submitter", - - // "workflow-item.send-back.button.cancel": "Cancel", - // TODO New key - Add a translation - "workflow-item.send-back.button.cancel": "Cancel", - - // "workflow-item.send-back.button.confirm": "Send back", - // TODO New key - Add a translation - "workflow-item.send-back.button.confirm": "Send back", - - } \ No newline at end of file diff --git a/src/assets/i18n/cs.json5 b/src/assets/i18n/cs.json5 index 187b507fc8..6a41ef7a05 100644 --- a/src/assets/i18n/cs.json5 +++ b/src/assets/i18n/cs.json5 @@ -312,22 +312,6 @@ - // "admin.access-control.epeople.actions.delete": "Delete EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.delete": "Delete EPerson", - - // "admin.access-control.epeople.actions.impersonate": "Impersonate EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.impersonate": "Impersonate EPerson", - - // "admin.access-control.epeople.actions.reset": "Reset password", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.reset": "Reset password", - - // "admin.access-control.epeople.actions.stop-impersonating": "Stop impersonating EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.stop-impersonating": "Stop impersonating EPerson", - // "admin.access-control.epeople.title": "DSpace Angular :: EPeople", // TODO New key - Add a translation "admin.access-control.epeople.title": "DSpace Angular :: EPeople", @@ -779,30 +763,6 @@ - - // "admin.workflow.breadcrumbs": "Administer Workflow", - // TODO New key - Add a translation - "admin.workflow.breadcrumbs": "Administer Workflow", - - // "admin.workflow.title": "Administer Workflow", - // TODO New key - Add a translation - "admin.workflow.title": "Administer Workflow", - - // "admin.workflow.item.workflow": "Workflow", - // TODO New key - Add a translation - "admin.workflow.item.workflow": "Workflow", - - // "admin.workflow.item.delete": "Delete", - // TODO New key - Add a translation - "admin.workflow.item.delete": "Delete", - - // "admin.workflow.item.send-back": "Send back", - // TODO New key - Add a translation - "admin.workflow.item.send-back": "Send back", - - - - // "auth.errors.invalid-user": "Invalid email address or password.", "auth.errors.invalid-user": "Neplatná e-mailová adresa nebo heslo.", @@ -1489,104 +1449,6 @@ - // "comcol-role.edit.no-group": "None", - // TODO New key - Add a translation - "comcol-role.edit.no-group": "None", - - // "comcol-role.edit.create": "Create", - // TODO New key - Add a translation - "comcol-role.edit.create": "Create", - - // "comcol-role.edit.restrict": "Restrict", - // TODO New key - Add a translation - "comcol-role.edit.restrict": "Restrict", - - // "comcol-role.edit.delete": "Delete", - // TODO New key - Add a translation - "comcol-role.edit.delete": "Delete", - - - // "comcol-role.edit.community-admin.name": "Administrators", - // TODO New key - Add a translation - "comcol-role.edit.community-admin.name": "Administrators", - - // "comcol-role.edit.collection-admin.name": "Administrators", - // TODO New key - Add a translation - "comcol-role.edit.collection-admin.name": "Administrators", - - - // "comcol-role.edit.community-admin.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - // TODO New key - Add a translation - "comcol-role.edit.community-admin.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - - // "comcol-role.edit.collection-admin.description": "Collection administrators decide who can submit items to the collection, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization for that collection).", - // TODO New key - Add a translation - "comcol-role.edit.collection-admin.description": "Collection administrators decide who can submit items to the collection, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization for that collection).", - - - // "comcol-role.edit.submitters.name": "Submitters", - // TODO New key - Add a translation - "comcol-role.edit.submitters.name": "Submitters", - - // "comcol-role.edit.submitters.description": "The E-People and Groups that have permission to submit new items to this collection.", - // TODO New key - Add a translation - "comcol-role.edit.submitters.description": "The E-People and Groups that have permission to submit new items to this collection.", - - - // "comcol-role.edit.item_read.name": "Default item read access", - // TODO New key - Add a translation - "comcol-role.edit.item_read.name": "Default item read access", - - // "comcol-role.edit.item_read.description": "E-People and Groups that can read new items submitted to this collection. Changes to this role are not retroactive. Existing items in the system will still be viewable by those who had read access at the time of their addition.", - // TODO New key - Add a translation - "comcol-role.edit.item_read.description": "E-People and Groups that can read new items submitted to this collection. Changes to this role are not retroactive. Existing items in the system will still be viewable by those who had read access at the time of their addition.", - - // "comcol-role.edit.item_read.anonymous-group": "Default read for incoming items is currently set to Anonymous.", - // TODO New key - Add a translation - "comcol-role.edit.item_read.anonymous-group": "Default read for incoming items is currently set to Anonymous.", - - - // "comcol-role.edit.bitstream_read.name": "Default bitstream read access", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.name": "Default bitstream read access", - - // "comcol-role.edit.bitstream_read.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - - // "comcol-role.edit.bitstream_read.anonymous-group": "Default read for incoming bitstreams is currently set to Anonymous.", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.anonymous-group": "Default read for incoming bitstreams is currently set to Anonymous.", - - - // "comcol-role.edit.editor.name": "Editors", - // TODO New key - Add a translation - "comcol-role.edit.editor.name": "Editors", - - // "comcol-role.edit.editor.description": "Editors are able to edit the metadata of incoming submissions, and then accept or reject them.", - // TODO New key - Add a translation - "comcol-role.edit.editor.description": "Editors are able to edit the metadata of incoming submissions, and then accept or reject them.", - - - // "comcol-role.edit.finaleditor.name": "Final editors", - // TODO New key - Add a translation - "comcol-role.edit.finaleditor.name": "Final editors", - - // "comcol-role.edit.finaleditor.description": "Final editors are able to edit the metadata of incoming submissions, but will not be able to reject them.", - // TODO New key - Add a translation - "comcol-role.edit.finaleditor.description": "Final editors are able to edit the metadata of incoming submissions, but will not be able to reject them.", - - - // "comcol-role.edit.reviewer.name": "Reviewers", - // TODO New key - Add a translation - "comcol-role.edit.reviewer.name": "Reviewers", - - // "comcol-role.edit.reviewer.description": "Reviewers are able to accept or reject incoming submissions. However, they are not able to edit the submission's metadata.", - // TODO New key - Add a translation - "comcol-role.edit.reviewer.description": "Reviewers are able to accept or reject incoming submissions. However, they are not able to edit the submission's metadata.", - - - // "community.form.abstract": "Short Description", // TODO New key - Add a translation "community.form.abstract": "Short Description", @@ -1654,10 +1516,6 @@ // TODO New key - Add a translation "dso-selector.create.item.head": "New item", - // "dso-selector.create.submission.head": "New submission", - // TODO New key - Add a translation - "dso-selector.create.submission.head": "New submission", - // "dso-selector.edit.collection.head": "Edit collection", // TODO New key - Add a translation "dso-selector.edit.collection.head": "Edit collection", @@ -1837,9 +1695,9 @@ // "form.search": "Search", "form.search": "Hledat", - // "form.search-help": "Click here to look for an existing correspondence", + // "form.search-help": "Click here to looking for an existing correspondence", // TODO New key - Add a translation - "form.search-help": "Click here to look for an existing correspondence", + "form.search-help": "Click here to looking for an existing correspondence", // "form.submit": "Submit", "form.submit": "Odeslat", @@ -1860,15 +1718,6 @@ - // "item.edit.authorizations.heading": "With this editor you can view and alter the policies of an item, plus alter policies of individual item components: bundles and bitstreams. Briefly, an item is a container of bundles, and bundles are containers of bitstreams. Containers usually have ADD/REMOVE/READ/WRITE policies, while bitstreams only have READ/WRITE policies.", - // TODO New key - Add a translation - "item.edit.authorizations.heading": "With this editor you can view and alter the policies of an item, plus alter policies of individual item components: bundles and bitstreams. Briefly, an item is a container of bundles, and bundles are containers of bitstreams. Containers usually have ADD/REMOVE/READ/WRITE policies, while bitstreams only have READ/WRITE policies.", - - // "item.edit.authorizations.title": "Edit item's Policies", - // TODO New key - Add a translation - "item.edit.authorizations.title": "Edit item's Policies", - - // "item.bitstreams.upload.bundle": "Bundle", // TODO New key - Add a translation @@ -3229,18 +3078,14 @@ "menu.section.toggle.statistics_task": "Toggle Statistics Task section", - // "menu.section.workflow": "Administer Workflow", - // TODO New key - Add a translation - "menu.section.workflow": "Administer Workflow", - // "mydspace.description": "", // TODO New key - Add a translation "mydspace.description": "", - // "mydspace.general.text-here": "here", + // "mydspace.general.text-here": "HERE", // TODO New key - Add a translation - "mydspace.general.text-here": "here", + "mydspace.general.text-here": "HERE", // "mydspace.messages.controller-help": "Select this option to send a message to item's submitter.", // TODO New key - Add a translation @@ -3370,14 +3215,6 @@ // TODO New key - Add a translation "mydspace.upload.upload-failed": "Error creating new workspace. Please verify the content uploaded before retry.", - // "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", - // TODO New key - Add a translation - "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", - - // "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", - // TODO New key - Add a translation - "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", - // "mydspace.upload.upload-multiple-successful": "{{qty}} new workspace items created.", // TODO New key - Add a translation "mydspace.upload.upload-multiple-successful": "{{qty}} new workspace items created.", @@ -3426,10 +3263,6 @@ // TODO New key - Add a translation "nav.statistics.header": "Statistics", - // "nav.stop-impersonating": "Stop impersonating EPerson", - // TODO New key - Add a translation - "nav.stop-impersonating": "Stop impersonating EPerson", - // "orgunit.listelement.badge": "Organizational Unit", @@ -3640,120 +3473,6 @@ - // "profile.breadcrumbs": "Update Profile", - // TODO New key - Add a translation - "profile.breadcrumbs": "Update Profile", - - // "profile.card.identify": "Identify", - // TODO New key - Add a translation - "profile.card.identify": "Identify", - - // "profile.card.security": "Security", - // TODO New key - Add a translation - "profile.card.security": "Security", - - // "profile.form.submit": "Update Profile", - // TODO New key - Add a translation - "profile.form.submit": "Update Profile", - - // "profile.groups.head": "Authorization groups you belong to", - // TODO New key - Add a translation - "profile.groups.head": "Authorization groups you belong to", - - // "profile.head": "Update Profile", - // TODO New key - Add a translation - "profile.head": "Update Profile", - - // "profile.metadata.form.error.firstname.required": "First Name is required", - // TODO New key - Add a translation - "profile.metadata.form.error.firstname.required": "First Name is required", - - // "profile.metadata.form.error.lastname.required": "Last Name is required", - // TODO New key - Add a translation - "profile.metadata.form.error.lastname.required": "Last Name is required", - - // "profile.metadata.form.label.email": "Email Address", - // TODO New key - Add a translation - "profile.metadata.form.label.email": "Email Address", - - // "profile.metadata.form.label.firstname": "First Name", - // TODO New key - Add a translation - "profile.metadata.form.label.firstname": "First Name", - - // "profile.metadata.form.label.language": "Language", - // TODO New key - Add a translation - "profile.metadata.form.label.language": "Language", - - // "profile.metadata.form.label.lastname": "Last Name", - // TODO New key - Add a translation - "profile.metadata.form.label.lastname": "Last Name", - - // "profile.metadata.form.label.phone": "Contact Telephone", - // TODO New key - Add a translation - "profile.metadata.form.label.phone": "Contact Telephone", - - // "profile.metadata.form.notifications.success.content": "Your changes to the profile were saved.", - // TODO New key - Add a translation - "profile.metadata.form.notifications.success.content": "Your changes to the profile were saved.", - - // "profile.metadata.form.notifications.success.title": "Profile saved", - // TODO New key - Add a translation - "profile.metadata.form.notifications.success.title": "Profile saved", - - // "profile.notifications.warning.no-changes.content": "No changes were made to the Profile.", - // TODO New key - Add a translation - "profile.notifications.warning.no-changes.content": "No changes were made to the Profile.", - - // "profile.notifications.warning.no-changes.title": "No changes", - // TODO New key - Add a translation - "profile.notifications.warning.no-changes.title": "No changes", - - // "profile.security.form.error.matching-passwords": "The passwords do not match.", - // TODO New key - Add a translation - "profile.security.form.error.matching-passwords": "The passwords do not match.", - - // "profile.security.form.error.password-length": "The password should be at least 6 characters long.", - // TODO New key - Add a translation - "profile.security.form.error.password-length": "The password should be at least 6 characters long.", - - // "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.", - // TODO New key - Add a translation - "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.", - - // "profile.security.form.label.password": "Password", - // TODO New key - Add a translation - "profile.security.form.label.password": "Password", - - // "profile.security.form.label.passwordrepeat": "Retype to confirm", - // TODO New key - Add a translation - "profile.security.form.label.passwordrepeat": "Retype to confirm", - - // "profile.security.form.notifications.success.content": "Your changes to the password were saved.", - // TODO New key - Add a translation - "profile.security.form.notifications.success.content": "Your changes to the password were saved.", - - // "profile.security.form.notifications.success.title": "Password saved", - // TODO New key - Add a translation - "profile.security.form.notifications.success.title": "Password saved", - - // "profile.security.form.notifications.error.title": "Error changing passwords", - // TODO New key - Add a translation - "profile.security.form.notifications.error.title": "Error changing passwords", - - // "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", - // TODO New key - Add a translation - "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", - - // "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", - // TODO New key - Add a translation - "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", - - // "profile.title": "Update Profile", - // TODO New key - Add a translation - "profile.title": "Update Profile", - - - // "project.listelement.badge": "Research Project", // TODO New key - Add a translation "project.listelement.badge": "Research Project", @@ -3888,192 +3607,6 @@ - // "resource-policies.add.button": "Add", - // TODO New key - Add a translation - "resource-policies.add.button": "Add", - - // "resource-policies.add.for.": "Add a new policy", - // TODO New key - Add a translation - "resource-policies.add.for.": "Add a new policy", - - // "resource-policies.add.for.bitstream": "Add a new Bitstream policy", - // TODO New key - Add a translation - "resource-policies.add.for.bitstream": "Add a new Bitstream policy", - - // "resource-policies.add.for.bundle": "Add a new Bundle policy", - // TODO New key - Add a translation - "resource-policies.add.for.bundle": "Add a new Bundle policy", - - // "resource-policies.add.for.item": "Add a new Item policy", - // TODO New key - Add a translation - "resource-policies.add.for.item": "Add a new Item policy", - - // "resource-policies.create.page.heading": "Create new resource policy for ", - // TODO New key - Add a translation - "resource-policies.create.page.heading": "Create new resource policy for ", - - // "resource-policies.create.page.failure.content": "An error occurred while creating the resource policy.", - // TODO New key - Add a translation - "resource-policies.create.page.failure.content": "An error occurred while creating the resource policy.", - - // "resource-policies.create.page.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.create.page.success.content": "Operation successful", - - // "resource-policies.create.page.title": "Create new resource policy", - // TODO New key - Add a translation - "resource-policies.create.page.title": "Create new resource policy", - - // "resource-policies.delete.btn": "Delete selected", - // TODO New key - Add a translation - "resource-policies.delete.btn": "Delete selected", - - // "resource-policies.delete.btn.title": "Delete selected resource policies", - // TODO New key - Add a translation - "resource-policies.delete.btn.title": "Delete selected resource policies", - - // "resource-policies.delete.failure.content": "An error occurred while deleting selected resource policies.", - // TODO New key - Add a translation - "resource-policies.delete.failure.content": "An error occurred while deleting selected resource policies.", - - // "resource-policies.delete.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.delete.success.content": "Operation successful", - - // "resource-policies.edit.page.heading": "Edit resource policy ", - // TODO New key - Add a translation - "resource-policies.edit.page.heading": "Edit resource policy ", - - // "resource-policies.edit.page.failure.content": "An error occurred while editing the resource policy.", - // TODO New key - Add a translation - "resource-policies.edit.page.failure.content": "An error occurred while editing the resource policy.", - - // "resource-policies.edit.page.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.edit.page.success.content": "Operation successful", - - // "resource-policies.edit.page.title": "Edit resource policy", - // TODO New key - Add a translation - "resource-policies.edit.page.title": "Edit resource policy", - - // "resource-policies.form.action-type.label": "Select the action type", - // TODO New key - Add a translation - "resource-policies.form.action-type.label": "Select the action type", - - // "resource-policies.form.action-type.required": "You must select the resource policy action.", - // TODO New key - Add a translation - "resource-policies.form.action-type.required": "You must select the resource policy action.", - - // "resource-policies.form.eperson-group-list.label": "The eperson or group that will be grant of the permission", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.label": "The eperson or group that will be grant of the permission", - - // "resource-policies.form.eperson-group-list.select.btn": "Select", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.select.btn": "Select", - - // "resource-policies.form.eperson-group-list.tab.eperson": "Search for a ePerson", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.tab.eperson": "Search for a ePerson", - - // "resource-policies.form.eperson-group-list.tab.group": "Search for a group", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.tab.group": "Search for a group", - - // "resource-policies.form.eperson-group-list.table.headers.action": "Action", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.action": "Action", - - // "resource-policies.form.eperson-group-list.table.headers.id": "ID", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.id": "ID", - - // "resource-policies.form.eperson-group-list.table.headers.name": "Name", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.name": "Name", - - // "resource-policies.form.date.end.label": "End Date", - // TODO New key - Add a translation - "resource-policies.form.date.end.label": "End Date", - - // "resource-policies.form.date.start.label": "Start Date", - // TODO New key - Add a translation - "resource-policies.form.date.start.label": "Start Date", - - // "resource-policies.form.description.label": "Description", - // TODO New key - Add a translation - "resource-policies.form.description.label": "Description", - - // "resource-policies.form.name.label": "Name", - // TODO New key - Add a translation - "resource-policies.form.name.label": "Name", - - // "resource-policies.form.policy-type.label": "Select the policy type", - // TODO New key - Add a translation - "resource-policies.form.policy-type.label": "Select the policy type", - - // "resource-policies.form.policy-type.required": "You must select the resource policy type.", - // TODO New key - Add a translation - "resource-policies.form.policy-type.required": "You must select the resource policy type.", - - // "resource-policies.table.headers.action": "Action", - // TODO New key - Add a translation - "resource-policies.table.headers.action": "Action", - - // "resource-policies.table.headers.date.end": "End Date", - // TODO New key - Add a translation - "resource-policies.table.headers.date.end": "End Date", - - // "resource-policies.table.headers.date.start": "Start Date", - // TODO New key - Add a translation - "resource-policies.table.headers.date.start": "Start Date", - - // "resource-policies.table.headers.edit": "Edit", - // TODO New key - Add a translation - "resource-policies.table.headers.edit": "Edit", - - // "resource-policies.table.headers.edit.group": "Edit group", - // TODO New key - Add a translation - "resource-policies.table.headers.edit.group": "Edit group", - - // "resource-policies.table.headers.edit.policy": "Edit policy", - // TODO New key - Add a translation - "resource-policies.table.headers.edit.policy": "Edit policy", - - // "resource-policies.table.headers.eperson": "EPerson", - // TODO New key - Add a translation - "resource-policies.table.headers.eperson": "EPerson", - - // "resource-policies.table.headers.group": "Group", - // TODO New key - Add a translation - "resource-policies.table.headers.group": "Group", - - // "resource-policies.table.headers.id": "ID", - // TODO New key - Add a translation - "resource-policies.table.headers.id": "ID", - - // "resource-policies.table.headers.name": "Name", - // TODO New key - Add a translation - "resource-policies.table.headers.name": "Name", - - // "resource-policies.table.headers.policyType": "type", - // TODO New key - Add a translation - "resource-policies.table.headers.policyType": "type", - - // "resource-policies.table.headers.title.for.bitstream": "Policies for Bitstream", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.bitstream": "Policies for Bitstream", - - // "resource-policies.table.headers.title.for.bundle": "Policies for Bundle", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.bundle": "Policies for Bundle", - - // "resource-policies.table.headers.title.for.item": "Policies for Item", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.item": "Policies for Item", - - - // "search.description": "", "search.description": "", @@ -4881,9 +4414,9 @@ // TODO New key - Add a translation "submission.sections.upload.form.date-required": "Date is required.", - // "submission.sections.upload.form.from-label": "Grant access from", + // "submission.sections.upload.form.from-label": "Access grant from", // TODO New key - Add a translation - "submission.sections.upload.form.from-label": "Grant access from", + "submission.sections.upload.form.from-label": "Access grant from", // "submission.sections.upload.form.from-placeholder": "From", // TODO New key - Add a translation @@ -4897,9 +4430,9 @@ // TODO New key - Add a translation "submission.sections.upload.form.group-required": "Group is required.", - // "submission.sections.upload.form.until-label": "Grant access until", + // "submission.sections.upload.form.until-label": "Access grant until", // TODO New key - Add a translation - "submission.sections.upload.form.until-label": "Grant access until", + "submission.sections.upload.form.until-label": "Access grant until", // "submission.sections.upload.form.until-placeholder": "Until", // TODO New key - Add a translation @@ -5108,78 +4641,5 @@ "virtual-metadata.delete-relationship.modal-head": "Select the items for which you want to save the virtual metadata as real metadata", - - // "workflowAdmin.search.results.head": "Administer Workflow", - // TODO New key - Add a translation - "workflowAdmin.search.results.head": "Administer Workflow", - - - - // "workflow-item.delete.notification.success.title": "Deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.success.title": "Deleted", - - // "workflow-item.delete.notification.success.content": "This workflow item was successfully deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.success.content": "This workflow item was successfully deleted", - - // "workflow-item.delete.notification.error.title": "Something went wrong", - // TODO New key - Add a translation - "workflow-item.delete.notification.error.title": "Something went wrong", - - // "workflow-item.delete.notification.error.content": "The workflow item could not be deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.error.content": "The workflow item could not be deleted", - - // "workflow-item.delete.title": "Delete workflow item", - // TODO New key - Add a translation - "workflow-item.delete.title": "Delete workflow item", - - // "workflow-item.delete.header": "Delete workflow item", - // TODO New key - Add a translation - "workflow-item.delete.header": "Delete workflow item", - - // "workflow-item.delete.button.cancel": "Cancel", - // TODO New key - Add a translation - "workflow-item.delete.button.cancel": "Cancel", - - // "workflow-item.delete.button.confirm": "Delete", - // TODO New key - Add a translation - "workflow-item.delete.button.confirm": "Delete", - - - // "workflow-item.send-back.notification.success.title": "Sent back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.success.title": "Sent back to submitter", - - // "workflow-item.send-back.notification.success.content": "This workflow item was successfully sent back to the submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.success.content": "This workflow item was successfully sent back to the submitter", - - // "workflow-item.send-back.notification.error.title": "Something went wrong", - // TODO New key - Add a translation - "workflow-item.send-back.notification.error.title": "Something went wrong", - - // "workflow-item.send-back.notification.error.content": "The workflow item could not be sent back to the submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.error.content": "The workflow item could not be sent back to the submitter", - - // "workflow-item.send-back.title": "Send workflow item back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.title": "Send workflow item back to submitter", - - // "workflow-item.send-back.header": "Send workflow item back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.header": "Send workflow item back to submitter", - - // "workflow-item.send-back.button.cancel": "Cancel", - // TODO New key - Add a translation - "workflow-item.send-back.button.cancel": "Cancel", - - // "workflow-item.send-back.button.confirm": "Send back", - // TODO New key - Add a translation - "workflow-item.send-back.button.confirm": "Send back", - - } \ No newline at end of file diff --git a/src/assets/i18n/de.json5 b/src/assets/i18n/de.json5 index 8fd4d3e92d..56398af537 100644 --- a/src/assets/i18n/de.json5 +++ b/src/assets/i18n/de.json5 @@ -252,22 +252,6 @@ - // "admin.access-control.epeople.actions.delete": "Delete EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.delete": "Delete EPerson", - - // "admin.access-control.epeople.actions.impersonate": "Impersonate EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.impersonate": "Impersonate EPerson", - - // "admin.access-control.epeople.actions.reset": "Reset password", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.reset": "Reset password", - - // "admin.access-control.epeople.actions.stop-impersonating": "Stop impersonating EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.stop-impersonating": "Stop impersonating EPerson", - // "admin.access-control.epeople.title": "DSpace Angular :: EPeople", // TODO New key - Add a translation "admin.access-control.epeople.title": "DSpace Angular :: EPeople", @@ -719,30 +703,6 @@ - - // "admin.workflow.breadcrumbs": "Administer Workflow", - // TODO New key - Add a translation - "admin.workflow.breadcrumbs": "Administer Workflow", - - // "admin.workflow.title": "Administer Workflow", - // TODO New key - Add a translation - "admin.workflow.title": "Administer Workflow", - - // "admin.workflow.item.workflow": "Workflow", - // TODO New key - Add a translation - "admin.workflow.item.workflow": "Workflow", - - // "admin.workflow.item.delete": "Delete", - // TODO New key - Add a translation - "admin.workflow.item.delete": "Delete", - - // "admin.workflow.item.send-back": "Send back", - // TODO New key - Add a translation - "admin.workflow.item.send-back": "Send back", - - - - // "auth.errors.invalid-user": "Invalid email address or password.", "auth.errors.invalid-user": "Password oder E-Mail-Adresse ungültig.", @@ -1288,104 +1248,6 @@ - // "comcol-role.edit.no-group": "None", - // TODO New key - Add a translation - "comcol-role.edit.no-group": "None", - - // "comcol-role.edit.create": "Create", - // TODO New key - Add a translation - "comcol-role.edit.create": "Create", - - // "comcol-role.edit.restrict": "Restrict", - // TODO New key - Add a translation - "comcol-role.edit.restrict": "Restrict", - - // "comcol-role.edit.delete": "Delete", - // TODO New key - Add a translation - "comcol-role.edit.delete": "Delete", - - - // "comcol-role.edit.community-admin.name": "Administrators", - // TODO New key - Add a translation - "comcol-role.edit.community-admin.name": "Administrators", - - // "comcol-role.edit.collection-admin.name": "Administrators", - // TODO New key - Add a translation - "comcol-role.edit.collection-admin.name": "Administrators", - - - // "comcol-role.edit.community-admin.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - // TODO New key - Add a translation - "comcol-role.edit.community-admin.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - - // "comcol-role.edit.collection-admin.description": "Collection administrators decide who can submit items to the collection, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization for that collection).", - // TODO New key - Add a translation - "comcol-role.edit.collection-admin.description": "Collection administrators decide who can submit items to the collection, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization for that collection).", - - - // "comcol-role.edit.submitters.name": "Submitters", - // TODO New key - Add a translation - "comcol-role.edit.submitters.name": "Submitters", - - // "comcol-role.edit.submitters.description": "The E-People and Groups that have permission to submit new items to this collection.", - // TODO New key - Add a translation - "comcol-role.edit.submitters.description": "The E-People and Groups that have permission to submit new items to this collection.", - - - // "comcol-role.edit.item_read.name": "Default item read access", - // TODO New key - Add a translation - "comcol-role.edit.item_read.name": "Default item read access", - - // "comcol-role.edit.item_read.description": "E-People and Groups that can read new items submitted to this collection. Changes to this role are not retroactive. Existing items in the system will still be viewable by those who had read access at the time of their addition.", - // TODO New key - Add a translation - "comcol-role.edit.item_read.description": "E-People and Groups that can read new items submitted to this collection. Changes to this role are not retroactive. Existing items in the system will still be viewable by those who had read access at the time of their addition.", - - // "comcol-role.edit.item_read.anonymous-group": "Default read for incoming items is currently set to Anonymous.", - // TODO New key - Add a translation - "comcol-role.edit.item_read.anonymous-group": "Default read for incoming items is currently set to Anonymous.", - - - // "comcol-role.edit.bitstream_read.name": "Default bitstream read access", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.name": "Default bitstream read access", - - // "comcol-role.edit.bitstream_read.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - - // "comcol-role.edit.bitstream_read.anonymous-group": "Default read for incoming bitstreams is currently set to Anonymous.", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.anonymous-group": "Default read for incoming bitstreams is currently set to Anonymous.", - - - // "comcol-role.edit.editor.name": "Editors", - // TODO New key - Add a translation - "comcol-role.edit.editor.name": "Editors", - - // "comcol-role.edit.editor.description": "Editors are able to edit the metadata of incoming submissions, and then accept or reject them.", - // TODO New key - Add a translation - "comcol-role.edit.editor.description": "Editors are able to edit the metadata of incoming submissions, and then accept or reject them.", - - - // "comcol-role.edit.finaleditor.name": "Final editors", - // TODO New key - Add a translation - "comcol-role.edit.finaleditor.name": "Final editors", - - // "comcol-role.edit.finaleditor.description": "Final editors are able to edit the metadata of incoming submissions, but will not be able to reject them.", - // TODO New key - Add a translation - "comcol-role.edit.finaleditor.description": "Final editors are able to edit the metadata of incoming submissions, but will not be able to reject them.", - - - // "comcol-role.edit.reviewer.name": "Reviewers", - // TODO New key - Add a translation - "comcol-role.edit.reviewer.name": "Reviewers", - - // "comcol-role.edit.reviewer.description": "Reviewers are able to accept or reject incoming submissions. However, they are not able to edit the submission's metadata.", - // TODO New key - Add a translation - "comcol-role.edit.reviewer.description": "Reviewers are able to accept or reject incoming submissions. However, they are not able to edit the submission's metadata.", - - - // "community.form.abstract": "Short Description", "community.form.abstract": "Kurzbeschreibung", @@ -1439,10 +1301,6 @@ // "dso-selector.create.item.head": "New item", "dso-selector.create.item.head": "Neue Ressource", - // "dso-selector.create.submission.head": "New submission", - // TODO New key - Add a translation - "dso-selector.create.submission.head": "New submission", - // "dso-selector.edit.collection.head": "Edit collection", "dso-selector.edit.collection.head": "Sammlung bearbeiten", @@ -1599,8 +1457,7 @@ // "form.search": "Search", "form.search": "Suche", - // "form.search-help": "Click here to look for an existing correspondence", - // TODO Source message changed - Revise the translation + // "form.search-help": "Click here to looking for an existing correspondence", "form.search-help": "Klicken Sie hier, um eine Übereinstimmung zu suchen", // "form.submit": "Submit", @@ -1622,15 +1479,6 @@ - // "item.edit.authorizations.heading": "With this editor you can view and alter the policies of an item, plus alter policies of individual item components: bundles and bitstreams. Briefly, an item is a container of bundles, and bundles are containers of bitstreams. Containers usually have ADD/REMOVE/READ/WRITE policies, while bitstreams only have READ/WRITE policies.", - // TODO New key - Add a translation - "item.edit.authorizations.heading": "With this editor you can view and alter the policies of an item, plus alter policies of individual item components: bundles and bitstreams. Briefly, an item is a container of bundles, and bundles are containers of bitstreams. Containers usually have ADD/REMOVE/READ/WRITE policies, while bitstreams only have READ/WRITE policies.", - - // "item.edit.authorizations.title": "Edit item's Policies", - // TODO New key - Add a translation - "item.edit.authorizations.title": "Edit item's Policies", - - // "item.bitstreams.upload.bundle": "Bundle", // TODO New key - Add a translation @@ -2755,16 +2603,11 @@ "menu.section.toggle.statistics_task": "Bereich Statistikaufgaben umschalten", - // "menu.section.workflow": "Administer Workflow", - // TODO New key - Add a translation - "menu.section.workflow": "Administer Workflow", - // "mydspace.description": "", "mydspace.description": "", - // "mydspace.general.text-here": "here", - // TODO Source message changed - Revise the translation + // "mydspace.general.text-here": "HERE", "mydspace.general.text-here": "Hier", // "mydspace.messages.controller-help": "Select this option to send a message to item's submitter.", @@ -2863,14 +2706,6 @@ // "mydspace.upload.upload-failed": "Error creating new workspace. Please verify the content uploaded before retry.", "mydspace.upload.upload-failed": "Fehler beim Anlegen eines neuen Arbeitsbereiches. Bitte überprüfen Sie den Inhalt bevor Sie es nochmal versuchen.", - // "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", - // TODO New key - Add a translation - "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", - - // "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", - // TODO New key - Add a translation - "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", - // "mydspace.upload.upload-multiple-successful": "{{qty}} new workspace items created.", "mydspace.upload.upload-multiple-successful": "{{qty}} neue(s) Arbeitsbereichressource(n) angelegt.", @@ -2910,10 +2745,6 @@ // "nav.statistics.header": "Statistics", "nav.statistics.header": "Statistiken", - // "nav.stop-impersonating": "Stop impersonating EPerson", - // TODO New key - Add a translation - "nav.stop-impersonating": "Stop impersonating EPerson", - // "orgunit.listelement.badge": "Organizational Unit", @@ -3105,120 +2936,6 @@ - // "profile.breadcrumbs": "Update Profile", - // TODO New key - Add a translation - "profile.breadcrumbs": "Update Profile", - - // "profile.card.identify": "Identify", - // TODO New key - Add a translation - "profile.card.identify": "Identify", - - // "profile.card.security": "Security", - // TODO New key - Add a translation - "profile.card.security": "Security", - - // "profile.form.submit": "Update Profile", - // TODO New key - Add a translation - "profile.form.submit": "Update Profile", - - // "profile.groups.head": "Authorization groups you belong to", - // TODO New key - Add a translation - "profile.groups.head": "Authorization groups you belong to", - - // "profile.head": "Update Profile", - // TODO New key - Add a translation - "profile.head": "Update Profile", - - // "profile.metadata.form.error.firstname.required": "First Name is required", - // TODO New key - Add a translation - "profile.metadata.form.error.firstname.required": "First Name is required", - - // "profile.metadata.form.error.lastname.required": "Last Name is required", - // TODO New key - Add a translation - "profile.metadata.form.error.lastname.required": "Last Name is required", - - // "profile.metadata.form.label.email": "Email Address", - // TODO New key - Add a translation - "profile.metadata.form.label.email": "Email Address", - - // "profile.metadata.form.label.firstname": "First Name", - // TODO New key - Add a translation - "profile.metadata.form.label.firstname": "First Name", - - // "profile.metadata.form.label.language": "Language", - // TODO New key - Add a translation - "profile.metadata.form.label.language": "Language", - - // "profile.metadata.form.label.lastname": "Last Name", - // TODO New key - Add a translation - "profile.metadata.form.label.lastname": "Last Name", - - // "profile.metadata.form.label.phone": "Contact Telephone", - // TODO New key - Add a translation - "profile.metadata.form.label.phone": "Contact Telephone", - - // "profile.metadata.form.notifications.success.content": "Your changes to the profile were saved.", - // TODO New key - Add a translation - "profile.metadata.form.notifications.success.content": "Your changes to the profile were saved.", - - // "profile.metadata.form.notifications.success.title": "Profile saved", - // TODO New key - Add a translation - "profile.metadata.form.notifications.success.title": "Profile saved", - - // "profile.notifications.warning.no-changes.content": "No changes were made to the Profile.", - // TODO New key - Add a translation - "profile.notifications.warning.no-changes.content": "No changes were made to the Profile.", - - // "profile.notifications.warning.no-changes.title": "No changes", - // TODO New key - Add a translation - "profile.notifications.warning.no-changes.title": "No changes", - - // "profile.security.form.error.matching-passwords": "The passwords do not match.", - // TODO New key - Add a translation - "profile.security.form.error.matching-passwords": "The passwords do not match.", - - // "profile.security.form.error.password-length": "The password should be at least 6 characters long.", - // TODO New key - Add a translation - "profile.security.form.error.password-length": "The password should be at least 6 characters long.", - - // "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.", - // TODO New key - Add a translation - "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.", - - // "profile.security.form.label.password": "Password", - // TODO New key - Add a translation - "profile.security.form.label.password": "Password", - - // "profile.security.form.label.passwordrepeat": "Retype to confirm", - // TODO New key - Add a translation - "profile.security.form.label.passwordrepeat": "Retype to confirm", - - // "profile.security.form.notifications.success.content": "Your changes to the password were saved.", - // TODO New key - Add a translation - "profile.security.form.notifications.success.content": "Your changes to the password were saved.", - - // "profile.security.form.notifications.success.title": "Password saved", - // TODO New key - Add a translation - "profile.security.form.notifications.success.title": "Password saved", - - // "profile.security.form.notifications.error.title": "Error changing passwords", - // TODO New key - Add a translation - "profile.security.form.notifications.error.title": "Error changing passwords", - - // "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", - // TODO New key - Add a translation - "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", - - // "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", - // TODO New key - Add a translation - "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", - - // "profile.title": "Update Profile", - // TODO New key - Add a translation - "profile.title": "Update Profile", - - - // "project.listelement.badge": "Research Project", "project.listelement.badge": "Forschungsprojekt", @@ -3321,192 +3038,6 @@ - // "resource-policies.add.button": "Add", - // TODO New key - Add a translation - "resource-policies.add.button": "Add", - - // "resource-policies.add.for.": "Add a new policy", - // TODO New key - Add a translation - "resource-policies.add.for.": "Add a new policy", - - // "resource-policies.add.for.bitstream": "Add a new Bitstream policy", - // TODO New key - Add a translation - "resource-policies.add.for.bitstream": "Add a new Bitstream policy", - - // "resource-policies.add.for.bundle": "Add a new Bundle policy", - // TODO New key - Add a translation - "resource-policies.add.for.bundle": "Add a new Bundle policy", - - // "resource-policies.add.for.item": "Add a new Item policy", - // TODO New key - Add a translation - "resource-policies.add.for.item": "Add a new Item policy", - - // "resource-policies.create.page.heading": "Create new resource policy for ", - // TODO New key - Add a translation - "resource-policies.create.page.heading": "Create new resource policy for ", - - // "resource-policies.create.page.failure.content": "An error occurred while creating the resource policy.", - // TODO New key - Add a translation - "resource-policies.create.page.failure.content": "An error occurred while creating the resource policy.", - - // "resource-policies.create.page.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.create.page.success.content": "Operation successful", - - // "resource-policies.create.page.title": "Create new resource policy", - // TODO New key - Add a translation - "resource-policies.create.page.title": "Create new resource policy", - - // "resource-policies.delete.btn": "Delete selected", - // TODO New key - Add a translation - "resource-policies.delete.btn": "Delete selected", - - // "resource-policies.delete.btn.title": "Delete selected resource policies", - // TODO New key - Add a translation - "resource-policies.delete.btn.title": "Delete selected resource policies", - - // "resource-policies.delete.failure.content": "An error occurred while deleting selected resource policies.", - // TODO New key - Add a translation - "resource-policies.delete.failure.content": "An error occurred while deleting selected resource policies.", - - // "resource-policies.delete.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.delete.success.content": "Operation successful", - - // "resource-policies.edit.page.heading": "Edit resource policy ", - // TODO New key - Add a translation - "resource-policies.edit.page.heading": "Edit resource policy ", - - // "resource-policies.edit.page.failure.content": "An error occurred while editing the resource policy.", - // TODO New key - Add a translation - "resource-policies.edit.page.failure.content": "An error occurred while editing the resource policy.", - - // "resource-policies.edit.page.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.edit.page.success.content": "Operation successful", - - // "resource-policies.edit.page.title": "Edit resource policy", - // TODO New key - Add a translation - "resource-policies.edit.page.title": "Edit resource policy", - - // "resource-policies.form.action-type.label": "Select the action type", - // TODO New key - Add a translation - "resource-policies.form.action-type.label": "Select the action type", - - // "resource-policies.form.action-type.required": "You must select the resource policy action.", - // TODO New key - Add a translation - "resource-policies.form.action-type.required": "You must select the resource policy action.", - - // "resource-policies.form.eperson-group-list.label": "The eperson or group that will be grant of the permission", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.label": "The eperson or group that will be grant of the permission", - - // "resource-policies.form.eperson-group-list.select.btn": "Select", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.select.btn": "Select", - - // "resource-policies.form.eperson-group-list.tab.eperson": "Search for a ePerson", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.tab.eperson": "Search for a ePerson", - - // "resource-policies.form.eperson-group-list.tab.group": "Search for a group", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.tab.group": "Search for a group", - - // "resource-policies.form.eperson-group-list.table.headers.action": "Action", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.action": "Action", - - // "resource-policies.form.eperson-group-list.table.headers.id": "ID", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.id": "ID", - - // "resource-policies.form.eperson-group-list.table.headers.name": "Name", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.name": "Name", - - // "resource-policies.form.date.end.label": "End Date", - // TODO New key - Add a translation - "resource-policies.form.date.end.label": "End Date", - - // "resource-policies.form.date.start.label": "Start Date", - // TODO New key - Add a translation - "resource-policies.form.date.start.label": "Start Date", - - // "resource-policies.form.description.label": "Description", - // TODO New key - Add a translation - "resource-policies.form.description.label": "Description", - - // "resource-policies.form.name.label": "Name", - // TODO New key - Add a translation - "resource-policies.form.name.label": "Name", - - // "resource-policies.form.policy-type.label": "Select the policy type", - // TODO New key - Add a translation - "resource-policies.form.policy-type.label": "Select the policy type", - - // "resource-policies.form.policy-type.required": "You must select the resource policy type.", - // TODO New key - Add a translation - "resource-policies.form.policy-type.required": "You must select the resource policy type.", - - // "resource-policies.table.headers.action": "Action", - // TODO New key - Add a translation - "resource-policies.table.headers.action": "Action", - - // "resource-policies.table.headers.date.end": "End Date", - // TODO New key - Add a translation - "resource-policies.table.headers.date.end": "End Date", - - // "resource-policies.table.headers.date.start": "Start Date", - // TODO New key - Add a translation - "resource-policies.table.headers.date.start": "Start Date", - - // "resource-policies.table.headers.edit": "Edit", - // TODO New key - Add a translation - "resource-policies.table.headers.edit": "Edit", - - // "resource-policies.table.headers.edit.group": "Edit group", - // TODO New key - Add a translation - "resource-policies.table.headers.edit.group": "Edit group", - - // "resource-policies.table.headers.edit.policy": "Edit policy", - // TODO New key - Add a translation - "resource-policies.table.headers.edit.policy": "Edit policy", - - // "resource-policies.table.headers.eperson": "EPerson", - // TODO New key - Add a translation - "resource-policies.table.headers.eperson": "EPerson", - - // "resource-policies.table.headers.group": "Group", - // TODO New key - Add a translation - "resource-policies.table.headers.group": "Group", - - // "resource-policies.table.headers.id": "ID", - // TODO New key - Add a translation - "resource-policies.table.headers.id": "ID", - - // "resource-policies.table.headers.name": "Name", - // TODO New key - Add a translation - "resource-policies.table.headers.name": "Name", - - // "resource-policies.table.headers.policyType": "type", - // TODO New key - Add a translation - "resource-policies.table.headers.policyType": "type", - - // "resource-policies.table.headers.title.for.bitstream": "Policies for Bitstream", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.bitstream": "Policies for Bitstream", - - // "resource-policies.table.headers.title.for.bundle": "Policies for Bundle", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.bundle": "Policies for Bundle", - - // "resource-policies.table.headers.title.for.item": "Policies for Item", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.item": "Policies for Item", - - - // "search.description": "", "search.description": "", @@ -4159,8 +3690,7 @@ // "submission.sections.upload.form.date-required": "Date is required.", "submission.sections.upload.form.date-required": "Datum erforderlich.", - // "submission.sections.upload.form.from-label": "Grant access from", - // TODO Source message changed - Revise the translation + // "submission.sections.upload.form.from-label": "Access grant from", "submission.sections.upload.form.from-label": "Zugriff gewährt ab", // "submission.sections.upload.form.from-placeholder": "From", @@ -4172,8 +3702,7 @@ // "submission.sections.upload.form.group-required": "Group is required.", "submission.sections.upload.form.group-required": "Gruppe ist erforderlich", - // "submission.sections.upload.form.until-label": "Grant access until", - // TODO Source message changed - Revise the translation + // "submission.sections.upload.form.until-label": "Access grant until", "submission.sections.upload.form.until-label": "Zugriff gewährt bis", // "submission.sections.upload.form.until-placeholder": "Until", @@ -4338,78 +3867,5 @@ "virtual-metadata.delete-relationship.modal-head": "Wählen Sie die Ressourcen für die Sie die virtuellen Metadaten als reelle Metadaten speichern wollen", - - // "workflowAdmin.search.results.head": "Administer Workflow", - // TODO New key - Add a translation - "workflowAdmin.search.results.head": "Administer Workflow", - - - - // "workflow-item.delete.notification.success.title": "Deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.success.title": "Deleted", - - // "workflow-item.delete.notification.success.content": "This workflow item was successfully deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.success.content": "This workflow item was successfully deleted", - - // "workflow-item.delete.notification.error.title": "Something went wrong", - // TODO New key - Add a translation - "workflow-item.delete.notification.error.title": "Something went wrong", - - // "workflow-item.delete.notification.error.content": "The workflow item could not be deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.error.content": "The workflow item could not be deleted", - - // "workflow-item.delete.title": "Delete workflow item", - // TODO New key - Add a translation - "workflow-item.delete.title": "Delete workflow item", - - // "workflow-item.delete.header": "Delete workflow item", - // TODO New key - Add a translation - "workflow-item.delete.header": "Delete workflow item", - - // "workflow-item.delete.button.cancel": "Cancel", - // TODO New key - Add a translation - "workflow-item.delete.button.cancel": "Cancel", - - // "workflow-item.delete.button.confirm": "Delete", - // TODO New key - Add a translation - "workflow-item.delete.button.confirm": "Delete", - - - // "workflow-item.send-back.notification.success.title": "Sent back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.success.title": "Sent back to submitter", - - // "workflow-item.send-back.notification.success.content": "This workflow item was successfully sent back to the submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.success.content": "This workflow item was successfully sent back to the submitter", - - // "workflow-item.send-back.notification.error.title": "Something went wrong", - // TODO New key - Add a translation - "workflow-item.send-back.notification.error.title": "Something went wrong", - - // "workflow-item.send-back.notification.error.content": "The workflow item could not be sent back to the submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.error.content": "The workflow item could not be sent back to the submitter", - - // "workflow-item.send-back.title": "Send workflow item back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.title": "Send workflow item back to submitter", - - // "workflow-item.send-back.header": "Send workflow item back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.header": "Send workflow item back to submitter", - - // "workflow-item.send-back.button.cancel": "Cancel", - // TODO New key - Add a translation - "workflow-item.send-back.button.cancel": "Cancel", - - // "workflow-item.send-back.button.confirm": "Send back", - // TODO New key - Add a translation - "workflow-item.send-back.button.confirm": "Send back", - - } \ No newline at end of file diff --git a/src/assets/i18n/es.json5 b/src/assets/i18n/es.json5 index 59463357d7..3e27fb3b04 100644 --- a/src/assets/i18n/es.json5 +++ b/src/assets/i18n/es.json5 @@ -1,4573 +1,4029 @@ { - + // "404.help": "We can't find the page you're looking for. The page may have been moved or deleted. You can use the button below to get back to the home page. ", "404.help": "No es posible encontrar la página que busca. La página puede haber sido movida o eliminada. Puede utilizar el botón de abajo para regresar a la página de inicio. ", - + // "404.link.home-page": "Take me to the home page", "404.link.home-page": "Ir a la página de inicio", - + // "404.page-not-found": "page not found", "404.page-not-found": "Página no encontrada", - - - + + + // "admin.registries.bitstream-formats.create.failure.content": "An error occurred while creating the new bitstream format.", "admin.registries.bitstream-formats.create.failure.content": "Ha ocurrido un error mientras se creaba el nuevo formato del archivo.", - + // "admin.registries.bitstream-formats.create.failure.head": "Failure", "admin.registries.bitstream-formats.create.failure.head": "Error", - + // "admin.registries.bitstream-formats.create.head": "Create Bitstream format", "admin.registries.bitstream-formats.create.head": "Crear formato de archivo", - + // "admin.registries.bitstream-formats.create.new": "Add a new bitstream format", "admin.registries.bitstream-formats.create.new": "Agregar un nuevo formato de archivo", - + // "admin.registries.bitstream-formats.create.success.content": "The new bitstream format was successfully created.", "admin.registries.bitstream-formats.create.success.content": "El nuevo formato de archivo fue creado exitosamente.", - + // "admin.registries.bitstream-formats.create.success.head": "Success", "admin.registries.bitstream-formats.create.success.head": "Éxito", - + // "admin.registries.bitstream-formats.delete.failure.amount": "Failed to remove {{ amount }} format(s)", "admin.registries.bitstream-formats.delete.failure.amount": "Error al eliminar {{ amount }} formato(s)", - + // "admin.registries.bitstream-formats.delete.failure.head": "Failure", "admin.registries.bitstream-formats.delete.failure.head": "Error", - + // "admin.registries.bitstream-formats.delete.success.amount": "Successfully removed {{ amount }} format(s)", "admin.registries.bitstream-formats.delete.success.amount": "Éxito al eliminar {{ amount }} formato(s)", - + // "admin.registries.bitstream-formats.delete.success.head": "Success", "admin.registries.bitstream-formats.delete.success.head": "Éxito", - + // "admin.registries.bitstream-formats.description": "This list of bitstream formats provides information about known formats and their support level.", "admin.registries.bitstream-formats.description": "Este listado de formatos de archivos provee información acerca de formatos conocidos y su nivel de soporte.", - + // "admin.registries.bitstream-formats.edit.description.hint": "", "admin.registries.bitstream-formats.edit.description.hint": "", - + // "admin.registries.bitstream-formats.edit.description.label": "Description", "admin.registries.bitstream-formats.edit.description.label": "Descripción", - + // "admin.registries.bitstream-formats.edit.extensions.hint": "Extensions are file extensions that are used to automatically identify the format of uploaded files. You can enter several extensions for each format.", "admin.registries.bitstream-formats.edit.extensions.hint": "Las extensiones son extensiones de archivos que son usados para identificar automáticamente el formato de los archivos cargados. Se puede ingresar varias extensiones para cada formato.", - + // "admin.registries.bitstream-formats.edit.extensions.label": "File extensions", "admin.registries.bitstream-formats.edit.extensions.label": "Extensiones de los archivos", - + // "admin.registries.bitstream-formats.edit.extensions.placeholder": "Enter a file extension without the dot", // TODO Source message changed - Revise the translation "admin.registries.bitstream-formats.edit.extensions.placeholder": "Ingrese la extensión del archivo sin punto", - + // "admin.registries.bitstream-formats.edit.failure.content": "An error occurred while editing the bitstream format.", "admin.registries.bitstream-formats.edit.failure.content": "Ha ocurrido un error mientras se editaba el formato del archivo.", - + // "admin.registries.bitstream-formats.edit.failure.head": "Failure", "admin.registries.bitstream-formats.edit.failure.head": "Error", - + // "admin.registries.bitstream-formats.edit.head": "Bitstream format: {{ format }}", "admin.registries.bitstream-formats.edit.head": "Formato de Archivo: {{ format }}", - + // "admin.registries.bitstream-formats.edit.internal.hint": "Formats marked as internal are hidden from the user, and used for administrative purposes.", // TODO Source message changed - Revise the translation "admin.registries.bitstream-formats.edit.internal.hint": "Los formatos marcados como internos están ocultos para el usuario y se utilizan con fines administrativos.", - + // "admin.registries.bitstream-formats.edit.internal.label": "Internal", "admin.registries.bitstream-formats.edit.internal.label": "Interno", - + // "admin.registries.bitstream-formats.edit.mimetype.hint": "The MIME type associated with this format, does not have to be unique.", "admin.registries.bitstream-formats.edit.mimetype.hint": "El tipo MIME asociado con este formato no tiene que ser único.", - + // "admin.registries.bitstream-formats.edit.mimetype.label": "MIME Type", "admin.registries.bitstream-formats.edit.mimetype.label": "Tipo MIME", - + // "admin.registries.bitstream-formats.edit.shortDescription.hint": "A unique name for this format, (e.g. Microsoft Word XP or Microsoft Word 2000)", "admin.registries.bitstream-formats.edit.shortDescription.hint": "Único nombre para este formato, (e.j. Microsoft Word XP o Microsoft Word 2000)", - + // "admin.registries.bitstream-formats.edit.shortDescription.label": "Name", "admin.registries.bitstream-formats.edit.shortDescription.label": "Nombre", - + // "admin.registries.bitstream-formats.edit.success.content": "The bitstream format was successfully edited.", "admin.registries.bitstream-formats.edit.success.content": "El formato del archivo fue editado exitosamente.", - + // "admin.registries.bitstream-formats.edit.success.head": "Success", "admin.registries.bitstream-formats.edit.success.head": "Éxito", - + // "admin.registries.bitstream-formats.edit.supportLevel.hint": "The level of support your institution pledges for this format.", "admin.registries.bitstream-formats.edit.supportLevel.hint": "El nivel de apoyo que su institución compromete para este formato.", - + // "admin.registries.bitstream-formats.edit.supportLevel.label": "Support level", "admin.registries.bitstream-formats.edit.supportLevel.label": "Nivel de soporte", - + // "admin.registries.bitstream-formats.head": "Bitstream Format Registry", "admin.registries.bitstream-formats.head": "Registro de formato de archivo", - + // "admin.registries.bitstream-formats.no-items": "No bitstream formats to show.", "admin.registries.bitstream-formats.no-items": "No hay formatos de archivo para mostrar.", - + // "admin.registries.bitstream-formats.table.delete": "Delete selected", "admin.registries.bitstream-formats.table.delete": "Eliminar lo seleccionado", - + // "admin.registries.bitstream-formats.table.deselect-all": "Deselect all", "admin.registries.bitstream-formats.table.deselect-all": "Eliminar selección", - + // "admin.registries.bitstream-formats.table.internal": "internal", "admin.registries.bitstream-formats.table.internal": "interno", - + // "admin.registries.bitstream-formats.table.mimetype": "MIME Type", "admin.registries.bitstream-formats.table.mimetype": "Tipo MIME", - + // "admin.registries.bitstream-formats.table.name": "Name", "admin.registries.bitstream-formats.table.name": "Nombre", - + // "admin.registries.bitstream-formats.table.return": "Return", "admin.registries.bitstream-formats.table.return": "Regreso", - + // "admin.registries.bitstream-formats.table.supportLevel.KNOWN": "Known", "admin.registries.bitstream-formats.table.supportLevel.KNOWN": "Conocido", - + // "admin.registries.bitstream-formats.table.supportLevel.SUPPORTED": "Supported", "admin.registries.bitstream-formats.table.supportLevel.SUPPORTED": "Soportado", - + // "admin.registries.bitstream-formats.table.supportLevel.UNKNOWN": "Unknown", "admin.registries.bitstream-formats.table.supportLevel.UNKNOWN": "Desconocido", - + // "admin.registries.bitstream-formats.table.supportLevel.head": "Support Level", "admin.registries.bitstream-formats.table.supportLevel.head": "Nivel de soporte", - + // "admin.registries.bitstream-formats.title": "DSpace Angular :: Bitstream Format Registry", "admin.registries.bitstream-formats.title": "DSpace Angular :: Registro de formato de archivo", - - - + + + // "admin.registries.metadata.description": "The metadata registry maintains a list of all metadata fields available in the repository. These fields may be divided amongst multiple schemas. However, DSpace requires the qualified Dublin Core schema.", "admin.registries.metadata.description": "El registro de metadatos mantiene una lista de todos los campos de metadatos disponibles en el repositorio. Estos campos pueden dividirse entre múltiples esquemas. Sin embargo, DSpace requiere el esquema calificado de Dublin Core.", - + // "admin.registries.metadata.form.create": "Create metadata schema", "admin.registries.metadata.form.create": "Crear esquema de metadatos", - + // "admin.registries.metadata.form.edit": "Edit metadata schema", "admin.registries.metadata.form.edit": "Editar esquema de metadatos", - + // "admin.registries.metadata.form.name": "Name", "admin.registries.metadata.form.name": "Nombre", - + // "admin.registries.metadata.form.namespace": "Namespace", "admin.registries.metadata.form.namespace": "Namespace", - + // "admin.registries.metadata.head": "Metadata Registry", "admin.registries.metadata.head": "Registro de metadatos", - + // "admin.registries.metadata.schemas.no-items": "No metadata schemas to show.", "admin.registries.metadata.schemas.no-items": "No existen esquemas de metadatos para mostrar.", - + // "admin.registries.metadata.schemas.table.delete": "Delete selected", "admin.registries.metadata.schemas.table.delete": "Eliminar selección", - + // "admin.registries.metadata.schemas.table.id": "ID", "admin.registries.metadata.schemas.table.id": "ID", - + // "admin.registries.metadata.schemas.table.name": "Name", "admin.registries.metadata.schemas.table.name": "Nombre", - + // "admin.registries.metadata.schemas.table.namespace": "Namespace", "admin.registries.metadata.schemas.table.namespace": "Namespace", - + // "admin.registries.metadata.title": "DSpace Angular :: Metadata Registry", "admin.registries.metadata.title": "DSpace Angular :: Registro de metadatos", - - + + // "admin.registries.schema.description": "This is the metadata schema for \"{{namespace}}\".", "admin.registries.schema.description": "Este es el esquema de metadatos para \"{{namespace}}\".", - + // "admin.registries.schema.fields.head": "Schema metadata fields", "admin.registries.schema.fields.head": "Campos del esquema de metadatos", - + // "admin.registries.schema.fields.no-items": "No metadata fields to show.", "admin.registries.schema.fields.no-items": "No hay campos de metadatos para mostrar.", - + // "admin.registries.schema.fields.table.delete": "Delete selected", "admin.registries.schema.fields.table.delete": "Eliminar selección", - + // "admin.registries.schema.fields.table.field": "Field", "admin.registries.schema.fields.table.field": "Campos", - + // "admin.registries.schema.fields.table.scopenote": "Scope Note", "admin.registries.schema.fields.table.scopenote": "Nota de alcance", - + // "admin.registries.schema.form.create": "Create metadata field", "admin.registries.schema.form.create": "Crear campos de metadatos", - + // "admin.registries.schema.form.edit": "Edit metadata field", "admin.registries.schema.form.edit": "Editar campos de metadatos", - + // "admin.registries.schema.form.element": "Element", "admin.registries.schema.form.element": "Elemento", - + // "admin.registries.schema.form.qualifier": "Qualifier", "admin.registries.schema.form.qualifier": "Calificador", - + // "admin.registries.schema.form.scopenote": "Scope Note", "admin.registries.schema.form.scopenote": "Nota de alcance", - + // "admin.registries.schema.head": "Metadata Schema", "admin.registries.schema.head": "Esquema de Metadatos", - + // "admin.registries.schema.notification.created": "Successfully created metadata schema \"{{prefix}}\"", "admin.registries.schema.notification.created": "Esquema de metadatos creado exitosamente \"{{prefix}}\"", - + // "admin.registries.schema.notification.deleted.failure": "Failed to delete {{amount}} metadata schemas", "admin.registries.schema.notification.deleted.failure": "Error al eliminar {{amount}} esquema de metadatos", - + // "admin.registries.schema.notification.deleted.success": "Successfully deleted {{amount}} metadata schemas", "admin.registries.schema.notification.deleted.success": "Exitosamente eliminado {{amount}} esquema de metadatos", - + // "admin.registries.schema.notification.edited": "Successfully edited metadata schema \"{{prefix}}\"", "admin.registries.schema.notification.edited": "Exitosamente editado el esquema de metadato \"{{prefix}}\"", - + // "admin.registries.schema.notification.failure": "Error", "admin.registries.schema.notification.failure": "Error", - + // "admin.registries.schema.notification.field.created": "Successfully created metadata field \"{{field}}\"", "admin.registries.schema.notification.field.created": "Exitosamente creado el campo de metadato \"{{field}}\"", - + // "admin.registries.schema.notification.field.deleted.failure": "Failed to delete {{amount}} metadata fields", "admin.registries.schema.notification.field.deleted.failure": "Error al eliminar {{amount}} campos de metadata", - + // "admin.registries.schema.notification.field.deleted.success": "Successfully deleted {{amount}} metadata fields", "admin.registries.schema.notification.field.deleted.success": "Exitosamente eliminado {{amount}} campos de metadatos", - + // "admin.registries.schema.notification.field.edited": "Successfully edited metadata field \"{{field}}\"", "admin.registries.schema.notification.field.edited": "Exitosamente editado el campo de metadato \"{{field}}\"", - + // "admin.registries.schema.notification.success": "Success", "admin.registries.schema.notification.success": "Éxito", - + // "admin.registries.schema.return": "Return", "admin.registries.schema.return": "Regreso", - + // "admin.registries.schema.title": "DSpace Angular :: Metadata Schema Registry", "admin.registries.schema.title": "DSpace Angular :: Registro de Esquema de Metadatos", - - - - // "admin.access-control.epeople.actions.delete": "Delete EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.delete": "Delete EPerson", - - // "admin.access-control.epeople.actions.impersonate": "Impersonate EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.impersonate": "Impersonate EPerson", - - // "admin.access-control.epeople.actions.reset": "Reset password", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.reset": "Reset password", - - // "admin.access-control.epeople.actions.stop-impersonating": "Stop impersonating EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.stop-impersonating": "Stop impersonating EPerson", - + + + // "admin.access-control.epeople.title": "DSpace Angular :: EPeople", // TODO New key - Add a translation "admin.access-control.epeople.title": "DSpace Angular :: EPeople", - + // "admin.access-control.epeople.head": "EPeople", // TODO New key - Add a translation "admin.access-control.epeople.head": "EPeople", - + // "admin.access-control.epeople.search.head": "Search", // TODO New key - Add a translation "admin.access-control.epeople.search.head": "Search", - + // "admin.access-control.epeople.button.see-all": "Browse All", // TODO New key - Add a translation "admin.access-control.epeople.button.see-all": "Browse All", - + // "admin.access-control.epeople.search.scope.metadata": "Metadata", // TODO New key - Add a translation "admin.access-control.epeople.search.scope.metadata": "Metadata", - + // "admin.access-control.epeople.search.scope.email": "E-mail (exact)", // TODO New key - Add a translation "admin.access-control.epeople.search.scope.email": "E-mail (exact)", - + // "admin.access-control.epeople.search.button": "Search", // TODO New key - Add a translation "admin.access-control.epeople.search.button": "Search", - + // "admin.access-control.epeople.button.add": "Add EPerson", // TODO New key - Add a translation "admin.access-control.epeople.button.add": "Add EPerson", - + // "admin.access-control.epeople.table.id": "ID", // TODO New key - Add a translation "admin.access-control.epeople.table.id": "ID", - + // "admin.access-control.epeople.table.name": "Name", // TODO New key - Add a translation "admin.access-control.epeople.table.name": "Name", - + // "admin.access-control.epeople.table.email": "E-mail (exact)", // TODO New key - Add a translation "admin.access-control.epeople.table.email": "E-mail (exact)", - + // "admin.access-control.epeople.table.edit": "Edit", // TODO New key - Add a translation "admin.access-control.epeople.table.edit": "Edit", - + // "admin.access-control.epeople.table.edit.buttons.edit": "Edit \"{{name}}\"", // TODO New key - Add a translation "admin.access-control.epeople.table.edit.buttons.edit": "Edit \"{{name}}\"", - + // "admin.access-control.epeople.table.edit.buttons.remove": "Delete \"{{name}}\"", // TODO New key - Add a translation "admin.access-control.epeople.table.edit.buttons.remove": "Delete \"{{name}}\"", - + // "admin.access-control.epeople.no-items": "No EPeople to show.", // TODO New key - Add a translation "admin.access-control.epeople.no-items": "No EPeople to show.", - + // "admin.access-control.epeople.form.create": "Create EPerson", // TODO New key - Add a translation "admin.access-control.epeople.form.create": "Create EPerson", - + // "admin.access-control.epeople.form.edit": "Edit EPerson", // TODO New key - Add a translation "admin.access-control.epeople.form.edit": "Edit EPerson", - + // "admin.access-control.epeople.form.firstName": "First name", // TODO New key - Add a translation "admin.access-control.epeople.form.firstName": "First name", - + // "admin.access-control.epeople.form.lastName": "Last name", // TODO New key - Add a translation "admin.access-control.epeople.form.lastName": "Last name", - + // "admin.access-control.epeople.form.email": "E-mail", // TODO New key - Add a translation "admin.access-control.epeople.form.email": "E-mail", - + // "admin.access-control.epeople.form.emailHint": "Must be valid e-mail address", // TODO New key - Add a translation "admin.access-control.epeople.form.emailHint": "Must be valid e-mail address", - + // "admin.access-control.epeople.form.canLogIn": "Can log in", // TODO New key - Add a translation "admin.access-control.epeople.form.canLogIn": "Can log in", - + // "admin.access-control.epeople.form.requireCertificate": "Requires certificate", // TODO New key - Add a translation "admin.access-control.epeople.form.requireCertificate": "Requires certificate", - + // "admin.access-control.epeople.form.notification.created.success": "Successfully created EPerson \"{{name}}\"", // TODO New key - Add a translation "admin.access-control.epeople.form.notification.created.success": "Successfully created EPerson \"{{name}}\"", - + // "admin.access-control.epeople.form.notification.created.failure": "Failed to create EPerson \"{{name}}\"", // TODO New key - Add a translation "admin.access-control.epeople.form.notification.created.failure": "Failed to create EPerson \"{{name}}\"", - + // "admin.access-control.epeople.form.notification.created.failure.emailInUse": "Failed to create EPerson \"{{name}}\", email \"{{email}}\" already in use.", // TODO New key - Add a translation "admin.access-control.epeople.form.notification.created.failure.emailInUse": "Failed to create EPerson \"{{name}}\", email \"{{email}}\" already in use.", - + // "admin.access-control.epeople.form.notification.edited.failure.emailInUse": "Failed to edit EPerson \"{{name}}\", email \"{{email}}\" already in use.", // TODO New key - Add a translation "admin.access-control.epeople.form.notification.edited.failure.emailInUse": "Failed to edit EPerson \"{{name}}\", email \"{{email}}\" already in use.", - + // "admin.access-control.epeople.form.notification.edited.success": "Successfully edited EPerson \"{{name}}\"", // TODO New key - Add a translation "admin.access-control.epeople.form.notification.edited.success": "Successfully edited EPerson \"{{name}}\"", - + // "admin.access-control.epeople.form.notification.edited.failure": "Failed to edit EPerson \"{{name}}\"", // TODO New key - Add a translation "admin.access-control.epeople.form.notification.edited.failure": "Failed to edit EPerson \"{{name}}\"", - + // "admin.access-control.epeople.form.groupsEPersonIsMemberOf": "Member of these groups:", // TODO New key - Add a translation "admin.access-control.epeople.form.groupsEPersonIsMemberOf": "Member of these groups:", - + // "admin.access-control.epeople.form.table.id": "ID", // TODO New key - Add a translation "admin.access-control.epeople.form.table.id": "ID", - + // "admin.access-control.epeople.form.table.name": "Name", // TODO New key - Add a translation "admin.access-control.epeople.form.table.name": "Name", - + // "admin.access-control.epeople.form.memberOfNoGroups": "This EPerson is not a member of any groups", // TODO New key - Add a translation "admin.access-control.epeople.form.memberOfNoGroups": "This EPerson is not a member of any groups", - + // "admin.access-control.epeople.form.goToGroups": "Add to groups", // TODO New key - Add a translation "admin.access-control.epeople.form.goToGroups": "Add to groups", - + // "admin.access-control.epeople.notification.deleted.failure": "Failed to delete EPerson: \"{{name}}\"", // TODO New key - Add a translation "admin.access-control.epeople.notification.deleted.failure": "Failed to delete EPerson: \"{{name}}\"", - + // "admin.access-control.epeople.notification.deleted.success": "Successfully deleted EPerson: \"{{name}}\"", // TODO New key - Add a translation "admin.access-control.epeople.notification.deleted.success": "Successfully deleted EPerson: \"{{name}}\"", - - - + + + // "admin.access-control.groups.title": "DSpace Angular :: Groups", // TODO New key - Add a translation "admin.access-control.groups.title": "DSpace Angular :: Groups", - + // "admin.access-control.groups.head": "Groups", // TODO New key - Add a translation "admin.access-control.groups.head": "Groups", - + // "admin.access-control.groups.button.add": "Add group", // TODO New key - Add a translation "admin.access-control.groups.button.add": "Add group", - + // "admin.access-control.groups.search.head": "Search groups", // TODO New key - Add a translation "admin.access-control.groups.search.head": "Search groups", - + // "admin.access-control.groups.button.see-all": "Browse all", // TODO New key - Add a translation "admin.access-control.groups.button.see-all": "Browse all", - + // "admin.access-control.groups.search.button": "Search", // TODO New key - Add a translation "admin.access-control.groups.search.button": "Search", - + // "admin.access-control.groups.table.id": "ID", // TODO New key - Add a translation "admin.access-control.groups.table.id": "ID", - + // "admin.access-control.groups.table.name": "Name", // TODO New key - Add a translation "admin.access-control.groups.table.name": "Name", - + // "admin.access-control.groups.table.members": "Members", // TODO New key - Add a translation "admin.access-control.groups.table.members": "Members", - + // "admin.access-control.groups.table.comcol": "Community / Collection", // TODO New key - Add a translation "admin.access-control.groups.table.comcol": "Community / Collection", - + // "admin.access-control.groups.table.edit": "Edit", // TODO New key - Add a translation "admin.access-control.groups.table.edit": "Edit", - + // "admin.access-control.groups.table.edit.buttons.edit": "Edit \"{{name}}\"", // TODO New key - Add a translation "admin.access-control.groups.table.edit.buttons.edit": "Edit \"{{name}}\"", - + // "admin.access-control.groups.table.edit.buttons.remove": "Delete \"{{name}}\"", // TODO New key - Add a translation "admin.access-control.groups.table.edit.buttons.remove": "Delete \"{{name}}\"", - + // "admin.access-control.groups.no-items": "No groups found with this in their name or this as UUID", // TODO New key - Add a translation "admin.access-control.groups.no-items": "No groups found with this in their name or this as UUID", - + // "admin.access-control.groups.notification.deleted.success": "Successfully deleted group \"{{name}}\"", // TODO New key - Add a translation "admin.access-control.groups.notification.deleted.success": "Successfully deleted group \"{{name}}\"", - + // "admin.access-control.groups.notification.deleted.failure": "Failed to delete group \"{{name}}\"", // TODO New key - Add a translation "admin.access-control.groups.notification.deleted.failure": "Failed to delete group \"{{name}}\"", - - + + // "admin.access-control.groups.form.head.create": "Create group", // TODO New key - Add a translation "admin.access-control.groups.form.head.create": "Create group", - + // "admin.access-control.groups.form.head.edit": "Edit group", // TODO New key - Add a translation "admin.access-control.groups.form.head.edit": "Edit group", - + // "admin.access-control.groups.form.groupName": "Group name", // TODO New key - Add a translation "admin.access-control.groups.form.groupName": "Group name", - + // "admin.access-control.groups.form.groupDescription": "Description", // TODO New key - Add a translation "admin.access-control.groups.form.groupDescription": "Description", - + // "admin.access-control.groups.form.notification.created.success": "Successfully created Group \"{{name}}\"", // TODO New key - Add a translation "admin.access-control.groups.form.notification.created.success": "Successfully created Group \"{{name}}\"", - + // "admin.access-control.groups.form.notification.created.failure": "Failed to create Group \"{{name}}\"", // TODO New key - Add a translation "admin.access-control.groups.form.notification.created.failure": "Failed to create Group \"{{name}}\"", - + // "admin.access-control.groups.form.notification.created.failure.groupNameInUse": "Failed to create Group with name: \"{{name}}\", make sure the name is not already in use.", // TODO New key - Add a translation "admin.access-control.groups.form.notification.created.failure.groupNameInUse": "Failed to create Group with name: \"{{name}}\", make sure the name is not already in use.", - + // "admin.access-control.groups.form.members-list.head": "EPeople", // TODO New key - Add a translation "admin.access-control.groups.form.members-list.head": "EPeople", - + // "admin.access-control.groups.form.members-list.search.head": "Add EPeople", // TODO New key - Add a translation "admin.access-control.groups.form.members-list.search.head": "Add EPeople", - + // "admin.access-control.groups.form.members-list.button.see-all": "Browse All", // TODO New key - Add a translation "admin.access-control.groups.form.members-list.button.see-all": "Browse All", - + // "admin.access-control.groups.form.members-list.headMembers": "Current Members", // TODO New key - Add a translation "admin.access-control.groups.form.members-list.headMembers": "Current Members", - + // "admin.access-control.groups.form.members-list.search.scope.metadata": "Metadata", // TODO New key - Add a translation "admin.access-control.groups.form.members-list.search.scope.metadata": "Metadata", - + // "admin.access-control.groups.form.members-list.search.scope.email": "E-mail (exact)", // TODO New key - Add a translation "admin.access-control.groups.form.members-list.search.scope.email": "E-mail (exact)", - + // "admin.access-control.groups.form.members-list.search.button": "Search", // TODO New key - Add a translation "admin.access-control.groups.form.members-list.search.button": "Search", - + // "admin.access-control.groups.form.members-list.table.id": "ID", // TODO New key - Add a translation "admin.access-control.groups.form.members-list.table.id": "ID", - + // "admin.access-control.groups.form.members-list.table.name": "Name", // TODO New key - Add a translation "admin.access-control.groups.form.members-list.table.name": "Name", - + // "admin.access-control.groups.form.members-list.table.edit": "Remove / Add", // TODO New key - Add a translation "admin.access-control.groups.form.members-list.table.edit": "Remove / Add", - + // "admin.access-control.groups.form.members-list.table.edit.buttons.remove": "Remove member with name \"{{name}}\"", // TODO New key - Add a translation "admin.access-control.groups.form.members-list.table.edit.buttons.remove": "Remove member with name \"{{name}}\"", - + // "admin.access-control.groups.form.members-list.notification.success.addMember": "Successfully added member: \"{{name}}\"", // TODO New key - Add a translation "admin.access-control.groups.form.members-list.notification.success.addMember": "Successfully added member: \"{{name}}\"", - + // "admin.access-control.groups.form.members-list.notification.failure.addMember": "Failed to add member: \"{{name}}\"", // TODO New key - Add a translation "admin.access-control.groups.form.members-list.notification.failure.addMember": "Failed to add member: \"{{name}}\"", - + // "admin.access-control.groups.form.members-list.notification.success.deleteMember": "Successfully deleted member: \"{{name}}\"", // TODO New key - Add a translation "admin.access-control.groups.form.members-list.notification.success.deleteMember": "Successfully deleted member: \"{{name}}\"", - + // "admin.access-control.groups.form.members-list.notification.failure.deleteMember": "Failed to delete member: \"{{name}}\"", // TODO New key - Add a translation "admin.access-control.groups.form.members-list.notification.failure.deleteMember": "Failed to delete member: \"{{name}}\"", - + // "admin.access-control.groups.form.members-list.table.edit.buttons.add": "Add member with name \"{{name}}\"", // TODO New key - Add a translation "admin.access-control.groups.form.members-list.table.edit.buttons.add": "Add member with name \"{{name}}\"", - + // "admin.access-control.groups.form.members-list.notification.failure.noActiveGroup": "No current active group, submit a name first.", // TODO New key - Add a translation "admin.access-control.groups.form.members-list.notification.failure.noActiveGroup": "No current active group, submit a name first.", - + // "admin.access-control.groups.form.members-list.no-members-yet": "No members in group yet, search and add.", // TODO New key - Add a translation "admin.access-control.groups.form.members-list.no-members-yet": "No members in group yet, search and add.", - + // "admin.access-control.groups.form.members-list.no-items": "No EPeople found in that search", // TODO New key - Add a translation "admin.access-control.groups.form.members-list.no-items": "No EPeople found in that search", - + // "admin.access-control.groups.form.subgroups-list.head": "Groups", // TODO New key - Add a translation "admin.access-control.groups.form.subgroups-list.head": "Groups", - + // "admin.access-control.groups.form.subgroups-list.search.head": "Add Subgroup", // TODO New key - Add a translation "admin.access-control.groups.form.subgroups-list.search.head": "Add Subgroup", - + // "admin.access-control.groups.form.subgroups-list.button.see-all": "Browse All", // TODO New key - Add a translation "admin.access-control.groups.form.subgroups-list.button.see-all": "Browse All", - + // "admin.access-control.groups.form.subgroups-list.headSubgroups": "Current Subgroups", // TODO New key - Add a translation "admin.access-control.groups.form.subgroups-list.headSubgroups": "Current Subgroups", - + // "admin.access-control.groups.form.subgroups-list.search.button": "Search", // TODO New key - Add a translation "admin.access-control.groups.form.subgroups-list.search.button": "Search", - + // "admin.access-control.groups.form.subgroups-list.table.id": "ID", // TODO New key - Add a translation "admin.access-control.groups.form.subgroups-list.table.id": "ID", - + // "admin.access-control.groups.form.subgroups-list.table.name": "Name", // TODO New key - Add a translation "admin.access-control.groups.form.subgroups-list.table.name": "Name", - + // "admin.access-control.groups.form.subgroups-list.table.edit": "Remove / Add", // TODO New key - Add a translation "admin.access-control.groups.form.subgroups-list.table.edit": "Remove / Add", - + // "admin.access-control.groups.form.subgroups-list.table.edit.buttons.remove": "Remove subgroup with name \"{{name}}\"", // TODO New key - Add a translation "admin.access-control.groups.form.subgroups-list.table.edit.buttons.remove": "Remove subgroup with name \"{{name}}\"", - + // "admin.access-control.groups.form.subgroups-list.table.edit.buttons.add": "Add subgroup with name \"{{name}}\"", // TODO New key - Add a translation "admin.access-control.groups.form.subgroups-list.table.edit.buttons.add": "Add subgroup with name \"{{name}}\"", - + // "admin.access-control.groups.form.subgroups-list.table.edit.currentGroup": "Current group", // TODO New key - Add a translation "admin.access-control.groups.form.subgroups-list.table.edit.currentGroup": "Current group", - + // "admin.access-control.groups.form.subgroups-list.notification.success.addSubgroup": "Successfully added subgroup: \"{{name}}\"", // TODO New key - Add a translation "admin.access-control.groups.form.subgroups-list.notification.success.addSubgroup": "Successfully added subgroup: \"{{name}}\"", - + // "admin.access-control.groups.form.subgroups-list.notification.failure.addSubgroup": "Failed to add subgroup: \"{{name}}\"", // TODO New key - Add a translation "admin.access-control.groups.form.subgroups-list.notification.failure.addSubgroup": "Failed to add subgroup: \"{{name}}\"", - + // "admin.access-control.groups.form.subgroups-list.notification.success.deleteSubgroup": "Successfully deleted subgroup: \"{{name}}\"", // TODO New key - Add a translation "admin.access-control.groups.form.subgroups-list.notification.success.deleteSubgroup": "Successfully deleted subgroup: \"{{name}}\"", - + // "admin.access-control.groups.form.subgroups-list.notification.failure.deleteSubgroup": "Failed to delete subgroup: \"{{name}}\"", // TODO New key - Add a translation "admin.access-control.groups.form.subgroups-list.notification.failure.deleteSubgroup": "Failed to delete subgroup: \"{{name}}\"", - + // "admin.access-control.groups.form.subgroups-list.notification.failure.noActiveGroup": "No current active group, submit a name first.", // TODO New key - Add a translation "admin.access-control.groups.form.subgroups-list.notification.failure.noActiveGroup": "No current active group, submit a name first.", - + // "admin.access-control.groups.form.subgroups-list.notification.failure.subgroupToAddIsActiveGroup": "This is the current group, can't be added.", // TODO New key - Add a translation "admin.access-control.groups.form.subgroups-list.notification.failure.subgroupToAddIsActiveGroup": "This is the current group, can't be added.", - + // "admin.access-control.groups.form.subgroups-list.no-items": "No groups found with this in their name or this as UUID", // TODO New key - Add a translation "admin.access-control.groups.form.subgroups-list.no-items": "No groups found with this in their name or this as UUID", - + // "admin.access-control.groups.form.subgroups-list.no-subgroups-yet": "No subgroups in group yet.", // TODO New key - Add a translation "admin.access-control.groups.form.subgroups-list.no-subgroups-yet": "No subgroups in group yet.", - + // "admin.access-control.groups.form.return": "Return to groups", // TODO New key - Add a translation "admin.access-control.groups.form.return": "Return to groups", - - - + + + // "admin.search.breadcrumbs": "Administrative Search", // TODO New key - Add a translation "admin.search.breadcrumbs": "Administrative Search", - + // "admin.search.collection.edit": "Edit", // TODO New key - Add a translation "admin.search.collection.edit": "Edit", - + // "admin.search.community.edit": "Edit", // TODO New key - Add a translation "admin.search.community.edit": "Edit", - + // "admin.search.item.delete": "Delete", // TODO New key - Add a translation "admin.search.item.delete": "Delete", - + // "admin.search.item.edit": "Edit", // TODO New key - Add a translation "admin.search.item.edit": "Edit", - + // "admin.search.item.make-private": "Make Private", // TODO New key - Add a translation "admin.search.item.make-private": "Make Private", - + // "admin.search.item.make-public": "Make Public", // TODO New key - Add a translation "admin.search.item.make-public": "Make Public", - + // "admin.search.item.move": "Move", // TODO New key - Add a translation "admin.search.item.move": "Move", - + // "admin.search.item.private": "Private", // TODO New key - Add a translation "admin.search.item.private": "Private", - + // "admin.search.item.reinstate": "Reinstate", // TODO New key - Add a translation "admin.search.item.reinstate": "Reinstate", - + // "admin.search.item.withdraw": "Withdraw", // TODO New key - Add a translation "admin.search.item.withdraw": "Withdraw", - + // "admin.search.item.withdrawn": "Withdrawn", // TODO New key - Add a translation "admin.search.item.withdrawn": "Withdrawn", - + // "admin.search.title": "Administrative Search", // TODO New key - Add a translation "admin.search.title": "Administrative Search", - - - - - // "admin.workflow.breadcrumbs": "Administer Workflow", - // TODO New key - Add a translation - "admin.workflow.breadcrumbs": "Administer Workflow", - - // "admin.workflow.title": "Administer Workflow", - // TODO New key - Add a translation - "admin.workflow.title": "Administer Workflow", - - // "admin.workflow.item.workflow": "Workflow", - // TODO New key - Add a translation - "admin.workflow.item.workflow": "Workflow", - - // "admin.workflow.item.delete": "Delete", - // TODO New key - Add a translation - "admin.workflow.item.delete": "Delete", - - // "admin.workflow.item.send-back": "Send back", - // TODO New key - Add a translation - "admin.workflow.item.send-back": "Send back", - - - - + + + // "auth.errors.invalid-user": "Invalid email address or password.", "auth.errors.invalid-user": "No es válida la dirección de correo o la clave.", - + // "auth.messages.expired": "Your session has expired. Please log in again.", "auth.messages.expired": "Su sesión ha expirado. Favor ingresar de nuevo.", - - - + + + // "bitstream.edit.bitstream": "Bitstream: ", // TODO New key - Add a translation "bitstream.edit.bitstream": "Bitstream: ", - + // "bitstream.edit.form.description.hint": "Optionally, provide a brief description of the file, for example \"Main article\" or \"Experiment data readings\".", // TODO New key - Add a translation "bitstream.edit.form.description.hint": "Optionally, provide a brief description of the file, for example \"Main article\" or \"Experiment data readings\".", - + // "bitstream.edit.form.description.label": "Description", // TODO New key - Add a translation "bitstream.edit.form.description.label": "Description", - + // "bitstream.edit.form.embargo.hint": "The first day from which access is allowed. This date cannot be modified on this form. To set an embargo date for a bitstream, go to the Item Status tab, click Authorizations..., create or edit the bitstream's READ policy, and set the Start Date as desired.", // TODO New key - Add a translation "bitstream.edit.form.embargo.hint": "The first day from which access is allowed. This date cannot be modified on this form. To set an embargo date for a bitstream, go to the Item Status tab, click Authorizations..., create or edit the bitstream's READ policy, and set the Start Date as desired.", - + // "bitstream.edit.form.embargo.label": "Embargo until specific date", // TODO New key - Add a translation "bitstream.edit.form.embargo.label": "Embargo until specific date", - + // "bitstream.edit.form.fileName.hint": "Change the filename for the bitstream. Note that this will change the display bitstream URL, but old links will still resolve as long as the sequence ID does not change.", // TODO New key - Add a translation "bitstream.edit.form.fileName.hint": "Change the filename for the bitstream. Note that this will change the display bitstream URL, but old links will still resolve as long as the sequence ID does not change.", - + // "bitstream.edit.form.fileName.label": "Filename", // TODO New key - Add a translation "bitstream.edit.form.fileName.label": "Filename", - + // "bitstream.edit.form.newFormat.label": "Describe new format", // TODO New key - Add a translation "bitstream.edit.form.newFormat.label": "Describe new format", - + // "bitstream.edit.form.newFormat.hint": "The application you used to create the file, and the version number (for example, \"ACMESoft SuperApp version 1.5\").", // TODO New key - Add a translation "bitstream.edit.form.newFormat.hint": "The application you used to create the file, and the version number (for example, \"ACMESoft SuperApp version 1.5\").", - + // "bitstream.edit.form.primaryBitstream.label": "Primary bitstream", // TODO New key - Add a translation "bitstream.edit.form.primaryBitstream.label": "Primary bitstream", - + // "bitstream.edit.form.selectedFormat.hint": "If the format is not in the above list, select \"format not in list\" above and describe it under \"Describe new format\".", // TODO New key - Add a translation "bitstream.edit.form.selectedFormat.hint": "If the format is not in the above list, select \"format not in list\" above and describe it under \"Describe new format\".", - + // "bitstream.edit.form.selectedFormat.label": "Selected Format", // TODO New key - Add a translation "bitstream.edit.form.selectedFormat.label": "Selected Format", - + // "bitstream.edit.form.selectedFormat.unknown": "Format not in list", // TODO New key - Add a translation "bitstream.edit.form.selectedFormat.unknown": "Format not in list", - + // "bitstream.edit.notifications.error.format.title": "An error occurred saving the bitstream's format", // TODO New key - Add a translation "bitstream.edit.notifications.error.format.title": "An error occurred saving the bitstream's format", - + // "bitstream.edit.notifications.saved.content": "Your changes to this bitstream were saved.", // TODO New key - Add a translation "bitstream.edit.notifications.saved.content": "Your changes to this bitstream were saved.", - + // "bitstream.edit.notifications.saved.title": "Bitstream saved", // TODO New key - Add a translation "bitstream.edit.notifications.saved.title": "Bitstream saved", - + // "bitstream.edit.title": "Edit bitstream", // TODO New key - Add a translation "bitstream.edit.title": "Edit bitstream", - - - + + + // "browse.comcol.by.author": "By Author", "browse.comcol.by.author": "Por Autor", - + // "browse.comcol.by.dateissued": "By Issue Date", "browse.comcol.by.dateissued": "Por Fecha de Publicación", - + // "browse.comcol.by.subject": "By Subject", "browse.comcol.by.subject": "Por Materia", - + // "browse.comcol.by.title": "By Title", "browse.comcol.by.title": "Por Título", - + // "browse.comcol.head": "Browse", "browse.comcol.head": "Navegar", - + // "browse.empty": "No items to show.", "browse.empty": "No ítemes para mostrar.", - + // "browse.metadata.author": "Author", "browse.metadata.author": "Autor", - + // "browse.metadata.dateissued": "Issue Date", "browse.metadata.dateissued": "Fecha de Publicación", - + // "browse.metadata.subject": "Subject", "browse.metadata.subject": "Materia", - + // "browse.metadata.title": "Title", "browse.metadata.title": "Título", - + // "browse.metadata.author.breadcrumbs": "Browse by Author", // TODO New key - Add a translation "browse.metadata.author.breadcrumbs": "Browse by Author", - + // "browse.metadata.dateissued.breadcrumbs": "Browse by Date", // TODO New key - Add a translation "browse.metadata.dateissued.breadcrumbs": "Browse by Date", - + // "browse.metadata.subject.breadcrumbs": "Browse by Subject", // TODO New key - Add a translation "browse.metadata.subject.breadcrumbs": "Browse by Subject", - + // "browse.metadata.title.breadcrumbs": "Browse by Title", // TODO New key - Add a translation "browse.metadata.title.breadcrumbs": "Browse by Title", - + // "browse.startsWith.choose_start": "(Choose start)", "browse.startsWith.choose_start": "(Seleccionar el inicio)", - + // "browse.startsWith.choose_year": "(Choose year)", "browse.startsWith.choose_year": "(Seleccionar el año)", - + // "browse.startsWith.jump": "Jump to a point in the index:", "browse.startsWith.jump": "Saltar a un punto en el índice:", - + // "browse.startsWith.months.april": "April", "browse.startsWith.months.april": "Abril", - + // "browse.startsWith.months.august": "August", "browse.startsWith.months.august": "Agosto", - + // "browse.startsWith.months.december": "December", "browse.startsWith.months.december": "Diciembre", - + // "browse.startsWith.months.february": "February", "browse.startsWith.months.february": "Febrero", - + // "browse.startsWith.months.january": "January", "browse.startsWith.months.january": "Enero", - + // "browse.startsWith.months.july": "July", "browse.startsWith.months.july": "Julio", - + // "browse.startsWith.months.june": "June", "browse.startsWith.months.june": "Junio", - + // "browse.startsWith.months.march": "March", "browse.startsWith.months.march": "Marzo", - + // "browse.startsWith.months.may": "May", "browse.startsWith.months.may": "Mayo", - + // "browse.startsWith.months.none": "(Choose month)", "browse.startsWith.months.none": "(Seleccionar el mes)", - + // "browse.startsWith.months.november": "November", "browse.startsWith.months.november": "Noviembre", - + // "browse.startsWith.months.october": "October", "browse.startsWith.months.october": "Octubre", - + // "browse.startsWith.months.september": "September", "browse.startsWith.months.september": "Septiembre", - + // "browse.startsWith.submit": "Go", "browse.startsWith.submit": "Ir", - + // "browse.startsWith.type_date": "Or type in a date (year-month):", "browse.startsWith.type_date": "O escriba una fecha (año-mes):", - + // "browse.startsWith.type_text": "Or enter first few letters:", "browse.startsWith.type_text": "O ingrese las primeras letras:", - + // "browse.title": "Browsing {{ collection }} by {{ field }} {{ value }}", "browse.title": "Navegando {{ collection }} por {{ field }} {{ value }}", - - + + // "chips.remove": "Remove chip", "chips.remove": "Eliminar chip", - - - + + + // "collection.create.head": "Create a Collection", "collection.create.head": "Crear una Colección", - + // "collection.create.notifications.success": "Successfully created the Collection", // TODO New key - Add a translation "collection.create.notifications.success": "Successfully created the Collection", - + // "collection.create.sub-head": "Create a Collection for Community {{ parent }}", "collection.create.sub-head": "Crear una Colección por Comunidad {{ parent }}", - + // "collection.delete.cancel": "Cancel", "collection.delete.cancel": "Cancelar", - + // "collection.delete.confirm": "Confirm", "collection.delete.confirm": "Confirmar", - + // "collection.delete.head": "Delete Collection", "collection.delete.head": "Eliminar la Colección", - + // "collection.delete.notification.fail": "Collection could not be deleted", "collection.delete.notification.fail": "La Colección no puede ser eliminada", - + // "collection.delete.notification.success": "Successfully deleted collection", "collection.delete.notification.success": "Colección eliminada exitosamente", - + // "collection.delete.text": "Are you sure you want to delete collection \"{{ dso }}\"", "collection.delete.text": "Está seguro de eliminar la colección \"{{ dso }}\"", - - - + + + // "collection.edit.delete": "Delete this collection", "collection.edit.delete": "Eliminar esta colección", - + // "collection.edit.head": "Edit Collection", "collection.edit.head": "Editar la Colección", - + // "collection.edit.breadcrumbs": "Edit Collection", // TODO New key - Add a translation "collection.edit.breadcrumbs": "Edit Collection", - - - + + + // "collection.edit.item-mapper.cancel": "Cancel", "collection.edit.item-mapper.cancel": "Cancelar", - + // "collection.edit.item-mapper.collection": "Collection: \"{{name}}\"", "collection.edit.item-mapper.collection": "Colección: \"{{name}}\"", - + // "collection.edit.item-mapper.confirm": "Map selected items", "collection.edit.item-mapper.confirm": "Mapa de ítemes seleccionados", - + // "collection.edit.item-mapper.description": "This is the item mapper tool that allows collection administrators to map items from other collections into this collection. You can search for items from other collections and map them, or browse the list of currently mapped items.", "collection.edit.item-mapper.description": "Esta es la herramienta de asignación de ítemes que permite a los administradores de colecciones asignar ítemes de otras colecciones a esta colección. Puede buscar ítemes de otras colecciones y asignarlos, o navegar la lista de elementos asignados actualmente.", - + // "collection.edit.item-mapper.head": "Item Mapper - Map Items from Other Collections", "collection.edit.item-mapper.head": "Asignación de ítem - Asignación de ítemes para otras Colecciones", - + // "collection.edit.item-mapper.no-search": "Please enter a query to search", "collection.edit.item-mapper.no-search": "Favor ingrese una consulta para buscar", - + // "collection.edit.item-mapper.notifications.map.error.content": "Errors occurred for mapping of {{amount}} items.", "collection.edit.item-mapper.notifications.map.error.content": "Errores encontrados para asignar {{amount}} ítemes.", - + // "collection.edit.item-mapper.notifications.map.error.head": "Mapping errors", "collection.edit.item-mapper.notifications.map.error.head": "Errores asignados", - + // "collection.edit.item-mapper.notifications.map.success.content": "Successfully mapped {{amount}} items.", "collection.edit.item-mapper.notifications.map.success.content": "Exitosamente asignado {{amount}} ítemes.", - + // "collection.edit.item-mapper.notifications.map.success.head": "Mapping completed", "collection.edit.item-mapper.notifications.map.success.head": "Asignación completa", - + // "collection.edit.item-mapper.notifications.unmap.error.content": "Errors occurred for removing the mappings of {{amount}} items.", "collection.edit.item-mapper.notifications.unmap.error.content": "Errores encontrados al eliminar la asignación de {{amount}} ítemes.", - + // "collection.edit.item-mapper.notifications.unmap.error.head": "Remove mapping errors", "collection.edit.item-mapper.notifications.unmap.error.head": "Eliminar errores de asignación", - + // "collection.edit.item-mapper.notifications.unmap.success.content": "Successfully removed the mappings of {{amount}} items.", "collection.edit.item-mapper.notifications.unmap.success.content": "Exitosamente eliminado las asignaciones de {{amount}} ítemes.", - + // "collection.edit.item-mapper.notifications.unmap.success.head": "Remove mapping completed", "collection.edit.item-mapper.notifications.unmap.success.head": "Asignación eliminada completa", - + // "collection.edit.item-mapper.remove": "Remove selected item mappings", "collection.edit.item-mapper.remove": "Eliminar asignaciones de ítemes seleccionados", - + // "collection.edit.item-mapper.tabs.browse": "Browse mapped items", "collection.edit.item-mapper.tabs.browse": "Navegar asignación de ítemes", - + // "collection.edit.item-mapper.tabs.map": "Map new items", "collection.edit.item-mapper.tabs.map": "Asignar nuevo ítemes", - - - + + + // "collection.edit.logo.label": "Collection logo", // TODO New key - Add a translation "collection.edit.logo.label": "Collection logo", - + // "collection.edit.logo.notifications.add.error": "Uploading Collection logo failed. Please verify the content before retrying.", // TODO New key - Add a translation "collection.edit.logo.notifications.add.error": "Uploading Collection logo failed. Please verify the content before retrying.", - + // "collection.edit.logo.notifications.add.success": "Upload Collection logo successful.", // TODO New key - Add a translation "collection.edit.logo.notifications.add.success": "Upload Collection logo successful.", - + // "collection.edit.logo.notifications.delete.success.title": "Logo deleted", // TODO New key - Add a translation "collection.edit.logo.notifications.delete.success.title": "Logo deleted", - + // "collection.edit.logo.notifications.delete.success.content": "Successfully deleted the collection's logo", // TODO New key - Add a translation "collection.edit.logo.notifications.delete.success.content": "Successfully deleted the collection's logo", - + // "collection.edit.logo.notifications.delete.error.title": "Error deleting logo", // TODO New key - Add a translation "collection.edit.logo.notifications.delete.error.title": "Error deleting logo", - + // "collection.edit.logo.upload": "Drop a Collection Logo to upload", // TODO New key - Add a translation "collection.edit.logo.upload": "Drop a Collection Logo to upload", - - - + + + // "collection.edit.notifications.success": "Successfully edited the Collection", // TODO New key - Add a translation "collection.edit.notifications.success": "Successfully edited the Collection", - + // "collection.edit.return": "Return", // TODO New key - Add a translation "collection.edit.return": "Return", - - - + + + // "collection.edit.tabs.curate.head": "Curate", // TODO New key - Add a translation "collection.edit.tabs.curate.head": "Curate", - + // "collection.edit.tabs.curate.title": "Collection Edit - Curate", // TODO New key - Add a translation "collection.edit.tabs.curate.title": "Collection Edit - Curate", - + // "collection.edit.tabs.metadata.head": "Edit Metadata", // TODO New key - Add a translation "collection.edit.tabs.metadata.head": "Edit Metadata", - + // "collection.edit.tabs.metadata.title": "Collection Edit - Metadata", // TODO New key - Add a translation "collection.edit.tabs.metadata.title": "Collection Edit - Metadata", - + // "collection.edit.tabs.roles.head": "Assign Roles", // TODO New key - Add a translation "collection.edit.tabs.roles.head": "Assign Roles", - + // "collection.edit.tabs.roles.title": "Collection Edit - Roles", // TODO New key - Add a translation "collection.edit.tabs.roles.title": "Collection Edit - Roles", - + // "collection.edit.tabs.source.external": "This collection harvests its content from an external source", // TODO New key - Add a translation "collection.edit.tabs.source.external": "This collection harvests its content from an external source", - + // "collection.edit.tabs.source.form.errors.oaiSource.required": "You must provide a set id of the target collection.", // TODO New key - Add a translation "collection.edit.tabs.source.form.errors.oaiSource.required": "You must provide a set id of the target collection.", - + // "collection.edit.tabs.source.form.harvestType": "Content being harvested", // TODO New key - Add a translation "collection.edit.tabs.source.form.harvestType": "Content being harvested", - + // "collection.edit.tabs.source.form.head": "Configure an external source", // TODO New key - Add a translation "collection.edit.tabs.source.form.head": "Configure an external source", - + // "collection.edit.tabs.source.form.metadataConfigId": "Metadata Format", // TODO New key - Add a translation "collection.edit.tabs.source.form.metadataConfigId": "Metadata Format", - + // "collection.edit.tabs.source.form.oaiSetId": "OAI specific set id", // TODO New key - Add a translation "collection.edit.tabs.source.form.oaiSetId": "OAI specific set id", - + // "collection.edit.tabs.source.form.oaiSource": "OAI Provider", // TODO New key - Add a translation "collection.edit.tabs.source.form.oaiSource": "OAI Provider", - + // "collection.edit.tabs.source.form.options.harvestType.METADATA_AND_BITSTREAMS": "Harvest metadata and bitstreams (requires ORE support)", // TODO New key - Add a translation "collection.edit.tabs.source.form.options.harvestType.METADATA_AND_BITSTREAMS": "Harvest metadata and bitstreams (requires ORE support)", - + // "collection.edit.tabs.source.form.options.harvestType.METADATA_AND_REF": "Harvest metadata and references to bitstreams (requires ORE support)", // TODO New key - Add a translation "collection.edit.tabs.source.form.options.harvestType.METADATA_AND_REF": "Harvest metadata and references to bitstreams (requires ORE support)", - + // "collection.edit.tabs.source.form.options.harvestType.METADATA_ONLY": "Harvest metadata only", // TODO New key - Add a translation "collection.edit.tabs.source.form.options.harvestType.METADATA_ONLY": "Harvest metadata only", - + // "collection.edit.tabs.source.head": "Content Source", // TODO New key - Add a translation "collection.edit.tabs.source.head": "Content Source", - + // "collection.edit.tabs.source.notifications.discarded.content": "Your changes were discarded. To reinstate your changes click the 'Undo' button", // TODO New key - Add a translation "collection.edit.tabs.source.notifications.discarded.content": "Your changes were discarded. To reinstate your changes click the 'Undo' button", - + // "collection.edit.tabs.source.notifications.discarded.title": "Changed discarded", // TODO New key - Add a translation "collection.edit.tabs.source.notifications.discarded.title": "Changed discarded", - + // "collection.edit.tabs.source.notifications.invalid.content": "Your changes were not saved. Please make sure all fields are valid before you save.", // TODO New key - Add a translation "collection.edit.tabs.source.notifications.invalid.content": "Your changes were not saved. Please make sure all fields are valid before you save.", - + // "collection.edit.tabs.source.notifications.invalid.title": "Metadata invalid", // TODO New key - Add a translation "collection.edit.tabs.source.notifications.invalid.title": "Metadata invalid", - + // "collection.edit.tabs.source.notifications.saved.content": "Your changes to this collection's content source were saved.", // TODO New key - Add a translation "collection.edit.tabs.source.notifications.saved.content": "Your changes to this collection's content source were saved.", - + // "collection.edit.tabs.source.notifications.saved.title": "Content Source saved", // TODO New key - Add a translation "collection.edit.tabs.source.notifications.saved.title": "Content Source saved", - + // "collection.edit.tabs.source.title": "Collection Edit - Content Source", // TODO New key - Add a translation "collection.edit.tabs.source.title": "Collection Edit - Content Source", - - - + + + // "collection.form.abstract": "Short Description", "collection.form.abstract": "Descripción breve", - + // "collection.form.description": "Introductory text (HTML)", "collection.form.description": "Texto introductorio (HTML)", - + // "collection.form.errors.title.required": "Please enter a collection name", "collection.form.errors.title.required": "Favor ingrese un nombre a la colección", - + // "collection.form.license": "License", "collection.form.license": "Licencia", - + // "collection.form.provenance": "Provenance", "collection.form.provenance": "Procedencia", - + // "collection.form.rights": "Copyright text (HTML)", "collection.form.rights": "Texto de copyright (HTML)", - + // "collection.form.tableofcontents": "News (HTML)", "collection.form.tableofcontents": "Noticias (HTML)", - + // "collection.form.title": "Name", "collection.form.title": "Nombre", - - - + + + // "collection.page.browse.recent.head": "Recent Submissions", "collection.page.browse.recent.head": "Envíos recientes", - + // "collection.page.browse.recent.empty": "No items to show", "collection.page.browse.recent.empty": "No ítemes para mostrar", - + // "collection.page.handle": "Permanent URI for this collection", "collection.page.handle": "URI permanente para esta colección", - + // "collection.page.license": "License", "collection.page.license": "Licencia", - + // "collection.page.news": "News", "collection.page.news": "Noticias", - - - + + + // "collection.select.confirm": "Confirm selected", "collection.select.confirm": "Confirmar la selección", - + // "collection.select.empty": "No collections to show", "collection.select.empty": "No hay colecciones para mostrar", - + // "collection.select.table.title": "Title", "collection.select.table.title": "Título", - - - + + + // "collection.source.update.notifications.error.content": "The provided settings have been tested and didn't work.", // TODO New key - Add a translation "collection.source.update.notifications.error.content": "The provided settings have been tested and didn't work.", - + // "collection.source.update.notifications.error.title": "Server Error", // TODO New key - Add a translation "collection.source.update.notifications.error.title": "Server Error", - - - + + + // "communityList.tabTitle": "DSpace - Community List", // TODO New key - Add a translation "communityList.tabTitle": "DSpace - Community List", - + // "communityList.title": "List of Communities", // TODO New key - Add a translation "communityList.title": "List of Communities", - + // "communityList.showMore": "Show More", // TODO New key - Add a translation "communityList.showMore": "Show More", - - - + + + // "community.create.head": "Create a Community", "community.create.head": "Crear una Comunidad", - + // "community.create.notifications.success": "Successfully created the Community", // TODO New key - Add a translation "community.create.notifications.success": "Successfully created the Community", - + // "community.create.sub-head": "Create a Sub-Community for Community {{ parent }}", "community.create.sub-head": "Crear una Sub-Comunidad por Communidad {{ parent }}", - + // "community.delete.cancel": "Cancel", "community.delete.cancel": "Cancelar", - + // "community.delete.confirm": "Confirm", "community.delete.confirm": "Confirmar", - + // "community.delete.head": "Delete Community", "community.delete.head": "Eliminar Comunidad", - + // "community.delete.notification.fail": "Community could not be deleted", "community.delete.notification.fail": "Esta comunidad no puede ser eliminada", - + // "community.delete.notification.success": "Successfully deleted community", "community.delete.notification.success": "Comunidad eliminada exitosamente", - + // "community.delete.text": "Are you sure you want to delete community \"{{ dso }}\"", "community.delete.text": "Está seguro de eliminar la comunidad \"{{ dso }}\"", - + // "community.edit.delete": "Delete this community", "community.edit.delete": "Eliminar esta comunidad", - + // "community.edit.head": "Edit Community", "community.edit.head": "Editar la Comunidad", - + // "community.edit.breadcrumbs": "Edit Community", // TODO New key - Add a translation "community.edit.breadcrumbs": "Edit Community", - - + + // "community.edit.logo.label": "Community logo", // TODO New key - Add a translation "community.edit.logo.label": "Community logo", - + // "community.edit.logo.notifications.add.error": "Uploading Community logo failed. Please verify the content before retrying.", // TODO New key - Add a translation "community.edit.logo.notifications.add.error": "Uploading Community logo failed. Please verify the content before retrying.", - + // "community.edit.logo.notifications.add.success": "Upload Community logo successful.", // TODO New key - Add a translation "community.edit.logo.notifications.add.success": "Upload Community logo successful.", - + // "community.edit.logo.notifications.delete.success.title": "Logo deleted", // TODO New key - Add a translation "community.edit.logo.notifications.delete.success.title": "Logo deleted", - + // "community.edit.logo.notifications.delete.success.content": "Successfully deleted the community's logo", // TODO New key - Add a translation "community.edit.logo.notifications.delete.success.content": "Successfully deleted the community's logo", - + // "community.edit.logo.notifications.delete.error.title": "Error deleting logo", // TODO New key - Add a translation "community.edit.logo.notifications.delete.error.title": "Error deleting logo", - + // "community.edit.logo.upload": "Drop a Community Logo to upload", // TODO New key - Add a translation "community.edit.logo.upload": "Drop a Community Logo to upload", - - - + + + // "community.edit.notifications.success": "Successfully edited the Community", // TODO New key - Add a translation "community.edit.notifications.success": "Successfully edited the Community", - + // "community.edit.return": "Return", // TODO New key - Add a translation "community.edit.return": "Return", - - - + + + // "community.edit.tabs.curate.head": "Curate", // TODO New key - Add a translation "community.edit.tabs.curate.head": "Curate", - + // "community.edit.tabs.curate.title": "Community Edit - Curate", // TODO New key - Add a translation "community.edit.tabs.curate.title": "Community Edit - Curate", - + // "community.edit.tabs.metadata.head": "Edit Metadata", // TODO New key - Add a translation "community.edit.tabs.metadata.head": "Edit Metadata", - + // "community.edit.tabs.metadata.title": "Community Edit - Metadata", // TODO New key - Add a translation "community.edit.tabs.metadata.title": "Community Edit - Metadata", - + // "community.edit.tabs.roles.head": "Assign Roles", // TODO New key - Add a translation "community.edit.tabs.roles.head": "Assign Roles", - + // "community.edit.tabs.roles.title": "Community Edit - Roles", // TODO New key - Add a translation "community.edit.tabs.roles.title": "Community Edit - Roles", - - - - // "comcol-role.edit.no-group": "None", - // TODO New key - Add a translation - "comcol-role.edit.no-group": "None", - - // "comcol-role.edit.create": "Create", - // TODO New key - Add a translation - "comcol-role.edit.create": "Create", - - // "comcol-role.edit.restrict": "Restrict", - // TODO New key - Add a translation - "comcol-role.edit.restrict": "Restrict", - - // "comcol-role.edit.delete": "Delete", - // TODO New key - Add a translation - "comcol-role.edit.delete": "Delete", - - - // "comcol-role.edit.community-admin.name": "Administrators", - // TODO New key - Add a translation - "comcol-role.edit.community-admin.name": "Administrators", - - // "comcol-role.edit.collection-admin.name": "Administrators", - // TODO New key - Add a translation - "comcol-role.edit.collection-admin.name": "Administrators", - - - // "comcol-role.edit.community-admin.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - // TODO New key - Add a translation - "comcol-role.edit.community-admin.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - - // "comcol-role.edit.collection-admin.description": "Collection administrators decide who can submit items to the collection, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization for that collection).", - // TODO New key - Add a translation - "comcol-role.edit.collection-admin.description": "Collection administrators decide who can submit items to the collection, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization for that collection).", - - - // "comcol-role.edit.submitters.name": "Submitters", - // TODO New key - Add a translation - "comcol-role.edit.submitters.name": "Submitters", - - // "comcol-role.edit.submitters.description": "The E-People and Groups that have permission to submit new items to this collection.", - // TODO New key - Add a translation - "comcol-role.edit.submitters.description": "The E-People and Groups that have permission to submit new items to this collection.", - - - // "comcol-role.edit.item_read.name": "Default item read access", - // TODO New key - Add a translation - "comcol-role.edit.item_read.name": "Default item read access", - - // "comcol-role.edit.item_read.description": "E-People and Groups that can read new items submitted to this collection. Changes to this role are not retroactive. Existing items in the system will still be viewable by those who had read access at the time of their addition.", - // TODO New key - Add a translation - "comcol-role.edit.item_read.description": "E-People and Groups that can read new items submitted to this collection. Changes to this role are not retroactive. Existing items in the system will still be viewable by those who had read access at the time of their addition.", - - // "comcol-role.edit.item_read.anonymous-group": "Default read for incoming items is currently set to Anonymous.", - // TODO New key - Add a translation - "comcol-role.edit.item_read.anonymous-group": "Default read for incoming items is currently set to Anonymous.", - - - // "comcol-role.edit.bitstream_read.name": "Default bitstream read access", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.name": "Default bitstream read access", - - // "comcol-role.edit.bitstream_read.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - - // "comcol-role.edit.bitstream_read.anonymous-group": "Default read for incoming bitstreams is currently set to Anonymous.", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.anonymous-group": "Default read for incoming bitstreams is currently set to Anonymous.", - - - // "comcol-role.edit.editor.name": "Editors", - // TODO New key - Add a translation - "comcol-role.edit.editor.name": "Editors", - - // "comcol-role.edit.editor.description": "Editors are able to edit the metadata of incoming submissions, and then accept or reject them.", - // TODO New key - Add a translation - "comcol-role.edit.editor.description": "Editors are able to edit the metadata of incoming submissions, and then accept or reject them.", - - - // "comcol-role.edit.finaleditor.name": "Final editors", - // TODO New key - Add a translation - "comcol-role.edit.finaleditor.name": "Final editors", - - // "comcol-role.edit.finaleditor.description": "Final editors are able to edit the metadata of incoming submissions, but will not be able to reject them.", - // TODO New key - Add a translation - "comcol-role.edit.finaleditor.description": "Final editors are able to edit the metadata of incoming submissions, but will not be able to reject them.", - - - // "comcol-role.edit.reviewer.name": "Reviewers", - // TODO New key - Add a translation - "comcol-role.edit.reviewer.name": "Reviewers", - - // "comcol-role.edit.reviewer.description": "Reviewers are able to accept or reject incoming submissions. However, they are not able to edit the submission's metadata.", - // TODO New key - Add a translation - "comcol-role.edit.reviewer.description": "Reviewers are able to accept or reject incoming submissions. However, they are not able to edit the submission's metadata.", - - - + + + // "community.form.abstract": "Short Description", "community.form.abstract": "Descripción breve", - + // "community.form.description": "Introductory text (HTML)", "community.form.description": "Texto introductorio (HTML)", - + // "community.form.errors.title.required": "Please enter a community name", "community.form.errors.title.required": "Favor ingresar el nombre de la comunidad", - + // "community.form.rights": "Copyright text (HTML)", "community.form.rights": "Texto de copyright (HTML)", - + // "community.form.tableofcontents": "News (HTML)", "community.form.tableofcontents": "Noticias (HTML)", - + // "community.form.title": "Name", "community.form.title": "Nombre", - + // "community.page.handle": "Permanent URI for this community", "community.page.handle": "URI permanente para esta comunidad", - + // "community.page.license": "License", "community.page.license": "Licencia", - + // "community.page.news": "News", "community.page.news": "Noticias", - + // "community.all-lists.head": "Subcommunities and Collections", "community.all-lists.head": "Subcomunidades y Colecciones", - + // "community.sub-collection-list.head": "Collections of this Community", "community.sub-collection-list.head": "Colecciones de esta Comunidad", - + // "community.sub-community-list.head": "Communities of this Community", "community.sub-community-list.head": "Comunidades de esta Comunidad", + - - + // "dso-selector.create.collection.head": "New collection", "dso-selector.create.collection.head": "Nueva colección", - + // "dso-selector.create.community.head": "New community", "dso-selector.create.community.head": "Nueva comunidad", - + // "dso-selector.create.community.sub-level": "Create a new community in", "dso-selector.create.community.sub-level": "Crear una nueva comunidad en", - + // "dso-selector.create.community.top-level": "Create a new top-level community", "dso-selector.create.community.top-level": "Crear una nueva comunidad de nivel superior", - + // "dso-selector.create.item.head": "New item", "dso-selector.create.item.head": "Nuevo ítem", - - // "dso-selector.create.submission.head": "New submission", - // TODO New key - Add a translation - "dso-selector.create.submission.head": "New submission", - + // "dso-selector.edit.collection.head": "Edit collection", "dso-selector.edit.collection.head": "Editar colección", - + // "dso-selector.edit.community.head": "Edit community", "dso-selector.edit.community.head": "Editar comunidad", - + // "dso-selector.edit.item.head": "Edit item", "dso-selector.edit.item.head": "Editar ítem", - + // "dso-selector.no-results": "No {{ type }} found", "dso-selector.no-results": "No se ha encontrado {{ type }}", - + // "dso-selector.placeholder": "Search for a {{ type }}", "dso-selector.placeholder": "Buscar por {{ type }}", - - + + // "error.bitstream": "Error fetching bitstream", // TODO New key - Add a translation "error.bitstream": "Error fetching bitstream", - + // "error.browse-by": "Error fetching items", "error.browse-by": "Error al recuperar los ítemes", - + // "error.collection": "Error fetching collection", "error.collection": "Error al recuperar la colección", - + // "error.collections": "Error fetching collections", "error.collections": "Error al recuperar las colecciones", - + // "error.community": "Error fetching community", "error.community": "Error al recuperar la comunidad", - + // "error.identifier": "No item found for the identifier", "error.identifier": "No se ha encontrado ningún ítem para el identificador.", - + // "error.default": "Error", "error.default": "Error", - + // "error.item": "Error fetching item", "error.item": "Error al recuperar el ítem", - + // "error.items": "Error fetching items", "error.items": "Error al recuperar los ítemes", - + // "error.objects": "Error fetching objects", "error.objects": "Error al recuperar los objetos", - + // "error.recent-submissions": "Error fetching recent submissions", "error.recent-submissions": "Error al recuperar los envíos recientes", - + // "error.search-results": "Error fetching search results", "error.search-results": "Error al recuperar los resultados de búsqueda", - + // "error.sub-collections": "Error fetching sub-collections", "error.sub-collections": "Error al recuperar las sub-colecciones", - + // "error.sub-communities": "Error fetching sub-communities", "error.sub-communities": "Error al recuperar las sub-comunidades", - + // "error.submission.sections.init-form-error": "An error occurred during section initialize, please check your input-form configuration. Details are below :

", "error.submission.sections.init-form-error": "Se produjo un error ocurrió durante el inicio de sesión, favor verifique su configuración del formulario de entrada. Los detalles están abajo :

", - + // "error.top-level-communities": "Error fetching top-level communities", "error.top-level-communities": "Error al recuperar las comunidades de nivel superior", - + // "error.validation.license.notgranted": "You must grant this license to complete your submission. If you are unable to grant this license at this time you may save your work and return later or remove the submission.", "error.validation.license.notgranted": "Debe otorgar esta licencia para completar su envío. Si no puede otorgar esta licencia en este momento, puede guardar su trabajo y regresar más tarde o eliminar el envío.", - + // "error.validation.pattern": "This input is restricted by the current pattern: {{ pattern }}.", "error.validation.pattern": "Esta entrada está restringida por el patrón actual: {{ pattern }}.", - + // "error.validation.filerequired": "The file upload is mandatory", // TODO New key - Add a translation "error.validation.filerequired": "The file upload is mandatory", - - - + + + // "footer.copyright": "copyright © 2002-{{ year }}", "footer.copyright": "derechos de autor © 2002-{{ year }}", - + // "footer.link.dspace": "DSpace software", "footer.link.dspace": "Software DSpace", - + // "footer.link.duraspace": "DuraSpace", "footer.link.duraspace": "DuraSpace", - - + + // "form.add": "Add", // TODO New key - Add a translation "form.add": "Add", - + // "form.add-help": "Click here to add the current entry and to add another one", // TODO New key - Add a translation "form.add-help": "Click here to add the current entry and to add another one", - + // "form.cancel": "Cancel", "form.cancel": "Cancelar", - + // "form.clear": "Clear", "form.clear": "Limpiar", - + // "form.clear-help": "Click here to remove the selected value", "form.clear-help": "Haga clic aquí para eliminar el valor seleccionado.", - + // "form.edit": "Edit", "form.edit": "Editar", - + // "form.edit-help": "Click here to edit the selected value", "form.edit-help": "Haga clic aquí para editar el valor seleccionado", - + // "form.first-name": "First name", "form.first-name": "Primer nombre", - + // "form.group-collapse": "Collapse", "form.group-collapse": "Contraer", - + // "form.group-collapse-help": "Click here to collapse", "form.group-collapse-help": "Clic aquí para contraer", - + // "form.group-expand": "Expand", "form.group-expand": "Expandir", - + // "form.group-expand-help": "Click here to expand and add more elements", "form.group-expand-help": "Clic aquí para expandir and agregar más elementos", - + // "form.last-name": "Last name", "form.last-name": "Apellido", - + // "form.loading": "Loading...", "form.loading": "Cargando...", - + // "form.lookup": "Lookup", // TODO New key - Add a translation "form.lookup": "Lookup", - + // "form.lookup-help": "Click here to look up an existing relation", // TODO New key - Add a translation "form.lookup-help": "Click here to look up an existing relation", - + // "form.no-results": "No results found", "form.no-results": "No se han encontrado resultados", - + // "form.no-value": "No value entered", "form.no-value": "Ningún valor ingresado", - + // "form.other-information": {}, "form.other-information": {}, - + // "form.remove": "Remove", "form.remove": "Eliminar", - + // "form.save": "Save", "form.save": "Guardar", - + // "form.save-help": "Save changes", "form.save-help": "Guardar cambios", - + // "form.search": "Search", "form.search": "Buscar", - - // "form.search-help": "Click here to look for an existing correspondence", - // TODO Source message changed - Revise the translation + + // "form.search-help": "Click here to looking for an existing correspondence", "form.search-help": "Haga clic aquí para buscar una correspondencia existente", - + // "form.submit": "Submit", "form.submit": "Enviar", - - - + + + // "home.description": "", "home.description": "", - + // "home.title": "DSpace Angular :: Home", "home.title": "DSpace Angular :: Inicio", - + // "home.top-level-communities.head": "Communities in DSpace", "home.top-level-communities.head": "Comunidades en DSpace", - + // "home.top-level-communities.help": "Select a community to browse its collections.", "home.top-level-communities.help": "Seleccionar una comunidad para navegar sus colecciones.", - - - // "item.edit.authorizations.heading": "With this editor you can view and alter the policies of an item, plus alter policies of individual item components: bundles and bitstreams. Briefly, an item is a container of bundles, and bundles are containers of bitstreams. Containers usually have ADD/REMOVE/READ/WRITE policies, while bitstreams only have READ/WRITE policies.", - // TODO New key - Add a translation - "item.edit.authorizations.heading": "With this editor you can view and alter the policies of an item, plus alter policies of individual item components: bundles and bitstreams. Briefly, an item is a container of bundles, and bundles are containers of bitstreams. Containers usually have ADD/REMOVE/READ/WRITE policies, while bitstreams only have READ/WRITE policies.", - - // "item.edit.authorizations.title": "Edit item's Policies", - // TODO New key - Add a translation - "item.edit.authorizations.title": "Edit item's Policies", - - - + + + // "item.bitstreams.upload.bundle": "Bundle", // TODO New key - Add a translation "item.bitstreams.upload.bundle": "Bundle", - + // "item.bitstreams.upload.bundle.placeholder": "Select a bundle", // TODO New key - Add a translation "item.bitstreams.upload.bundle.placeholder": "Select a bundle", - + // "item.bitstreams.upload.bundle.new": "Create bundle", // TODO New key - Add a translation "item.bitstreams.upload.bundle.new": "Create bundle", - + // "item.bitstreams.upload.bundles.empty": "This item doesn\'t contain any bundles to upload a bitstream to.", // TODO New key - Add a translation "item.bitstreams.upload.bundles.empty": "This item doesn\'t contain any bundles to upload a bitstream to.", - + // "item.bitstreams.upload.cancel": "Cancel", // TODO New key - Add a translation "item.bitstreams.upload.cancel": "Cancel", - + // "item.bitstreams.upload.drop-message": "Drop a file to upload", // TODO New key - Add a translation "item.bitstreams.upload.drop-message": "Drop a file to upload", - + // "item.bitstreams.upload.item": "Item: ", // TODO New key - Add a translation "item.bitstreams.upload.item": "Item: ", - + // "item.bitstreams.upload.notifications.bundle.created.content": "Successfully created new bundle.", // TODO New key - Add a translation "item.bitstreams.upload.notifications.bundle.created.content": "Successfully created new bundle.", - + // "item.bitstreams.upload.notifications.bundle.created.title": "Created bundle", // TODO New key - Add a translation "item.bitstreams.upload.notifications.bundle.created.title": "Created bundle", - + // "item.bitstreams.upload.notifications.upload.failed": "Upload failed. Please verify the content before retrying.", // TODO New key - Add a translation "item.bitstreams.upload.notifications.upload.failed": "Upload failed. Please verify the content before retrying.", - + // "item.bitstreams.upload.title": "Upload bitstream", // TODO New key - Add a translation "item.bitstreams.upload.title": "Upload bitstream", - - - + + + // "item.edit.bitstreams.bundle.edit.buttons.upload": "Upload", // TODO New key - Add a translation "item.edit.bitstreams.bundle.edit.buttons.upload": "Upload", - + // "item.edit.bitstreams.bundle.displaying": "Currently displaying {{ amount }} bitstreams of {{ total }}.", // TODO New key - Add a translation "item.edit.bitstreams.bundle.displaying": "Currently displaying {{ amount }} bitstreams of {{ total }}.", - + // "item.edit.bitstreams.bundle.load.all": "Load all ({{ total }})", // TODO New key - Add a translation "item.edit.bitstreams.bundle.load.all": "Load all ({{ total }})", - + // "item.edit.bitstreams.bundle.load.more": "Load more", // TODO New key - Add a translation "item.edit.bitstreams.bundle.load.more": "Load more", - + // "item.edit.bitstreams.bundle.name": "BUNDLE: {{ name }}", // TODO New key - Add a translation "item.edit.bitstreams.bundle.name": "BUNDLE: {{ name }}", - + // "item.edit.bitstreams.discard-button": "Discard", // TODO New key - Add a translation "item.edit.bitstreams.discard-button": "Discard", - + // "item.edit.bitstreams.edit.buttons.download": "Download", // TODO New key - Add a translation "item.edit.bitstreams.edit.buttons.download": "Download", - + // "item.edit.bitstreams.edit.buttons.drag": "Drag", // TODO New key - Add a translation "item.edit.bitstreams.edit.buttons.drag": "Drag", - + // "item.edit.bitstreams.edit.buttons.edit": "Edit", // TODO New key - Add a translation "item.edit.bitstreams.edit.buttons.edit": "Edit", - + // "item.edit.bitstreams.edit.buttons.remove": "Remove", // TODO New key - Add a translation "item.edit.bitstreams.edit.buttons.remove": "Remove", - + // "item.edit.bitstreams.edit.buttons.undo": "Undo changes", // TODO New key - Add a translation "item.edit.bitstreams.edit.buttons.undo": "Undo changes", - + // "item.edit.bitstreams.empty": "This item doesn't contain any bitstreams. Click the upload button to create one.", // TODO New key - Add a translation "item.edit.bitstreams.empty": "This item doesn't contain any bitstreams. Click the upload button to create one.", - + // "item.edit.bitstreams.headers.actions": "Actions", // TODO New key - Add a translation "item.edit.bitstreams.headers.actions": "Actions", - + // "item.edit.bitstreams.headers.bundle": "Bundle", // TODO New key - Add a translation "item.edit.bitstreams.headers.bundle": "Bundle", - + // "item.edit.bitstreams.headers.description": "Description", // TODO New key - Add a translation "item.edit.bitstreams.headers.description": "Description", - + // "item.edit.bitstreams.headers.format": "Format", // TODO New key - Add a translation "item.edit.bitstreams.headers.format": "Format", - + // "item.edit.bitstreams.headers.name": "Name", // TODO New key - Add a translation "item.edit.bitstreams.headers.name": "Name", - + // "item.edit.bitstreams.notifications.discarded.content": "Your changes were discarded. To reinstate your changes click the 'Undo' button", // TODO New key - Add a translation "item.edit.bitstreams.notifications.discarded.content": "Your changes were discarded. To reinstate your changes click the 'Undo' button", - + // "item.edit.bitstreams.notifications.discarded.title": "Changes discarded", // TODO New key - Add a translation "item.edit.bitstreams.notifications.discarded.title": "Changes discarded", - + // "item.edit.bitstreams.notifications.move.failed.title": "Error moving bitstreams", // TODO New key - Add a translation "item.edit.bitstreams.notifications.move.failed.title": "Error moving bitstreams", - + // "item.edit.bitstreams.notifications.move.saved.content": "Your move changes to this item's bitstreams and bundles have been saved.", // TODO New key - Add a translation "item.edit.bitstreams.notifications.move.saved.content": "Your move changes to this item's bitstreams and bundles have been saved.", - + // "item.edit.bitstreams.notifications.move.saved.title": "Move changes saved", // TODO New key - Add a translation "item.edit.bitstreams.notifications.move.saved.title": "Move changes saved", - + // "item.edit.bitstreams.notifications.outdated.content": "The item you're currently working on has been changed by another user. Your current changes are discarded to prevent conflicts", // TODO New key - Add a translation "item.edit.bitstreams.notifications.outdated.content": "The item you're currently working on has been changed by another user. Your current changes are discarded to prevent conflicts", - + // "item.edit.bitstreams.notifications.outdated.title": "Changes outdated", // TODO New key - Add a translation "item.edit.bitstreams.notifications.outdated.title": "Changes outdated", - + // "item.edit.bitstreams.notifications.remove.failed.title": "Error deleting bitstream", // TODO New key - Add a translation "item.edit.bitstreams.notifications.remove.failed.title": "Error deleting bitstream", - + // "item.edit.bitstreams.notifications.remove.saved.content": "Your removal changes to this item's bitstreams have been saved.", // TODO New key - Add a translation "item.edit.bitstreams.notifications.remove.saved.content": "Your removal changes to this item's bitstreams have been saved.", - + // "item.edit.bitstreams.notifications.remove.saved.title": "Removal changes saved", // TODO New key - Add a translation "item.edit.bitstreams.notifications.remove.saved.title": "Removal changes saved", - + // "item.edit.bitstreams.reinstate-button": "Undo", // TODO New key - Add a translation "item.edit.bitstreams.reinstate-button": "Undo", - + // "item.edit.bitstreams.save-button": "Save", // TODO New key - Add a translation "item.edit.bitstreams.save-button": "Save", - + // "item.edit.bitstreams.upload-button": "Upload", // TODO New key - Add a translation "item.edit.bitstreams.upload-button": "Upload", - - - + + + // "item.edit.delete.cancel": "Cancel", "item.edit.delete.cancel": "Cancelar", - + // "item.edit.delete.confirm": "Delete", "item.edit.delete.confirm": "Eliminar", - + // "item.edit.delete.description": "Are you sure this item should be completely deleted? Caution: At present, no tombstone would be left.", "item.edit.delete.description": "¿Estás seguro de que este ítem debe eliminarse por completo? Precaución: en la actualidad no quedaría ningún tombstone.", - + // "item.edit.delete.error": "An error occurred while deleting the item", "item.edit.delete.error": "Se produjo un error al eliminar el ítem.", - + // "item.edit.delete.header": "Delete item: {{ id }}", "item.edit.delete.header": "Eliminar el ítem: {{ id }}", - + // "item.edit.delete.success": "The item has been deleted", "item.edit.delete.success": "El ítem ha sido eliminado", - + // "item.edit.head": "Edit Item", "item.edit.head": "Editar el ítem", - + // "item.edit.breadcrumbs": "Edit Item", // TODO New key - Add a translation "item.edit.breadcrumbs": "Edit Item", - - - + + + // "item.edit.item-mapper.buttons.add": "Map item to selected collections", "item.edit.item-mapper.buttons.add": "Asignar el ítem a las colecciones seleccionadas", - + // "item.edit.item-mapper.buttons.remove": "Remove item's mapping for selected collections", "item.edit.item-mapper.buttons.remove": "Eliminar la asignación de ítemes para las colecciones seleccionadas", - + // "item.edit.item-mapper.cancel": "Cancel", "item.edit.item-mapper.cancel": "Cancelar", - + // "item.edit.item-mapper.description": "This is the item mapper tool that allows administrators to map this item to other collections. You can search for collections and map them, or browse the list of collections the item is currently mapped to.", "item.edit.item-mapper.description": "Esta es la herramienta de asignación de ítemes que permite a los administradores asignar este ítem a otras colecciones. Puede buscar colecciones y asignarlas, o navegar la lista de colecciones a las que está asignado actualmente el ítem", - + // "item.edit.item-mapper.head": "Item Mapper - Map Item to Collections", "item.edit.item-mapper.head": "Asignación de ítemes - Asignación del ítem a las Colecciones", - + // "item.edit.item-mapper.item": "Item: \"{{name}}\"", "item.edit.item-mapper.item": "Item: \"{{name}}\"", - + // "item.edit.item-mapper.no-search": "Please enter a query to search", "item.edit.item-mapper.no-search": "Favor ingrese una consulta para buscar", - + // "item.edit.item-mapper.notifications.add.error.content": "Errors occurred for mapping of item to {{amount}} collections.", "item.edit.item-mapper.notifications.add.error.content": "Se produjeron errores al asignar el ítem a las {{amount}} colecciones.", - + // "item.edit.item-mapper.notifications.add.error.head": "Mapping errors", "item.edit.item-mapper.notifications.add.error.head": "Errores de asignación", - + // "item.edit.item-mapper.notifications.add.success.content": "Successfully mapped item to {{amount}} collections.", "item.edit.item-mapper.notifications.add.success.content": "Exitosamente asignado el ítem a las {{amount}} colecciones.", - + // "item.edit.item-mapper.notifications.add.success.head": "Mapping completed", "item.edit.item-mapper.notifications.add.success.head": "Asignación completa", - + // "item.edit.item-mapper.notifications.remove.error.content": "Errors occurred for the removal of the mapping to {{amount}} collections.", "item.edit.item-mapper.notifications.remove.error.content": "Se produjeron errores al eliminar la asignación a las {{amount}} colecciones.", - + // "item.edit.item-mapper.notifications.remove.error.head": "Removal of mapping errors", "item.edit.item-mapper.notifications.remove.error.head": "Eliminación de errores de mapeo", - + // "item.edit.item-mapper.notifications.remove.success.content": "Successfully removed mapping of item to {{amount}} collections.", "item.edit.item-mapper.notifications.remove.success.content": "Se eliminó con éxito la asignación del elemento a {{amount}} colecciones.", - + // "item.edit.item-mapper.notifications.remove.success.head": "Removal of mapping completed", "item.edit.item-mapper.notifications.remove.success.head": "Eliminación completa de asignación", - + // "item.edit.item-mapper.tabs.browse": "Browse mapped collections", "item.edit.item-mapper.tabs.browse": "Navegar colecciones asignadas", - + // "item.edit.item-mapper.tabs.map": "Map new collections", "item.edit.item-mapper.tabs.map": "Asignar nuevas colecciones", - - - + + + // "item.edit.metadata.add-button": "Add", "item.edit.metadata.add-button": "Agregar", - + // "item.edit.metadata.discard-button": "Discard", "item.edit.metadata.discard-button": "Descartar", - + // "item.edit.metadata.edit.buttons.edit": "Edit", "item.edit.metadata.edit.buttons.edit": "Editar", - + // "item.edit.metadata.edit.buttons.remove": "Remove", "item.edit.metadata.edit.buttons.remove": "Eliminar", - + // "item.edit.metadata.edit.buttons.undo": "Undo changes", "item.edit.metadata.edit.buttons.undo": "Deshacer cambios", - + // "item.edit.metadata.edit.buttons.unedit": "Stop editing", "item.edit.metadata.edit.buttons.unedit": "Parar la edición", - + // "item.edit.metadata.headers.edit": "Edit", "item.edit.metadata.headers.edit": "Editar", - + // "item.edit.metadata.headers.field": "Field", "item.edit.metadata.headers.field": "Campo", - + // "item.edit.metadata.headers.language": "Lang", "item.edit.metadata.headers.language": "Lenguaje", - + // "item.edit.metadata.headers.value": "Value", "item.edit.metadata.headers.value": "Valor", - + // "item.edit.metadata.metadatafield.invalid": "Please choose a valid metadata field", "item.edit.metadata.metadatafield.invalid": "Favor escoger un campo de metadato válido", - + // "item.edit.metadata.notifications.discarded.content": "Your changes were discarded. To reinstate your changes click the 'Undo' button", "item.edit.metadata.notifications.discarded.content": "Los cambios fueron descartados. Para restablecer sus cambios, haga clic en el botón 'Deshacer'", - + // "item.edit.metadata.notifications.discarded.title": "Changed discarded", "item.edit.metadata.notifications.discarded.title": "Cambio descartado", - + // "item.edit.metadata.notifications.invalid.content": "Your changes were not saved. Please make sure all fields are valid before you save.", "item.edit.metadata.notifications.invalid.content": "No se guardaron los cambios. Asegúrese de que todos los campos sean válidos antes de guardar.", - + // "item.edit.metadata.notifications.invalid.title": "Metadata invalid", "item.edit.metadata.notifications.invalid.title": "Metadatos inválidos", - + // "item.edit.metadata.notifications.outdated.content": "The item you're currently working on has been changed by another user. Your current changes are discarded to prevent conflicts", "item.edit.metadata.notifications.outdated.content": "El ítem en el que está trabajando actualmente ha sido cambiado por otro usuario. Sus cambios actuales se descartan para evitar conflictos", - + // "item.edit.metadata.notifications.outdated.title": "Changed outdated", "item.edit.metadata.notifications.outdated.title": "Cambio desactualizado", - + // "item.edit.metadata.notifications.saved.content": "Your changes to this item's metadata were saved.", "item.edit.metadata.notifications.saved.content": "Se guaradaron los cambios de la metadata para este ítem.", - + // "item.edit.metadata.notifications.saved.title": "Metadata saved", "item.edit.metadata.notifications.saved.title": "Metadatos guardados", - + // "item.edit.metadata.reinstate-button": "Undo", "item.edit.metadata.reinstate-button": "Deshacer", - + // "item.edit.metadata.save-button": "Save", "item.edit.metadata.save-button": "Guardar", - - - + + + // "item.edit.modify.overview.field": "Field", "item.edit.modify.overview.field": "Campo", - + // "item.edit.modify.overview.language": "Language", "item.edit.modify.overview.language": "Lenguaje", - + // "item.edit.modify.overview.value": "Value", "item.edit.modify.overview.value": "Valor", - - - + + + // "item.edit.move.cancel": "Cancel", "item.edit.move.cancel": "Cancelar", - + // "item.edit.move.description": "Select the collection you wish to move this item to. To narrow down the list of displayed collections, you can enter a search query in the box.", "item.edit.move.description": "Seleccione la colección a la que desea mover este ítem. Para reducir la lista de colecciones mostradas, puede ingresar una consulta de búsqueda en el cuadro.", - + // "item.edit.move.error": "An error occurred when attempting to move the item", "item.edit.move.error": "Ha ocurrido un error cuando ha intentado mover el ítem", - + // "item.edit.move.head": "Move item: {{id}}", "item.edit.move.head": "Mover el ítem: {{id}}", - + // "item.edit.move.inheritpolicies.checkbox": "Inherit policies", "item.edit.move.inheritpolicies.checkbox": "Heredar políticas", - + // "item.edit.move.inheritpolicies.description": "Inherit the default policies of the destination collection", "item.edit.move.inheritpolicies.description": "Heredar las políticas predeterminadas de la colección de destino.", - + // "item.edit.move.move": "Move", "item.edit.move.move": "Mover", - + // "item.edit.move.processing": "Moving...", "item.edit.move.processing": "Moviendo...", - + // "item.edit.move.search.placeholder": "Enter a search query to look for collections", "item.edit.move.search.placeholder": "Ingrese una consulta para buscar colecciones", - + // "item.edit.move.success": "The item has been moved successfully", "item.edit.move.success": "El ítem ha sido movido exitosamente", - + // "item.edit.move.title": "Move item", "item.edit.move.title": "Mover ítem", - - - + + + // "item.edit.private.cancel": "Cancel", "item.edit.private.cancel": "Cancelar", - + // "item.edit.private.confirm": "Make it Private", "item.edit.private.confirm": "Hacerle privado", - + // "item.edit.private.description": "Are you sure this item should be made private in the archive?", "item.edit.private.description": "¿Está seguro de que este ítem debe ser privado en el archivo?", - + // "item.edit.private.error": "An error occurred while making the item private", "item.edit.private.error": "Se produjo un error mientras se hacía privado el ítem.", - + // "item.edit.private.header": "Make item private: {{ id }}", "item.edit.private.header": "Hacer privado el ítem: {{ id }}", - + // "item.edit.private.success": "The item is now private", "item.edit.private.success": "Ahora está privado el ítem", - - - + + + // "item.edit.public.cancel": "Cancel", "item.edit.public.cancel": "Cancelar", - + // "item.edit.public.confirm": "Make it Public", "item.edit.public.confirm": "Hacerle público", - + // "item.edit.public.description": "Are you sure this item should be made public in the archive?", "item.edit.public.description": "¿Estás seguro de que este ítem debe hacerse público en el archivo?", - + // "item.edit.public.error": "An error occurred while making the item public", "item.edit.public.error": "Se produjo un error mientras se hacía público el ítem.", - + // "item.edit.public.header": "Make item public: {{ id }}", "item.edit.public.header": "Hacer público el ítem: {{ id }}", - + // "item.edit.public.success": "The item is now public", "item.edit.public.success": "Ahora está público el ítem", - - - + + + // "item.edit.reinstate.cancel": "Cancel", "item.edit.reinstate.cancel": "Cancelar", - + // "item.edit.reinstate.confirm": "Reinstate", "item.edit.reinstate.confirm": "Reintegrar", - + // "item.edit.reinstate.description": "Are you sure this item should be reinstated to the archive?", "item.edit.reinstate.description": "¿Está seguro de que este ítem debe reintegrarse en el archivo?", - + // "item.edit.reinstate.error": "An error occurred while reinstating the item", "item.edit.reinstate.error": "Se produjo un error al restablecer el ítem.", - + // "item.edit.reinstate.header": "Reinstate item: {{ id }}", "item.edit.reinstate.header": "Reintegrar ítem: {{ id }}", - + // "item.edit.reinstate.success": "The item was reinstated successfully", "item.edit.reinstate.success": "El ítem fue reintegrado exitosamente", - - - + + + // "item.edit.relationships.discard-button": "Discard", "item.edit.relationships.discard-button": "Descartar", - + // "item.edit.relationships.edit.buttons.remove": "Remove", "item.edit.relationships.edit.buttons.remove": "Remover", - + // "item.edit.relationships.edit.buttons.undo": "Undo changes", "item.edit.relationships.edit.buttons.undo": "Deshacer cambios", - + // "item.edit.relationships.notifications.discarded.content": "Your changes were discarded. To reinstate your changes click the 'Undo' button", "item.edit.relationships.notifications.discarded.content": "Los cambios fueron descartados. Para restablecer sus cambios, haga clic en el botón 'Deshacer'", - + // "item.edit.relationships.notifications.discarded.title": "Changes discarded", "item.edit.relationships.notifications.discarded.title": "Cambios descartados", - + // "item.edit.relationships.notifications.failed.title": "Error deleting relationship", "item.edit.relationships.notifications.failed.title": "Error al eliminar la relación", - + // "item.edit.relationships.notifications.outdated.content": "The item you're currently working on has been changed by another user. Your current changes are discarded to prevent conflicts", "item.edit.relationships.notifications.outdated.content": "El ítem en el que está trabajando actualmente ha sido cambiado por otro usuario. Sus cambios actuales se descartan para evitar conflictos", - + // "item.edit.relationships.notifications.outdated.title": "Changes outdated", "item.edit.relationships.notifications.outdated.title": "Cambio desactualizado", - + // "item.edit.relationships.notifications.saved.content": "Your changes to this item's relationships were saved.", "item.edit.relationships.notifications.saved.content": "Se guardaron los cambios en las relaciones de este ítem.", - + // "item.edit.relationships.notifications.saved.title": "Relationships saved", "item.edit.relationships.notifications.saved.title": "Relación guardada", - + // "item.edit.relationships.reinstate-button": "Undo", "item.edit.relationships.reinstate-button": "Deshacer", - + // "item.edit.relationships.save-button": "Save", "item.edit.relationships.save-button": "Guardar", - - - + + + // "item.edit.tabs.bitstreams.head": "Bitstreams", // TODO Source message changed - Revise the translation "item.edit.tabs.bitstreams.head": "Archivos del ítem", - + // "item.edit.tabs.bitstreams.title": "Item Edit - Bitstreams", "item.edit.tabs.bitstreams.title": "Editar ítem - Archivos", - + // "item.edit.tabs.curate.head": "Curate", "item.edit.tabs.curate.head": "Curar", - + // "item.edit.tabs.curate.title": "Item Edit - Curate", "item.edit.tabs.curate.title": "Editar - Curar Item", - + // "item.edit.tabs.metadata.head": "Metadata", // TODO Source message changed - Revise the translation "item.edit.tabs.metadata.head": "Metadatos del ítem", - + // "item.edit.tabs.metadata.title": "Item Edit - Metadata", "item.edit.tabs.metadata.title": "Editar ítem - Metadatos", - + // "item.edit.tabs.relationships.head": "Relationships", // TODO Source message changed - Revise the translation "item.edit.tabs.relationships.head": "Relacionador de ítem", - + // "item.edit.tabs.relationships.title": "Item Edit - Relationships", "item.edit.tabs.relationships.title": "Editar ítem - Relacionador", - + // "item.edit.tabs.status.buttons.authorizations.button": "Authorizations...", "item.edit.tabs.status.buttons.authorizations.button": "Autorizaciones...", - + // "item.edit.tabs.status.buttons.authorizations.label": "Edit item's authorization policies", "item.edit.tabs.status.buttons.authorizations.label": "Editar políticas de autorización de ítemes", - + // "item.edit.tabs.status.buttons.delete.button": "Permanently delete", "item.edit.tabs.status.buttons.delete.button": "Eliminar permanentemente", - + // "item.edit.tabs.status.buttons.delete.label": "Completely expunge item", "item.edit.tabs.status.buttons.delete.label": "Ítem completamente eliminado", - + // "item.edit.tabs.status.buttons.mappedCollections.button": "Mapped collections", "item.edit.tabs.status.buttons.mappedCollections.button": "Colecciones asignadas", - + // "item.edit.tabs.status.buttons.mappedCollections.label": "Manage mapped collections", "item.edit.tabs.status.buttons.mappedCollections.label": "Gestionar colecciones asignadas", - + // "item.edit.tabs.status.buttons.move.button": "Move...", "item.edit.tabs.status.buttons.move.button": "Mover...", - + // "item.edit.tabs.status.buttons.move.label": "Move item to another collection", "item.edit.tabs.status.buttons.move.label": "Mover el ítem a otra colección", - + // "item.edit.tabs.status.buttons.private.button": "Make it private...", "item.edit.tabs.status.buttons.private.button": "Hacerle privado...", - + // "item.edit.tabs.status.buttons.private.label": "Make item private", "item.edit.tabs.status.buttons.private.label": "Hacer privado el ítem", - + // "item.edit.tabs.status.buttons.public.button": "Make it public...", "item.edit.tabs.status.buttons.public.button": "Hacerle público...", - + // "item.edit.tabs.status.buttons.public.label": "Make item public", "item.edit.tabs.status.buttons.public.label": "Hacer público el ítem", - + // "item.edit.tabs.status.buttons.reinstate.button": "Reinstate...", "item.edit.tabs.status.buttons.reinstate.button": "Reintegrar...", - + // "item.edit.tabs.status.buttons.reinstate.label": "Reinstate item into the repository", "item.edit.tabs.status.buttons.reinstate.label": "Reintegrar el ítem al repositorio", - + // "item.edit.tabs.status.buttons.withdraw.button": "Withdraw...", "item.edit.tabs.status.buttons.withdraw.button": "Retirar...", - + // "item.edit.tabs.status.buttons.withdraw.label": "Withdraw item from the repository", "item.edit.tabs.status.buttons.withdraw.label": "Retirar el ítem del repositorio", - + // "item.edit.tabs.status.description": "Welcome to the item management page. From here you can withdraw, reinstate, move or delete the item. You may also update or add new metadata / bitstreams on the other tabs.", "item.edit.tabs.status.description": "Bienvenido a la página de gestión de ítemes. Desde aquí puede retirar, restablecer, mover o eliminar el ítem. También puede actualizar o agregar nuevos metadatos / archivos en las otras pestañas.", - + // "item.edit.tabs.status.head": "Status", // TODO Source message changed - Revise the translation "item.edit.tabs.status.head": "Estado del ítem", - + // "item.edit.tabs.status.labels.handle": "Handle", "item.edit.tabs.status.labels.handle": "Handle", - + // "item.edit.tabs.status.labels.id": "Item Internal ID", "item.edit.tabs.status.labels.id": "ID interno del ítem", - + // "item.edit.tabs.status.labels.itemPage": "Item Page", "item.edit.tabs.status.labels.itemPage": "Página del ítem", - + // "item.edit.tabs.status.labels.lastModified": "Last Modified", "item.edit.tabs.status.labels.lastModified": "Última modificación", - + // "item.edit.tabs.status.title": "Item Edit - Status", "item.edit.tabs.status.title": "Editar ítem - Estado", - + // "item.edit.tabs.versionhistory.head": "Version History", // TODO New key - Add a translation "item.edit.tabs.versionhistory.head": "Version History", - + // "item.edit.tabs.versionhistory.title": "Item Edit - Version History", // TODO New key - Add a translation "item.edit.tabs.versionhistory.title": "Item Edit - Version History", - + // "item.edit.tabs.versionhistory.under-construction": "Editing or adding new versions is not yet possible in this user interface.", // TODO New key - Add a translation "item.edit.tabs.versionhistory.under-construction": "Editing or adding new versions is not yet possible in this user interface.", - + // "item.edit.tabs.view.head": "View Item", "item.edit.tabs.view.head": "Ver ítem", - + // "item.edit.tabs.view.title": "Item Edit - View", "item.edit.tabs.view.title": "Editar ítem - Ver", - - - + + + // "item.edit.withdraw.cancel": "Cancel", "item.edit.withdraw.cancel": "Cancelar", - + // "item.edit.withdraw.confirm": "Withdraw", "item.edit.withdraw.confirm": "Retirar", - + // "item.edit.withdraw.description": "Are you sure this item should be withdrawn from the archive?", "item.edit.withdraw.description": "¿Estás seguro de que este ítem debe ser retirado del archivo?", - + // "item.edit.withdraw.error": "An error occurred while withdrawing the item", "item.edit.withdraw.error": "Ha ocurrido un error mientras se retiraba el ítem", - + // "item.edit.withdraw.header": "Withdraw item: {{ id }}", "item.edit.withdraw.header": "Retirar el ítem: {{ id }}", - + // "item.edit.withdraw.success": "The item was withdrawn successfully", "item.edit.withdraw.success": "Fue retirado exitosamente el ítem", - - - + + + // "item.page.abstract": "Abstract", "item.page.abstract": "Resumen", - + // "item.page.author": "Authors", "item.page.author": "Autores", - + // "item.page.citation": "Citation", "item.page.citation": "Citación", - + // "item.page.collections": "Collections", "item.page.collections": "Colecciones", - + // "item.page.date": "Date", "item.page.date": "Fecha", - + // "item.page.files": "Files", "item.page.files": "Archivos", - + // "item.page.filesection.description": "Description:", "item.page.filesection.description": "Descripción:", - + // "item.page.filesection.download": "Download", "item.page.filesection.download": "Descargar", - + // "item.page.filesection.format": "Format:", "item.page.filesection.format": "Formato:", - + // "item.page.filesection.name": "Name:", "item.page.filesection.name": "Nombre:", - + // "item.page.filesection.size": "Size:", "item.page.filesection.size": "Tamaño:", - + // "item.page.journal.search.title": "Articles in this journal", "item.page.journal.search.title": "Artículos en esta revista", - + // "item.page.link.full": "Full item page", "item.page.link.full": "Página completa del ítem", - + // "item.page.link.simple": "Simple item page", "item.page.link.simple": "Página simple del ítem", - + // "item.page.person.search.title": "Articles by this author", "item.page.person.search.title": "Artículos por este autor", - + // "item.page.related-items.view-more": "Show {{ amount }} more", // TODO Source message changed - Revise the translation "item.page.related-items.view-more": "Ver más", - + // "item.page.related-items.view-less": "Hide last {{ amount }}", // TODO Source message changed - Revise the translation "item.page.related-items.view-less": "View menos", - + // "item.page.relationships.isAuthorOfPublication": "Publications", // TODO New key - Add a translation "item.page.relationships.isAuthorOfPublication": "Publications", - + // "item.page.relationships.isJournalOfPublication": "Publications", // TODO New key - Add a translation "item.page.relationships.isJournalOfPublication": "Publications", - + // "item.page.relationships.isOrgUnitOfPerson": "Authors", // TODO New key - Add a translation "item.page.relationships.isOrgUnitOfPerson": "Authors", - + // "item.page.relationships.isOrgUnitOfProject": "Research Projects", // TODO New key - Add a translation "item.page.relationships.isOrgUnitOfProject": "Research Projects", - + // "item.page.subject": "Keywords", "item.page.subject": "Claves", - + // "item.page.uri": "URI", "item.page.uri": "URI", - - - + + + // "item.select.confirm": "Confirm selected", "item.select.confirm": "Confirmar lo seleccionado", - + // "item.select.empty": "No items to show", "item.select.empty": "No ítemes para mostrar", - + // "item.select.table.author": "Author", "item.select.table.author": "Autor", - + // "item.select.table.collection": "Collection", "item.select.table.collection": "Colección", - + // "item.select.table.title": "Title", "item.select.table.title": "Título", - - + + // "item.version.history.empty": "There are no other versions for this item yet.", // TODO New key - Add a translation "item.version.history.empty": "There are no other versions for this item yet.", - + // "item.version.history.head": "Version History", // TODO New key - Add a translation "item.version.history.head": "Version History", - + // "item.version.history.return": "Return", // TODO New key - Add a translation "item.version.history.return": "Return", - + // "item.version.history.selected": "Selected version", // TODO New key - Add a translation "item.version.history.selected": "Selected version", - + // "item.version.history.table.version": "Version", // TODO New key - Add a translation "item.version.history.table.version": "Version", - + // "item.version.history.table.item": "Item", // TODO New key - Add a translation "item.version.history.table.item": "Item", - + // "item.version.history.table.editor": "Editor", // TODO New key - Add a translation "item.version.history.table.editor": "Editor", - + // "item.version.history.table.date": "Date", // TODO New key - Add a translation "item.version.history.table.date": "Date", - + // "item.version.history.table.summary": "Summary", // TODO New key - Add a translation "item.version.history.table.summary": "Summary", - - - + + + // "item.version.notice": "This is not the latest version of this item. The latest version can be found here.", // TODO New key - Add a translation "item.version.notice": "This is not the latest version of this item. The latest version can be found here.", - - - + + + // "journal.listelement.badge": "Journal", "journal.listelement.badge": "Revista", - + // "journal.page.description": "Description", "journal.page.description": "Descripción", - + // "journal.page.editor": "Editor-in-Chief", "journal.page.editor": "Editor-en-Jefe", - + // "journal.page.issn": "ISSN", "journal.page.issn": "ISSN", - + // "journal.page.publisher": "Publisher", "journal.page.publisher": "Editor", - + // "journal.page.titleprefix": "Journal: ", "journal.page.titleprefix": "Revista: ", - + // "journal.search.results.head": "Journal Search Results", "journal.search.results.head": "Resultados de búsqueda de revistas", - + // "journal.search.title": "DSpace Angular :: Journal Search", "journal.search.title": "DSpace Angular :: Búsqueda de revistas", - - - + + + // "journalissue.listelement.badge": "Journal Issue", "journalissue.listelement.badge": "Número de Revista", - + // "journalissue.page.description": "Description", "journalissue.page.description": "Descripción", - + // "journalissue.page.issuedate": "Issue Date", "journalissue.page.issuedate": "Fecha de Publicación", - + // "journalissue.page.journal-issn": "Journal ISSN", "journalissue.page.journal-issn": "ISSN de Revista", - + // "journalissue.page.journal-title": "Journal Title", "journalissue.page.journal-title": "Título de Revista", - + // "journalissue.page.keyword": "Keywords", "journalissue.page.keyword": "Claves", - + // "journalissue.page.number": "Number", "journalissue.page.number": "Número", - + // "journalissue.page.titleprefix": "Journal Issue: ", "journalissue.page.titleprefix": "Número de Revista: ", - - - + + + // "journalvolume.listelement.badge": "Journal Volume", "journalvolume.listelement.badge": "Volumen de la Revista", - + // "journalvolume.page.description": "Description", "journalvolume.page.description": "Descripción", - + // "journalvolume.page.issuedate": "Issue Date", "journalvolume.page.issuedate": "Fecha de Publicación", - + // "journalvolume.page.titleprefix": "Journal Volume: ", "journalvolume.page.titleprefix": "Volumen de la Revista: ", - + // "journalvolume.page.volume": "Volume", "journalvolume.page.volume": "Volumen", - - - + + + // "loading.bitstream": "Loading bitstream...", // TODO New key - Add a translation "loading.bitstream": "Loading bitstream...", - + // "loading.bitstreams": "Loading bitstreams...", // TODO New key - Add a translation "loading.bitstreams": "Loading bitstreams...", - + // "loading.browse-by": "Loading items...", "loading.browse-by": "Cargando ítemes...", - + // "loading.browse-by-page": "Loading page...", "loading.browse-by-page": "Cargando página...", - + // "loading.collection": "Loading collection...", "loading.collection": "Cargando colección...", - + // "loading.collections": "Loading collections...", "loading.collections": "Cargando colecciones...", - + // "loading.content-source": "Loading content source...", // TODO New key - Add a translation "loading.content-source": "Loading content source...", - + // "loading.community": "Loading community...", "loading.community": "Cargando comunidad...", - + // "loading.default": "Loading...", "loading.default": "Cargando...", - + // "loading.item": "Loading item...", "loading.item": "Cargando ítem...", - + // "loading.items": "Loading items...", "loading.items": "Cargando ítemes...", - + // "loading.mydspace-results": "Loading items...", "loading.mydspace-results": "Cargando ítemes...", - + // "loading.objects": "Loading...", "loading.objects": "Cargando...", - + // "loading.recent-submissions": "Loading recent submissions...", "loading.recent-submissions": "Cargando envíos recientes...", - + // "loading.search-results": "Loading search results...", "loading.search-results": "Cargando resultados de búsqueda...", - + // "loading.sub-collections": "Loading sub-collections...", "loading.sub-collections": "Cargando sub-colecciones...", - + // "loading.sub-communities": "Loading sub-communities...", "loading.sub-communities": "Cargando sub-comunidades...", - + // "loading.top-level-communities": "Loading top-level communities...", "loading.top-level-communities": "Cargando comunidades de nivel superior...", - - - + + + // "login.form.email": "Email address", "login.form.email": "Dirección de correo electrónico", - + // "login.form.forgot-password": "Have you forgotten your password?", "login.form.forgot-password": "¿Ha olvidado su contraseña?", - + // "login.form.header": "Please log in to DSpace", "login.form.header": "Favor inicie sesión en DSpace", - + // "login.form.new-user": "New user? Click here to register.", "login.form.new-user": "¿Usuario nuevo? Clic aquí para registrarse.", - + // "login.form.or-divider": "or", // TODO New key - Add a translation "login.form.or-divider": "or", - + // "login.form.password": "Password", "login.form.password": "Clave", - + // "login.form.shibboleth": "Log in with Shibboleth", // TODO New key - Add a translation "login.form.shibboleth": "Log in with Shibboleth", - + // "login.form.submit": "Log in", "login.form.submit": "Iniciar sesión", - + // "login.title": "Login", "login.title": "Iniciar sesión", - + // "login.breadcrumbs": "Login", // TODO New key - Add a translation "login.breadcrumbs": "Login", - - - + + + // "logout.form.header": "Log out from DSpace", "logout.form.header": "Cerrar sesión de DSpace", - + // "logout.form.submit": "Log out", "logout.form.submit": "Cerrar sesión", - + // "logout.title": "Logout", "logout.title": "Cerrar sesión", - - - + + + // "menu.header.admin": "Admin", "menu.header.admin": "Administrar", - + // "menu.header.image.logo": "Repository logo", "menu.header.image.logo": "Logo del Repositorio ", - - - + + + // "menu.section.access_control": "Access Control", "menu.section.access_control": "Control de acceso", - + // "menu.section.access_control_authorizations": "Authorizations", "menu.section.access_control_authorizations": "Autorizaciones", - + // "menu.section.access_control_groups": "Groups", "menu.section.access_control_groups": "Grupos", - + // "menu.section.access_control_people": "People", "menu.section.access_control_people": "Personas", - - - + + + // "menu.section.admin_search": "Admin Search", // TODO New key - Add a translation "menu.section.admin_search": "Admin Search", - - - + + + // "menu.section.browse_community": "This Community", "menu.section.browse_community": "Esta comunidad", - + // "menu.section.browse_community_by_author": "By Author", "menu.section.browse_community_by_author": "Por Autor", - + // "menu.section.browse_community_by_issue_date": "By Issue Date", "menu.section.browse_community_by_issue_date": "Por Fecha de Publicación", - + // "menu.section.browse_community_by_title": "By Title", "menu.section.browse_community_by_title": "Por Título", - + // "menu.section.browse_global": "All of DSpace", "menu.section.browse_global": "Todo DSpace", - + // "menu.section.browse_global_by_author": "By Author", "menu.section.browse_global_by_author": "Por Autor", - + // "menu.section.browse_global_by_dateissued": "By Issue Date", "menu.section.browse_global_by_dateissued": "Por Fecha de Publicación", - + // "menu.section.browse_global_by_subject": "By Subject", "menu.section.browse_global_by_subject": "Por Materia", - + // "menu.section.browse_global_by_title": "By Title", "menu.section.browse_global_by_title": "Por Título", - + // "menu.section.browse_global_communities_and_collections": "Communities & Collections", "menu.section.browse_global_communities_and_collections": "Comunidades & Colecciones", - - - + + + // "menu.section.control_panel": "Control Panel", "menu.section.control_panel": "Panel de Control", - + // "menu.section.curation_task": "Curation Task", "menu.section.curation_task": "Tarea de Curación", - - - + + + // "menu.section.edit": "Edit", "menu.section.edit": "Editar", - + // "menu.section.edit_collection": "Collection", "menu.section.edit_collection": "Colección", - + // "menu.section.edit_community": "Community", "menu.section.edit_community": "Comunidad", - + // "menu.section.edit_item": "Item", "menu.section.edit_item": "Ítem", - - - + + + // "menu.section.export": "Export", "menu.section.export": "Exportar", - + // "menu.section.export_collection": "Collection", "menu.section.export_collection": "Colección", - + // "menu.section.export_community": "Community", "menu.section.export_community": "Comunidad", - + // "menu.section.export_item": "Item", "menu.section.export_item": "Ítem", - + // "menu.section.export_metadata": "Metadata", "menu.section.export_metadata": "Metadatos", - - - + + + // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "Sección del menú de Control de Acceso", - + // "menu.section.icon.admin_search": "Admin search menu section", // TODO New key - Add a translation "menu.section.icon.admin_search": "Admin search menu section", - + // "menu.section.icon.control_panel": "Control Panel menu section", "menu.section.icon.control_panel": "Sección del menú de Panel Control", - + // "menu.section.icon.curation_task": "Curation Task menu section", "menu.section.icon.curation_task": "Sección del menú de Tarea de Curación", - + // "menu.section.icon.edit": "Edit menu section", "menu.section.icon.edit": "Sección del Menú Editar", - + // "menu.section.icon.export": "Export menu section", "menu.section.icon.export": "Sección del Menú Exportar", - + // "menu.section.icon.find": "Find menu section", "menu.section.icon.find": "Sección del Menú Encontrar", - + // "menu.section.icon.import": "Import menu section", "menu.section.icon.import": "Sección del Menú Importar", - + // "menu.section.icon.new": "New menu section", "menu.section.icon.new": "Sección del Menú Nuevo", - + // "menu.section.icon.pin": "Pin sidebar", "menu.section.icon.pin": "Pin sidebar", - + // "menu.section.icon.registries": "Registries menu section", "menu.section.icon.registries": "Sección del Menú Registros", - + // "menu.section.icon.statistics_task": "Statistics Task menu section", "menu.section.icon.statistics_task": "Sección del Menú Tarea de Estadísticas", - + // "menu.section.icon.unpin": "Unpin sidebar", "menu.section.icon.unpin": "Unpin sidebar", - - - + + + // "menu.section.import": "Import", "menu.section.import": "Importar", - + // "menu.section.import_batch": "Batch Import (ZIP)", "menu.section.import_batch": "Importar Batch (ZIP)", - + // "menu.section.import_metadata": "Metadata", "menu.section.import_metadata": "Metadatos", - - - + + + // "menu.section.new": "New", "menu.section.new": "Nuevo", - + // "menu.section.new_collection": "Collection", "menu.section.new_collection": "Colección", - + // "menu.section.new_community": "Community", "menu.section.new_community": "Comunidad", - + // "menu.section.new_item": "Item", "menu.section.new_item": "Ítem", - + // "menu.section.new_item_version": "Item Version", "menu.section.new_item_version": "Version del Ítem", - - - + + + // "menu.section.pin": "Pin sidebar", "menu.section.pin": "Pin sidebar", - + // "menu.section.unpin": "Unpin sidebar", "menu.section.unpin": "Unpin sidebar", - - - + + + // "menu.section.registries": "Registries", "menu.section.registries": "Registros", - + // "menu.section.registries_format": "Format", "menu.section.registries_format": "Formato", - + // "menu.section.registries_metadata": "Metadata", "menu.section.registries_metadata": "Metadatos", - - + + // "menu.section.statistics": "Statistics", "menu.section.statistics": "Estadísticas", - + // "menu.section.statistics_task": "Statistics Task", "menu.section.statistics_task": "Tarea de Estadíisticas", - - - + + + // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Alternar la sección de Control de Acceso", - + // "menu.section.toggle.control_panel": "Toggle Control Panel section", "menu.section.toggle.control_panel": "Alternar la sección de Panel de Control", - + // "menu.section.toggle.curation_task": "Toggle Curation Task section", "menu.section.toggle.curation_task": "Alternar la sección de Tarea de Curación", - + // "menu.section.toggle.edit": "Toggle Edit section", "menu.section.toggle.edit": "Alternar la sección de Editar", - + // "menu.section.toggle.export": "Toggle Export section", "menu.section.toggle.export": "Alternar la sección de Exportar", - + // "menu.section.toggle.find": "Toggle Find section", "menu.section.toggle.find": "Alternar la sección de Encontrar", - + // "menu.section.toggle.import": "Toggle Import section", "menu.section.toggle.import": "Alternar la sección de Importar", - + // "menu.section.toggle.new": "Toggle New section", "menu.section.toggle.new": "Alternar la sección de Nuevo", - + // "menu.section.toggle.registries": "Toggle Registries section", "menu.section.toggle.registries": "Alternar la sección de Registros", - + // "menu.section.toggle.statistics_task": "Toggle Statistics Task section", "menu.section.toggle.statistics_task": "Alternar la sección de Tareas de Estadísticas", - - - // "menu.section.workflow": "Administer Workflow", - // TODO New key - Add a translation - "menu.section.workflow": "Administer Workflow", - - + + + // "mydspace.description": "", "mydspace.description": "", - - // "mydspace.general.text-here": "here", - // TODO Source message changed - Revise the translation + + // "mydspace.general.text-here": "HERE", "mydspace.general.text-here": "AQUÍ", - + // "mydspace.messages.controller-help": "Select this option to send a message to item's submitter.", "mydspace.messages.controller-help": "Seleccione esta opción para enviar un mensaje al remitente del ítem.", - + // "mydspace.messages.description-placeholder": "Insert your message here...", "mydspace.messages.description-placeholder": "Ingrese su mensaje aquí...", - + // "mydspace.messages.hide-msg": "Hide message", "mydspace.messages.hide-msg": "Ocultar mensaje", - + // "mydspace.messages.mark-as-read": "Mark as read", "mydspace.messages.mark-as-read": "Marcar como leído", - + // "mydspace.messages.mark-as-unread": "Mark as unread", "mydspace.messages.mark-as-unread": "Macar como no leído", - + // "mydspace.messages.no-content": "No content.", "mydspace.messages.no-content": "Sin contenido.", - + // "mydspace.messages.no-messages": "No messages yet.", "mydspace.messages.no-messages": "Aún no hay mensajes.", - + // "mydspace.messages.send-btn": "Send", "mydspace.messages.send-btn": "Enviar", - + // "mydspace.messages.show-msg": "Show message", "mydspace.messages.show-msg": "Mostrar mensaje", - + // "mydspace.messages.subject-placeholder": "Subject...", "mydspace.messages.subject-placeholder": "Materia...", - + // "mydspace.messages.submitter-help": "Select this option to send a message to controller.", "mydspace.messages.submitter-help": "Seleccione esta opción para enviar un mensaje al controlador.", - + // "mydspace.messages.title": "Messages", "mydspace.messages.title": "Mensajes", - + // "mydspace.messages.to": "To", "mydspace.messages.to": "Para", - + // "mydspace.new-submission": "New submission", "mydspace.new-submission": "Nuevo envío", - + // "mydspace.results.head": "Your submissions", "mydspace.results.head": "Sus envíos", - + // "mydspace.results.no-abstract": "No Abstract", "mydspace.results.no-abstract": "Sin Resumen", - + // "mydspace.results.no-authors": "No Authors", "mydspace.results.no-authors": "Sin Autores", - + // "mydspace.results.no-collections": "No Collections", "mydspace.results.no-collections": "Sin Colecciones", - + // "mydspace.results.no-date": "No Date", "mydspace.results.no-date": "Sin Fecha", - + // "mydspace.results.no-files": "No Files", "mydspace.results.no-files": "Sin Archivos", - + // "mydspace.results.no-results": "There were no items to show", "mydspace.results.no-results": "No hay ítemes para mostrar", - + // "mydspace.results.no-title": "No title", "mydspace.results.no-title": "Sin título", - + // "mydspace.results.no-uri": "No Uri", "mydspace.results.no-uri": "Sin Uri", - + // "mydspace.show.workflow": "All tasks", "mydspace.show.workflow": "Todas las tareas", - + // "mydspace.show.workspace": "Your Submissions", "mydspace.show.workspace": "Sus envíos", - + // "mydspace.status.archived": "Archived", "mydspace.status.archived": "Archivado", - + // "mydspace.status.validation": "Validation", "mydspace.status.validation": "Validación", - + // "mydspace.status.waiting-for-controller": "Waiting for controller", "mydspace.status.waiting-for-controller": "Esperando controlador", - + // "mydspace.status.workflow": "Workflow", "mydspace.status.workflow": "Flujo de trabajo", - + // "mydspace.status.workspace": "Workspace", "mydspace.status.workspace": "Workspace", - + // "mydspace.title": "MyDSpace", "mydspace.title": "MiDSpace", - + // "mydspace.upload.upload-failed": "Error creating new workspace. Please verify the content uploaded before retry.", "mydspace.upload.upload-failed": "Error al crear nuevo Workspace. Verifique el contenido cargado antes de intentar.", - - // "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", - // TODO New key - Add a translation - "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", - - // "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", - // TODO New key - Add a translation - "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", - + // "mydspace.upload.upload-multiple-successful": "{{qty}} new workspace items created.", "mydspace.upload.upload-multiple-successful": "{{qty}} Nuevos ítemes de workspace creados.", - + // "mydspace.upload.upload-successful": "New workspace item created. Click {{here}} for edit it.", "mydspace.upload.upload-successful": "Nuevos ítemes de workspace creados. Clic {{here}} para editar.", - + // "mydspace.view-btn": "View", "mydspace.view-btn": "Ver", - - - + + + // "nav.browse.header": "All of DSpace", "nav.browse.header": "Todo DSpace", - + // "nav.community-browse.header": "By Community", "nav.community-browse.header": "Por Comunidad", - + // "nav.language": "Language switch", "nav.language": "Cambio de idioma", - + // "nav.login": "Log In", "nav.login": "Inicio de Sesión", - + // "nav.logout": "Log Out", "nav.logout": "Cerrar Sesión", - + // "nav.mydspace": "MyDSpace", "nav.mydspace": "Mi DSpace", - + // "nav.profile": "Profile", // TODO New key - Add a translation "nav.profile": "Profile", - + // "nav.search": "Search", "nav.search": "Buscar", - + // "nav.statistics.header": "Statistics", "nav.statistics.header": "Estadísticas", - - // "nav.stop-impersonating": "Stop impersonating EPerson", - // TODO New key - Add a translation - "nav.stop-impersonating": "Stop impersonating EPerson", - - - + + + // "orgunit.listelement.badge": "Organizational Unit", "orgunit.listelement.badge": "Unidad organizacional", - + // "orgunit.page.city": "City", "orgunit.page.city": "Ciudad", - + // "orgunit.page.country": "Country", "orgunit.page.country": "País", - + // "orgunit.page.dateestablished": "Date established", "orgunit.page.dateestablished": "Fecha establecida", - + // "orgunit.page.description": "Description", "orgunit.page.description": "Descripción", - + // "orgunit.page.id": "ID", "orgunit.page.id": "ID", - + // "orgunit.page.titleprefix": "Organizational Unit: ", "orgunit.page.titleprefix": "Unidad organizacional: ", - - - + + + // "pagination.results-per-page": "Results Per Page", "pagination.results-per-page": "Resultados por Página", - + // "pagination.showing.detail": "{{ range }} of {{ total }}", "pagination.showing.detail": "{{ range }} de {{ total }}", - + // "pagination.showing.label": "Now showing ", "pagination.showing.label": "Mostrando ", - + // "pagination.sort-direction": "Sort Options", "pagination.sort-direction": "Opciones de orden", - - - + + + // "person.listelement.badge": "Person", "person.listelement.badge": "Persona", - + // "person.page.birthdate": "Birth Date", "person.page.birthdate": "Fecha de Nacimiento", - + // "person.page.email": "Email Address", "person.page.email": "Dirección de correo electrónico", - + // "person.page.firstname": "First Name", "person.page.firstname": "Nombre", - + // "person.page.jobtitle": "Job Title", "person.page.jobtitle": "Título profesional", - + // "person.page.lastname": "Last Name", "person.page.lastname": "Apellido", - + // "person.page.link.full": "Show all metadata", "person.page.link.full": "Mostrar todos los metadatos", - + // "person.page.orcid": "ORCID", "person.page.orcid": "ORCID", - + // "person.page.staffid": "Staff ID", "person.page.staffid": "Identificación del personal", - + // "person.page.titleprefix": "Person: ", "person.page.titleprefix": "Persona: ", - + // "person.search.results.head": "Person Search Results", "person.search.results.head": "Resultados de búsqueda de personas", - + // "person.search.title": "DSpace Angular :: Person Search", "person.search.title": "DSpace Angular :: Búsqueda de persona", - - - + + + // "profile.breadcrumbs": "Update Profile", // TODO New key - Add a translation "profile.breadcrumbs": "Update Profile", - + // "profile.card.identify": "Identify", // TODO New key - Add a translation "profile.card.identify": "Identify", - + // "profile.card.security": "Security", // TODO New key - Add a translation "profile.card.security": "Security", - + // "profile.form.submit": "Update Profile", // TODO New key - Add a translation "profile.form.submit": "Update Profile", - + // "profile.groups.head": "Authorization groups you belong to", // TODO New key - Add a translation "profile.groups.head": "Authorization groups you belong to", - + // "profile.head": "Update Profile", // TODO New key - Add a translation "profile.head": "Update Profile", - + // "profile.metadata.form.error.firstname.required": "First Name is required", // TODO New key - Add a translation "profile.metadata.form.error.firstname.required": "First Name is required", - + // "profile.metadata.form.error.lastname.required": "Last Name is required", // TODO New key - Add a translation "profile.metadata.form.error.lastname.required": "Last Name is required", - + // "profile.metadata.form.label.email": "Email Address", // TODO New key - Add a translation "profile.metadata.form.label.email": "Email Address", - + // "profile.metadata.form.label.firstname": "First Name", // TODO New key - Add a translation "profile.metadata.form.label.firstname": "First Name", - + // "profile.metadata.form.label.language": "Language", // TODO New key - Add a translation "profile.metadata.form.label.language": "Language", - + // "profile.metadata.form.label.lastname": "Last Name", // TODO New key - Add a translation "profile.metadata.form.label.lastname": "Last Name", - + // "profile.metadata.form.label.phone": "Contact Telephone", // TODO New key - Add a translation "profile.metadata.form.label.phone": "Contact Telephone", - + // "profile.metadata.form.notifications.success.content": "Your changes to the profile were saved.", // TODO New key - Add a translation "profile.metadata.form.notifications.success.content": "Your changes to the profile were saved.", - + // "profile.metadata.form.notifications.success.title": "Profile saved", // TODO New key - Add a translation "profile.metadata.form.notifications.success.title": "Profile saved", - + // "profile.notifications.warning.no-changes.content": "No changes were made to the Profile.", // TODO New key - Add a translation "profile.notifications.warning.no-changes.content": "No changes were made to the Profile.", - + // "profile.notifications.warning.no-changes.title": "No changes", // TODO New key - Add a translation "profile.notifications.warning.no-changes.title": "No changes", - + // "profile.security.form.error.matching-passwords": "The passwords do not match.", // TODO New key - Add a translation "profile.security.form.error.matching-passwords": "The passwords do not match.", - + // "profile.security.form.error.password-length": "The password should be at least 6 characters long.", // TODO New key - Add a translation "profile.security.form.error.password-length": "The password should be at least 6 characters long.", - + // "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.", // TODO New key - Add a translation "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.", - + // "profile.security.form.label.password": "Password", // TODO New key - Add a translation "profile.security.form.label.password": "Password", - + // "profile.security.form.label.passwordrepeat": "Retype to confirm", // TODO New key - Add a translation "profile.security.form.label.passwordrepeat": "Retype to confirm", - + // "profile.security.form.notifications.success.content": "Your changes to the password were saved.", // TODO New key - Add a translation "profile.security.form.notifications.success.content": "Your changes to the password were saved.", - + // "profile.security.form.notifications.success.title": "Password saved", // TODO New key - Add a translation "profile.security.form.notifications.success.title": "Password saved", - + // "profile.security.form.notifications.error.title": "Error changing passwords", // TODO New key - Add a translation "profile.security.form.notifications.error.title": "Error changing passwords", - + // "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", // TODO New key - Add a translation "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", - + // "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", // TODO New key - Add a translation "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", - + // "profile.title": "Update Profile", // TODO New key - Add a translation "profile.title": "Update Profile", - - - - // "profile.breadcrumbs": "Update Profile", - // TODO New key - Add a translation - "profile.breadcrumbs": "Update Profile", - - // "profile.card.identify": "Identify", - // TODO New key - Add a translation - "profile.card.identify": "Identify", - - // "profile.card.security": "Security", - // TODO New key - Add a translation - "profile.card.security": "Security", - - // "profile.form.submit": "Update Profile", - // TODO New key - Add a translation - "profile.form.submit": "Update Profile", - - // "profile.groups.head": "Authorization groups you belong to", - // TODO New key - Add a translation - "profile.groups.head": "Authorization groups you belong to", - - // "profile.head": "Update Profile", - // TODO New key - Add a translation - "profile.head": "Update Profile", - - // "profile.metadata.form.error.firstname.required": "First Name is required", - // TODO New key - Add a translation - "profile.metadata.form.error.firstname.required": "First Name is required", - - // "profile.metadata.form.error.lastname.required": "Last Name is required", - // TODO New key - Add a translation - "profile.metadata.form.error.lastname.required": "Last Name is required", - - // "profile.metadata.form.label.email": "Email Address", - // TODO New key - Add a translation - "profile.metadata.form.label.email": "Email Address", - - // "profile.metadata.form.label.firstname": "First Name", - // TODO New key - Add a translation - "profile.metadata.form.label.firstname": "First Name", - - // "profile.metadata.form.label.language": "Language", - // TODO New key - Add a translation - "profile.metadata.form.label.language": "Language", - - // "profile.metadata.form.label.lastname": "Last Name", - // TODO New key - Add a translation - "profile.metadata.form.label.lastname": "Last Name", - - // "profile.metadata.form.label.phone": "Contact Telephone", - // TODO New key - Add a translation - "profile.metadata.form.label.phone": "Contact Telephone", - - // "profile.metadata.form.notifications.success.content": "Your changes to the profile were saved.", - // TODO New key - Add a translation - "profile.metadata.form.notifications.success.content": "Your changes to the profile were saved.", - - // "profile.metadata.form.notifications.success.title": "Profile saved", - // TODO New key - Add a translation - "profile.metadata.form.notifications.success.title": "Profile saved", - - // "profile.notifications.warning.no-changes.content": "No changes were made to the Profile.", - // TODO New key - Add a translation - "profile.notifications.warning.no-changes.content": "No changes were made to the Profile.", - - // "profile.notifications.warning.no-changes.title": "No changes", - // TODO New key - Add a translation - "profile.notifications.warning.no-changes.title": "No changes", - - // "profile.security.form.error.matching-passwords": "The passwords do not match.", - // TODO New key - Add a translation - "profile.security.form.error.matching-passwords": "The passwords do not match.", - - // "profile.security.form.error.password-length": "The password should be at least 6 characters long.", - // TODO New key - Add a translation - "profile.security.form.error.password-length": "The password should be at least 6 characters long.", - - // "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.", - // TODO New key - Add a translation - "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.", - - // "profile.security.form.label.password": "Password", - // TODO New key - Add a translation - "profile.security.form.label.password": "Password", - - // "profile.security.form.label.passwordrepeat": "Retype to confirm", - // TODO New key - Add a translation - "profile.security.form.label.passwordrepeat": "Retype to confirm", - - // "profile.security.form.notifications.success.content": "Your changes to the password were saved.", - // TODO New key - Add a translation - "profile.security.form.notifications.success.content": "Your changes to the password were saved.", - - // "profile.security.form.notifications.success.title": "Password saved", - // TODO New key - Add a translation - "profile.security.form.notifications.success.title": "Password saved", - - // "profile.security.form.notifications.error.title": "Error changing passwords", - // TODO New key - Add a translation - "profile.security.form.notifications.error.title": "Error changing passwords", - - // "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", - // TODO New key - Add a translation - "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", - - // "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", - // TODO New key - Add a translation - "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", - - // "profile.title": "Update Profile", - // TODO New key - Add a translation - "profile.title": "Update Profile", - - - + + + // "project.listelement.badge": "Research Project", "project.listelement.badge": "Proyecto de investigación", - + // "project.page.contributor": "Contributors", "project.page.contributor": "Contribuyentes", - + // "project.page.description": "Description", "project.page.description": "Descripción", - + // "project.page.expectedcompletion": "Expected Completion", "project.page.expectedcompletion": "Finalización prevista", - + // "project.page.funder": "Funders", "project.page.funder": "Financiadores", - + // "project.page.id": "ID", "project.page.id": "ID", - + // "project.page.keyword": "Keywords", "project.page.keyword": "Claves", - + // "project.page.status": "Status", "project.page.status": "Estado", - + // "project.page.titleprefix": "Research Project: ", "project.page.titleprefix": "Proyecto de investigación: ", - + // "project.search.results.head": "Project Search Results", // TODO New key - Add a translation "project.search.results.head": "Project Search Results", - - - + + + // "publication.listelement.badge": "Publication", "publication.listelement.badge": "Publicación", - + // "publication.page.description": "Description", "publication.page.description": "Descripción", - + // "publication.page.journal-issn": "Journal ISSN", "publication.page.journal-issn": "Revista ISSN", - + // "publication.page.journal-title": "Journal Title", "publication.page.journal-title": "Título de Revista", - + // "publication.page.publisher": "Publisher", "publication.page.publisher": "Editor", - + // "publication.page.titleprefix": "Publication: ", "publication.page.titleprefix": "Publicación: ", - + // "publication.page.volume-title": "Volume Title", "publication.page.volume-title": "Título del Volumen", - + // "publication.search.results.head": "Publication Search Results", "publication.search.results.head": "Resultados de la búsqueda de publicaciones", - + // "publication.search.title": "DSpace Angular :: Publication Search", "publication.search.title": "DSpace Angular :: Búsqueda de publicación", - - - + + + // "relationships.isAuthorOf": "Authors", "relationships.isAuthorOf": "Autores", - + // "relationships.isIssueOf": "Journal Issues", "relationships.isIssueOf": "Números de Revista", - + // "relationships.isJournalIssueOf": "Journal Issue", "relationships.isJournalIssueOf": "Número de Revista", - + // "relationships.isJournalOf": "Journals", "relationships.isJournalOf": "Revistas", - + // "relationships.isOrgUnitOf": "Organizational Units", "relationships.isOrgUnitOf": "Unidades Organizacionales", - + // "relationships.isPersonOf": "Authors", "relationships.isPersonOf": "Autores", - + // "relationships.isProjectOf": "Research Projects", "relationships.isProjectOf": "Proyectos de investigación", - + // "relationships.isPublicationOf": "Publications", "relationships.isPublicationOf": "Publicaciones", - + // "relationships.isPublicationOfJournalIssue": "Articles", "relationships.isPublicationOfJournalIssue": "Artículos", - + // "relationships.isSingleJournalOf": "Journal", "relationships.isSingleJournalOf": "Revista", - + // "relationships.isSingleVolumeOf": "Journal Volume", "relationships.isSingleVolumeOf": "Volumen de Revista", - + // "relationships.isVolumeOf": "Journal Volumes", "relationships.isVolumeOf": "Volúmenes de Revista", - + // "relationships.isContributorOf": "Contributors", // TODO New key - Add a translation "relationships.isContributorOf": "Contributors", - - - - // "resource-policies.add.button": "Add", - // TODO New key - Add a translation - "resource-policies.add.button": "Add", - - // "resource-policies.add.for.": "Add a new policy", - // TODO New key - Add a translation - "resource-policies.add.for.": "Add a new policy", - - // "resource-policies.add.for.bitstream": "Add a new Bitstream policy", - // TODO New key - Add a translation - "resource-policies.add.for.bitstream": "Add a new Bitstream policy", - - // "resource-policies.add.for.bundle": "Add a new Bundle policy", - // TODO New key - Add a translation - "resource-policies.add.for.bundle": "Add a new Bundle policy", - - // "resource-policies.add.for.item": "Add a new Item policy", - // TODO New key - Add a translation - "resource-policies.add.for.item": "Add a new Item policy", - - // "resource-policies.create.page.heading": "Create new resource policy for ", - // TODO New key - Add a translation - "resource-policies.create.page.heading": "Create new resource policy for ", - - // "resource-policies.create.page.failure.content": "An error occurred while creating the resource policy.", - // TODO New key - Add a translation - "resource-policies.create.page.failure.content": "An error occurred while creating the resource policy.", - - // "resource-policies.create.page.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.create.page.success.content": "Operation successful", - - // "resource-policies.create.page.title": "Create new resource policy", - // TODO New key - Add a translation - "resource-policies.create.page.title": "Create new resource policy", - - // "resource-policies.delete.btn": "Delete selected", - // TODO New key - Add a translation - "resource-policies.delete.btn": "Delete selected", - - // "resource-policies.delete.btn.title": "Delete selected resource policies", - // TODO New key - Add a translation - "resource-policies.delete.btn.title": "Delete selected resource policies", - - // "resource-policies.delete.failure.content": "An error occurred while deleting selected resource policies.", - // TODO New key - Add a translation - "resource-policies.delete.failure.content": "An error occurred while deleting selected resource policies.", - - // "resource-policies.delete.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.delete.success.content": "Operation successful", - - // "resource-policies.edit.page.heading": "Edit resource policy ", - // TODO New key - Add a translation - "resource-policies.edit.page.heading": "Edit resource policy ", - - // "resource-policies.edit.page.failure.content": "An error occurred while editing the resource policy.", - // TODO New key - Add a translation - "resource-policies.edit.page.failure.content": "An error occurred while editing the resource policy.", - - // "resource-policies.edit.page.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.edit.page.success.content": "Operation successful", - - // "resource-policies.edit.page.title": "Edit resource policy", - // TODO New key - Add a translation - "resource-policies.edit.page.title": "Edit resource policy", - - // "resource-policies.form.action-type.label": "Select the action type", - // TODO New key - Add a translation - "resource-policies.form.action-type.label": "Select the action type", - - // "resource-policies.form.action-type.required": "You must select the resource policy action.", - // TODO New key - Add a translation - "resource-policies.form.action-type.required": "You must select the resource policy action.", - - // "resource-policies.form.eperson-group-list.label": "The eperson or group that will be grant of the permission", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.label": "The eperson or group that will be grant of the permission", - - // "resource-policies.form.eperson-group-list.select.btn": "Select", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.select.btn": "Select", - - // "resource-policies.form.eperson-group-list.tab.eperson": "Search for a ePerson", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.tab.eperson": "Search for a ePerson", - - // "resource-policies.form.eperson-group-list.tab.group": "Search for a group", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.tab.group": "Search for a group", - - // "resource-policies.form.eperson-group-list.table.headers.action": "Action", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.action": "Action", - - // "resource-policies.form.eperson-group-list.table.headers.id": "ID", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.id": "ID", - - // "resource-policies.form.eperson-group-list.table.headers.name": "Name", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.name": "Name", - - // "resource-policies.form.date.end.label": "End Date", - // TODO New key - Add a translation - "resource-policies.form.date.end.label": "End Date", - - // "resource-policies.form.date.start.label": "Start Date", - // TODO New key - Add a translation - "resource-policies.form.date.start.label": "Start Date", - - // "resource-policies.form.description.label": "Description", - // TODO New key - Add a translation - "resource-policies.form.description.label": "Description", - - // "resource-policies.form.name.label": "Name", - // TODO New key - Add a translation - "resource-policies.form.name.label": "Name", - - // "resource-policies.form.policy-type.label": "Select the policy type", - // TODO New key - Add a translation - "resource-policies.form.policy-type.label": "Select the policy type", - - // "resource-policies.form.policy-type.required": "You must select the resource policy type.", - // TODO New key - Add a translation - "resource-policies.form.policy-type.required": "You must select the resource policy type.", - - // "resource-policies.table.headers.action": "Action", - // TODO New key - Add a translation - "resource-policies.table.headers.action": "Action", - - // "resource-policies.table.headers.date.end": "End Date", - // TODO New key - Add a translation - "resource-policies.table.headers.date.end": "End Date", - - // "resource-policies.table.headers.date.start": "Start Date", - // TODO New key - Add a translation - "resource-policies.table.headers.date.start": "Start Date", - - // "resource-policies.table.headers.edit": "Edit", - // TODO New key - Add a translation - "resource-policies.table.headers.edit": "Edit", - - // "resource-policies.table.headers.edit.group": "Edit group", - // TODO New key - Add a translation - "resource-policies.table.headers.edit.group": "Edit group", - - // "resource-policies.table.headers.edit.policy": "Edit policy", - // TODO New key - Add a translation - "resource-policies.table.headers.edit.policy": "Edit policy", - - // "resource-policies.table.headers.eperson": "EPerson", - // TODO New key - Add a translation - "resource-policies.table.headers.eperson": "EPerson", - - // "resource-policies.table.headers.group": "Group", - // TODO New key - Add a translation - "resource-policies.table.headers.group": "Group", - - // "resource-policies.table.headers.id": "ID", - // TODO New key - Add a translation - "resource-policies.table.headers.id": "ID", - - // "resource-policies.table.headers.name": "Name", - // TODO New key - Add a translation - "resource-policies.table.headers.name": "Name", - - // "resource-policies.table.headers.policyType": "type", - // TODO New key - Add a translation - "resource-policies.table.headers.policyType": "type", - - // "resource-policies.table.headers.title.for.bitstream": "Policies for Bitstream", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.bitstream": "Policies for Bitstream", - - // "resource-policies.table.headers.title.for.bundle": "Policies for Bundle", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.bundle": "Policies for Bundle", - - // "resource-policies.table.headers.title.for.item": "Policies for Item", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.item": "Policies for Item", - - - + + + // "search.description": "", "search.description": "", - + // "search.switch-configuration.title": "Show", // TODO Source message changed - Revise the translation "search.switch-configuration.title": "Show", - + // "search.title": "DSpace Angular :: Search", // TODO Source message changed - Revise the translation "search.title": "DSpace Angular :: Search", - + // "search.breadcrumbs": "Search", // TODO New key - Add a translation "search.breadcrumbs": "Search", - - + + // "search.filters.applied.f.author": "Author", "search.filters.applied.f.author": "Autor", - + // "search.filters.applied.f.dateIssued.max": "End date", "search.filters.applied.f.dateIssued.max": "Fecha Final", - + // "search.filters.applied.f.dateIssued.min": "Start date", "search.filters.applied.f.dateIssued.min": "Fecha de Inicio", - + // "search.filters.applied.f.dateSubmitted": "Date submitted", "search.filters.applied.f.dateSubmitted": "Fecha de Envío", - + // "search.filters.applied.f.discoverable": "Private", // TODO New key - Add a translation "search.filters.applied.f.discoverable": "Private", - + // "search.filters.applied.f.entityType": "Item Type", "search.filters.applied.f.entityType": "Tipo de Ítem", - + // "search.filters.applied.f.has_content_in_original_bundle": "Has files", "search.filters.applied.f.has_content_in_original_bundle": "Tiene archivos", - + // "search.filters.applied.f.itemtype": "Type", "search.filters.applied.f.itemtype": "Tipo", - + // "search.filters.applied.f.namedresourcetype": "Status", "search.filters.applied.f.namedresourcetype": "Estado", - + // "search.filters.applied.f.subject": "Subject", "search.filters.applied.f.subject": "Materia", - + // "search.filters.applied.f.submitter": "Submitter", "search.filters.applied.f.submitter": "Remitente", - + // "search.filters.applied.f.jobTitle": "Job Title", // TODO New key - Add a translation "search.filters.applied.f.jobTitle": "Job Title", - + // "search.filters.applied.f.birthDate.max": "End birth date", // TODO New key - Add a translation "search.filters.applied.f.birthDate.max": "End birth date", - + // "search.filters.applied.f.birthDate.min": "Start birth date", // TODO New key - Add a translation "search.filters.applied.f.birthDate.min": "Start birth date", - + // "search.filters.applied.f.withdrawn": "Withdrawn", // TODO New key - Add a translation "search.filters.applied.f.withdrawn": "Withdrawn", - - - + + + // "search.filters.filter.author.head": "Author", "search.filters.filter.author.head": "Autor", - + // "search.filters.filter.author.placeholder": "Author name", "search.filters.filter.author.placeholder": "Nombre del autor", - + // "search.filters.filter.birthDate.head": "Birth Date", "search.filters.filter.birthDate.head": "Fecha de Nacimiento", - + // "search.filters.filter.birthDate.placeholder": "Birth Date", "search.filters.filter.birthDate.placeholder": "Fecha de Nacimiento", - + // "search.filters.filter.creativeDatePublished.head": "Date Published", "search.filters.filter.creativeDatePublished.head": "Fecha de Publicación", - + // "search.filters.filter.creativeDatePublished.placeholder": "Date Published", "search.filters.filter.creativeDatePublished.placeholder": "Fecha de Publicación", - + // "search.filters.filter.creativeWorkEditor.head": "Editor", "search.filters.filter.creativeWorkEditor.head": "Editor", - + // "search.filters.filter.creativeWorkEditor.placeholder": "Editor", "search.filters.filter.creativeWorkEditor.placeholder": "Editor", - + // "search.filters.filter.creativeWorkKeywords.head": "Subject", "search.filters.filter.creativeWorkKeywords.head": "Materia", - + // "search.filters.filter.creativeWorkKeywords.placeholder": "Subject", "search.filters.filter.creativeWorkKeywords.placeholder": "Materia", - + // "search.filters.filter.creativeWorkPublisher.head": "Publisher", "search.filters.filter.creativeWorkPublisher.head": "Editor", - + // "search.filters.filter.creativeWorkPublisher.placeholder": "Publisher", "search.filters.filter.creativeWorkPublisher.placeholder": "Editor", - + // "search.filters.filter.dateIssued.head": "Date", "search.filters.filter.dateIssued.head": "Fecha", - + // "search.filters.filter.dateIssued.max.placeholder": "Minimum Date", "search.filters.filter.dateIssued.max.placeholder": "Fecha Mínima", - + // "search.filters.filter.dateIssued.min.placeholder": "Maximum Date", "search.filters.filter.dateIssued.min.placeholder": "Fecha Máxima", - + // "search.filters.filter.dateSubmitted.head": "Date submitted", "search.filters.filter.dateSubmitted.head": "Fecha de Envío", - + // "search.filters.filter.dateSubmitted.placeholder": "Date submitted", "search.filters.filter.dateSubmitted.placeholder": "Fecha de Envío", - + // "search.filters.filter.discoverable.head": "Private", // TODO New key - Add a translation "search.filters.filter.discoverable.head": "Private", - + // "search.filters.filter.withdrawn.head": "Withdrawn", // TODO New key - Add a translation "search.filters.filter.withdrawn.head": "Withdrawn", - + // "search.filters.filter.entityType.head": "Item Type", "search.filters.filter.entityType.head": "Tipo de Ítem", - + // "search.filters.filter.entityType.placeholder": "Item Type", "search.filters.filter.entityType.placeholder": "Tipo de Ítem", - + // "search.filters.filter.has_content_in_original_bundle.head": "Has files", "search.filters.filter.has_content_in_original_bundle.head": "Tiene archivos", - + // "search.filters.filter.itemtype.head": "Type", "search.filters.filter.itemtype.head": "Tipo", - + // "search.filters.filter.itemtype.placeholder": "Type", "search.filters.filter.itemtype.placeholder": "Tipo", - + // "search.filters.filter.jobTitle.head": "Job Title", "search.filters.filter.jobTitle.head": "Título profesional", - + // "search.filters.filter.jobTitle.placeholder": "Job Title", "search.filters.filter.jobTitle.placeholder": "Título profesional", - + // "search.filters.filter.knowsLanguage.head": "Known language", "search.filters.filter.knowsLanguage.head": "Idioma conocido", - + // "search.filters.filter.knowsLanguage.placeholder": "Known language", "search.filters.filter.knowsLanguage.placeholder": "Idioma conocido", - + // "search.filters.filter.namedresourcetype.head": "Status", "search.filters.filter.namedresourcetype.head": "Estado", - + // "search.filters.filter.namedresourcetype.placeholder": "Status", "search.filters.filter.namedresourcetype.placeholder": "Estado", - + // "search.filters.filter.objectpeople.head": "People", "search.filters.filter.objectpeople.head": "Persona", - + // "search.filters.filter.objectpeople.placeholder": "People", "search.filters.filter.objectpeople.placeholder": "Persona", - + // "search.filters.filter.organizationAddressCountry.head": "Country", "search.filters.filter.organizationAddressCountry.head": "País", - + // "search.filters.filter.organizationAddressCountry.placeholder": "Country", "search.filters.filter.organizationAddressCountry.placeholder": "País", - + // "search.filters.filter.organizationAddressLocality.head": "City", "search.filters.filter.organizationAddressLocality.head": "Ciudad", - + // "search.filters.filter.organizationAddressLocality.placeholder": "City", "search.filters.filter.organizationAddressLocality.placeholder": "Ciudad", - + // "search.filters.filter.organizationFoundingDate.head": "Date Founded", "search.filters.filter.organizationFoundingDate.head": "Fecha de fundación", - + // "search.filters.filter.organizationFoundingDate.placeholder": "Date Founded", "search.filters.filter.organizationFoundingDate.placeholder": "Fecha de fundación", - + // "search.filters.filter.scope.head": "Scope", "search.filters.filter.scope.head": "Alcance", - + // "search.filters.filter.scope.placeholder": "Scope filter", "search.filters.filter.scope.placeholder": "Filtro del Alcance", - + // "search.filters.filter.show-less": "Collapse", "search.filters.filter.show-less": "Contraer", - + // "search.filters.filter.show-more": "Show more", "search.filters.filter.show-more": "Mostrar más", - + // "search.filters.filter.subject.head": "Subject", "search.filters.filter.subject.head": "Materia", - + // "search.filters.filter.subject.placeholder": "Subject", "search.filters.filter.subject.placeholder": "Materia", - + // "search.filters.filter.submitter.head": "Submitter", "search.filters.filter.submitter.head": "Remitente", - + // "search.filters.filter.submitter.placeholder": "Submitter", "search.filters.filter.submitter.placeholder": "Remitente", - - - + + + // "search.filters.entityType.JournalIssue": "Journal Issue", // TODO New key - Add a translation "search.filters.entityType.JournalIssue": "Journal Issue", - + // "search.filters.entityType.JournalVolume": "Journal Volume", // TODO New key - Add a translation "search.filters.entityType.JournalVolume": "Journal Volume", - + // "search.filters.entityType.OrgUnit": "Organizational Unit", // TODO New key - Add a translation "search.filters.entityType.OrgUnit": "Organizational Unit", - + // "search.filters.has_content_in_original_bundle.true": "Yes", // TODO New key - Add a translation "search.filters.has_content_in_original_bundle.true": "Yes", - + // "search.filters.has_content_in_original_bundle.false": "No", // TODO New key - Add a translation "search.filters.has_content_in_original_bundle.false": "No", - + // "search.filters.discoverable.true": "No", // TODO New key - Add a translation "search.filters.discoverable.true": "No", - + // "search.filters.discoverable.false": "Yes", // TODO New key - Add a translation "search.filters.discoverable.false": "Yes", - + // "search.filters.withdrawn.true": "Yes", // TODO New key - Add a translation "search.filters.withdrawn.true": "Yes", - + // "search.filters.withdrawn.false": "No", // TODO New key - Add a translation "search.filters.withdrawn.false": "No", - - + + // "search.filters.head": "Filters", "search.filters.head": "Filtros", - + // "search.filters.reset": "Reset filters", "search.filters.reset": "Restablecer filtros", - - - + + + // "search.form.search": "Search", "search.form.search": "Buscar", - + // "search.form.search_dspace": "Search DSpace", "search.form.search_dspace": "Buscar DSpace", - + // "search.form.search_mydspace": "Search MyDSpace", "search.form.search_mydspace": "Buscar MyDSpace", - - - + + + // "search.results.head": "Search Results", "search.results.head": "Resultados de Búsqueda", - + // "search.results.no-results": "Your search returned no results. Having trouble finding what you're looking for? Try putting", // TODO Source message changed - Revise the translation "search.results.no-results": "Your search returned no results. Having trouble finding what you're looking for? Try putting", - + // "search.results.no-results-link": "quotes around it", "search.results.no-results-link": "citas a su alrededor", - + // "search.results.empty": "Your search returned no results.", // TODO New key - Add a translation "search.results.empty": "Your search returned no results.", - - - + + + // "search.sidebar.close": "Back to results", "search.sidebar.close": "Regresar a resultados", - + // "search.sidebar.filters.title": "Filters", "search.sidebar.filters.title": "Filtros", - + // "search.sidebar.open": "Search Tools", "search.sidebar.open": "Herramientas de búsqueda", - + // "search.sidebar.results": "results", "search.sidebar.results": "resultados", - + // "search.sidebar.settings.rpp": "Results per page", "search.sidebar.settings.rpp": "Resultados por página", - + // "search.sidebar.settings.sort-by": "Sort By", "search.sidebar.settings.sort-by": "Ordenar por", - + // "search.sidebar.settings.title": "Settings", "search.sidebar.settings.title": "Configuraciones", - - - + + + // "search.view-switch.show-detail": "Show detail", "search.view-switch.show-detail": "Mostrar detalle", - + // "search.view-switch.show-grid": "Show as grid", "search.view-switch.show-grid": "Mostrar como cuadriculado", - + // "search.view-switch.show-list": "Show as list", "search.view-switch.show-list": "Mostrar como lista", - - - + + + // "sorting.dc.title.ASC": "Title Ascending", "sorting.dc.title.ASC": "Título Ascendente", - + // "sorting.dc.title.DESC": "Title Descending", "sorting.dc.title.DESC": "Título Descendente", - + // "sorting.score.DESC": "Relevance", "sorting.score.DESC": "Relevancia", - - - + + + // "submission.edit.title": "Edit Submission", "submission.edit.title": "Editar envío", - + // "submission.general.cannot_submit": "You have not the privilege to make a new submission.", "submission.general.cannot_submit": "No tiene el privilegio de hacer un nuevo envío.", - + // "submission.general.deposit": "Deposit", "submission.general.deposit": "Depositar", - + // "submission.general.discard.confirm.cancel": "Cancel", "submission.general.discard.confirm.cancel": "Cancelar", - + // "submission.general.discard.confirm.info": "This operation can't be undone. Are you sure?", "submission.general.discard.confirm.info": "Esta operación no se puede deshacer. Está seguro?", - + // "submission.general.discard.confirm.submit": "Yes, I'm sure", "submission.general.discard.confirm.submit": "Si, Estoy seguro", - + // "submission.general.discard.confirm.title": "Discard submission", "submission.general.discard.confirm.title": "Descartar el envío", - + // "submission.general.discard.submit": "Discard", "submission.general.discard.submit": "Descartar", - + // "submission.general.save": "Save", "submission.general.save": "Guardar", - + // "submission.general.save-later": "Save for later", "submission.general.save-later": "Guardar para más adelante", - - - + + + // "submission.sections.describe.relationship-lookup.close": "Close", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.close": "Close", - + // "submission.sections.describe.relationship-lookup.external-source.added": "Successfully added local entry to the selection", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.added": "Successfully added local entry to the selection", - + // "submission.sections.describe.relationship-lookup.external-source.import-button-title.Author": "Import remote author", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.import-button-title.Author": "Import remote author", - + // "submission.sections.describe.relationship-lookup.external-source.import-button-title.Journal": "Import remote journal", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.import-button-title.Journal": "Import remote journal", - + // "submission.sections.describe.relationship-lookup.external-source.import-button-title.Journal Issue": "Import remote journal issue", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.import-button-title.Journal Issue": "Import remote journal issue", - + // "submission.sections.describe.relationship-lookup.external-source.import-button-title.Journal Volume": "Import remote journal volume", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.import-button-title.Journal Volume": "Import remote journal volume", - + // "submission.sections.describe.relationship-lookup.external-source.import-modal.Author.title": "Import Remote Author", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.import-modal.Author.title": "Import Remote Author", - + // "submission.sections.describe.relationship-lookup.external-source.import-modal.Author.added.local-entity": "Successfully added local author to the selection", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.import-modal.Author.added.local-entity": "Successfully added local author to the selection", - + // "submission.sections.describe.relationship-lookup.external-source.import-modal.Author.added.new-entity": "Successfully imported and added external author to the selection", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.import-modal.Author.added.new-entity": "Successfully imported and added external author to the selection", - + // "submission.sections.describe.relationship-lookup.external-source.import-modal.authority": "Authority", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.import-modal.authority": "Authority", - + // "submission.sections.describe.relationship-lookup.external-source.import-modal.authority.new": "Import as a new local authority entry", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.import-modal.authority.new": "Import as a new local authority entry", - + // "submission.sections.describe.relationship-lookup.external-source.import-modal.cancel": "Cancel", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.import-modal.cancel": "Cancel", - + // "submission.sections.describe.relationship-lookup.external-source.import-modal.collection": "Select a collection to import new entries to", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.import-modal.collection": "Select a collection to import new entries to", - + // "submission.sections.describe.relationship-lookup.external-source.import-modal.entities": "Entities", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.import-modal.entities": "Entities", - + // "submission.sections.describe.relationship-lookup.external-source.import-modal.entities.new": "Import as a new local entity", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.import-modal.entities.new": "Import as a new local entity", - + // "submission.sections.describe.relationship-lookup.external-source.import-modal.head.lcname": "Importing from LC Name", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.import-modal.head.lcname": "Importing from LC Name", - + // "submission.sections.describe.relationship-lookup.external-source.import-modal.head.orcidV2": "Importing from ORCID", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.import-modal.head.orcidV2": "Importing from ORCID", - + // "submission.sections.describe.relationship-lookup.external-source.import-modal.head.sherpaJournal": "Importing from Sherpa Journal", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.import-modal.head.sherpaJournal": "Importing from Sherpa Journal", - + // "submission.sections.describe.relationship-lookup.external-source.import-modal.head.sherpaPublisher": "Importing from Sherpa Publisher", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.import-modal.head.sherpaPublisher": "Importing from Sherpa Publisher", - + // "submission.sections.describe.relationship-lookup.external-source.import-modal.import": "Import", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.import-modal.import": "Import", - + // "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal.title": "Import Remote Journal", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal.title": "Import Remote Journal", - + // "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal.added.local-entity": "Successfully added local journal to the selection", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal.added.local-entity": "Successfully added local journal to the selection", - + // "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal.added.new-entity": "Successfully imported and added external journal to the selection", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal.added.new-entity": "Successfully imported and added external journal to the selection", - + // "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Issue.title": "Import Remote Journal Issue", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Issue.title": "Import Remote Journal Issue", - + // "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Issue.added.local-entity": "Successfully added local journal issue to the selection", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Issue.added.local-entity": "Successfully added local journal issue to the selection", - + // "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Issue.added.new-entity": "Successfully imported and added external journal issue to the selection", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Issue.added.new-entity": "Successfully imported and added external journal issue to the selection", - + // "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Volume.title": "Import Remote Journal Volume", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Volume.title": "Import Remote Journal Volume", - + // "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Volume.added.local-entity": "Successfully added local journal volume to the selection", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Volume.added.local-entity": "Successfully added local journal volume to the selection", - + // "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Volume.added.new-entity": "Successfully imported and added external journal volume to the selection", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Volume.added.new-entity": "Successfully imported and added external journal volume to the selection", - + // "submission.sections.describe.relationship-lookup.external-source.import-modal.select": "Select a local match:", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.external-source.import-modal.select": "Select a local match:", - + // "submission.sections.describe.relationship-lookup.search-tab.deselect-all": "Deselect all", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.search-tab.deselect-all": "Deselect all", - + // "submission.sections.describe.relationship-lookup.search-tab.deselect-page": "Deselect page", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.search-tab.deselect-page": "Deselect page", - + // "submission.sections.describe.relationship-lookup.search-tab.loading": "Loading...", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.search-tab.loading": "Loading...", - + // "submission.sections.describe.relationship-lookup.search-tab.placeholder": "Search query", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.search-tab.placeholder": "Search query", - + // "submission.sections.describe.relationship-lookup.search-tab.search": "Go", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.search-tab.search": "Go", - + // "submission.sections.describe.relationship-lookup.search-tab.select-all": "Select all", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.search-tab.select-all": "Select all", - + // "submission.sections.describe.relationship-lookup.search-tab.select-page": "Select page", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.search-tab.select-page": "Select page", - + // "submission.sections.describe.relationship-lookup.selected": "Selected {{ size }} items", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.selected": "Selected {{ size }} items", - + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.Author": "Local Authors ({{ count }})", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.search-tab.tab-title.Author": "Local Authors ({{ count }})", - + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.Journal": "Local Journals ({{ count }})", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.search-tab.tab-title.Journal": "Local Journals ({{ count }})", - + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.Journal Issue": "Local Journal Issues ({{ count }})", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.search-tab.tab-title.Journal Issue": "Local Journal Issues ({{ count }})", - + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.Journal Volume": "Local Journal Volumes ({{ count }})", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.search-tab.tab-title.Journal Volume": "Local Journal Volumes ({{ count }})", - + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.sherpaJournal": "Sherpa Journals ({{ count }})", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.search-tab.tab-title.sherpaJournal": "Sherpa Journals ({{ count }})", - + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.sherpaPublisher": "Sherpa Publishers ({{ count }})", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.search-tab.tab-title.sherpaPublisher": "Sherpa Publishers ({{ count }})", - + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.orcidV2": "ORCID ({{ count }})", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.search-tab.tab-title.orcidV2": "ORCID ({{ count }})", - + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.lcname": "LC Names ({{ count }})", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.search-tab.tab-title.lcname": "LC Names ({{ count }})", - + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.Funding Agency": "Search for Funding Agencies", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.search-tab.tab-title.Funding Agency": "Search for Funding Agencies", - + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.Funding": "Search for Funding", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.search-tab.tab-title.Funding": "Search for Funding", - + // "submission.sections.describe.relationship-lookup.selection-tab.tab-title": "Current Selection ({{ count }})", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.selection-tab.tab-title": "Current Selection ({{ count }})", - + // "submission.sections.describe.relationship-lookup.title.Journal Issue": "Journal Issues", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.title.Journal Issue": "Journal Issues", - + // "submission.sections.describe.relationship-lookup.title.Journal Volume": "Journal Volumes", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.title.Journal Volume": "Journal Volumes", - + // "submission.sections.describe.relationship-lookup.title.Journal": "Journals", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.title.Journal": "Journals", - + // "submission.sections.describe.relationship-lookup.title.Author": "Authors", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.title.Author": "Authors", - + // "submission.sections.describe.relationship-lookup.title.Funding Agency": "Funding Agency", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.title.Funding Agency": "Funding Agency", - + // "submission.sections.describe.relationship-lookup.title.Funding": "Funding", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.title.Funding": "Funding", - + // "submission.sections.describe.relationship-lookup.search-tab.toggle-dropdown": "Toggle dropdown", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.search-tab.toggle-dropdown": "Toggle dropdown", - + // "submission.sections.describe.relationship-lookup.selection-tab.settings": "Settings", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.selection-tab.settings": "Settings", - + // "submission.sections.describe.relationship-lookup.selection-tab.no-selection": "Your selection is currently empty.", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.selection-tab.no-selection": "Your selection is currently empty.", - + // "submission.sections.describe.relationship-lookup.selection-tab.title.Author": "Selected Authors", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.selection-tab.title.Author": "Selected Authors", - + // "submission.sections.describe.relationship-lookup.selection-tab.title.Journal": "Selected Journals", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.selection-tab.title.Journal": "Selected Journals", - + // "submission.sections.describe.relationship-lookup.selection-tab.title.Journal Volume": "Selected Journal Volume", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.selection-tab.title.Journal Volume": "Selected Journal Volume", - + // "submission.sections.describe.relationship-lookup.selection-tab.title.Journal Issue": "Selected Issue", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.selection-tab.title.Journal Issue": "Selected Issue", - + // "submission.sections.describe.relationship-lookup.selection-tab.title.sherpaJournal": "Search Results", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.selection-tab.title.sherpaJournal": "Search Results", - + // "submission.sections.describe.relationship-lookup.selection-tab.title.sherpaPublisher": "Search Results", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.selection-tab.title.sherpaPublisher": "Search Results", - + // "submission.sections.describe.relationship-lookup.selection-tab.title.orcidV2": "Search Results", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.selection-tab.title.orcidV2": "Search Results", - + // "submission.sections.describe.relationship-lookup.selection-tab.title.lcname": "Search Results", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.selection-tab.title.lcname": "Search Results", - + // "submission.sections.describe.relationship-lookup.name-variant.notification.content": "Would you like to save \"{{ value }}\" as a name variant for this person so you and others can reuse it for future submissions? If you don\'t you can still use it for this submission.", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.name-variant.notification.content": "Would you like to save \"{{ value }}\" as a name variant for this person so you and others can reuse it for future submissions? If you don\'t you can still use it for this submission.", - + // "submission.sections.describe.relationship-lookup.name-variant.notification.confirm": "Save a new name variant", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.name-variant.notification.confirm": "Save a new name variant", - + // "submission.sections.describe.relationship-lookup.name-variant.notification.decline": "Use only for this submission", // TODO New key - Add a translation "submission.sections.describe.relationship-lookup.name-variant.notification.decline": "Use only for this submission", - + // "submission.sections.general.add-more": "Add more", "submission.sections.general.add-more": "Agregar más", - + // "submission.sections.general.collection": "Collection", "submission.sections.general.collection": "Colección", - + // "submission.sections.general.deposit_error_notice": "There was an issue when submitting the item, please try again later.", "submission.sections.general.deposit_error_notice": "Hubo un problema al enviar el artículo, inténtelo más tarde.", - + // "submission.sections.general.deposit_success_notice": "Submission deposited successfully.", "submission.sections.general.deposit_success_notice": "Envío depositado exitosamente.", - + // "submission.sections.general.discard_error_notice": "There was an issue when discarding the item, please try again later.", "submission.sections.general.discard_error_notice": "Hubo un problema cuando se descartó el ítem, inténtelo más tarde.", - + // "submission.sections.general.discard_success_notice": "Submission discarded successfully.", "submission.sections.general.discard_success_notice": "Envío descartado exitosamente.", - + // "submission.sections.general.metadata-extracted": "New metadata have been extracted and added to the {{sectionId}} section.", "submission.sections.general.metadata-extracted": "Nueva metadata ha sido extraída y agregada a la sección {{sectionId}}.", - + // "submission.sections.general.metadata-extracted-new-section": "New {{sectionId}} section has been added to submission.", "submission.sections.general.metadata-extracted-new-section": "Nueva sección {{sectionId}} ha sido enviada.", - + // "submission.sections.general.no-collection": "No collection found", "submission.sections.general.no-collection": "Nueva colección enviada", - + // "submission.sections.general.no-sections": "No options available", "submission.sections.general.no-sections": "No hay opciones disponibles", - + // "submission.sections.general.save_error_notice": "There was an issue when saving the item, please try again later.", "submission.sections.general.save_error_notice": "Hubo un problema cuando se guardó el ítem, inténtelo más tarde.", - + // "submission.sections.general.save_success_notice": "Submission saved successfully.", "submission.sections.general.save_success_notice": "Envío guardado exitosamente.", - + // "submission.sections.general.search-collection": "Search for a collection", "submission.sections.general.search-collection": "Search for a collection", - + // "submission.sections.general.sections_not_valid": "There are incomplete sections.", "submission.sections.general.sections_not_valid": "Existen secciones incompletas.", - - - + + + // "submission.sections.submit.progressbar.cclicense": "Creative commons license", "submission.sections.submit.progressbar.cclicense": "Licencia Creative Commons ", - + // "submission.sections.submit.progressbar.describe.recycle": "Recycle", "submission.sections.submit.progressbar.describe.recycle": "Reciclar", - + // "submission.sections.submit.progressbar.describe.stepcustom": "Describe", "submission.sections.submit.progressbar.describe.stepcustom": "Describir", - + // "submission.sections.submit.progressbar.describe.stepone": "Describe", "submission.sections.submit.progressbar.describe.stepone": "Describir", - + // "submission.sections.submit.progressbar.describe.steptwo": "Describe", "submission.sections.submit.progressbar.describe.steptwo": "Describir", - + // "submission.sections.submit.progressbar.detect-duplicate": "Potential duplicates", "submission.sections.submit.progressbar.detect-duplicate": "Posibles duplicados", - + // "submission.sections.submit.progressbar.license": "Deposit license", "submission.sections.submit.progressbar.license": "Licencia de depósito", - + // "submission.sections.submit.progressbar.upload": "Upload files", "submission.sections.submit.progressbar.upload": "Subir archivos", - - - + + + // "submission.sections.upload.delete.confirm.cancel": "Cancel", "submission.sections.upload.delete.confirm.cancel": "Cancelar", - + // "submission.sections.upload.delete.confirm.info": "This operation can't be undone. Are you sure?", "submission.sections.upload.delete.confirm.info": "Esta operación no se puede deshacer. Está seguro?", - + // "submission.sections.upload.delete.confirm.submit": "Yes, I'm sure", "submission.sections.upload.delete.confirm.submit": "Si, Estoy seguro", - + // "submission.sections.upload.delete.confirm.title": "Delete bitstream", "submission.sections.upload.delete.confirm.title": "Eliminar archivo", - + // "submission.sections.upload.delete.submit": "Delete", "submission.sections.upload.delete.submit": "Eliminar", - + // "submission.sections.upload.drop-message": "Drop files to attach them to the item", "submission.sections.upload.drop-message": "Bajar archivos para adjuntarlos al ítem", - + // "submission.sections.upload.form.access-condition-label": "Access condition type", "submission.sections.upload.form.access-condition-label": "Tipo de condición de acceso", - + // "submission.sections.upload.form.date-required": "Date is required.", "submission.sections.upload.form.date-required": "La fecha es requerida.", - - // "submission.sections.upload.form.from-label": "Grant access from", - // TODO Source message changed - Revise the translation + + // "submission.sections.upload.form.from-label": "Access grant from", "submission.sections.upload.form.from-label": "Concesión de acceso desde", - + // "submission.sections.upload.form.from-placeholder": "From", "submission.sections.upload.form.from-placeholder": "Desde", - + // "submission.sections.upload.form.group-label": "Group", "submission.sections.upload.form.group-label": "Grupo", - + // "submission.sections.upload.form.group-required": "Group is required.", "submission.sections.upload.form.group-required": "El Grupo es requerido.", - - // "submission.sections.upload.form.until-label": "Grant access until", - // TODO Source message changed - Revise the translation + + // "submission.sections.upload.form.until-label": "Access grant until", "submission.sections.upload.form.until-label": "Concesión de acceso hasta", - + // "submission.sections.upload.form.until-placeholder": "Until", "submission.sections.upload.form.until-placeholder": "Hasta", - + // "submission.sections.upload.header.policy.default.nolist": "Uploaded files in the {{collectionName}} collection will be accessible according to the following group(s):", "submission.sections.upload.header.policy.default.nolist": "Archivos subidos a la colección {{collectionName}} serán accesibles según el siguiente grupo(s):", - + // "submission.sections.upload.header.policy.default.withlist": "Please note that uploaded files in the {{collectionName}} collection will be accessible, in addition to what is explicitly decided for the single file, with the following group(s):", "submission.sections.upload.header.policy.default.withlist": "Tenga en cuenta que los archivos cargados en la colección {{collectionName}} serán accesibles, además de lo que se decida explísitamente para el único archivo con el siguiente grupo(s):", - + // "submission.sections.upload.info": "Here you will find all the files currently in the item. You can update the file metadata and access conditions or upload additional files just dragging & dropping them everywhere in the page", "submission.sections.upload.info": "Aquí encontrará todos los archivos aque actualmente están en el ítem.. Puede actualizar los metadatos del archivo y las condiciones de acceso o cargar los archivos adicionales simplemente arrastrándolos y soltándolos en cualquier parte de la página", - + // "submission.sections.upload.no-entry": "No", "submission.sections.upload.no-entry": "No", - + // "submission.sections.upload.no-file-uploaded": "No file uploaded yet.", "submission.sections.upload.no-file-uploaded": "Todavía no hay archivos cargados.", - + // "submission.sections.upload.save-metadata": "Save metadata", "submission.sections.upload.save-metadata": "Metadatos guardados", - + // "submission.sections.upload.undo": "Cancel", "submission.sections.upload.undo": "Cancelar", - + // "submission.sections.upload.upload-failed": "Upload failed", "submission.sections.upload.upload-failed": "Falla en la carga", - + // "submission.sections.upload.upload-successful": "Upload successful", "submission.sections.upload.upload-successful": "Carga exitosa", - - - + + + // "submission.submit.title": "Submission", "submission.submit.title": "Envío", - - - + + + // "submission.workflow.generic.delete": "Delete", "submission.workflow.generic.delete": "Eliminar", - + // "submission.workflow.generic.delete-help": "If you would to discard this item, select \"Delete\". You will then be asked to confirm it.", "submission.workflow.generic.delete-help": "Si desea descartar este ítem, seleccion \"Eliminar\". Después se solicitará que confirme.", - + // "submission.workflow.generic.edit": "Edit", "submission.workflow.generic.edit": "Editar", - + // "submission.workflow.generic.edit-help": "Select this option to change the item's metadata.", "submission.workflow.generic.edit-help": "Seleccione la opción para cambiar los metadatos del ítem.", - + // "submission.workflow.generic.view": "View", "submission.workflow.generic.view": "Ver", - + // "submission.workflow.generic.view-help": "Select this option to view the item's metadata.", "submission.workflow.generic.view-help": "Seleccion esta opción para visualizar los metadatos del ítem.", - - - + + + // "submission.workflow.tasks.claimed.approve": "Approve", "submission.workflow.tasks.claimed.approve": "Aprobar", - + // "submission.workflow.tasks.claimed.approve_help": "If you have reviewed the item and it is suitable for inclusion in the collection, select \"Approve\".", "submission.workflow.tasks.claimed.approve_help": "Si ha revisado el ítem y es adecuado para su inclusión en la colección., seleccione \"Aprobar\".", - + // "submission.workflow.tasks.claimed.edit": "Edit", "submission.workflow.tasks.claimed.edit": "Editar", - + // "submission.workflow.tasks.claimed.edit_help": "Select this option to change the item's metadata.", "submission.workflow.tasks.claimed.edit_help": "Seleccione esta opción para cambiar los metadatos del ítem.", - + // "submission.workflow.tasks.claimed.reject.reason.info": "Please enter your reason for rejecting the submission into the box below, indicating whether the submitter may fix a problem and resubmit.", "submission.workflow.tasks.claimed.reject.reason.info": "Favor ingrese abajo su motivo para rechazar el envío, indicando si el remitente puede solucionar un problema y volver a enviar.", - + // "submission.workflow.tasks.claimed.reject.reason.placeholder": "Describe the reason of reject", "submission.workflow.tasks.claimed.reject.reason.placeholder": "Describe el motivo del rechazo", - + // "submission.workflow.tasks.claimed.reject.reason.submit": "Reject item", "submission.workflow.tasks.claimed.reject.reason.submit": "Rechazar el 'item", - + // "submission.workflow.tasks.claimed.reject.reason.title": "Reason", "submission.workflow.tasks.claimed.reject.reason.title": "Razón", - + // "submission.workflow.tasks.claimed.reject.submit": "Reject", "submission.workflow.tasks.claimed.reject.submit": "Rechazar", - + // "submission.workflow.tasks.claimed.reject_help": "If you have reviewed the item and found it is not suitable for inclusion in the collection, select \"Reject\". You will then be asked to enter a message indicating why the item is unsuitable, and whether the submitter should change something and resubmit.", "submission.workflow.tasks.claimed.reject_help": "Si ha revisado el ítem y ha encontrado que no es adecuado para su inclusión en la colección, seleccione \"Rechazar\". Después se le pedirá que ingrese un mensaje que indique por qué el ítem no es adecuado y si el remitente debe cambiar algo y volver a enviarlo.", - + // "submission.workflow.tasks.claimed.return": "Return to pool", "submission.workflow.tasks.claimed.return": "Regresar al pool", - + // "submission.workflow.tasks.claimed.return_help": "Return the task to the pool so that another user may perform the task.", "submission.workflow.tasks.claimed.return_help": "Devolver la tarea al pool para que otro usuario pueda realizar la tarea..", - - - + + + // "submission.workflow.tasks.generic.error": "Error occurred during operation...", "submission.workflow.tasks.generic.error": "Ha ocurrido un error durante la operación...", - + // "submission.workflow.tasks.generic.processing": "Processing...", "submission.workflow.tasks.generic.processing": "Procesando...", - + // "submission.workflow.tasks.generic.submitter": "Submitter", "submission.workflow.tasks.generic.submitter": "Remitente", - + // "submission.workflow.tasks.generic.success": "Operation successful", "submission.workflow.tasks.generic.success": "Operación exitosa", - - - + + + // "submission.workflow.tasks.pool.claim": "Claim", "submission.workflow.tasks.pool.claim": "Reclamar", - + // "submission.workflow.tasks.pool.claim_help": "Assign this task to yourself.", "submission.workflow.tasks.pool.claim_help": "Asígnese esta tarea a usted mismo.", - + // "submission.workflow.tasks.pool.hide-detail": "Hide detail", "submission.workflow.tasks.pool.hide-detail": "Ocultar detalles", - + // "submission.workflow.tasks.pool.show-detail": "Show detail", "submission.workflow.tasks.pool.show-detail": "Mostrar detalles", - - - + + + // "title": "DSpace", "title": "DSpace", - - + + // "administrativeView.search.results.head": "Administrative Search", // TODO New key - Add a translation "administrativeView.search.results.head": "Administrative Search", - + // "menu.section.admin_search": "Admin Search", // TODO New key - Add a translation "menu.section.admin_search": "Admin Search", - - - + + + // "uploader.browse": "browse", "uploader.browse": "navegar", - + // "uploader.drag-message": "Drag & Drop your files here", "uploader.drag-message": "Arrastrar y soltar sus archivos aquí", - + // "uploader.or": ", or", "uploader.or": ", o", - + // "uploader.processing": "Processing", "uploader.processing": "Procesando", - + // "uploader.queue-length": "Queue length", "uploader.queue-length": "Longitud de la cola", - + // "virtual-metadata.delete-item.info": "Select the types for which you want to save the virtual metadata as real metadata", // TODO New key - Add a translation "virtual-metadata.delete-item.info": "Select the types for which you want to save the virtual metadata as real metadata", - + // "virtual-metadata.delete-item.modal-head": "The virtual metadata of this relation", // TODO New key - Add a translation "virtual-metadata.delete-item.modal-head": "The virtual metadata of this relation", - + // "virtual-metadata.delete-relationship.modal-head": "Select the items for which you want to save the virtual metadata as real metadata", // TODO New key - Add a translation "virtual-metadata.delete-relationship.modal-head": "Select the items for which you want to save the virtual metadata as real metadata", - - - - // "workflowAdmin.search.results.head": "Administer Workflow", - // TODO New key - Add a translation - "workflowAdmin.search.results.head": "Administer Workflow", - - - - // "workflow-item.delete.notification.success.title": "Deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.success.title": "Deleted", - - // "workflow-item.delete.notification.success.content": "This workflow item was successfully deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.success.content": "This workflow item was successfully deleted", - - // "workflow-item.delete.notification.error.title": "Something went wrong", - // TODO New key - Add a translation - "workflow-item.delete.notification.error.title": "Something went wrong", - - // "workflow-item.delete.notification.error.content": "The workflow item could not be deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.error.content": "The workflow item could not be deleted", - - // "workflow-item.delete.title": "Delete workflow item", - // TODO New key - Add a translation - "workflow-item.delete.title": "Delete workflow item", - - // "workflow-item.delete.header": "Delete workflow item", - // TODO New key - Add a translation - "workflow-item.delete.header": "Delete workflow item", - - // "workflow-item.delete.button.cancel": "Cancel", - // TODO New key - Add a translation - "workflow-item.delete.button.cancel": "Cancel", - - // "workflow-item.delete.button.confirm": "Delete", - // TODO New key - Add a translation - "workflow-item.delete.button.confirm": "Delete", - - - // "workflow-item.send-back.notification.success.title": "Sent back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.success.title": "Sent back to submitter", - - // "workflow-item.send-back.notification.success.content": "This workflow item was successfully sent back to the submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.success.content": "This workflow item was successfully sent back to the submitter", - - // "workflow-item.send-back.notification.error.title": "Something went wrong", - // TODO New key - Add a translation - "workflow-item.send-back.notification.error.title": "Something went wrong", - - // "workflow-item.send-back.notification.error.content": "The workflow item could not be sent back to the submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.error.content": "The workflow item could not be sent back to the submitter", - - // "workflow-item.send-back.title": "Send workflow item back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.title": "Send workflow item back to submitter", - - // "workflow-item.send-back.header": "Send workflow item back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.header": "Send workflow item back to submitter", - - // "workflow-item.send-back.button.cancel": "Cancel", - // TODO New key - Add a translation - "workflow-item.send-back.button.cancel": "Cancel", - - // "workflow-item.send-back.button.confirm": "Send back", - // TODO New key - Add a translation - "workflow-item.send-back.button.confirm": "Send back", - - -} \ No newline at end of file + + +} diff --git a/src/assets/i18n/fi.json5 b/src/assets/i18n/fi.json5 index 9bf316b7aa..a8556c4684 100644 --- a/src/assets/i18n/fi.json5 +++ b/src/assets/i18n/fi.json5 @@ -256,22 +256,6 @@ - // "admin.access-control.epeople.actions.delete": "Delete EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.delete": "Delete EPerson", - - // "admin.access-control.epeople.actions.impersonate": "Impersonate EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.impersonate": "Impersonate EPerson", - - // "admin.access-control.epeople.actions.reset": "Reset password", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.reset": "Reset password", - - // "admin.access-control.epeople.actions.stop-impersonating": "Stop impersonating EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.stop-impersonating": "Stop impersonating EPerson", - // "admin.access-control.epeople.title": "DSpace Angular :: EPeople", // TODO New key - Add a translation "admin.access-control.epeople.title": "DSpace Angular :: EPeople", @@ -723,30 +707,6 @@ - - // "admin.workflow.breadcrumbs": "Administer Workflow", - // TODO New key - Add a translation - "admin.workflow.breadcrumbs": "Administer Workflow", - - // "admin.workflow.title": "Administer Workflow", - // TODO New key - Add a translation - "admin.workflow.title": "Administer Workflow", - - // "admin.workflow.item.workflow": "Workflow", - // TODO New key - Add a translation - "admin.workflow.item.workflow": "Workflow", - - // "admin.workflow.item.delete": "Delete", - // TODO New key - Add a translation - "admin.workflow.item.delete": "Delete", - - // "admin.workflow.item.send-back": "Send back", - // TODO New key - Add a translation - "admin.workflow.item.send-back": "Send back", - - - - // "auth.errors.invalid-user": "Invalid email address or password.", "auth.errors.invalid-user": "Virheellinen sähköpostiosoite tai salasana.", @@ -1356,104 +1316,6 @@ - // "comcol-role.edit.no-group": "None", - // TODO New key - Add a translation - "comcol-role.edit.no-group": "None", - - // "comcol-role.edit.create": "Create", - // TODO New key - Add a translation - "comcol-role.edit.create": "Create", - - // "comcol-role.edit.restrict": "Restrict", - // TODO New key - Add a translation - "comcol-role.edit.restrict": "Restrict", - - // "comcol-role.edit.delete": "Delete", - // TODO New key - Add a translation - "comcol-role.edit.delete": "Delete", - - - // "comcol-role.edit.community-admin.name": "Administrators", - // TODO New key - Add a translation - "comcol-role.edit.community-admin.name": "Administrators", - - // "comcol-role.edit.collection-admin.name": "Administrators", - // TODO New key - Add a translation - "comcol-role.edit.collection-admin.name": "Administrators", - - - // "comcol-role.edit.community-admin.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - // TODO New key - Add a translation - "comcol-role.edit.community-admin.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - - // "comcol-role.edit.collection-admin.description": "Collection administrators decide who can submit items to the collection, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization for that collection).", - // TODO New key - Add a translation - "comcol-role.edit.collection-admin.description": "Collection administrators decide who can submit items to the collection, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization for that collection).", - - - // "comcol-role.edit.submitters.name": "Submitters", - // TODO New key - Add a translation - "comcol-role.edit.submitters.name": "Submitters", - - // "comcol-role.edit.submitters.description": "The E-People and Groups that have permission to submit new items to this collection.", - // TODO New key - Add a translation - "comcol-role.edit.submitters.description": "The E-People and Groups that have permission to submit new items to this collection.", - - - // "comcol-role.edit.item_read.name": "Default item read access", - // TODO New key - Add a translation - "comcol-role.edit.item_read.name": "Default item read access", - - // "comcol-role.edit.item_read.description": "E-People and Groups that can read new items submitted to this collection. Changes to this role are not retroactive. Existing items in the system will still be viewable by those who had read access at the time of their addition.", - // TODO New key - Add a translation - "comcol-role.edit.item_read.description": "E-People and Groups that can read new items submitted to this collection. Changes to this role are not retroactive. Existing items in the system will still be viewable by those who had read access at the time of their addition.", - - // "comcol-role.edit.item_read.anonymous-group": "Default read for incoming items is currently set to Anonymous.", - // TODO New key - Add a translation - "comcol-role.edit.item_read.anonymous-group": "Default read for incoming items is currently set to Anonymous.", - - - // "comcol-role.edit.bitstream_read.name": "Default bitstream read access", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.name": "Default bitstream read access", - - // "comcol-role.edit.bitstream_read.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - - // "comcol-role.edit.bitstream_read.anonymous-group": "Default read for incoming bitstreams is currently set to Anonymous.", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.anonymous-group": "Default read for incoming bitstreams is currently set to Anonymous.", - - - // "comcol-role.edit.editor.name": "Editors", - // TODO New key - Add a translation - "comcol-role.edit.editor.name": "Editors", - - // "comcol-role.edit.editor.description": "Editors are able to edit the metadata of incoming submissions, and then accept or reject them.", - // TODO New key - Add a translation - "comcol-role.edit.editor.description": "Editors are able to edit the metadata of incoming submissions, and then accept or reject them.", - - - // "comcol-role.edit.finaleditor.name": "Final editors", - // TODO New key - Add a translation - "comcol-role.edit.finaleditor.name": "Final editors", - - // "comcol-role.edit.finaleditor.description": "Final editors are able to edit the metadata of incoming submissions, but will not be able to reject them.", - // TODO New key - Add a translation - "comcol-role.edit.finaleditor.description": "Final editors are able to edit the metadata of incoming submissions, but will not be able to reject them.", - - - // "comcol-role.edit.reviewer.name": "Reviewers", - // TODO New key - Add a translation - "comcol-role.edit.reviewer.name": "Reviewers", - - // "comcol-role.edit.reviewer.description": "Reviewers are able to accept or reject incoming submissions. However, they are not able to edit the submission's metadata.", - // TODO New key - Add a translation - "comcol-role.edit.reviewer.description": "Reviewers are able to accept or reject incoming submissions. However, they are not able to edit the submission's metadata.", - - - // "community.form.abstract": "Short Description", "community.form.abstract": "Lyhyt kuvaus", @@ -1507,10 +1369,6 @@ // "dso-selector.create.item.head": "New item", "dso-selector.create.item.head": "Uusi tietue", - // "dso-selector.create.submission.head": "New submission", - // TODO New key - Add a translation - "dso-selector.create.submission.head": "New submission", - // "dso-selector.edit.collection.head": "Edit collection", "dso-selector.edit.collection.head": "Muokkaa kokoelmaa", @@ -1672,8 +1530,7 @@ // "form.search": "Search", "form.search": "Hae", - // "form.search-help": "Click here to look for an existing correspondence", - // TODO Source message changed - Revise the translation + // "form.search-help": "Click here to looking for an existing correspondence", "form.search-help": "Valitse etsiäksesi olemassa olevaa vastaavuutta", // "form.submit": "Submit", @@ -1695,15 +1552,6 @@ - // "item.edit.authorizations.heading": "With this editor you can view and alter the policies of an item, plus alter policies of individual item components: bundles and bitstreams. Briefly, an item is a container of bundles, and bundles are containers of bitstreams. Containers usually have ADD/REMOVE/READ/WRITE policies, while bitstreams only have READ/WRITE policies.", - // TODO New key - Add a translation - "item.edit.authorizations.heading": "With this editor you can view and alter the policies of an item, plus alter policies of individual item components: bundles and bitstreams. Briefly, an item is a container of bundles, and bundles are containers of bitstreams. Containers usually have ADD/REMOVE/READ/WRITE policies, while bitstreams only have READ/WRITE policies.", - - // "item.edit.authorizations.title": "Edit item's Policies", - // TODO New key - Add a translation - "item.edit.authorizations.title": "Edit item's Policies", - - // "item.bitstreams.upload.bundle": "Bundle", // TODO New key - Add a translation @@ -2832,16 +2680,11 @@ "menu.section.toggle.statistics_task": "Vaihda Tilastointitehtävä-osion tilaa", - // "menu.section.workflow": "Administer Workflow", - // TODO New key - Add a translation - "menu.section.workflow": "Administer Workflow", - // "mydspace.description": "", "mydspace.description": "", - // "mydspace.general.text-here": "here", - // TODO Source message changed - Revise the translation + // "mydspace.general.text-here": "HERE", "mydspace.general.text-here": "TÄSSÄ", // "mydspace.messages.controller-help": "Select this option to send a message to item's submitter.", @@ -2940,14 +2783,6 @@ // "mydspace.upload.upload-failed": "Error creating new workspace. Please verify the content uploaded before retry.", "mydspace.upload.upload-failed": "Virhe uutta työtilaa luotaessa. Tarkista ladattava sisältö ennen kuin yrität uudelleen.", - // "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", - // TODO New key - Add a translation - "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", - - // "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", - // TODO New key - Add a translation - "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", - // "mydspace.upload.upload-multiple-successful": "{{qty}} new workspace items created.", "mydspace.upload.upload-multiple-successful": "{{qty}} uutta työtilaa luotu.", @@ -2987,10 +2822,6 @@ // "nav.statistics.header": "Statistics", "nav.statistics.header": "Tilastot", - // "nav.stop-impersonating": "Stop impersonating EPerson", - // TODO New key - Add a translation - "nav.stop-impersonating": "Stop impersonating EPerson", - // "orgunit.listelement.badge": "Organizational Unit", @@ -3182,120 +3013,6 @@ - // "profile.breadcrumbs": "Update Profile", - // TODO New key - Add a translation - "profile.breadcrumbs": "Update Profile", - - // "profile.card.identify": "Identify", - // TODO New key - Add a translation - "profile.card.identify": "Identify", - - // "profile.card.security": "Security", - // TODO New key - Add a translation - "profile.card.security": "Security", - - // "profile.form.submit": "Update Profile", - // TODO New key - Add a translation - "profile.form.submit": "Update Profile", - - // "profile.groups.head": "Authorization groups you belong to", - // TODO New key - Add a translation - "profile.groups.head": "Authorization groups you belong to", - - // "profile.head": "Update Profile", - // TODO New key - Add a translation - "profile.head": "Update Profile", - - // "profile.metadata.form.error.firstname.required": "First Name is required", - // TODO New key - Add a translation - "profile.metadata.form.error.firstname.required": "First Name is required", - - // "profile.metadata.form.error.lastname.required": "Last Name is required", - // TODO New key - Add a translation - "profile.metadata.form.error.lastname.required": "Last Name is required", - - // "profile.metadata.form.label.email": "Email Address", - // TODO New key - Add a translation - "profile.metadata.form.label.email": "Email Address", - - // "profile.metadata.form.label.firstname": "First Name", - // TODO New key - Add a translation - "profile.metadata.form.label.firstname": "First Name", - - // "profile.metadata.form.label.language": "Language", - // TODO New key - Add a translation - "profile.metadata.form.label.language": "Language", - - // "profile.metadata.form.label.lastname": "Last Name", - // TODO New key - Add a translation - "profile.metadata.form.label.lastname": "Last Name", - - // "profile.metadata.form.label.phone": "Contact Telephone", - // TODO New key - Add a translation - "profile.metadata.form.label.phone": "Contact Telephone", - - // "profile.metadata.form.notifications.success.content": "Your changes to the profile were saved.", - // TODO New key - Add a translation - "profile.metadata.form.notifications.success.content": "Your changes to the profile were saved.", - - // "profile.metadata.form.notifications.success.title": "Profile saved", - // TODO New key - Add a translation - "profile.metadata.form.notifications.success.title": "Profile saved", - - // "profile.notifications.warning.no-changes.content": "No changes were made to the Profile.", - // TODO New key - Add a translation - "profile.notifications.warning.no-changes.content": "No changes were made to the Profile.", - - // "profile.notifications.warning.no-changes.title": "No changes", - // TODO New key - Add a translation - "profile.notifications.warning.no-changes.title": "No changes", - - // "profile.security.form.error.matching-passwords": "The passwords do not match.", - // TODO New key - Add a translation - "profile.security.form.error.matching-passwords": "The passwords do not match.", - - // "profile.security.form.error.password-length": "The password should be at least 6 characters long.", - // TODO New key - Add a translation - "profile.security.form.error.password-length": "The password should be at least 6 characters long.", - - // "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.", - // TODO New key - Add a translation - "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.", - - // "profile.security.form.label.password": "Password", - // TODO New key - Add a translation - "profile.security.form.label.password": "Password", - - // "profile.security.form.label.passwordrepeat": "Retype to confirm", - // TODO New key - Add a translation - "profile.security.form.label.passwordrepeat": "Retype to confirm", - - // "profile.security.form.notifications.success.content": "Your changes to the password were saved.", - // TODO New key - Add a translation - "profile.security.form.notifications.success.content": "Your changes to the password were saved.", - - // "profile.security.form.notifications.success.title": "Password saved", - // TODO New key - Add a translation - "profile.security.form.notifications.success.title": "Password saved", - - // "profile.security.form.notifications.error.title": "Error changing passwords", - // TODO New key - Add a translation - "profile.security.form.notifications.error.title": "Error changing passwords", - - // "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", - // TODO New key - Add a translation - "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", - - // "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", - // TODO New key - Add a translation - "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", - - // "profile.title": "Update Profile", - // TODO New key - Add a translation - "profile.title": "Update Profile", - - - // "project.listelement.badge": "Research Project", "project.listelement.badge": "Tutkimusprojekti", @@ -3400,192 +3117,6 @@ - // "resource-policies.add.button": "Add", - // TODO New key - Add a translation - "resource-policies.add.button": "Add", - - // "resource-policies.add.for.": "Add a new policy", - // TODO New key - Add a translation - "resource-policies.add.for.": "Add a new policy", - - // "resource-policies.add.for.bitstream": "Add a new Bitstream policy", - // TODO New key - Add a translation - "resource-policies.add.for.bitstream": "Add a new Bitstream policy", - - // "resource-policies.add.for.bundle": "Add a new Bundle policy", - // TODO New key - Add a translation - "resource-policies.add.for.bundle": "Add a new Bundle policy", - - // "resource-policies.add.for.item": "Add a new Item policy", - // TODO New key - Add a translation - "resource-policies.add.for.item": "Add a new Item policy", - - // "resource-policies.create.page.heading": "Create new resource policy for ", - // TODO New key - Add a translation - "resource-policies.create.page.heading": "Create new resource policy for ", - - // "resource-policies.create.page.failure.content": "An error occurred while creating the resource policy.", - // TODO New key - Add a translation - "resource-policies.create.page.failure.content": "An error occurred while creating the resource policy.", - - // "resource-policies.create.page.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.create.page.success.content": "Operation successful", - - // "resource-policies.create.page.title": "Create new resource policy", - // TODO New key - Add a translation - "resource-policies.create.page.title": "Create new resource policy", - - // "resource-policies.delete.btn": "Delete selected", - // TODO New key - Add a translation - "resource-policies.delete.btn": "Delete selected", - - // "resource-policies.delete.btn.title": "Delete selected resource policies", - // TODO New key - Add a translation - "resource-policies.delete.btn.title": "Delete selected resource policies", - - // "resource-policies.delete.failure.content": "An error occurred while deleting selected resource policies.", - // TODO New key - Add a translation - "resource-policies.delete.failure.content": "An error occurred while deleting selected resource policies.", - - // "resource-policies.delete.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.delete.success.content": "Operation successful", - - // "resource-policies.edit.page.heading": "Edit resource policy ", - // TODO New key - Add a translation - "resource-policies.edit.page.heading": "Edit resource policy ", - - // "resource-policies.edit.page.failure.content": "An error occurred while editing the resource policy.", - // TODO New key - Add a translation - "resource-policies.edit.page.failure.content": "An error occurred while editing the resource policy.", - - // "resource-policies.edit.page.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.edit.page.success.content": "Operation successful", - - // "resource-policies.edit.page.title": "Edit resource policy", - // TODO New key - Add a translation - "resource-policies.edit.page.title": "Edit resource policy", - - // "resource-policies.form.action-type.label": "Select the action type", - // TODO New key - Add a translation - "resource-policies.form.action-type.label": "Select the action type", - - // "resource-policies.form.action-type.required": "You must select the resource policy action.", - // TODO New key - Add a translation - "resource-policies.form.action-type.required": "You must select the resource policy action.", - - // "resource-policies.form.eperson-group-list.label": "The eperson or group that will be grant of the permission", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.label": "The eperson or group that will be grant of the permission", - - // "resource-policies.form.eperson-group-list.select.btn": "Select", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.select.btn": "Select", - - // "resource-policies.form.eperson-group-list.tab.eperson": "Search for a ePerson", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.tab.eperson": "Search for a ePerson", - - // "resource-policies.form.eperson-group-list.tab.group": "Search for a group", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.tab.group": "Search for a group", - - // "resource-policies.form.eperson-group-list.table.headers.action": "Action", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.action": "Action", - - // "resource-policies.form.eperson-group-list.table.headers.id": "ID", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.id": "ID", - - // "resource-policies.form.eperson-group-list.table.headers.name": "Name", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.name": "Name", - - // "resource-policies.form.date.end.label": "End Date", - // TODO New key - Add a translation - "resource-policies.form.date.end.label": "End Date", - - // "resource-policies.form.date.start.label": "Start Date", - // TODO New key - Add a translation - "resource-policies.form.date.start.label": "Start Date", - - // "resource-policies.form.description.label": "Description", - // TODO New key - Add a translation - "resource-policies.form.description.label": "Description", - - // "resource-policies.form.name.label": "Name", - // TODO New key - Add a translation - "resource-policies.form.name.label": "Name", - - // "resource-policies.form.policy-type.label": "Select the policy type", - // TODO New key - Add a translation - "resource-policies.form.policy-type.label": "Select the policy type", - - // "resource-policies.form.policy-type.required": "You must select the resource policy type.", - // TODO New key - Add a translation - "resource-policies.form.policy-type.required": "You must select the resource policy type.", - - // "resource-policies.table.headers.action": "Action", - // TODO New key - Add a translation - "resource-policies.table.headers.action": "Action", - - // "resource-policies.table.headers.date.end": "End Date", - // TODO New key - Add a translation - "resource-policies.table.headers.date.end": "End Date", - - // "resource-policies.table.headers.date.start": "Start Date", - // TODO New key - Add a translation - "resource-policies.table.headers.date.start": "Start Date", - - // "resource-policies.table.headers.edit": "Edit", - // TODO New key - Add a translation - "resource-policies.table.headers.edit": "Edit", - - // "resource-policies.table.headers.edit.group": "Edit group", - // TODO New key - Add a translation - "resource-policies.table.headers.edit.group": "Edit group", - - // "resource-policies.table.headers.edit.policy": "Edit policy", - // TODO New key - Add a translation - "resource-policies.table.headers.edit.policy": "Edit policy", - - // "resource-policies.table.headers.eperson": "EPerson", - // TODO New key - Add a translation - "resource-policies.table.headers.eperson": "EPerson", - - // "resource-policies.table.headers.group": "Group", - // TODO New key - Add a translation - "resource-policies.table.headers.group": "Group", - - // "resource-policies.table.headers.id": "ID", - // TODO New key - Add a translation - "resource-policies.table.headers.id": "ID", - - // "resource-policies.table.headers.name": "Name", - // TODO New key - Add a translation - "resource-policies.table.headers.name": "Name", - - // "resource-policies.table.headers.policyType": "type", - // TODO New key - Add a translation - "resource-policies.table.headers.policyType": "type", - - // "resource-policies.table.headers.title.for.bitstream": "Policies for Bitstream", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.bitstream": "Policies for Bitstream", - - // "resource-policies.table.headers.title.for.bundle": "Policies for Bundle", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.bundle": "Policies for Bundle", - - // "resource-policies.table.headers.title.for.item": "Policies for Item", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.item": "Policies for Item", - - - // "search.description": "", "search.description": "", @@ -4312,8 +3843,7 @@ // "submission.sections.upload.form.date-required": "Date is required.", "submission.sections.upload.form.date-required": "Päivämäärä on pakollinen tieto.", - // "submission.sections.upload.form.from-label": "Grant access from", - // TODO Source message changed - Revise the translation + // "submission.sections.upload.form.from-label": "Access grant from", "submission.sections.upload.form.from-label": "Pääsyoikeus alkaa", // "submission.sections.upload.form.from-placeholder": "From", @@ -4325,8 +3855,7 @@ // "submission.sections.upload.form.group-required": "Group is required.", "submission.sections.upload.form.group-required": "Ryhmä on pakollinen tieto.", - // "submission.sections.upload.form.until-label": "Grant access until", - // TODO Source message changed - Revise the translation + // "submission.sections.upload.form.until-label": "Access grant until", "submission.sections.upload.form.until-label": "Pääsyoikeus päättyy", // "submission.sections.upload.form.until-placeholder": "Until", @@ -4497,78 +4026,5 @@ "virtual-metadata.delete-relationship.modal-head": "Select the items for which you want to save the virtual metadata as real metadata", - - // "workflowAdmin.search.results.head": "Administer Workflow", - // TODO New key - Add a translation - "workflowAdmin.search.results.head": "Administer Workflow", - - - - // "workflow-item.delete.notification.success.title": "Deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.success.title": "Deleted", - - // "workflow-item.delete.notification.success.content": "This workflow item was successfully deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.success.content": "This workflow item was successfully deleted", - - // "workflow-item.delete.notification.error.title": "Something went wrong", - // TODO New key - Add a translation - "workflow-item.delete.notification.error.title": "Something went wrong", - - // "workflow-item.delete.notification.error.content": "The workflow item could not be deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.error.content": "The workflow item could not be deleted", - - // "workflow-item.delete.title": "Delete workflow item", - // TODO New key - Add a translation - "workflow-item.delete.title": "Delete workflow item", - - // "workflow-item.delete.header": "Delete workflow item", - // TODO New key - Add a translation - "workflow-item.delete.header": "Delete workflow item", - - // "workflow-item.delete.button.cancel": "Cancel", - // TODO New key - Add a translation - "workflow-item.delete.button.cancel": "Cancel", - - // "workflow-item.delete.button.confirm": "Delete", - // TODO New key - Add a translation - "workflow-item.delete.button.confirm": "Delete", - - - // "workflow-item.send-back.notification.success.title": "Sent back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.success.title": "Sent back to submitter", - - // "workflow-item.send-back.notification.success.content": "This workflow item was successfully sent back to the submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.success.content": "This workflow item was successfully sent back to the submitter", - - // "workflow-item.send-back.notification.error.title": "Something went wrong", - // TODO New key - Add a translation - "workflow-item.send-back.notification.error.title": "Something went wrong", - - // "workflow-item.send-back.notification.error.content": "The workflow item could not be sent back to the submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.error.content": "The workflow item could not be sent back to the submitter", - - // "workflow-item.send-back.title": "Send workflow item back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.title": "Send workflow item back to submitter", - - // "workflow-item.send-back.header": "Send workflow item back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.header": "Send workflow item back to submitter", - - // "workflow-item.send-back.button.cancel": "Cancel", - // TODO New key - Add a translation - "workflow-item.send-back.button.cancel": "Cancel", - - // "workflow-item.send-back.button.confirm": "Send back", - // TODO New key - Add a translation - "workflow-item.send-back.button.confirm": "Send back", - - -} \ No newline at end of file +} diff --git a/src/assets/i18n/fr.json5 b/src/assets/i18n/fr.json5 index 6a8ccf303c..24d0726a68 100644 --- a/src/assets/i18n/fr.json5 +++ b/src/assets/i18n/fr.json5 @@ -253,22 +253,6 @@ - // "admin.access-control.epeople.actions.delete": "Delete EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.delete": "Delete EPerson", - - // "admin.access-control.epeople.actions.impersonate": "Impersonate EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.impersonate": "Impersonate EPerson", - - // "admin.access-control.epeople.actions.reset": "Reset password", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.reset": "Reset password", - - // "admin.access-control.epeople.actions.stop-impersonating": "Stop impersonating EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.stop-impersonating": "Stop impersonating EPerson", - // "admin.access-control.epeople.title": "DSpace Angular :: EPeople", // TODO New key - Add a translation "admin.access-control.epeople.title": "DSpace Angular :: EPeople", @@ -720,30 +704,6 @@ - - // "admin.workflow.breadcrumbs": "Administer Workflow", - // TODO New key - Add a translation - "admin.workflow.breadcrumbs": "Administer Workflow", - - // "admin.workflow.title": "Administer Workflow", - // TODO New key - Add a translation - "admin.workflow.title": "Administer Workflow", - - // "admin.workflow.item.workflow": "Workflow", - // TODO New key - Add a translation - "admin.workflow.item.workflow": "Workflow", - - // "admin.workflow.item.delete": "Delete", - // TODO New key - Add a translation - "admin.workflow.item.delete": "Delete", - - // "admin.workflow.item.send-back": "Send back", - // TODO New key - Add a translation - "admin.workflow.item.send-back": "Send back", - - - - // "auth.errors.invalid-user": "Invalid email address or password.", "auth.errors.invalid-user": "Adresse e-mail ou mot de passe non valide.", @@ -1350,104 +1310,6 @@ - // "comcol-role.edit.no-group": "None", - // TODO New key - Add a translation - "comcol-role.edit.no-group": "None", - - // "comcol-role.edit.create": "Create", - // TODO New key - Add a translation - "comcol-role.edit.create": "Create", - - // "comcol-role.edit.restrict": "Restrict", - // TODO New key - Add a translation - "comcol-role.edit.restrict": "Restrict", - - // "comcol-role.edit.delete": "Delete", - // TODO New key - Add a translation - "comcol-role.edit.delete": "Delete", - - - // "comcol-role.edit.community-admin.name": "Administrators", - // TODO New key - Add a translation - "comcol-role.edit.community-admin.name": "Administrators", - - // "comcol-role.edit.collection-admin.name": "Administrators", - // TODO New key - Add a translation - "comcol-role.edit.collection-admin.name": "Administrators", - - - // "comcol-role.edit.community-admin.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - // TODO New key - Add a translation - "comcol-role.edit.community-admin.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - - // "comcol-role.edit.collection-admin.description": "Collection administrators decide who can submit items to the collection, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization for that collection).", - // TODO New key - Add a translation - "comcol-role.edit.collection-admin.description": "Collection administrators decide who can submit items to the collection, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization for that collection).", - - - // "comcol-role.edit.submitters.name": "Submitters", - // TODO New key - Add a translation - "comcol-role.edit.submitters.name": "Submitters", - - // "comcol-role.edit.submitters.description": "The E-People and Groups that have permission to submit new items to this collection.", - // TODO New key - Add a translation - "comcol-role.edit.submitters.description": "The E-People and Groups that have permission to submit new items to this collection.", - - - // "comcol-role.edit.item_read.name": "Default item read access", - // TODO New key - Add a translation - "comcol-role.edit.item_read.name": "Default item read access", - - // "comcol-role.edit.item_read.description": "E-People and Groups that can read new items submitted to this collection. Changes to this role are not retroactive. Existing items in the system will still be viewable by those who had read access at the time of their addition.", - // TODO New key - Add a translation - "comcol-role.edit.item_read.description": "E-People and Groups that can read new items submitted to this collection. Changes to this role are not retroactive. Existing items in the system will still be viewable by those who had read access at the time of their addition.", - - // "comcol-role.edit.item_read.anonymous-group": "Default read for incoming items is currently set to Anonymous.", - // TODO New key - Add a translation - "comcol-role.edit.item_read.anonymous-group": "Default read for incoming items is currently set to Anonymous.", - - - // "comcol-role.edit.bitstream_read.name": "Default bitstream read access", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.name": "Default bitstream read access", - - // "comcol-role.edit.bitstream_read.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - - // "comcol-role.edit.bitstream_read.anonymous-group": "Default read for incoming bitstreams is currently set to Anonymous.", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.anonymous-group": "Default read for incoming bitstreams is currently set to Anonymous.", - - - // "comcol-role.edit.editor.name": "Editors", - // TODO New key - Add a translation - "comcol-role.edit.editor.name": "Editors", - - // "comcol-role.edit.editor.description": "Editors are able to edit the metadata of incoming submissions, and then accept or reject them.", - // TODO New key - Add a translation - "comcol-role.edit.editor.description": "Editors are able to edit the metadata of incoming submissions, and then accept or reject them.", - - - // "comcol-role.edit.finaleditor.name": "Final editors", - // TODO New key - Add a translation - "comcol-role.edit.finaleditor.name": "Final editors", - - // "comcol-role.edit.finaleditor.description": "Final editors are able to edit the metadata of incoming submissions, but will not be able to reject them.", - // TODO New key - Add a translation - "comcol-role.edit.finaleditor.description": "Final editors are able to edit the metadata of incoming submissions, but will not be able to reject them.", - - - // "comcol-role.edit.reviewer.name": "Reviewers", - // TODO New key - Add a translation - "comcol-role.edit.reviewer.name": "Reviewers", - - // "comcol-role.edit.reviewer.description": "Reviewers are able to accept or reject incoming submissions. However, they are not able to edit the submission's metadata.", - // TODO New key - Add a translation - "comcol-role.edit.reviewer.description": "Reviewers are able to accept or reject incoming submissions. However, they are not able to edit the submission's metadata.", - - - // "community.form.abstract": "Short Description", "community.form.abstract": "Description succincte", @@ -1501,10 +1363,6 @@ // "dso-selector.create.item.head": "New item", "dso-selector.create.item.head": "Nouvel Item", - // "dso-selector.create.submission.head": "New submission", - // TODO New key - Add a translation - "dso-selector.create.submission.head": "New submission", - // "dso-selector.edit.collection.head": "Edit collection", "dso-selector.edit.collection.head": "Éditer Collection", @@ -1667,8 +1525,7 @@ // "form.search": "Search", "form.search": "Rechercher", - // "form.search-help": "Click here to look for an existing correspondence", - // TODO Source message changed - Revise the translation + // "form.search-help": "Click here to looking for an existing correspondence", "form.search-help": "Cliquer ici pour rechercher une correspondance existante", // "form.submit": "Submit", @@ -1690,15 +1547,6 @@ - // "item.edit.authorizations.heading": "With this editor you can view and alter the policies of an item, plus alter policies of individual item components: bundles and bitstreams. Briefly, an item is a container of bundles, and bundles are containers of bitstreams. Containers usually have ADD/REMOVE/READ/WRITE policies, while bitstreams only have READ/WRITE policies.", - // TODO New key - Add a translation - "item.edit.authorizations.heading": "With this editor you can view and alter the policies of an item, plus alter policies of individual item components: bundles and bitstreams. Briefly, an item is a container of bundles, and bundles are containers of bitstreams. Containers usually have ADD/REMOVE/READ/WRITE policies, while bitstreams only have READ/WRITE policies.", - - // "item.edit.authorizations.title": "Edit item's Policies", - // TODO New key - Add a translation - "item.edit.authorizations.title": "Edit item's Policies", - - // "item.bitstreams.upload.bundle": "Bundle", // TODO New key - Add a translation @@ -2836,16 +2684,11 @@ "menu.section.toggle.statistics_task": "Ouvrir/Fermer section Tâche statistiques", - // "menu.section.workflow": "Administer Workflow", - // TODO New key - Add a translation - "menu.section.workflow": "Administer Workflow", - // "mydspace.description": "", "mydspace.description": "", - // "mydspace.general.text-here": "here", - // TODO Source message changed - Revise the translation + // "mydspace.general.text-here": "HERE", "mydspace.general.text-here": "ICI", // "mydspace.messages.controller-help": "Select this option to send a message to item's submitter.", @@ -2944,14 +2787,6 @@ // "mydspace.upload.upload-failed": "Error creating new workspace. Please verify the content uploaded before retry.", "mydspace.upload.upload-failed": "Erreur à la création du Workspace. Veuillez vérifier le contenu téléchargé avant de réessayer.", - // "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", - // TODO New key - Add a translation - "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", - - // "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", - // TODO New key - Add a translation - "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", - // "mydspace.upload.upload-multiple-successful": "{{qty}} new workspace items created.", "mydspace.upload.upload-multiple-successful": "{{qty}} nouveaux Items créés dans le Workspace.", @@ -2991,10 +2826,6 @@ // "nav.statistics.header": "Statistics", "nav.statistics.header": "Statistiques", - // "nav.stop-impersonating": "Stop impersonating EPerson", - // TODO New key - Add a translation - "nav.stop-impersonating": "Stop impersonating EPerson", - // "orgunit.listelement.badge": "Organizational Unit", @@ -3186,120 +3017,6 @@ - // "profile.breadcrumbs": "Update Profile", - // TODO New key - Add a translation - "profile.breadcrumbs": "Update Profile", - - // "profile.card.identify": "Identify", - // TODO New key - Add a translation - "profile.card.identify": "Identify", - - // "profile.card.security": "Security", - // TODO New key - Add a translation - "profile.card.security": "Security", - - // "profile.form.submit": "Update Profile", - // TODO New key - Add a translation - "profile.form.submit": "Update Profile", - - // "profile.groups.head": "Authorization groups you belong to", - // TODO New key - Add a translation - "profile.groups.head": "Authorization groups you belong to", - - // "profile.head": "Update Profile", - // TODO New key - Add a translation - "profile.head": "Update Profile", - - // "profile.metadata.form.error.firstname.required": "First Name is required", - // TODO New key - Add a translation - "profile.metadata.form.error.firstname.required": "First Name is required", - - // "profile.metadata.form.error.lastname.required": "Last Name is required", - // TODO New key - Add a translation - "profile.metadata.form.error.lastname.required": "Last Name is required", - - // "profile.metadata.form.label.email": "Email Address", - // TODO New key - Add a translation - "profile.metadata.form.label.email": "Email Address", - - // "profile.metadata.form.label.firstname": "First Name", - // TODO New key - Add a translation - "profile.metadata.form.label.firstname": "First Name", - - // "profile.metadata.form.label.language": "Language", - // TODO New key - Add a translation - "profile.metadata.form.label.language": "Language", - - // "profile.metadata.form.label.lastname": "Last Name", - // TODO New key - Add a translation - "profile.metadata.form.label.lastname": "Last Name", - - // "profile.metadata.form.label.phone": "Contact Telephone", - // TODO New key - Add a translation - "profile.metadata.form.label.phone": "Contact Telephone", - - // "profile.metadata.form.notifications.success.content": "Your changes to the profile were saved.", - // TODO New key - Add a translation - "profile.metadata.form.notifications.success.content": "Your changes to the profile were saved.", - - // "profile.metadata.form.notifications.success.title": "Profile saved", - // TODO New key - Add a translation - "profile.metadata.form.notifications.success.title": "Profile saved", - - // "profile.notifications.warning.no-changes.content": "No changes were made to the Profile.", - // TODO New key - Add a translation - "profile.notifications.warning.no-changes.content": "No changes were made to the Profile.", - - // "profile.notifications.warning.no-changes.title": "No changes", - // TODO New key - Add a translation - "profile.notifications.warning.no-changes.title": "No changes", - - // "profile.security.form.error.matching-passwords": "The passwords do not match.", - // TODO New key - Add a translation - "profile.security.form.error.matching-passwords": "The passwords do not match.", - - // "profile.security.form.error.password-length": "The password should be at least 6 characters long.", - // TODO New key - Add a translation - "profile.security.form.error.password-length": "The password should be at least 6 characters long.", - - // "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.", - // TODO New key - Add a translation - "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.", - - // "profile.security.form.label.password": "Password", - // TODO New key - Add a translation - "profile.security.form.label.password": "Password", - - // "profile.security.form.label.passwordrepeat": "Retype to confirm", - // TODO New key - Add a translation - "profile.security.form.label.passwordrepeat": "Retype to confirm", - - // "profile.security.form.notifications.success.content": "Your changes to the password were saved.", - // TODO New key - Add a translation - "profile.security.form.notifications.success.content": "Your changes to the password were saved.", - - // "profile.security.form.notifications.success.title": "Password saved", - // TODO New key - Add a translation - "profile.security.form.notifications.success.title": "Password saved", - - // "profile.security.form.notifications.error.title": "Error changing passwords", - // TODO New key - Add a translation - "profile.security.form.notifications.error.title": "Error changing passwords", - - // "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", - // TODO New key - Add a translation - "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", - - // "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", - // TODO New key - Add a translation - "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", - - // "profile.title": "Update Profile", - // TODO New key - Add a translation - "profile.title": "Update Profile", - - - // "project.listelement.badge": "Research Project", "project.listelement.badge": "Projet de recherche", @@ -3404,192 +3121,6 @@ - // "resource-policies.add.button": "Add", - // TODO New key - Add a translation - "resource-policies.add.button": "Add", - - // "resource-policies.add.for.": "Add a new policy", - // TODO New key - Add a translation - "resource-policies.add.for.": "Add a new policy", - - // "resource-policies.add.for.bitstream": "Add a new Bitstream policy", - // TODO New key - Add a translation - "resource-policies.add.for.bitstream": "Add a new Bitstream policy", - - // "resource-policies.add.for.bundle": "Add a new Bundle policy", - // TODO New key - Add a translation - "resource-policies.add.for.bundle": "Add a new Bundle policy", - - // "resource-policies.add.for.item": "Add a new Item policy", - // TODO New key - Add a translation - "resource-policies.add.for.item": "Add a new Item policy", - - // "resource-policies.create.page.heading": "Create new resource policy for ", - // TODO New key - Add a translation - "resource-policies.create.page.heading": "Create new resource policy for ", - - // "resource-policies.create.page.failure.content": "An error occurred while creating the resource policy.", - // TODO New key - Add a translation - "resource-policies.create.page.failure.content": "An error occurred while creating the resource policy.", - - // "resource-policies.create.page.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.create.page.success.content": "Operation successful", - - // "resource-policies.create.page.title": "Create new resource policy", - // TODO New key - Add a translation - "resource-policies.create.page.title": "Create new resource policy", - - // "resource-policies.delete.btn": "Delete selected", - // TODO New key - Add a translation - "resource-policies.delete.btn": "Delete selected", - - // "resource-policies.delete.btn.title": "Delete selected resource policies", - // TODO New key - Add a translation - "resource-policies.delete.btn.title": "Delete selected resource policies", - - // "resource-policies.delete.failure.content": "An error occurred while deleting selected resource policies.", - // TODO New key - Add a translation - "resource-policies.delete.failure.content": "An error occurred while deleting selected resource policies.", - - // "resource-policies.delete.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.delete.success.content": "Operation successful", - - // "resource-policies.edit.page.heading": "Edit resource policy ", - // TODO New key - Add a translation - "resource-policies.edit.page.heading": "Edit resource policy ", - - // "resource-policies.edit.page.failure.content": "An error occurred while editing the resource policy.", - // TODO New key - Add a translation - "resource-policies.edit.page.failure.content": "An error occurred while editing the resource policy.", - - // "resource-policies.edit.page.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.edit.page.success.content": "Operation successful", - - // "resource-policies.edit.page.title": "Edit resource policy", - // TODO New key - Add a translation - "resource-policies.edit.page.title": "Edit resource policy", - - // "resource-policies.form.action-type.label": "Select the action type", - // TODO New key - Add a translation - "resource-policies.form.action-type.label": "Select the action type", - - // "resource-policies.form.action-type.required": "You must select the resource policy action.", - // TODO New key - Add a translation - "resource-policies.form.action-type.required": "You must select the resource policy action.", - - // "resource-policies.form.eperson-group-list.label": "The eperson or group that will be grant of the permission", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.label": "The eperson or group that will be grant of the permission", - - // "resource-policies.form.eperson-group-list.select.btn": "Select", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.select.btn": "Select", - - // "resource-policies.form.eperson-group-list.tab.eperson": "Search for a ePerson", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.tab.eperson": "Search for a ePerson", - - // "resource-policies.form.eperson-group-list.tab.group": "Search for a group", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.tab.group": "Search for a group", - - // "resource-policies.form.eperson-group-list.table.headers.action": "Action", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.action": "Action", - - // "resource-policies.form.eperson-group-list.table.headers.id": "ID", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.id": "ID", - - // "resource-policies.form.eperson-group-list.table.headers.name": "Name", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.name": "Name", - - // "resource-policies.form.date.end.label": "End Date", - // TODO New key - Add a translation - "resource-policies.form.date.end.label": "End Date", - - // "resource-policies.form.date.start.label": "Start Date", - // TODO New key - Add a translation - "resource-policies.form.date.start.label": "Start Date", - - // "resource-policies.form.description.label": "Description", - // TODO New key - Add a translation - "resource-policies.form.description.label": "Description", - - // "resource-policies.form.name.label": "Name", - // TODO New key - Add a translation - "resource-policies.form.name.label": "Name", - - // "resource-policies.form.policy-type.label": "Select the policy type", - // TODO New key - Add a translation - "resource-policies.form.policy-type.label": "Select the policy type", - - // "resource-policies.form.policy-type.required": "You must select the resource policy type.", - // TODO New key - Add a translation - "resource-policies.form.policy-type.required": "You must select the resource policy type.", - - // "resource-policies.table.headers.action": "Action", - // TODO New key - Add a translation - "resource-policies.table.headers.action": "Action", - - // "resource-policies.table.headers.date.end": "End Date", - // TODO New key - Add a translation - "resource-policies.table.headers.date.end": "End Date", - - // "resource-policies.table.headers.date.start": "Start Date", - // TODO New key - Add a translation - "resource-policies.table.headers.date.start": "Start Date", - - // "resource-policies.table.headers.edit": "Edit", - // TODO New key - Add a translation - "resource-policies.table.headers.edit": "Edit", - - // "resource-policies.table.headers.edit.group": "Edit group", - // TODO New key - Add a translation - "resource-policies.table.headers.edit.group": "Edit group", - - // "resource-policies.table.headers.edit.policy": "Edit policy", - // TODO New key - Add a translation - "resource-policies.table.headers.edit.policy": "Edit policy", - - // "resource-policies.table.headers.eperson": "EPerson", - // TODO New key - Add a translation - "resource-policies.table.headers.eperson": "EPerson", - - // "resource-policies.table.headers.group": "Group", - // TODO New key - Add a translation - "resource-policies.table.headers.group": "Group", - - // "resource-policies.table.headers.id": "ID", - // TODO New key - Add a translation - "resource-policies.table.headers.id": "ID", - - // "resource-policies.table.headers.name": "Name", - // TODO New key - Add a translation - "resource-policies.table.headers.name": "Name", - - // "resource-policies.table.headers.policyType": "type", - // TODO New key - Add a translation - "resource-policies.table.headers.policyType": "type", - - // "resource-policies.table.headers.title.for.bitstream": "Policies for Bitstream", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.bitstream": "Policies for Bitstream", - - // "resource-policies.table.headers.title.for.bundle": "Policies for Bundle", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.bundle": "Policies for Bundle", - - // "resource-policies.table.headers.title.for.item": "Policies for Item", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.item": "Policies for Item", - - - // "search.description": "", "search.description": "", @@ -4316,8 +3847,7 @@ // "submission.sections.upload.form.date-required": "Date is required.", "submission.sections.upload.form.date-required": "Date obligatoire.", - // "submission.sections.upload.form.from-label": "Grant access from", - // TODO Source message changed - Revise the translation + // "submission.sections.upload.form.from-label": "Access grant from", "submission.sections.upload.form.from-label": "Accès accordé depuis", // "submission.sections.upload.form.from-placeholder": "From", @@ -4329,8 +3859,7 @@ // "submission.sections.upload.form.group-required": "Group is required.", "submission.sections.upload.form.group-required": "Groupe requis.", - // "submission.sections.upload.form.until-label": "Grant access until", - // TODO Source message changed - Revise the translation + // "submission.sections.upload.form.until-label": "Access grant until", "submission.sections.upload.form.until-label": "Accès accordé jusque", // "submission.sections.upload.form.until-placeholder": "Until", @@ -4499,78 +4028,5 @@ "virtual-metadata.delete-relationship.modal-head": "Select the items for which you want to save the virtual metadata as real metadata", - - // "workflowAdmin.search.results.head": "Administer Workflow", - // TODO New key - Add a translation - "workflowAdmin.search.results.head": "Administer Workflow", - - - - // "workflow-item.delete.notification.success.title": "Deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.success.title": "Deleted", - - // "workflow-item.delete.notification.success.content": "This workflow item was successfully deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.success.content": "This workflow item was successfully deleted", - - // "workflow-item.delete.notification.error.title": "Something went wrong", - // TODO New key - Add a translation - "workflow-item.delete.notification.error.title": "Something went wrong", - - // "workflow-item.delete.notification.error.content": "The workflow item could not be deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.error.content": "The workflow item could not be deleted", - - // "workflow-item.delete.title": "Delete workflow item", - // TODO New key - Add a translation - "workflow-item.delete.title": "Delete workflow item", - - // "workflow-item.delete.header": "Delete workflow item", - // TODO New key - Add a translation - "workflow-item.delete.header": "Delete workflow item", - - // "workflow-item.delete.button.cancel": "Cancel", - // TODO New key - Add a translation - "workflow-item.delete.button.cancel": "Cancel", - - // "workflow-item.delete.button.confirm": "Delete", - // TODO New key - Add a translation - "workflow-item.delete.button.confirm": "Delete", - - - // "workflow-item.send-back.notification.success.title": "Sent back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.success.title": "Sent back to submitter", - - // "workflow-item.send-back.notification.success.content": "This workflow item was successfully sent back to the submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.success.content": "This workflow item was successfully sent back to the submitter", - - // "workflow-item.send-back.notification.error.title": "Something went wrong", - // TODO New key - Add a translation - "workflow-item.send-back.notification.error.title": "Something went wrong", - - // "workflow-item.send-back.notification.error.content": "The workflow item could not be sent back to the submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.error.content": "The workflow item could not be sent back to the submitter", - - // "workflow-item.send-back.title": "Send workflow item back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.title": "Send workflow item back to submitter", - - // "workflow-item.send-back.header": "Send workflow item back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.header": "Send workflow item back to submitter", - - // "workflow-item.send-back.button.cancel": "Cancel", - // TODO New key - Add a translation - "workflow-item.send-back.button.cancel": "Cancel", - - // "workflow-item.send-back.button.confirm": "Send back", - // TODO New key - Add a translation - "workflow-item.send-back.button.confirm": "Send back", - - } \ No newline at end of file diff --git a/src/assets/i18n/ja.json5 b/src/assets/i18n/ja.json5 index 64a775dee8..d7afa97f08 100644 --- a/src/assets/i18n/ja.json5 +++ b/src/assets/i18n/ja.json5 @@ -332,22 +332,6 @@ - // "admin.access-control.epeople.actions.delete": "Delete EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.delete": "Delete EPerson", - - // "admin.access-control.epeople.actions.impersonate": "Impersonate EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.impersonate": "Impersonate EPerson", - - // "admin.access-control.epeople.actions.reset": "Reset password", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.reset": "Reset password", - - // "admin.access-control.epeople.actions.stop-impersonating": "Stop impersonating EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.stop-impersonating": "Stop impersonating EPerson", - // "admin.access-control.epeople.title": "DSpace Angular :: EPeople", // TODO New key - Add a translation "admin.access-control.epeople.title": "DSpace Angular :: EPeople", @@ -799,30 +783,6 @@ - - // "admin.workflow.breadcrumbs": "Administer Workflow", - // TODO New key - Add a translation - "admin.workflow.breadcrumbs": "Administer Workflow", - - // "admin.workflow.title": "Administer Workflow", - // TODO New key - Add a translation - "admin.workflow.title": "Administer Workflow", - - // "admin.workflow.item.workflow": "Workflow", - // TODO New key - Add a translation - "admin.workflow.item.workflow": "Workflow", - - // "admin.workflow.item.delete": "Delete", - // TODO New key - Add a translation - "admin.workflow.item.delete": "Delete", - - // "admin.workflow.item.send-back": "Send back", - // TODO New key - Add a translation - "admin.workflow.item.send-back": "Send back", - - - - // "auth.errors.invalid-user": "Invalid email address or password.", // TODO New key - Add a translation "auth.errors.invalid-user": "Invalid email address or password.", @@ -1515,104 +1475,6 @@ - // "comcol-role.edit.no-group": "None", - // TODO New key - Add a translation - "comcol-role.edit.no-group": "None", - - // "comcol-role.edit.create": "Create", - // TODO New key - Add a translation - "comcol-role.edit.create": "Create", - - // "comcol-role.edit.restrict": "Restrict", - // TODO New key - Add a translation - "comcol-role.edit.restrict": "Restrict", - - // "comcol-role.edit.delete": "Delete", - // TODO New key - Add a translation - "comcol-role.edit.delete": "Delete", - - - // "comcol-role.edit.community-admin.name": "Administrators", - // TODO New key - Add a translation - "comcol-role.edit.community-admin.name": "Administrators", - - // "comcol-role.edit.collection-admin.name": "Administrators", - // TODO New key - Add a translation - "comcol-role.edit.collection-admin.name": "Administrators", - - - // "comcol-role.edit.community-admin.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - // TODO New key - Add a translation - "comcol-role.edit.community-admin.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - - // "comcol-role.edit.collection-admin.description": "Collection administrators decide who can submit items to the collection, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization for that collection).", - // TODO New key - Add a translation - "comcol-role.edit.collection-admin.description": "Collection administrators decide who can submit items to the collection, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization for that collection).", - - - // "comcol-role.edit.submitters.name": "Submitters", - // TODO New key - Add a translation - "comcol-role.edit.submitters.name": "Submitters", - - // "comcol-role.edit.submitters.description": "The E-People and Groups that have permission to submit new items to this collection.", - // TODO New key - Add a translation - "comcol-role.edit.submitters.description": "The E-People and Groups that have permission to submit new items to this collection.", - - - // "comcol-role.edit.item_read.name": "Default item read access", - // TODO New key - Add a translation - "comcol-role.edit.item_read.name": "Default item read access", - - // "comcol-role.edit.item_read.description": "E-People and Groups that can read new items submitted to this collection. Changes to this role are not retroactive. Existing items in the system will still be viewable by those who had read access at the time of their addition.", - // TODO New key - Add a translation - "comcol-role.edit.item_read.description": "E-People and Groups that can read new items submitted to this collection. Changes to this role are not retroactive. Existing items in the system will still be viewable by those who had read access at the time of their addition.", - - // "comcol-role.edit.item_read.anonymous-group": "Default read for incoming items is currently set to Anonymous.", - // TODO New key - Add a translation - "comcol-role.edit.item_read.anonymous-group": "Default read for incoming items is currently set to Anonymous.", - - - // "comcol-role.edit.bitstream_read.name": "Default bitstream read access", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.name": "Default bitstream read access", - - // "comcol-role.edit.bitstream_read.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - - // "comcol-role.edit.bitstream_read.anonymous-group": "Default read for incoming bitstreams is currently set to Anonymous.", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.anonymous-group": "Default read for incoming bitstreams is currently set to Anonymous.", - - - // "comcol-role.edit.editor.name": "Editors", - // TODO New key - Add a translation - "comcol-role.edit.editor.name": "Editors", - - // "comcol-role.edit.editor.description": "Editors are able to edit the metadata of incoming submissions, and then accept or reject them.", - // TODO New key - Add a translation - "comcol-role.edit.editor.description": "Editors are able to edit the metadata of incoming submissions, and then accept or reject them.", - - - // "comcol-role.edit.finaleditor.name": "Final editors", - // TODO New key - Add a translation - "comcol-role.edit.finaleditor.name": "Final editors", - - // "comcol-role.edit.finaleditor.description": "Final editors are able to edit the metadata of incoming submissions, but will not be able to reject them.", - // TODO New key - Add a translation - "comcol-role.edit.finaleditor.description": "Final editors are able to edit the metadata of incoming submissions, but will not be able to reject them.", - - - // "comcol-role.edit.reviewer.name": "Reviewers", - // TODO New key - Add a translation - "comcol-role.edit.reviewer.name": "Reviewers", - - // "comcol-role.edit.reviewer.description": "Reviewers are able to accept or reject incoming submissions. However, they are not able to edit the submission's metadata.", - // TODO New key - Add a translation - "comcol-role.edit.reviewer.description": "Reviewers are able to accept or reject incoming submissions. However, they are not able to edit the submission's metadata.", - - - // "community.form.abstract": "Short Description", // TODO New key - Add a translation "community.form.abstract": "Short Description", @@ -1683,10 +1545,6 @@ // TODO New key - Add a translation "dso-selector.create.item.head": "New item", - // "dso-selector.create.submission.head": "New submission", - // TODO New key - Add a translation - "dso-selector.create.submission.head": "New submission", - // "dso-selector.edit.collection.head": "Edit collection", // TODO New key - Add a translation "dso-selector.edit.collection.head": "Edit collection", @@ -1892,9 +1750,9 @@ // TODO New key - Add a translation "form.search": "Search", - // "form.search-help": "Click here to look for an existing correspondence", + // "form.search-help": "Click here to looking for an existing correspondence", // TODO New key - Add a translation - "form.search-help": "Click here to look for an existing correspondence", + "form.search-help": "Click here to looking for an existing correspondence", // "form.submit": "Submit", // TODO New key - Add a translation @@ -1920,15 +1778,6 @@ - // "item.edit.authorizations.heading": "With this editor you can view and alter the policies of an item, plus alter policies of individual item components: bundles and bitstreams. Briefly, an item is a container of bundles, and bundles are containers of bitstreams. Containers usually have ADD/REMOVE/READ/WRITE policies, while bitstreams only have READ/WRITE policies.", - // TODO New key - Add a translation - "item.edit.authorizations.heading": "With this editor you can view and alter the policies of an item, plus alter policies of individual item components: bundles and bitstreams. Briefly, an item is a container of bundles, and bundles are containers of bitstreams. Containers usually have ADD/REMOVE/READ/WRITE policies, while bitstreams only have READ/WRITE policies.", - - // "item.edit.authorizations.title": "Edit item's Policies", - // TODO New key - Add a translation - "item.edit.authorizations.title": "Edit item's Policies", - - // "item.bitstreams.upload.bundle": "Bundle", // TODO New key - Add a translation @@ -3318,18 +3167,14 @@ "menu.section.toggle.statistics_task": "Toggle Statistics Task section", - // "menu.section.workflow": "Administer Workflow", - // TODO New key - Add a translation - "menu.section.workflow": "Administer Workflow", - // "mydspace.description": "", // TODO New key - Add a translation "mydspace.description": "", - // "mydspace.general.text-here": "here", + // "mydspace.general.text-here": "HERE", // TODO New key - Add a translation - "mydspace.general.text-here": "here", + "mydspace.general.text-here": "HERE", // "mydspace.messages.controller-help": "Select this option to send a message to item's submitter.", // TODO New key - Add a translation @@ -3459,14 +3304,6 @@ // TODO New key - Add a translation "mydspace.upload.upload-failed": "Error creating new workspace. Please verify the content uploaded before retry.", - // "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", - // TODO New key - Add a translation - "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", - - // "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", - // TODO New key - Add a translation - "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", - // "mydspace.upload.upload-multiple-successful": "{{qty}} new workspace items created.", // TODO New key - Add a translation "mydspace.upload.upload-multiple-successful": "{{qty}} new workspace items created.", @@ -3517,10 +3354,6 @@ // TODO New key - Add a translation "nav.statistics.header": "Statistics", - // "nav.stop-impersonating": "Stop impersonating EPerson", - // TODO New key - Add a translation - "nav.stop-impersonating": "Stop impersonating EPerson", - // "orgunit.listelement.badge": "Organizational Unit", @@ -3735,120 +3568,6 @@ - // "profile.breadcrumbs": "Update Profile", - // TODO New key - Add a translation - "profile.breadcrumbs": "Update Profile", - - // "profile.card.identify": "Identify", - // TODO New key - Add a translation - "profile.card.identify": "Identify", - - // "profile.card.security": "Security", - // TODO New key - Add a translation - "profile.card.security": "Security", - - // "profile.form.submit": "Update Profile", - // TODO New key - Add a translation - "profile.form.submit": "Update Profile", - - // "profile.groups.head": "Authorization groups you belong to", - // TODO New key - Add a translation - "profile.groups.head": "Authorization groups you belong to", - - // "profile.head": "Update Profile", - // TODO New key - Add a translation - "profile.head": "Update Profile", - - // "profile.metadata.form.error.firstname.required": "First Name is required", - // TODO New key - Add a translation - "profile.metadata.form.error.firstname.required": "First Name is required", - - // "profile.metadata.form.error.lastname.required": "Last Name is required", - // TODO New key - Add a translation - "profile.metadata.form.error.lastname.required": "Last Name is required", - - // "profile.metadata.form.label.email": "Email Address", - // TODO New key - Add a translation - "profile.metadata.form.label.email": "Email Address", - - // "profile.metadata.form.label.firstname": "First Name", - // TODO New key - Add a translation - "profile.metadata.form.label.firstname": "First Name", - - // "profile.metadata.form.label.language": "Language", - // TODO New key - Add a translation - "profile.metadata.form.label.language": "Language", - - // "profile.metadata.form.label.lastname": "Last Name", - // TODO New key - Add a translation - "profile.metadata.form.label.lastname": "Last Name", - - // "profile.metadata.form.label.phone": "Contact Telephone", - // TODO New key - Add a translation - "profile.metadata.form.label.phone": "Contact Telephone", - - // "profile.metadata.form.notifications.success.content": "Your changes to the profile were saved.", - // TODO New key - Add a translation - "profile.metadata.form.notifications.success.content": "Your changes to the profile were saved.", - - // "profile.metadata.form.notifications.success.title": "Profile saved", - // TODO New key - Add a translation - "profile.metadata.form.notifications.success.title": "Profile saved", - - // "profile.notifications.warning.no-changes.content": "No changes were made to the Profile.", - // TODO New key - Add a translation - "profile.notifications.warning.no-changes.content": "No changes were made to the Profile.", - - // "profile.notifications.warning.no-changes.title": "No changes", - // TODO New key - Add a translation - "profile.notifications.warning.no-changes.title": "No changes", - - // "profile.security.form.error.matching-passwords": "The passwords do not match.", - // TODO New key - Add a translation - "profile.security.form.error.matching-passwords": "The passwords do not match.", - - // "profile.security.form.error.password-length": "The password should be at least 6 characters long.", - // TODO New key - Add a translation - "profile.security.form.error.password-length": "The password should be at least 6 characters long.", - - // "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.", - // TODO New key - Add a translation - "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.", - - // "profile.security.form.label.password": "Password", - // TODO New key - Add a translation - "profile.security.form.label.password": "Password", - - // "profile.security.form.label.passwordrepeat": "Retype to confirm", - // TODO New key - Add a translation - "profile.security.form.label.passwordrepeat": "Retype to confirm", - - // "profile.security.form.notifications.success.content": "Your changes to the password were saved.", - // TODO New key - Add a translation - "profile.security.form.notifications.success.content": "Your changes to the password were saved.", - - // "profile.security.form.notifications.success.title": "Password saved", - // TODO New key - Add a translation - "profile.security.form.notifications.success.title": "Password saved", - - // "profile.security.form.notifications.error.title": "Error changing passwords", - // TODO New key - Add a translation - "profile.security.form.notifications.error.title": "Error changing passwords", - - // "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", - // TODO New key - Add a translation - "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", - - // "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", - // TODO New key - Add a translation - "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", - - // "profile.title": "Update Profile", - // TODO New key - Add a translation - "profile.title": "Update Profile", - - - // "project.listelement.badge": "Research Project", // TODO New key - Add a translation "project.listelement.badge": "Research Project", @@ -3983,192 +3702,6 @@ - // "resource-policies.add.button": "Add", - // TODO New key - Add a translation - "resource-policies.add.button": "Add", - - // "resource-policies.add.for.": "Add a new policy", - // TODO New key - Add a translation - "resource-policies.add.for.": "Add a new policy", - - // "resource-policies.add.for.bitstream": "Add a new Bitstream policy", - // TODO New key - Add a translation - "resource-policies.add.for.bitstream": "Add a new Bitstream policy", - - // "resource-policies.add.for.bundle": "Add a new Bundle policy", - // TODO New key - Add a translation - "resource-policies.add.for.bundle": "Add a new Bundle policy", - - // "resource-policies.add.for.item": "Add a new Item policy", - // TODO New key - Add a translation - "resource-policies.add.for.item": "Add a new Item policy", - - // "resource-policies.create.page.heading": "Create new resource policy for ", - // TODO New key - Add a translation - "resource-policies.create.page.heading": "Create new resource policy for ", - - // "resource-policies.create.page.failure.content": "An error occurred while creating the resource policy.", - // TODO New key - Add a translation - "resource-policies.create.page.failure.content": "An error occurred while creating the resource policy.", - - // "resource-policies.create.page.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.create.page.success.content": "Operation successful", - - // "resource-policies.create.page.title": "Create new resource policy", - // TODO New key - Add a translation - "resource-policies.create.page.title": "Create new resource policy", - - // "resource-policies.delete.btn": "Delete selected", - // TODO New key - Add a translation - "resource-policies.delete.btn": "Delete selected", - - // "resource-policies.delete.btn.title": "Delete selected resource policies", - // TODO New key - Add a translation - "resource-policies.delete.btn.title": "Delete selected resource policies", - - // "resource-policies.delete.failure.content": "An error occurred while deleting selected resource policies.", - // TODO New key - Add a translation - "resource-policies.delete.failure.content": "An error occurred while deleting selected resource policies.", - - // "resource-policies.delete.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.delete.success.content": "Operation successful", - - // "resource-policies.edit.page.heading": "Edit resource policy ", - // TODO New key - Add a translation - "resource-policies.edit.page.heading": "Edit resource policy ", - - // "resource-policies.edit.page.failure.content": "An error occurred while editing the resource policy.", - // TODO New key - Add a translation - "resource-policies.edit.page.failure.content": "An error occurred while editing the resource policy.", - - // "resource-policies.edit.page.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.edit.page.success.content": "Operation successful", - - // "resource-policies.edit.page.title": "Edit resource policy", - // TODO New key - Add a translation - "resource-policies.edit.page.title": "Edit resource policy", - - // "resource-policies.form.action-type.label": "Select the action type", - // TODO New key - Add a translation - "resource-policies.form.action-type.label": "Select the action type", - - // "resource-policies.form.action-type.required": "You must select the resource policy action.", - // TODO New key - Add a translation - "resource-policies.form.action-type.required": "You must select the resource policy action.", - - // "resource-policies.form.eperson-group-list.label": "The eperson or group that will be grant of the permission", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.label": "The eperson or group that will be grant of the permission", - - // "resource-policies.form.eperson-group-list.select.btn": "Select", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.select.btn": "Select", - - // "resource-policies.form.eperson-group-list.tab.eperson": "Search for a ePerson", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.tab.eperson": "Search for a ePerson", - - // "resource-policies.form.eperson-group-list.tab.group": "Search for a group", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.tab.group": "Search for a group", - - // "resource-policies.form.eperson-group-list.table.headers.action": "Action", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.action": "Action", - - // "resource-policies.form.eperson-group-list.table.headers.id": "ID", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.id": "ID", - - // "resource-policies.form.eperson-group-list.table.headers.name": "Name", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.name": "Name", - - // "resource-policies.form.date.end.label": "End Date", - // TODO New key - Add a translation - "resource-policies.form.date.end.label": "End Date", - - // "resource-policies.form.date.start.label": "Start Date", - // TODO New key - Add a translation - "resource-policies.form.date.start.label": "Start Date", - - // "resource-policies.form.description.label": "Description", - // TODO New key - Add a translation - "resource-policies.form.description.label": "Description", - - // "resource-policies.form.name.label": "Name", - // TODO New key - Add a translation - "resource-policies.form.name.label": "Name", - - // "resource-policies.form.policy-type.label": "Select the policy type", - // TODO New key - Add a translation - "resource-policies.form.policy-type.label": "Select the policy type", - - // "resource-policies.form.policy-type.required": "You must select the resource policy type.", - // TODO New key - Add a translation - "resource-policies.form.policy-type.required": "You must select the resource policy type.", - - // "resource-policies.table.headers.action": "Action", - // TODO New key - Add a translation - "resource-policies.table.headers.action": "Action", - - // "resource-policies.table.headers.date.end": "End Date", - // TODO New key - Add a translation - "resource-policies.table.headers.date.end": "End Date", - - // "resource-policies.table.headers.date.start": "Start Date", - // TODO New key - Add a translation - "resource-policies.table.headers.date.start": "Start Date", - - // "resource-policies.table.headers.edit": "Edit", - // TODO New key - Add a translation - "resource-policies.table.headers.edit": "Edit", - - // "resource-policies.table.headers.edit.group": "Edit group", - // TODO New key - Add a translation - "resource-policies.table.headers.edit.group": "Edit group", - - // "resource-policies.table.headers.edit.policy": "Edit policy", - // TODO New key - Add a translation - "resource-policies.table.headers.edit.policy": "Edit policy", - - // "resource-policies.table.headers.eperson": "EPerson", - // TODO New key - Add a translation - "resource-policies.table.headers.eperson": "EPerson", - - // "resource-policies.table.headers.group": "Group", - // TODO New key - Add a translation - "resource-policies.table.headers.group": "Group", - - // "resource-policies.table.headers.id": "ID", - // TODO New key - Add a translation - "resource-policies.table.headers.id": "ID", - - // "resource-policies.table.headers.name": "Name", - // TODO New key - Add a translation - "resource-policies.table.headers.name": "Name", - - // "resource-policies.table.headers.policyType": "type", - // TODO New key - Add a translation - "resource-policies.table.headers.policyType": "type", - - // "resource-policies.table.headers.title.for.bitstream": "Policies for Bitstream", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.bitstream": "Policies for Bitstream", - - // "resource-policies.table.headers.title.for.bundle": "Policies for Bundle", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.bundle": "Policies for Bundle", - - // "resource-policies.table.headers.title.for.item": "Policies for Item", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.item": "Policies for Item", - - - // "search.description": "", // TODO New key - Add a translation "search.description": "", @@ -5013,9 +4546,9 @@ // TODO New key - Add a translation "submission.sections.upload.form.date-required": "Date is required.", - // "submission.sections.upload.form.from-label": "Grant access from", + // "submission.sections.upload.form.from-label": "Access grant from", // TODO New key - Add a translation - "submission.sections.upload.form.from-label": "Grant access from", + "submission.sections.upload.form.from-label": "Access grant from", // "submission.sections.upload.form.from-placeholder": "From", // TODO New key - Add a translation @@ -5029,9 +4562,9 @@ // TODO New key - Add a translation "submission.sections.upload.form.group-required": "Group is required.", - // "submission.sections.upload.form.until-label": "Grant access until", + // "submission.sections.upload.form.until-label": "Access grant until", // TODO New key - Add a translation - "submission.sections.upload.form.until-label": "Grant access until", + "submission.sections.upload.form.until-label": "Access grant until", // "submission.sections.upload.form.until-placeholder": "Until", // TODO New key - Add a translation @@ -5241,78 +4774,5 @@ "virtual-metadata.delete-relationship.modal-head": "Select the items for which you want to save the virtual metadata as real metadata", - - // "workflowAdmin.search.results.head": "Administer Workflow", - // TODO New key - Add a translation - "workflowAdmin.search.results.head": "Administer Workflow", - - - - // "workflow-item.delete.notification.success.title": "Deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.success.title": "Deleted", - - // "workflow-item.delete.notification.success.content": "This workflow item was successfully deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.success.content": "This workflow item was successfully deleted", - - // "workflow-item.delete.notification.error.title": "Something went wrong", - // TODO New key - Add a translation - "workflow-item.delete.notification.error.title": "Something went wrong", - - // "workflow-item.delete.notification.error.content": "The workflow item could not be deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.error.content": "The workflow item could not be deleted", - - // "workflow-item.delete.title": "Delete workflow item", - // TODO New key - Add a translation - "workflow-item.delete.title": "Delete workflow item", - - // "workflow-item.delete.header": "Delete workflow item", - // TODO New key - Add a translation - "workflow-item.delete.header": "Delete workflow item", - - // "workflow-item.delete.button.cancel": "Cancel", - // TODO New key - Add a translation - "workflow-item.delete.button.cancel": "Cancel", - - // "workflow-item.delete.button.confirm": "Delete", - // TODO New key - Add a translation - "workflow-item.delete.button.confirm": "Delete", - - - // "workflow-item.send-back.notification.success.title": "Sent back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.success.title": "Sent back to submitter", - - // "workflow-item.send-back.notification.success.content": "This workflow item was successfully sent back to the submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.success.content": "This workflow item was successfully sent back to the submitter", - - // "workflow-item.send-back.notification.error.title": "Something went wrong", - // TODO New key - Add a translation - "workflow-item.send-back.notification.error.title": "Something went wrong", - - // "workflow-item.send-back.notification.error.content": "The workflow item could not be sent back to the submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.error.content": "The workflow item could not be sent back to the submitter", - - // "workflow-item.send-back.title": "Send workflow item back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.title": "Send workflow item back to submitter", - - // "workflow-item.send-back.header": "Send workflow item back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.header": "Send workflow item back to submitter", - - // "workflow-item.send-back.button.cancel": "Cancel", - // TODO New key - Add a translation - "workflow-item.send-back.button.cancel": "Cancel", - - // "workflow-item.send-back.button.confirm": "Send back", - // TODO New key - Add a translation - "workflow-item.send-back.button.confirm": "Send back", - - } \ No newline at end of file diff --git a/src/assets/i18n/lv.json5 b/src/assets/i18n/lv.json5 index eca704a3e2..4ad07d7ae9 100644 --- a/src/assets/i18n/lv.json5 +++ b/src/assets/i18n/lv.json5 @@ -252,22 +252,6 @@ - // "admin.access-control.epeople.actions.delete": "Delete EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.delete": "Delete EPerson", - - // "admin.access-control.epeople.actions.impersonate": "Impersonate EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.impersonate": "Impersonate EPerson", - - // "admin.access-control.epeople.actions.reset": "Reset password", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.reset": "Reset password", - - // "admin.access-control.epeople.actions.stop-impersonating": "Stop impersonating EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.stop-impersonating": "Stop impersonating EPerson", - // "admin.access-control.epeople.title": "DSpace Angular :: EPeople", "admin.access-control.epeople.title": "DSpace Angular :: EPersonas", @@ -679,30 +663,6 @@ - - // "admin.workflow.breadcrumbs": "Administer Workflow", - // TODO New key - Add a translation - "admin.workflow.breadcrumbs": "Administer Workflow", - - // "admin.workflow.title": "Administer Workflow", - // TODO New key - Add a translation - "admin.workflow.title": "Administer Workflow", - - // "admin.workflow.item.workflow": "Workflow", - // TODO New key - Add a translation - "admin.workflow.item.workflow": "Workflow", - - // "admin.workflow.item.delete": "Delete", - // TODO New key - Add a translation - "admin.workflow.item.delete": "Delete", - - // "admin.workflow.item.send-back": "Send back", - // TODO New key - Add a translation - "admin.workflow.item.send-back": "Send back", - - - - // "auth.errors.invalid-user": "Invalid email address or password.", "auth.errors.invalid-user": "Nepareizs e-pasta adrese vai parole.", @@ -1248,104 +1208,6 @@ - // "comcol-role.edit.no-group": "None", - // TODO New key - Add a translation - "comcol-role.edit.no-group": "None", - - // "comcol-role.edit.create": "Create", - // TODO New key - Add a translation - "comcol-role.edit.create": "Create", - - // "comcol-role.edit.restrict": "Restrict", - // TODO New key - Add a translation - "comcol-role.edit.restrict": "Restrict", - - // "comcol-role.edit.delete": "Delete", - // TODO New key - Add a translation - "comcol-role.edit.delete": "Delete", - - - // "comcol-role.edit.community-admin.name": "Administrators", - // TODO New key - Add a translation - "comcol-role.edit.community-admin.name": "Administrators", - - // "comcol-role.edit.collection-admin.name": "Administrators", - // TODO New key - Add a translation - "comcol-role.edit.collection-admin.name": "Administrators", - - - // "comcol-role.edit.community-admin.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - // TODO New key - Add a translation - "comcol-role.edit.community-admin.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - - // "comcol-role.edit.collection-admin.description": "Collection administrators decide who can submit items to the collection, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization for that collection).", - // TODO New key - Add a translation - "comcol-role.edit.collection-admin.description": "Collection administrators decide who can submit items to the collection, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization for that collection).", - - - // "comcol-role.edit.submitters.name": "Submitters", - // TODO New key - Add a translation - "comcol-role.edit.submitters.name": "Submitters", - - // "comcol-role.edit.submitters.description": "The E-People and Groups that have permission to submit new items to this collection.", - // TODO New key - Add a translation - "comcol-role.edit.submitters.description": "The E-People and Groups that have permission to submit new items to this collection.", - - - // "comcol-role.edit.item_read.name": "Default item read access", - // TODO New key - Add a translation - "comcol-role.edit.item_read.name": "Default item read access", - - // "comcol-role.edit.item_read.description": "E-People and Groups that can read new items submitted to this collection. Changes to this role are not retroactive. Existing items in the system will still be viewable by those who had read access at the time of their addition.", - // TODO New key - Add a translation - "comcol-role.edit.item_read.description": "E-People and Groups that can read new items submitted to this collection. Changes to this role are not retroactive. Existing items in the system will still be viewable by those who had read access at the time of their addition.", - - // "comcol-role.edit.item_read.anonymous-group": "Default read for incoming items is currently set to Anonymous.", - // TODO New key - Add a translation - "comcol-role.edit.item_read.anonymous-group": "Default read for incoming items is currently set to Anonymous.", - - - // "comcol-role.edit.bitstream_read.name": "Default bitstream read access", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.name": "Default bitstream read access", - - // "comcol-role.edit.bitstream_read.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - - // "comcol-role.edit.bitstream_read.anonymous-group": "Default read for incoming bitstreams is currently set to Anonymous.", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.anonymous-group": "Default read for incoming bitstreams is currently set to Anonymous.", - - - // "comcol-role.edit.editor.name": "Editors", - // TODO New key - Add a translation - "comcol-role.edit.editor.name": "Editors", - - // "comcol-role.edit.editor.description": "Editors are able to edit the metadata of incoming submissions, and then accept or reject them.", - // TODO New key - Add a translation - "comcol-role.edit.editor.description": "Editors are able to edit the metadata of incoming submissions, and then accept or reject them.", - - - // "comcol-role.edit.finaleditor.name": "Final editors", - // TODO New key - Add a translation - "comcol-role.edit.finaleditor.name": "Final editors", - - // "comcol-role.edit.finaleditor.description": "Final editors are able to edit the metadata of incoming submissions, but will not be able to reject them.", - // TODO New key - Add a translation - "comcol-role.edit.finaleditor.description": "Final editors are able to edit the metadata of incoming submissions, but will not be able to reject them.", - - - // "comcol-role.edit.reviewer.name": "Reviewers", - // TODO New key - Add a translation - "comcol-role.edit.reviewer.name": "Reviewers", - - // "comcol-role.edit.reviewer.description": "Reviewers are able to accept or reject incoming submissions. However, they are not able to edit the submission's metadata.", - // TODO New key - Add a translation - "comcol-role.edit.reviewer.description": "Reviewers are able to accept or reject incoming submissions. However, they are not able to edit the submission's metadata.", - - - // "community.form.abstract": "Short Description", "community.form.abstract": "Īss apraksts", @@ -1399,10 +1261,6 @@ // "dso-selector.create.item.head": "New item", "dso-selector.create.item.head": "Jauns materiāls", - // "dso-selector.create.submission.head": "New submission", - // TODO New key - Add a translation - "dso-selector.create.submission.head": "New submission", - // "dso-selector.edit.collection.head": "Edit collection", "dso-selector.edit.collection.head": "Rediģēt kolekciju", @@ -1559,8 +1417,7 @@ // "form.search": "Search", "form.search": "Meklēt", - // "form.search-help": "Click here to look for an existing correspondence", - // TODO Source message changed - Revise the translation + // "form.search-help": "Click here to looking for an existing correspondence", "form.search-help": "Noklikšķiniet šeit, lai meklētu esošu korespondenci", // "form.submit": "Submit", @@ -1582,15 +1439,6 @@ - // "item.edit.authorizations.heading": "With this editor you can view and alter the policies of an item, plus alter policies of individual item components: bundles and bitstreams. Briefly, an item is a container of bundles, and bundles are containers of bitstreams. Containers usually have ADD/REMOVE/READ/WRITE policies, while bitstreams only have READ/WRITE policies.", - // TODO New key - Add a translation - "item.edit.authorizations.heading": "With this editor you can view and alter the policies of an item, plus alter policies of individual item components: bundles and bitstreams. Briefly, an item is a container of bundles, and bundles are containers of bitstreams. Containers usually have ADD/REMOVE/READ/WRITE policies, while bitstreams only have READ/WRITE policies.", - - // "item.edit.authorizations.title": "Edit item's Policies", - // TODO New key - Add a translation - "item.edit.authorizations.title": "Edit item's Policies", - - // "item.bitstreams.upload.bundle": "Bundle", // TODO New key - Add a translation @@ -2700,16 +2548,11 @@ "menu.section.toggle.statistics_task": "Pārslēgt Statistikas Uzdevumu sadaļu", - // "menu.section.workflow": "Administer Workflow", - // TODO New key - Add a translation - "menu.section.workflow": "Administer Workflow", - // "mydspace.description": "", "mydspace.description": "", - // "mydspace.general.text-here": "here", - // TODO Source message changed - Revise the translation + // "mydspace.general.text-here": "HERE", "mydspace.general.text-here": "ŠEIT", // "mydspace.messages.controller-help": "Select this option to send a message to item's submitter.", @@ -2808,14 +2651,6 @@ // "mydspace.upload.upload-failed": "Error creating new workspace. Please verify the content uploaded before retry.", "mydspace.upload.upload-failed": "Veidojot jaunu darbvietu, radās kļūda. Lūdzu pārbaudiet augšupielādēto saturu pirms mēģiniet vēlreiz.", - // "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", - // TODO New key - Add a translation - "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", - - // "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", - // TODO New key - Add a translation - "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", - // "mydspace.upload.upload-multiple-successful": "{{qty}} new workspace items created.", "mydspace.upload.upload-multiple-successful": "{{qty}} izveidoti jauni darbvietas materiāli.", @@ -2854,10 +2689,6 @@ // "nav.statistics.header": "Statistics", "nav.statistics.header": "Statistika", - // "nav.stop-impersonating": "Stop impersonating EPerson", - // TODO New key - Add a translation - "nav.stop-impersonating": "Stop impersonating EPerson", - // "orgunit.listelement.badge": "Organizational Unit", @@ -3021,92 +2852,6 @@ - // "profile.breadcrumbs": "Update Profile", - "profile.breadcrumbs": "Atjaunot Profilu", - - // "profile.card.identify": "Identify", - "profile.card.identify": "Identificēt", - - // "profile.card.security": "Security", - "profile.card.security": "Drošība", - - // "profile.form.submit": "Update Profile", - "profile.form.submit": "Atjaunot Profilu", - - // "profile.groups.head": "Authorization groups you belong to", - "profile.groups.head": "Autorizācijas grupas, kurām jūs piederat", - - // "profile.head": "Update Profile", - "profile.head": "Atjaunot Profilu", - - // "profile.metadata.form.error.firstname.required": "First Name is required", - "profile.metadata.form.error.firstname.required": "Vārds ir nepieciešams", - - // "profile.metadata.form.error.lastname.required": "Last Name is required", - "profile.metadata.form.error.lastname.required": "Uzvārds ir nepieciešams", - - // "profile.metadata.form.label.email": "Email Address", - "profile.metadata.form.label.email": "E-pasta adrese", - - // "profile.metadata.form.label.firstname": "First Name", - "profile.metadata.form.label.firstname": "Vārds", - - // "profile.metadata.form.label.language": "Language", - "profile.metadata.form.label.language": "Valoda", - - // "profile.metadata.form.label.lastname": "Last Name", - "profile.metadata.form.label.lastname": "Uzvārds", - - // "profile.metadata.form.label.phone": "Contact Telephone", - "profile.metadata.form.label.phone": "Kontakttālrunis", - - // "profile.metadata.form.notifications.success.content": "Your changes to the profile were saved.", - "profile.metadata.form.notifications.success.content": "Profila izmaiņas tika saglabātas.", - - // "profile.metadata.form.notifications.success.title": "Profile saved", - "profile.metadata.form.notifications.success.title": "Profils saglabāts", - - // "profile.notifications.warning.no-changes.content": "No changes were made to the Profile.", - "profile.notifications.warning.no-changes.content": "Profilā izmaiņas netika veiktas.", - - // "profile.notifications.warning.no-changes.title": "No changes", - "profile.notifications.warning.no-changes.title": "Bez izmaiņām", - - // "profile.security.form.error.matching-passwords": "The passwords do not match.", - "profile.security.form.error.matching-passwords": "Paroles nesakrīt.", - - // "profile.security.form.error.password-length": "The password should be at least 6 characters long.", - "profile.security.form.error.password-length": "Parolei jābūt vismaz 6 rakstzīmju garai.", - - // "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.", - "profile.security.form.info": "Pēc izvēles zemāk esošajā lodziņā varat ievadīt jaunu paroli un apstiprināt to, atkārtoti ierakstot to otrajā lodziņā. Tam jābūt vismaz sešu rakstzīmju garam.", - - // "profile.security.form.label.password": "Password", - "profile.security.form.label.password": "Parole", - - // "profile.security.form.label.passwordrepeat": "Retype to confirm", - "profile.security.form.label.passwordrepeat": "Atkārtojiet, lai apstiprinātu", - - // "profile.security.form.notifications.success.content": "Your changes to the password were saved.", - "profile.security.form.notifications.success.content": "Jūsu paroles izmaiņas tika saglabātas.", - - // "profile.security.form.notifications.success.title": "Password saved", - "profile.security.form.notifications.success.title": "Parole saglabāta", - - // "profile.security.form.notifications.error.title": "Error changing passwords", - "profile.security.form.notifications.error.title": "Kļūda mainot paroles", - - // "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", - "profile.security.form.notifications.error.not-long-enough": "Parolei jābūt vismaz 6 rakstzīmju garai.", - - // "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", - "profile.security.form.notifications.error.not-same": "Norādītās paroles nav vienādas.", - - // "profile.title": "Update Profile", - "profile.title": "Atjaunot profilu", - - - // "project.listelement.badge": "Research Project", "project.listelement.badge": "Izpētes projekts", @@ -3209,192 +2954,6 @@ - // "resource-policies.add.button": "Add", - // TODO New key - Add a translation - "resource-policies.add.button": "Add", - - // "resource-policies.add.for.": "Add a new policy", - // TODO New key - Add a translation - "resource-policies.add.for.": "Add a new policy", - - // "resource-policies.add.for.bitstream": "Add a new Bitstream policy", - // TODO New key - Add a translation - "resource-policies.add.for.bitstream": "Add a new Bitstream policy", - - // "resource-policies.add.for.bundle": "Add a new Bundle policy", - // TODO New key - Add a translation - "resource-policies.add.for.bundle": "Add a new Bundle policy", - - // "resource-policies.add.for.item": "Add a new Item policy", - // TODO New key - Add a translation - "resource-policies.add.for.item": "Add a new Item policy", - - // "resource-policies.create.page.heading": "Create new resource policy for ", - // TODO New key - Add a translation - "resource-policies.create.page.heading": "Create new resource policy for ", - - // "resource-policies.create.page.failure.content": "An error occurred while creating the resource policy.", - // TODO New key - Add a translation - "resource-policies.create.page.failure.content": "An error occurred while creating the resource policy.", - - // "resource-policies.create.page.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.create.page.success.content": "Operation successful", - - // "resource-policies.create.page.title": "Create new resource policy", - // TODO New key - Add a translation - "resource-policies.create.page.title": "Create new resource policy", - - // "resource-policies.delete.btn": "Delete selected", - // TODO New key - Add a translation - "resource-policies.delete.btn": "Delete selected", - - // "resource-policies.delete.btn.title": "Delete selected resource policies", - // TODO New key - Add a translation - "resource-policies.delete.btn.title": "Delete selected resource policies", - - // "resource-policies.delete.failure.content": "An error occurred while deleting selected resource policies.", - // TODO New key - Add a translation - "resource-policies.delete.failure.content": "An error occurred while deleting selected resource policies.", - - // "resource-policies.delete.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.delete.success.content": "Operation successful", - - // "resource-policies.edit.page.heading": "Edit resource policy ", - // TODO New key - Add a translation - "resource-policies.edit.page.heading": "Edit resource policy ", - - // "resource-policies.edit.page.failure.content": "An error occurred while editing the resource policy.", - // TODO New key - Add a translation - "resource-policies.edit.page.failure.content": "An error occurred while editing the resource policy.", - - // "resource-policies.edit.page.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.edit.page.success.content": "Operation successful", - - // "resource-policies.edit.page.title": "Edit resource policy", - // TODO New key - Add a translation - "resource-policies.edit.page.title": "Edit resource policy", - - // "resource-policies.form.action-type.label": "Select the action type", - // TODO New key - Add a translation - "resource-policies.form.action-type.label": "Select the action type", - - // "resource-policies.form.action-type.required": "You must select the resource policy action.", - // TODO New key - Add a translation - "resource-policies.form.action-type.required": "You must select the resource policy action.", - - // "resource-policies.form.eperson-group-list.label": "The eperson or group that will be grant of the permission", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.label": "The eperson or group that will be grant of the permission", - - // "resource-policies.form.eperson-group-list.select.btn": "Select", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.select.btn": "Select", - - // "resource-policies.form.eperson-group-list.tab.eperson": "Search for a ePerson", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.tab.eperson": "Search for a ePerson", - - // "resource-policies.form.eperson-group-list.tab.group": "Search for a group", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.tab.group": "Search for a group", - - // "resource-policies.form.eperson-group-list.table.headers.action": "Action", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.action": "Action", - - // "resource-policies.form.eperson-group-list.table.headers.id": "ID", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.id": "ID", - - // "resource-policies.form.eperson-group-list.table.headers.name": "Name", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.name": "Name", - - // "resource-policies.form.date.end.label": "End Date", - // TODO New key - Add a translation - "resource-policies.form.date.end.label": "End Date", - - // "resource-policies.form.date.start.label": "Start Date", - // TODO New key - Add a translation - "resource-policies.form.date.start.label": "Start Date", - - // "resource-policies.form.description.label": "Description", - // TODO New key - Add a translation - "resource-policies.form.description.label": "Description", - - // "resource-policies.form.name.label": "Name", - // TODO New key - Add a translation - "resource-policies.form.name.label": "Name", - - // "resource-policies.form.policy-type.label": "Select the policy type", - // TODO New key - Add a translation - "resource-policies.form.policy-type.label": "Select the policy type", - - // "resource-policies.form.policy-type.required": "You must select the resource policy type.", - // TODO New key - Add a translation - "resource-policies.form.policy-type.required": "You must select the resource policy type.", - - // "resource-policies.table.headers.action": "Action", - // TODO New key - Add a translation - "resource-policies.table.headers.action": "Action", - - // "resource-policies.table.headers.date.end": "End Date", - // TODO New key - Add a translation - "resource-policies.table.headers.date.end": "End Date", - - // "resource-policies.table.headers.date.start": "Start Date", - // TODO New key - Add a translation - "resource-policies.table.headers.date.start": "Start Date", - - // "resource-policies.table.headers.edit": "Edit", - // TODO New key - Add a translation - "resource-policies.table.headers.edit": "Edit", - - // "resource-policies.table.headers.edit.group": "Edit group", - // TODO New key - Add a translation - "resource-policies.table.headers.edit.group": "Edit group", - - // "resource-policies.table.headers.edit.policy": "Edit policy", - // TODO New key - Add a translation - "resource-policies.table.headers.edit.policy": "Edit policy", - - // "resource-policies.table.headers.eperson": "EPerson", - // TODO New key - Add a translation - "resource-policies.table.headers.eperson": "EPerson", - - // "resource-policies.table.headers.group": "Group", - // TODO New key - Add a translation - "resource-policies.table.headers.group": "Group", - - // "resource-policies.table.headers.id": "ID", - // TODO New key - Add a translation - "resource-policies.table.headers.id": "ID", - - // "resource-policies.table.headers.name": "Name", - // TODO New key - Add a translation - "resource-policies.table.headers.name": "Name", - - // "resource-policies.table.headers.policyType": "type", - // TODO New key - Add a translation - "resource-policies.table.headers.policyType": "type", - - // "resource-policies.table.headers.title.for.bitstream": "Policies for Bitstream", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.bitstream": "Policies for Bitstream", - - // "resource-policies.table.headers.title.for.bundle": "Policies for Bundle", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.bundle": "Policies for Bundle", - - // "resource-policies.table.headers.title.for.item": "Policies for Item", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.item": "Policies for Item", - - - // "search.description": "", "search.description": "", @@ -4034,8 +3593,7 @@ // "submission.sections.upload.form.date-required": "Date is required.", "submission.sections.upload.form.date-required": "Datums ir nepieciešams.", - // "submission.sections.upload.form.from-label": "Grant access from", - // TODO Source message changed - Revise the translation + // "submission.sections.upload.form.from-label": "Access grant from", "submission.sections.upload.form.from-label": "Iespēja izmantot no", // "submission.sections.upload.form.from-placeholder": "From", @@ -4047,8 +3605,7 @@ // "submission.sections.upload.form.group-required": "Group is required.", "submission.sections.upload.form.group-required": "Nepieciešama grupa.", - // "submission.sections.upload.form.until-label": "Grant access until", - // TODO Source message changed - Revise the translation + // "submission.sections.upload.form.until-label": "Access grant until", "submission.sections.upload.form.until-label": "Piekļuvas atļauja līdz", // "submission.sections.upload.form.until-placeholder": "Until", @@ -4211,78 +3768,5 @@ "virtual-metadata.delete-relationship.modal-head": "Izēlieties materiālus, kam vēlaties saglabāt virtuālos metadatus kā reālus metadatus", - - // "workflowAdmin.search.results.head": "Administer Workflow", - // TODO New key - Add a translation - "workflowAdmin.search.results.head": "Administer Workflow", - - - - // "workflow-item.delete.notification.success.title": "Deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.success.title": "Deleted", - - // "workflow-item.delete.notification.success.content": "This workflow item was successfully deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.success.content": "This workflow item was successfully deleted", - - // "workflow-item.delete.notification.error.title": "Something went wrong", - // TODO New key - Add a translation - "workflow-item.delete.notification.error.title": "Something went wrong", - - // "workflow-item.delete.notification.error.content": "The workflow item could not be deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.error.content": "The workflow item could not be deleted", - - // "workflow-item.delete.title": "Delete workflow item", - // TODO New key - Add a translation - "workflow-item.delete.title": "Delete workflow item", - - // "workflow-item.delete.header": "Delete workflow item", - // TODO New key - Add a translation - "workflow-item.delete.header": "Delete workflow item", - - // "workflow-item.delete.button.cancel": "Cancel", - // TODO New key - Add a translation - "workflow-item.delete.button.cancel": "Cancel", - - // "workflow-item.delete.button.confirm": "Delete", - // TODO New key - Add a translation - "workflow-item.delete.button.confirm": "Delete", - - - // "workflow-item.send-back.notification.success.title": "Sent back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.success.title": "Sent back to submitter", - - // "workflow-item.send-back.notification.success.content": "This workflow item was successfully sent back to the submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.success.content": "This workflow item was successfully sent back to the submitter", - - // "workflow-item.send-back.notification.error.title": "Something went wrong", - // TODO New key - Add a translation - "workflow-item.send-back.notification.error.title": "Something went wrong", - - // "workflow-item.send-back.notification.error.content": "The workflow item could not be sent back to the submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.error.content": "The workflow item could not be sent back to the submitter", - - // "workflow-item.send-back.title": "Send workflow item back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.title": "Send workflow item back to submitter", - - // "workflow-item.send-back.header": "Send workflow item back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.header": "Send workflow item back to submitter", - - // "workflow-item.send-back.button.cancel": "Cancel", - // TODO New key - Add a translation - "workflow-item.send-back.button.cancel": "Cancel", - - // "workflow-item.send-back.button.confirm": "Send back", - // TODO New key - Add a translation - "workflow-item.send-back.button.confirm": "Send back", - - } \ No newline at end of file diff --git a/src/assets/i18n/nl.json5 b/src/assets/i18n/nl.json5 index 6f4a4fc394..4fd9f444e6 100644 --- a/src/assets/i18n/nl.json5 +++ b/src/assets/i18n/nl.json5 @@ -252,22 +252,6 @@ - // "admin.access-control.epeople.actions.delete": "Delete EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.delete": "Delete EPerson", - - // "admin.access-control.epeople.actions.impersonate": "Impersonate EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.impersonate": "Impersonate EPerson", - - // "admin.access-control.epeople.actions.reset": "Reset password", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.reset": "Reset password", - - // "admin.access-control.epeople.actions.stop-impersonating": "Stop impersonating EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.stop-impersonating": "Stop impersonating EPerson", - // "admin.access-control.epeople.title": "DSpace Angular :: EPeople", // TODO New key - Add a translation "admin.access-control.epeople.title": "DSpace Angular :: EPeople", @@ -719,30 +703,6 @@ - - // "admin.workflow.breadcrumbs": "Administer Workflow", - // TODO New key - Add a translation - "admin.workflow.breadcrumbs": "Administer Workflow", - - // "admin.workflow.title": "Administer Workflow", - // TODO New key - Add a translation - "admin.workflow.title": "Administer Workflow", - - // "admin.workflow.item.workflow": "Workflow", - // TODO New key - Add a translation - "admin.workflow.item.workflow": "Workflow", - - // "admin.workflow.item.delete": "Delete", - // TODO New key - Add a translation - "admin.workflow.item.delete": "Delete", - - // "admin.workflow.item.send-back": "Send back", - // TODO New key - Add a translation - "admin.workflow.item.send-back": "Send back", - - - - // "auth.errors.invalid-user": "Invalid email address or password.", "auth.errors.invalid-user": "Ongeldig e-mailadres of wachtwoord.", @@ -1349,104 +1309,6 @@ - // "comcol-role.edit.no-group": "None", - // TODO New key - Add a translation - "comcol-role.edit.no-group": "None", - - // "comcol-role.edit.create": "Create", - // TODO New key - Add a translation - "comcol-role.edit.create": "Create", - - // "comcol-role.edit.restrict": "Restrict", - // TODO New key - Add a translation - "comcol-role.edit.restrict": "Restrict", - - // "comcol-role.edit.delete": "Delete", - // TODO New key - Add a translation - "comcol-role.edit.delete": "Delete", - - - // "comcol-role.edit.community-admin.name": "Administrators", - // TODO New key - Add a translation - "comcol-role.edit.community-admin.name": "Administrators", - - // "comcol-role.edit.collection-admin.name": "Administrators", - // TODO New key - Add a translation - "comcol-role.edit.collection-admin.name": "Administrators", - - - // "comcol-role.edit.community-admin.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - // TODO New key - Add a translation - "comcol-role.edit.community-admin.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - - // "comcol-role.edit.collection-admin.description": "Collection administrators decide who can submit items to the collection, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization for that collection).", - // TODO New key - Add a translation - "comcol-role.edit.collection-admin.description": "Collection administrators decide who can submit items to the collection, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization for that collection).", - - - // "comcol-role.edit.submitters.name": "Submitters", - // TODO New key - Add a translation - "comcol-role.edit.submitters.name": "Submitters", - - // "comcol-role.edit.submitters.description": "The E-People and Groups that have permission to submit new items to this collection.", - // TODO New key - Add a translation - "comcol-role.edit.submitters.description": "The E-People and Groups that have permission to submit new items to this collection.", - - - // "comcol-role.edit.item_read.name": "Default item read access", - // TODO New key - Add a translation - "comcol-role.edit.item_read.name": "Default item read access", - - // "comcol-role.edit.item_read.description": "E-People and Groups that can read new items submitted to this collection. Changes to this role are not retroactive. Existing items in the system will still be viewable by those who had read access at the time of their addition.", - // TODO New key - Add a translation - "comcol-role.edit.item_read.description": "E-People and Groups that can read new items submitted to this collection. Changes to this role are not retroactive. Existing items in the system will still be viewable by those who had read access at the time of their addition.", - - // "comcol-role.edit.item_read.anonymous-group": "Default read for incoming items is currently set to Anonymous.", - // TODO New key - Add a translation - "comcol-role.edit.item_read.anonymous-group": "Default read for incoming items is currently set to Anonymous.", - - - // "comcol-role.edit.bitstream_read.name": "Default bitstream read access", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.name": "Default bitstream read access", - - // "comcol-role.edit.bitstream_read.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - - // "comcol-role.edit.bitstream_read.anonymous-group": "Default read for incoming bitstreams is currently set to Anonymous.", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.anonymous-group": "Default read for incoming bitstreams is currently set to Anonymous.", - - - // "comcol-role.edit.editor.name": "Editors", - // TODO New key - Add a translation - "comcol-role.edit.editor.name": "Editors", - - // "comcol-role.edit.editor.description": "Editors are able to edit the metadata of incoming submissions, and then accept or reject them.", - // TODO New key - Add a translation - "comcol-role.edit.editor.description": "Editors are able to edit the metadata of incoming submissions, and then accept or reject them.", - - - // "comcol-role.edit.finaleditor.name": "Final editors", - // TODO New key - Add a translation - "comcol-role.edit.finaleditor.name": "Final editors", - - // "comcol-role.edit.finaleditor.description": "Final editors are able to edit the metadata of incoming submissions, but will not be able to reject them.", - // TODO New key - Add a translation - "comcol-role.edit.finaleditor.description": "Final editors are able to edit the metadata of incoming submissions, but will not be able to reject them.", - - - // "comcol-role.edit.reviewer.name": "Reviewers", - // TODO New key - Add a translation - "comcol-role.edit.reviewer.name": "Reviewers", - - // "comcol-role.edit.reviewer.description": "Reviewers are able to accept or reject incoming submissions. However, they are not able to edit the submission's metadata.", - // TODO New key - Add a translation - "comcol-role.edit.reviewer.description": "Reviewers are able to accept or reject incoming submissions. However, they are not able to edit the submission's metadata.", - - - // "community.form.abstract": "Short Description", "community.form.abstract": "Korte beschrijving", @@ -1500,10 +1362,6 @@ // "dso-selector.create.item.head": "New item", "dso-selector.create.item.head": "Nieuw item", - // "dso-selector.create.submission.head": "New submission", - // TODO New key - Add a translation - "dso-selector.create.submission.head": "New submission", - // "dso-selector.edit.collection.head": "Edit collection", "dso-selector.edit.collection.head": "Bewerk collectie", @@ -1665,9 +1523,9 @@ // "form.search": "Search", "form.search": "Zoek", - // "form.search-help": "Click here to look for an existing correspondence", + // "form.search-help": "Click here to looking for an existing correspondence", // TODO New key - Add a translation - "form.search-help": "Click here to look for an existing correspondence", + "form.search-help": "Click here to looking for an existing correspondence", // "form.submit": "Submit", "form.submit": "Verstuur", @@ -1688,15 +1546,6 @@ - // "item.edit.authorizations.heading": "With this editor you can view and alter the policies of an item, plus alter policies of individual item components: bundles and bitstreams. Briefly, an item is a container of bundles, and bundles are containers of bitstreams. Containers usually have ADD/REMOVE/READ/WRITE policies, while bitstreams only have READ/WRITE policies.", - // TODO New key - Add a translation - "item.edit.authorizations.heading": "With this editor you can view and alter the policies of an item, plus alter policies of individual item components: bundles and bitstreams. Briefly, an item is a container of bundles, and bundles are containers of bitstreams. Containers usually have ADD/REMOVE/READ/WRITE policies, while bitstreams only have READ/WRITE policies.", - - // "item.edit.authorizations.title": "Edit item's Policies", - // TODO New key - Add a translation - "item.edit.authorizations.title": "Edit item's Policies", - - // "item.bitstreams.upload.bundle": "Bundle", // TODO New key - Add a translation @@ -2830,16 +2679,11 @@ "menu.section.toggle.statistics_task": "Sectie statistiektaken aan/uit", - // "menu.section.workflow": "Administer Workflow", - // TODO New key - Add a translation - "menu.section.workflow": "Administer Workflow", - // "mydspace.description": "", "mydspace.description": "", - // "mydspace.general.text-here": "here", - // TODO Source message changed - Revise the translation + // "mydspace.general.text-here": "HERE", "mydspace.general.text-here": "HIER", // "mydspace.messages.controller-help": "Select this option to send a message to item's submitter.", @@ -2938,14 +2782,6 @@ // "mydspace.upload.upload-failed": "Error creating new workspace. Please verify the content uploaded before retry.", "mydspace.upload.upload-failed": "Er is een fout opgetreden bij het aanmaken van de nieuwe workspace. Controleer alstublieft de inhoud voordat u het opnieuw probeert.", - // "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", - // TODO New key - Add a translation - "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", - - // "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", - // TODO New key - Add a translation - "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", - // "mydspace.upload.upload-multiple-successful": "{{qty}} new workspace items created.", "mydspace.upload.upload-multiple-successful": "{{qty}} nieuwe workspace items aangemaakt.", @@ -2985,10 +2821,6 @@ // "nav.statistics.header": "Statistics", "nav.statistics.header": "Statistieken", - // "nav.stop-impersonating": "Stop impersonating EPerson", - // TODO New key - Add a translation - "nav.stop-impersonating": "Stop impersonating EPerson", - // "orgunit.listelement.badge": "Organizational Unit", @@ -3180,120 +3012,6 @@ - // "profile.breadcrumbs": "Update Profile", - // TODO New key - Add a translation - "profile.breadcrumbs": "Update Profile", - - // "profile.card.identify": "Identify", - // TODO New key - Add a translation - "profile.card.identify": "Identify", - - // "profile.card.security": "Security", - // TODO New key - Add a translation - "profile.card.security": "Security", - - // "profile.form.submit": "Update Profile", - // TODO New key - Add a translation - "profile.form.submit": "Update Profile", - - // "profile.groups.head": "Authorization groups you belong to", - // TODO New key - Add a translation - "profile.groups.head": "Authorization groups you belong to", - - // "profile.head": "Update Profile", - // TODO New key - Add a translation - "profile.head": "Update Profile", - - // "profile.metadata.form.error.firstname.required": "First Name is required", - // TODO New key - Add a translation - "profile.metadata.form.error.firstname.required": "First Name is required", - - // "profile.metadata.form.error.lastname.required": "Last Name is required", - // TODO New key - Add a translation - "profile.metadata.form.error.lastname.required": "Last Name is required", - - // "profile.metadata.form.label.email": "Email Address", - // TODO New key - Add a translation - "profile.metadata.form.label.email": "Email Address", - - // "profile.metadata.form.label.firstname": "First Name", - // TODO New key - Add a translation - "profile.metadata.form.label.firstname": "First Name", - - // "profile.metadata.form.label.language": "Language", - // TODO New key - Add a translation - "profile.metadata.form.label.language": "Language", - - // "profile.metadata.form.label.lastname": "Last Name", - // TODO New key - Add a translation - "profile.metadata.form.label.lastname": "Last Name", - - // "profile.metadata.form.label.phone": "Contact Telephone", - // TODO New key - Add a translation - "profile.metadata.form.label.phone": "Contact Telephone", - - // "profile.metadata.form.notifications.success.content": "Your changes to the profile were saved.", - // TODO New key - Add a translation - "profile.metadata.form.notifications.success.content": "Your changes to the profile were saved.", - - // "profile.metadata.form.notifications.success.title": "Profile saved", - // TODO New key - Add a translation - "profile.metadata.form.notifications.success.title": "Profile saved", - - // "profile.notifications.warning.no-changes.content": "No changes were made to the Profile.", - // TODO New key - Add a translation - "profile.notifications.warning.no-changes.content": "No changes were made to the Profile.", - - // "profile.notifications.warning.no-changes.title": "No changes", - // TODO New key - Add a translation - "profile.notifications.warning.no-changes.title": "No changes", - - // "profile.security.form.error.matching-passwords": "The passwords do not match.", - // TODO New key - Add a translation - "profile.security.form.error.matching-passwords": "The passwords do not match.", - - // "profile.security.form.error.password-length": "The password should be at least 6 characters long.", - // TODO New key - Add a translation - "profile.security.form.error.password-length": "The password should be at least 6 characters long.", - - // "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.", - // TODO New key - Add a translation - "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.", - - // "profile.security.form.label.password": "Password", - // TODO New key - Add a translation - "profile.security.form.label.password": "Password", - - // "profile.security.form.label.passwordrepeat": "Retype to confirm", - // TODO New key - Add a translation - "profile.security.form.label.passwordrepeat": "Retype to confirm", - - // "profile.security.form.notifications.success.content": "Your changes to the password were saved.", - // TODO New key - Add a translation - "profile.security.form.notifications.success.content": "Your changes to the password were saved.", - - // "profile.security.form.notifications.success.title": "Password saved", - // TODO New key - Add a translation - "profile.security.form.notifications.success.title": "Password saved", - - // "profile.security.form.notifications.error.title": "Error changing passwords", - // TODO New key - Add a translation - "profile.security.form.notifications.error.title": "Error changing passwords", - - // "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", - // TODO New key - Add a translation - "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", - - // "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", - // TODO New key - Add a translation - "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", - - // "profile.title": "Update Profile", - // TODO New key - Add a translation - "profile.title": "Update Profile", - - - // "project.listelement.badge": "Research Project", "project.listelement.badge": "Onderzoeksproject", @@ -3398,192 +3116,6 @@ - // "resource-policies.add.button": "Add", - // TODO New key - Add a translation - "resource-policies.add.button": "Add", - - // "resource-policies.add.for.": "Add a new policy", - // TODO New key - Add a translation - "resource-policies.add.for.": "Add a new policy", - - // "resource-policies.add.for.bitstream": "Add a new Bitstream policy", - // TODO New key - Add a translation - "resource-policies.add.for.bitstream": "Add a new Bitstream policy", - - // "resource-policies.add.for.bundle": "Add a new Bundle policy", - // TODO New key - Add a translation - "resource-policies.add.for.bundle": "Add a new Bundle policy", - - // "resource-policies.add.for.item": "Add a new Item policy", - // TODO New key - Add a translation - "resource-policies.add.for.item": "Add a new Item policy", - - // "resource-policies.create.page.heading": "Create new resource policy for ", - // TODO New key - Add a translation - "resource-policies.create.page.heading": "Create new resource policy for ", - - // "resource-policies.create.page.failure.content": "An error occurred while creating the resource policy.", - // TODO New key - Add a translation - "resource-policies.create.page.failure.content": "An error occurred while creating the resource policy.", - - // "resource-policies.create.page.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.create.page.success.content": "Operation successful", - - // "resource-policies.create.page.title": "Create new resource policy", - // TODO New key - Add a translation - "resource-policies.create.page.title": "Create new resource policy", - - // "resource-policies.delete.btn": "Delete selected", - // TODO New key - Add a translation - "resource-policies.delete.btn": "Delete selected", - - // "resource-policies.delete.btn.title": "Delete selected resource policies", - // TODO New key - Add a translation - "resource-policies.delete.btn.title": "Delete selected resource policies", - - // "resource-policies.delete.failure.content": "An error occurred while deleting selected resource policies.", - // TODO New key - Add a translation - "resource-policies.delete.failure.content": "An error occurred while deleting selected resource policies.", - - // "resource-policies.delete.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.delete.success.content": "Operation successful", - - // "resource-policies.edit.page.heading": "Edit resource policy ", - // TODO New key - Add a translation - "resource-policies.edit.page.heading": "Edit resource policy ", - - // "resource-policies.edit.page.failure.content": "An error occurred while editing the resource policy.", - // TODO New key - Add a translation - "resource-policies.edit.page.failure.content": "An error occurred while editing the resource policy.", - - // "resource-policies.edit.page.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.edit.page.success.content": "Operation successful", - - // "resource-policies.edit.page.title": "Edit resource policy", - // TODO New key - Add a translation - "resource-policies.edit.page.title": "Edit resource policy", - - // "resource-policies.form.action-type.label": "Select the action type", - // TODO New key - Add a translation - "resource-policies.form.action-type.label": "Select the action type", - - // "resource-policies.form.action-type.required": "You must select the resource policy action.", - // TODO New key - Add a translation - "resource-policies.form.action-type.required": "You must select the resource policy action.", - - // "resource-policies.form.eperson-group-list.label": "The eperson or group that will be grant of the permission", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.label": "The eperson or group that will be grant of the permission", - - // "resource-policies.form.eperson-group-list.select.btn": "Select", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.select.btn": "Select", - - // "resource-policies.form.eperson-group-list.tab.eperson": "Search for a ePerson", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.tab.eperson": "Search for a ePerson", - - // "resource-policies.form.eperson-group-list.tab.group": "Search for a group", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.tab.group": "Search for a group", - - // "resource-policies.form.eperson-group-list.table.headers.action": "Action", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.action": "Action", - - // "resource-policies.form.eperson-group-list.table.headers.id": "ID", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.id": "ID", - - // "resource-policies.form.eperson-group-list.table.headers.name": "Name", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.name": "Name", - - // "resource-policies.form.date.end.label": "End Date", - // TODO New key - Add a translation - "resource-policies.form.date.end.label": "End Date", - - // "resource-policies.form.date.start.label": "Start Date", - // TODO New key - Add a translation - "resource-policies.form.date.start.label": "Start Date", - - // "resource-policies.form.description.label": "Description", - // TODO New key - Add a translation - "resource-policies.form.description.label": "Description", - - // "resource-policies.form.name.label": "Name", - // TODO New key - Add a translation - "resource-policies.form.name.label": "Name", - - // "resource-policies.form.policy-type.label": "Select the policy type", - // TODO New key - Add a translation - "resource-policies.form.policy-type.label": "Select the policy type", - - // "resource-policies.form.policy-type.required": "You must select the resource policy type.", - // TODO New key - Add a translation - "resource-policies.form.policy-type.required": "You must select the resource policy type.", - - // "resource-policies.table.headers.action": "Action", - // TODO New key - Add a translation - "resource-policies.table.headers.action": "Action", - - // "resource-policies.table.headers.date.end": "End Date", - // TODO New key - Add a translation - "resource-policies.table.headers.date.end": "End Date", - - // "resource-policies.table.headers.date.start": "Start Date", - // TODO New key - Add a translation - "resource-policies.table.headers.date.start": "Start Date", - - // "resource-policies.table.headers.edit": "Edit", - // TODO New key - Add a translation - "resource-policies.table.headers.edit": "Edit", - - // "resource-policies.table.headers.edit.group": "Edit group", - // TODO New key - Add a translation - "resource-policies.table.headers.edit.group": "Edit group", - - // "resource-policies.table.headers.edit.policy": "Edit policy", - // TODO New key - Add a translation - "resource-policies.table.headers.edit.policy": "Edit policy", - - // "resource-policies.table.headers.eperson": "EPerson", - // TODO New key - Add a translation - "resource-policies.table.headers.eperson": "EPerson", - - // "resource-policies.table.headers.group": "Group", - // TODO New key - Add a translation - "resource-policies.table.headers.group": "Group", - - // "resource-policies.table.headers.id": "ID", - // TODO New key - Add a translation - "resource-policies.table.headers.id": "ID", - - // "resource-policies.table.headers.name": "Name", - // TODO New key - Add a translation - "resource-policies.table.headers.name": "Name", - - // "resource-policies.table.headers.policyType": "type", - // TODO New key - Add a translation - "resource-policies.table.headers.policyType": "type", - - // "resource-policies.table.headers.title.for.bitstream": "Policies for Bitstream", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.bitstream": "Policies for Bitstream", - - // "resource-policies.table.headers.title.for.bundle": "Policies for Bundle", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.bundle": "Policies for Bundle", - - // "resource-policies.table.headers.title.for.item": "Policies for Item", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.item": "Policies for Item", - - - // "search.description": "", "search.description": "", @@ -4310,8 +3842,7 @@ // "submission.sections.upload.form.date-required": "Date is required.", "submission.sections.upload.form.date-required": "De datum is verplicht.", - // "submission.sections.upload.form.from-label": "Grant access from", - // TODO Source message changed - Revise the translation + // "submission.sections.upload.form.from-label": "Access grant from", "submission.sections.upload.form.from-label": "Toegang vanaf", // "submission.sections.upload.form.from-placeholder": "From", @@ -4323,8 +3854,7 @@ // "submission.sections.upload.form.group-required": "Group is required.", "submission.sections.upload.form.group-required": "Groep is verplicht.", - // "submission.sections.upload.form.until-label": "Grant access until", - // TODO Source message changed - Revise the translation + // "submission.sections.upload.form.until-label": "Access grant until", "submission.sections.upload.form.until-label": "Toegang tot", // "submission.sections.upload.form.until-placeholder": "Until", @@ -4492,78 +4022,5 @@ "virtual-metadata.delete-relationship.modal-head": "Select the items for which you want to save the virtual metadata as real metadata", - - // "workflowAdmin.search.results.head": "Administer Workflow", - // TODO New key - Add a translation - "workflowAdmin.search.results.head": "Administer Workflow", - - - - // "workflow-item.delete.notification.success.title": "Deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.success.title": "Deleted", - - // "workflow-item.delete.notification.success.content": "This workflow item was successfully deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.success.content": "This workflow item was successfully deleted", - - // "workflow-item.delete.notification.error.title": "Something went wrong", - // TODO New key - Add a translation - "workflow-item.delete.notification.error.title": "Something went wrong", - - // "workflow-item.delete.notification.error.content": "The workflow item could not be deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.error.content": "The workflow item could not be deleted", - - // "workflow-item.delete.title": "Delete workflow item", - // TODO New key - Add a translation - "workflow-item.delete.title": "Delete workflow item", - - // "workflow-item.delete.header": "Delete workflow item", - // TODO New key - Add a translation - "workflow-item.delete.header": "Delete workflow item", - - // "workflow-item.delete.button.cancel": "Cancel", - // TODO New key - Add a translation - "workflow-item.delete.button.cancel": "Cancel", - - // "workflow-item.delete.button.confirm": "Delete", - // TODO New key - Add a translation - "workflow-item.delete.button.confirm": "Delete", - - - // "workflow-item.send-back.notification.success.title": "Sent back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.success.title": "Sent back to submitter", - - // "workflow-item.send-back.notification.success.content": "This workflow item was successfully sent back to the submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.success.content": "This workflow item was successfully sent back to the submitter", - - // "workflow-item.send-back.notification.error.title": "Something went wrong", - // TODO New key - Add a translation - "workflow-item.send-back.notification.error.title": "Something went wrong", - - // "workflow-item.send-back.notification.error.content": "The workflow item could not be sent back to the submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.error.content": "The workflow item could not be sent back to the submitter", - - // "workflow-item.send-back.title": "Send workflow item back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.title": "Send workflow item back to submitter", - - // "workflow-item.send-back.header": "Send workflow item back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.header": "Send workflow item back to submitter", - - // "workflow-item.send-back.button.cancel": "Cancel", - // TODO New key - Add a translation - "workflow-item.send-back.button.cancel": "Cancel", - - // "workflow-item.send-back.button.confirm": "Send back", - // TODO New key - Add a translation - "workflow-item.send-back.button.confirm": "Send back", - - } \ No newline at end of file diff --git a/src/assets/i18n/pl.json5 b/src/assets/i18n/pl.json5 index 64a775dee8..d7afa97f08 100644 --- a/src/assets/i18n/pl.json5 +++ b/src/assets/i18n/pl.json5 @@ -332,22 +332,6 @@ - // "admin.access-control.epeople.actions.delete": "Delete EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.delete": "Delete EPerson", - - // "admin.access-control.epeople.actions.impersonate": "Impersonate EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.impersonate": "Impersonate EPerson", - - // "admin.access-control.epeople.actions.reset": "Reset password", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.reset": "Reset password", - - // "admin.access-control.epeople.actions.stop-impersonating": "Stop impersonating EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.stop-impersonating": "Stop impersonating EPerson", - // "admin.access-control.epeople.title": "DSpace Angular :: EPeople", // TODO New key - Add a translation "admin.access-control.epeople.title": "DSpace Angular :: EPeople", @@ -799,30 +783,6 @@ - - // "admin.workflow.breadcrumbs": "Administer Workflow", - // TODO New key - Add a translation - "admin.workflow.breadcrumbs": "Administer Workflow", - - // "admin.workflow.title": "Administer Workflow", - // TODO New key - Add a translation - "admin.workflow.title": "Administer Workflow", - - // "admin.workflow.item.workflow": "Workflow", - // TODO New key - Add a translation - "admin.workflow.item.workflow": "Workflow", - - // "admin.workflow.item.delete": "Delete", - // TODO New key - Add a translation - "admin.workflow.item.delete": "Delete", - - // "admin.workflow.item.send-back": "Send back", - // TODO New key - Add a translation - "admin.workflow.item.send-back": "Send back", - - - - // "auth.errors.invalid-user": "Invalid email address or password.", // TODO New key - Add a translation "auth.errors.invalid-user": "Invalid email address or password.", @@ -1515,104 +1475,6 @@ - // "comcol-role.edit.no-group": "None", - // TODO New key - Add a translation - "comcol-role.edit.no-group": "None", - - // "comcol-role.edit.create": "Create", - // TODO New key - Add a translation - "comcol-role.edit.create": "Create", - - // "comcol-role.edit.restrict": "Restrict", - // TODO New key - Add a translation - "comcol-role.edit.restrict": "Restrict", - - // "comcol-role.edit.delete": "Delete", - // TODO New key - Add a translation - "comcol-role.edit.delete": "Delete", - - - // "comcol-role.edit.community-admin.name": "Administrators", - // TODO New key - Add a translation - "comcol-role.edit.community-admin.name": "Administrators", - - // "comcol-role.edit.collection-admin.name": "Administrators", - // TODO New key - Add a translation - "comcol-role.edit.collection-admin.name": "Administrators", - - - // "comcol-role.edit.community-admin.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - // TODO New key - Add a translation - "comcol-role.edit.community-admin.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - - // "comcol-role.edit.collection-admin.description": "Collection administrators decide who can submit items to the collection, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization for that collection).", - // TODO New key - Add a translation - "comcol-role.edit.collection-admin.description": "Collection administrators decide who can submit items to the collection, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization for that collection).", - - - // "comcol-role.edit.submitters.name": "Submitters", - // TODO New key - Add a translation - "comcol-role.edit.submitters.name": "Submitters", - - // "comcol-role.edit.submitters.description": "The E-People and Groups that have permission to submit new items to this collection.", - // TODO New key - Add a translation - "comcol-role.edit.submitters.description": "The E-People and Groups that have permission to submit new items to this collection.", - - - // "comcol-role.edit.item_read.name": "Default item read access", - // TODO New key - Add a translation - "comcol-role.edit.item_read.name": "Default item read access", - - // "comcol-role.edit.item_read.description": "E-People and Groups that can read new items submitted to this collection. Changes to this role are not retroactive. Existing items in the system will still be viewable by those who had read access at the time of their addition.", - // TODO New key - Add a translation - "comcol-role.edit.item_read.description": "E-People and Groups that can read new items submitted to this collection. Changes to this role are not retroactive. Existing items in the system will still be viewable by those who had read access at the time of their addition.", - - // "comcol-role.edit.item_read.anonymous-group": "Default read for incoming items is currently set to Anonymous.", - // TODO New key - Add a translation - "comcol-role.edit.item_read.anonymous-group": "Default read for incoming items is currently set to Anonymous.", - - - // "comcol-role.edit.bitstream_read.name": "Default bitstream read access", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.name": "Default bitstream read access", - - // "comcol-role.edit.bitstream_read.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - - // "comcol-role.edit.bitstream_read.anonymous-group": "Default read for incoming bitstreams is currently set to Anonymous.", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.anonymous-group": "Default read for incoming bitstreams is currently set to Anonymous.", - - - // "comcol-role.edit.editor.name": "Editors", - // TODO New key - Add a translation - "comcol-role.edit.editor.name": "Editors", - - // "comcol-role.edit.editor.description": "Editors are able to edit the metadata of incoming submissions, and then accept or reject them.", - // TODO New key - Add a translation - "comcol-role.edit.editor.description": "Editors are able to edit the metadata of incoming submissions, and then accept or reject them.", - - - // "comcol-role.edit.finaleditor.name": "Final editors", - // TODO New key - Add a translation - "comcol-role.edit.finaleditor.name": "Final editors", - - // "comcol-role.edit.finaleditor.description": "Final editors are able to edit the metadata of incoming submissions, but will not be able to reject them.", - // TODO New key - Add a translation - "comcol-role.edit.finaleditor.description": "Final editors are able to edit the metadata of incoming submissions, but will not be able to reject them.", - - - // "comcol-role.edit.reviewer.name": "Reviewers", - // TODO New key - Add a translation - "comcol-role.edit.reviewer.name": "Reviewers", - - // "comcol-role.edit.reviewer.description": "Reviewers are able to accept or reject incoming submissions. However, they are not able to edit the submission's metadata.", - // TODO New key - Add a translation - "comcol-role.edit.reviewer.description": "Reviewers are able to accept or reject incoming submissions. However, they are not able to edit the submission's metadata.", - - - // "community.form.abstract": "Short Description", // TODO New key - Add a translation "community.form.abstract": "Short Description", @@ -1683,10 +1545,6 @@ // TODO New key - Add a translation "dso-selector.create.item.head": "New item", - // "dso-selector.create.submission.head": "New submission", - // TODO New key - Add a translation - "dso-selector.create.submission.head": "New submission", - // "dso-selector.edit.collection.head": "Edit collection", // TODO New key - Add a translation "dso-selector.edit.collection.head": "Edit collection", @@ -1892,9 +1750,9 @@ // TODO New key - Add a translation "form.search": "Search", - // "form.search-help": "Click here to look for an existing correspondence", + // "form.search-help": "Click here to looking for an existing correspondence", // TODO New key - Add a translation - "form.search-help": "Click here to look for an existing correspondence", + "form.search-help": "Click here to looking for an existing correspondence", // "form.submit": "Submit", // TODO New key - Add a translation @@ -1920,15 +1778,6 @@ - // "item.edit.authorizations.heading": "With this editor you can view and alter the policies of an item, plus alter policies of individual item components: bundles and bitstreams. Briefly, an item is a container of bundles, and bundles are containers of bitstreams. Containers usually have ADD/REMOVE/READ/WRITE policies, while bitstreams only have READ/WRITE policies.", - // TODO New key - Add a translation - "item.edit.authorizations.heading": "With this editor you can view and alter the policies of an item, plus alter policies of individual item components: bundles and bitstreams. Briefly, an item is a container of bundles, and bundles are containers of bitstreams. Containers usually have ADD/REMOVE/READ/WRITE policies, while bitstreams only have READ/WRITE policies.", - - // "item.edit.authorizations.title": "Edit item's Policies", - // TODO New key - Add a translation - "item.edit.authorizations.title": "Edit item's Policies", - - // "item.bitstreams.upload.bundle": "Bundle", // TODO New key - Add a translation @@ -3318,18 +3167,14 @@ "menu.section.toggle.statistics_task": "Toggle Statistics Task section", - // "menu.section.workflow": "Administer Workflow", - // TODO New key - Add a translation - "menu.section.workflow": "Administer Workflow", - // "mydspace.description": "", // TODO New key - Add a translation "mydspace.description": "", - // "mydspace.general.text-here": "here", + // "mydspace.general.text-here": "HERE", // TODO New key - Add a translation - "mydspace.general.text-here": "here", + "mydspace.general.text-here": "HERE", // "mydspace.messages.controller-help": "Select this option to send a message to item's submitter.", // TODO New key - Add a translation @@ -3459,14 +3304,6 @@ // TODO New key - Add a translation "mydspace.upload.upload-failed": "Error creating new workspace. Please verify the content uploaded before retry.", - // "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", - // TODO New key - Add a translation - "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", - - // "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", - // TODO New key - Add a translation - "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", - // "mydspace.upload.upload-multiple-successful": "{{qty}} new workspace items created.", // TODO New key - Add a translation "mydspace.upload.upload-multiple-successful": "{{qty}} new workspace items created.", @@ -3517,10 +3354,6 @@ // TODO New key - Add a translation "nav.statistics.header": "Statistics", - // "nav.stop-impersonating": "Stop impersonating EPerson", - // TODO New key - Add a translation - "nav.stop-impersonating": "Stop impersonating EPerson", - // "orgunit.listelement.badge": "Organizational Unit", @@ -3735,120 +3568,6 @@ - // "profile.breadcrumbs": "Update Profile", - // TODO New key - Add a translation - "profile.breadcrumbs": "Update Profile", - - // "profile.card.identify": "Identify", - // TODO New key - Add a translation - "profile.card.identify": "Identify", - - // "profile.card.security": "Security", - // TODO New key - Add a translation - "profile.card.security": "Security", - - // "profile.form.submit": "Update Profile", - // TODO New key - Add a translation - "profile.form.submit": "Update Profile", - - // "profile.groups.head": "Authorization groups you belong to", - // TODO New key - Add a translation - "profile.groups.head": "Authorization groups you belong to", - - // "profile.head": "Update Profile", - // TODO New key - Add a translation - "profile.head": "Update Profile", - - // "profile.metadata.form.error.firstname.required": "First Name is required", - // TODO New key - Add a translation - "profile.metadata.form.error.firstname.required": "First Name is required", - - // "profile.metadata.form.error.lastname.required": "Last Name is required", - // TODO New key - Add a translation - "profile.metadata.form.error.lastname.required": "Last Name is required", - - // "profile.metadata.form.label.email": "Email Address", - // TODO New key - Add a translation - "profile.metadata.form.label.email": "Email Address", - - // "profile.metadata.form.label.firstname": "First Name", - // TODO New key - Add a translation - "profile.metadata.form.label.firstname": "First Name", - - // "profile.metadata.form.label.language": "Language", - // TODO New key - Add a translation - "profile.metadata.form.label.language": "Language", - - // "profile.metadata.form.label.lastname": "Last Name", - // TODO New key - Add a translation - "profile.metadata.form.label.lastname": "Last Name", - - // "profile.metadata.form.label.phone": "Contact Telephone", - // TODO New key - Add a translation - "profile.metadata.form.label.phone": "Contact Telephone", - - // "profile.metadata.form.notifications.success.content": "Your changes to the profile were saved.", - // TODO New key - Add a translation - "profile.metadata.form.notifications.success.content": "Your changes to the profile were saved.", - - // "profile.metadata.form.notifications.success.title": "Profile saved", - // TODO New key - Add a translation - "profile.metadata.form.notifications.success.title": "Profile saved", - - // "profile.notifications.warning.no-changes.content": "No changes were made to the Profile.", - // TODO New key - Add a translation - "profile.notifications.warning.no-changes.content": "No changes were made to the Profile.", - - // "profile.notifications.warning.no-changes.title": "No changes", - // TODO New key - Add a translation - "profile.notifications.warning.no-changes.title": "No changes", - - // "profile.security.form.error.matching-passwords": "The passwords do not match.", - // TODO New key - Add a translation - "profile.security.form.error.matching-passwords": "The passwords do not match.", - - // "profile.security.form.error.password-length": "The password should be at least 6 characters long.", - // TODO New key - Add a translation - "profile.security.form.error.password-length": "The password should be at least 6 characters long.", - - // "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.", - // TODO New key - Add a translation - "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.", - - // "profile.security.form.label.password": "Password", - // TODO New key - Add a translation - "profile.security.form.label.password": "Password", - - // "profile.security.form.label.passwordrepeat": "Retype to confirm", - // TODO New key - Add a translation - "profile.security.form.label.passwordrepeat": "Retype to confirm", - - // "profile.security.form.notifications.success.content": "Your changes to the password were saved.", - // TODO New key - Add a translation - "profile.security.form.notifications.success.content": "Your changes to the password were saved.", - - // "profile.security.form.notifications.success.title": "Password saved", - // TODO New key - Add a translation - "profile.security.form.notifications.success.title": "Password saved", - - // "profile.security.form.notifications.error.title": "Error changing passwords", - // TODO New key - Add a translation - "profile.security.form.notifications.error.title": "Error changing passwords", - - // "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", - // TODO New key - Add a translation - "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", - - // "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", - // TODO New key - Add a translation - "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", - - // "profile.title": "Update Profile", - // TODO New key - Add a translation - "profile.title": "Update Profile", - - - // "project.listelement.badge": "Research Project", // TODO New key - Add a translation "project.listelement.badge": "Research Project", @@ -3983,192 +3702,6 @@ - // "resource-policies.add.button": "Add", - // TODO New key - Add a translation - "resource-policies.add.button": "Add", - - // "resource-policies.add.for.": "Add a new policy", - // TODO New key - Add a translation - "resource-policies.add.for.": "Add a new policy", - - // "resource-policies.add.for.bitstream": "Add a new Bitstream policy", - // TODO New key - Add a translation - "resource-policies.add.for.bitstream": "Add a new Bitstream policy", - - // "resource-policies.add.for.bundle": "Add a new Bundle policy", - // TODO New key - Add a translation - "resource-policies.add.for.bundle": "Add a new Bundle policy", - - // "resource-policies.add.for.item": "Add a new Item policy", - // TODO New key - Add a translation - "resource-policies.add.for.item": "Add a new Item policy", - - // "resource-policies.create.page.heading": "Create new resource policy for ", - // TODO New key - Add a translation - "resource-policies.create.page.heading": "Create new resource policy for ", - - // "resource-policies.create.page.failure.content": "An error occurred while creating the resource policy.", - // TODO New key - Add a translation - "resource-policies.create.page.failure.content": "An error occurred while creating the resource policy.", - - // "resource-policies.create.page.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.create.page.success.content": "Operation successful", - - // "resource-policies.create.page.title": "Create new resource policy", - // TODO New key - Add a translation - "resource-policies.create.page.title": "Create new resource policy", - - // "resource-policies.delete.btn": "Delete selected", - // TODO New key - Add a translation - "resource-policies.delete.btn": "Delete selected", - - // "resource-policies.delete.btn.title": "Delete selected resource policies", - // TODO New key - Add a translation - "resource-policies.delete.btn.title": "Delete selected resource policies", - - // "resource-policies.delete.failure.content": "An error occurred while deleting selected resource policies.", - // TODO New key - Add a translation - "resource-policies.delete.failure.content": "An error occurred while deleting selected resource policies.", - - // "resource-policies.delete.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.delete.success.content": "Operation successful", - - // "resource-policies.edit.page.heading": "Edit resource policy ", - // TODO New key - Add a translation - "resource-policies.edit.page.heading": "Edit resource policy ", - - // "resource-policies.edit.page.failure.content": "An error occurred while editing the resource policy.", - // TODO New key - Add a translation - "resource-policies.edit.page.failure.content": "An error occurred while editing the resource policy.", - - // "resource-policies.edit.page.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.edit.page.success.content": "Operation successful", - - // "resource-policies.edit.page.title": "Edit resource policy", - // TODO New key - Add a translation - "resource-policies.edit.page.title": "Edit resource policy", - - // "resource-policies.form.action-type.label": "Select the action type", - // TODO New key - Add a translation - "resource-policies.form.action-type.label": "Select the action type", - - // "resource-policies.form.action-type.required": "You must select the resource policy action.", - // TODO New key - Add a translation - "resource-policies.form.action-type.required": "You must select the resource policy action.", - - // "resource-policies.form.eperson-group-list.label": "The eperson or group that will be grant of the permission", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.label": "The eperson or group that will be grant of the permission", - - // "resource-policies.form.eperson-group-list.select.btn": "Select", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.select.btn": "Select", - - // "resource-policies.form.eperson-group-list.tab.eperson": "Search for a ePerson", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.tab.eperson": "Search for a ePerson", - - // "resource-policies.form.eperson-group-list.tab.group": "Search for a group", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.tab.group": "Search for a group", - - // "resource-policies.form.eperson-group-list.table.headers.action": "Action", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.action": "Action", - - // "resource-policies.form.eperson-group-list.table.headers.id": "ID", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.id": "ID", - - // "resource-policies.form.eperson-group-list.table.headers.name": "Name", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.name": "Name", - - // "resource-policies.form.date.end.label": "End Date", - // TODO New key - Add a translation - "resource-policies.form.date.end.label": "End Date", - - // "resource-policies.form.date.start.label": "Start Date", - // TODO New key - Add a translation - "resource-policies.form.date.start.label": "Start Date", - - // "resource-policies.form.description.label": "Description", - // TODO New key - Add a translation - "resource-policies.form.description.label": "Description", - - // "resource-policies.form.name.label": "Name", - // TODO New key - Add a translation - "resource-policies.form.name.label": "Name", - - // "resource-policies.form.policy-type.label": "Select the policy type", - // TODO New key - Add a translation - "resource-policies.form.policy-type.label": "Select the policy type", - - // "resource-policies.form.policy-type.required": "You must select the resource policy type.", - // TODO New key - Add a translation - "resource-policies.form.policy-type.required": "You must select the resource policy type.", - - // "resource-policies.table.headers.action": "Action", - // TODO New key - Add a translation - "resource-policies.table.headers.action": "Action", - - // "resource-policies.table.headers.date.end": "End Date", - // TODO New key - Add a translation - "resource-policies.table.headers.date.end": "End Date", - - // "resource-policies.table.headers.date.start": "Start Date", - // TODO New key - Add a translation - "resource-policies.table.headers.date.start": "Start Date", - - // "resource-policies.table.headers.edit": "Edit", - // TODO New key - Add a translation - "resource-policies.table.headers.edit": "Edit", - - // "resource-policies.table.headers.edit.group": "Edit group", - // TODO New key - Add a translation - "resource-policies.table.headers.edit.group": "Edit group", - - // "resource-policies.table.headers.edit.policy": "Edit policy", - // TODO New key - Add a translation - "resource-policies.table.headers.edit.policy": "Edit policy", - - // "resource-policies.table.headers.eperson": "EPerson", - // TODO New key - Add a translation - "resource-policies.table.headers.eperson": "EPerson", - - // "resource-policies.table.headers.group": "Group", - // TODO New key - Add a translation - "resource-policies.table.headers.group": "Group", - - // "resource-policies.table.headers.id": "ID", - // TODO New key - Add a translation - "resource-policies.table.headers.id": "ID", - - // "resource-policies.table.headers.name": "Name", - // TODO New key - Add a translation - "resource-policies.table.headers.name": "Name", - - // "resource-policies.table.headers.policyType": "type", - // TODO New key - Add a translation - "resource-policies.table.headers.policyType": "type", - - // "resource-policies.table.headers.title.for.bitstream": "Policies for Bitstream", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.bitstream": "Policies for Bitstream", - - // "resource-policies.table.headers.title.for.bundle": "Policies for Bundle", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.bundle": "Policies for Bundle", - - // "resource-policies.table.headers.title.for.item": "Policies for Item", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.item": "Policies for Item", - - - // "search.description": "", // TODO New key - Add a translation "search.description": "", @@ -5013,9 +4546,9 @@ // TODO New key - Add a translation "submission.sections.upload.form.date-required": "Date is required.", - // "submission.sections.upload.form.from-label": "Grant access from", + // "submission.sections.upload.form.from-label": "Access grant from", // TODO New key - Add a translation - "submission.sections.upload.form.from-label": "Grant access from", + "submission.sections.upload.form.from-label": "Access grant from", // "submission.sections.upload.form.from-placeholder": "From", // TODO New key - Add a translation @@ -5029,9 +4562,9 @@ // TODO New key - Add a translation "submission.sections.upload.form.group-required": "Group is required.", - // "submission.sections.upload.form.until-label": "Grant access until", + // "submission.sections.upload.form.until-label": "Access grant until", // TODO New key - Add a translation - "submission.sections.upload.form.until-label": "Grant access until", + "submission.sections.upload.form.until-label": "Access grant until", // "submission.sections.upload.form.until-placeholder": "Until", // TODO New key - Add a translation @@ -5241,78 +4774,5 @@ "virtual-metadata.delete-relationship.modal-head": "Select the items for which you want to save the virtual metadata as real metadata", - - // "workflowAdmin.search.results.head": "Administer Workflow", - // TODO New key - Add a translation - "workflowAdmin.search.results.head": "Administer Workflow", - - - - // "workflow-item.delete.notification.success.title": "Deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.success.title": "Deleted", - - // "workflow-item.delete.notification.success.content": "This workflow item was successfully deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.success.content": "This workflow item was successfully deleted", - - // "workflow-item.delete.notification.error.title": "Something went wrong", - // TODO New key - Add a translation - "workflow-item.delete.notification.error.title": "Something went wrong", - - // "workflow-item.delete.notification.error.content": "The workflow item could not be deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.error.content": "The workflow item could not be deleted", - - // "workflow-item.delete.title": "Delete workflow item", - // TODO New key - Add a translation - "workflow-item.delete.title": "Delete workflow item", - - // "workflow-item.delete.header": "Delete workflow item", - // TODO New key - Add a translation - "workflow-item.delete.header": "Delete workflow item", - - // "workflow-item.delete.button.cancel": "Cancel", - // TODO New key - Add a translation - "workflow-item.delete.button.cancel": "Cancel", - - // "workflow-item.delete.button.confirm": "Delete", - // TODO New key - Add a translation - "workflow-item.delete.button.confirm": "Delete", - - - // "workflow-item.send-back.notification.success.title": "Sent back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.success.title": "Sent back to submitter", - - // "workflow-item.send-back.notification.success.content": "This workflow item was successfully sent back to the submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.success.content": "This workflow item was successfully sent back to the submitter", - - // "workflow-item.send-back.notification.error.title": "Something went wrong", - // TODO New key - Add a translation - "workflow-item.send-back.notification.error.title": "Something went wrong", - - // "workflow-item.send-back.notification.error.content": "The workflow item could not be sent back to the submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.error.content": "The workflow item could not be sent back to the submitter", - - // "workflow-item.send-back.title": "Send workflow item back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.title": "Send workflow item back to submitter", - - // "workflow-item.send-back.header": "Send workflow item back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.header": "Send workflow item back to submitter", - - // "workflow-item.send-back.button.cancel": "Cancel", - // TODO New key - Add a translation - "workflow-item.send-back.button.cancel": "Cancel", - - // "workflow-item.send-back.button.confirm": "Send back", - // TODO New key - Add a translation - "workflow-item.send-back.button.confirm": "Send back", - - } \ No newline at end of file diff --git a/src/assets/i18n/pt.json5 b/src/assets/i18n/pt.json5 index 131c046207..da71ddec11 100644 --- a/src/assets/i18n/pt.json5 +++ b/src/assets/i18n/pt.json5 @@ -252,22 +252,6 @@ - // "admin.access-control.epeople.actions.delete": "Delete EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.delete": "Delete EPerson", - - // "admin.access-control.epeople.actions.impersonate": "Impersonate EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.impersonate": "Impersonate EPerson", - - // "admin.access-control.epeople.actions.reset": "Reset password", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.reset": "Reset password", - - // "admin.access-control.epeople.actions.stop-impersonating": "Stop impersonating EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.stop-impersonating": "Stop impersonating EPerson", - // "admin.access-control.epeople.title": "DSpace Angular :: EPeople", // TODO New key - Add a translation "admin.access-control.epeople.title": "DSpace Angular :: EPeople", @@ -719,30 +703,6 @@ - - // "admin.workflow.breadcrumbs": "Administer Workflow", - // TODO New key - Add a translation - "admin.workflow.breadcrumbs": "Administer Workflow", - - // "admin.workflow.title": "Administer Workflow", - // TODO New key - Add a translation - "admin.workflow.title": "Administer Workflow", - - // "admin.workflow.item.workflow": "Workflow", - // TODO New key - Add a translation - "admin.workflow.item.workflow": "Workflow", - - // "admin.workflow.item.delete": "Delete", - // TODO New key - Add a translation - "admin.workflow.item.delete": "Delete", - - // "admin.workflow.item.send-back": "Send back", - // TODO New key - Add a translation - "admin.workflow.item.send-back": "Send back", - - - - // "auth.errors.invalid-user": "Invalid email address or password.", "auth.errors.invalid-user": "Endereço de email ou senha inválidos.", @@ -1349,104 +1309,6 @@ - // "comcol-role.edit.no-group": "None", - // TODO New key - Add a translation - "comcol-role.edit.no-group": "None", - - // "comcol-role.edit.create": "Create", - // TODO New key - Add a translation - "comcol-role.edit.create": "Create", - - // "comcol-role.edit.restrict": "Restrict", - // TODO New key - Add a translation - "comcol-role.edit.restrict": "Restrict", - - // "comcol-role.edit.delete": "Delete", - // TODO New key - Add a translation - "comcol-role.edit.delete": "Delete", - - - // "comcol-role.edit.community-admin.name": "Administrators", - // TODO New key - Add a translation - "comcol-role.edit.community-admin.name": "Administrators", - - // "comcol-role.edit.collection-admin.name": "Administrators", - // TODO New key - Add a translation - "comcol-role.edit.collection-admin.name": "Administrators", - - - // "comcol-role.edit.community-admin.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - // TODO New key - Add a translation - "comcol-role.edit.community-admin.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - - // "comcol-role.edit.collection-admin.description": "Collection administrators decide who can submit items to the collection, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization for that collection).", - // TODO New key - Add a translation - "comcol-role.edit.collection-admin.description": "Collection administrators decide who can submit items to the collection, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization for that collection).", - - - // "comcol-role.edit.submitters.name": "Submitters", - // TODO New key - Add a translation - "comcol-role.edit.submitters.name": "Submitters", - - // "comcol-role.edit.submitters.description": "The E-People and Groups that have permission to submit new items to this collection.", - // TODO New key - Add a translation - "comcol-role.edit.submitters.description": "The E-People and Groups that have permission to submit new items to this collection.", - - - // "comcol-role.edit.item_read.name": "Default item read access", - // TODO New key - Add a translation - "comcol-role.edit.item_read.name": "Default item read access", - - // "comcol-role.edit.item_read.description": "E-People and Groups that can read new items submitted to this collection. Changes to this role are not retroactive. Existing items in the system will still be viewable by those who had read access at the time of their addition.", - // TODO New key - Add a translation - "comcol-role.edit.item_read.description": "E-People and Groups that can read new items submitted to this collection. Changes to this role are not retroactive. Existing items in the system will still be viewable by those who had read access at the time of their addition.", - - // "comcol-role.edit.item_read.anonymous-group": "Default read for incoming items is currently set to Anonymous.", - // TODO New key - Add a translation - "comcol-role.edit.item_read.anonymous-group": "Default read for incoming items is currently set to Anonymous.", - - - // "comcol-role.edit.bitstream_read.name": "Default bitstream read access", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.name": "Default bitstream read access", - - // "comcol-role.edit.bitstream_read.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - - // "comcol-role.edit.bitstream_read.anonymous-group": "Default read for incoming bitstreams is currently set to Anonymous.", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.anonymous-group": "Default read for incoming bitstreams is currently set to Anonymous.", - - - // "comcol-role.edit.editor.name": "Editors", - // TODO New key - Add a translation - "comcol-role.edit.editor.name": "Editors", - - // "comcol-role.edit.editor.description": "Editors are able to edit the metadata of incoming submissions, and then accept or reject them.", - // TODO New key - Add a translation - "comcol-role.edit.editor.description": "Editors are able to edit the metadata of incoming submissions, and then accept or reject them.", - - - // "comcol-role.edit.finaleditor.name": "Final editors", - // TODO New key - Add a translation - "comcol-role.edit.finaleditor.name": "Final editors", - - // "comcol-role.edit.finaleditor.description": "Final editors are able to edit the metadata of incoming submissions, but will not be able to reject them.", - // TODO New key - Add a translation - "comcol-role.edit.finaleditor.description": "Final editors are able to edit the metadata of incoming submissions, but will not be able to reject them.", - - - // "comcol-role.edit.reviewer.name": "Reviewers", - // TODO New key - Add a translation - "comcol-role.edit.reviewer.name": "Reviewers", - - // "comcol-role.edit.reviewer.description": "Reviewers are able to accept or reject incoming submissions. However, they are not able to edit the submission's metadata.", - // TODO New key - Add a translation - "comcol-role.edit.reviewer.description": "Reviewers are able to accept or reject incoming submissions. However, they are not able to edit the submission's metadata.", - - - // "community.form.abstract": "Short Description", "community.form.abstract": "Descrição curta", @@ -1500,10 +1362,6 @@ // "dso-selector.create.item.head": "New item", "dso-selector.create.item.head": "Novo item", - // "dso-selector.create.submission.head": "New submission", - // TODO New key - Add a translation - "dso-selector.create.submission.head": "New submission", - // "dso-selector.edit.collection.head": "Edit collection", "dso-selector.edit.collection.head": "Editar coleção", @@ -1665,8 +1523,7 @@ // "form.search": "Search", "form.search": "Buscar", - // "form.search-help": "Click here to look for an existing correspondence", - // TODO Source message changed - Revise the translation + // "form.search-help": "Click here to looking for an existing correspondence", "form.search-help": "Clique aqui para procurar por uma correspondência existente", // "form.submit": "Submit", @@ -1689,15 +1546,6 @@ - // "item.edit.authorizations.heading": "With this editor you can view and alter the policies of an item, plus alter policies of individual item components: bundles and bitstreams. Briefly, an item is a container of bundles, and bundles are containers of bitstreams. Containers usually have ADD/REMOVE/READ/WRITE policies, while bitstreams only have READ/WRITE policies.", - // TODO New key - Add a translation - "item.edit.authorizations.heading": "With this editor you can view and alter the policies of an item, plus alter policies of individual item components: bundles and bitstreams. Briefly, an item is a container of bundles, and bundles are containers of bitstreams. Containers usually have ADD/REMOVE/READ/WRITE policies, while bitstreams only have READ/WRITE policies.", - - // "item.edit.authorizations.title": "Edit item's Policies", - // TODO New key - Add a translation - "item.edit.authorizations.title": "Edit item's Policies", - - // "item.bitstreams.upload.bundle": "Bundle", // TODO New key - Add a translation @@ -2831,16 +2679,11 @@ "menu.section.toggle.statistics_task": "Alternar Seção Tarefas de Estatísticas", - // "menu.section.workflow": "Administer Workflow", - // TODO New key - Add a translation - "menu.section.workflow": "Administer Workflow", - // "mydspace.description": "", "mydspace.description": "", - // "mydspace.general.text-here": "here", - // TODO Source message changed - Revise the translation + // "mydspace.general.text-here": "HERE", "mydspace.general.text-here": "AQUI", // "mydspace.messages.controller-help": "Select this option to send a message to item's submitter.", @@ -2939,14 +2782,6 @@ // "mydspace.upload.upload-failed": "Error creating new workspace. Please verify the content uploaded before retry.", "mydspace.upload.upload-failed": "Erro ao criar novo espaço de trabalho. Por favor verifique o conteúdo enviado antes de tentar novamente.", - // "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", - // TODO New key - Add a translation - "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", - - // "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", - // TODO New key - Add a translation - "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", - // "mydspace.upload.upload-multiple-successful": "{{qty}} new workspace items created.", "mydspace.upload.upload-multiple-successful": "{{qty}} novo(s) item(ns) de espaço de trabalho criados.", @@ -2986,10 +2821,6 @@ // "nav.statistics.header": "Statistics", "nav.statistics.header": "Estatísticas", - // "nav.stop-impersonating": "Stop impersonating EPerson", - // TODO New key - Add a translation - "nav.stop-impersonating": "Stop impersonating EPerson", - // "orgunit.listelement.badge": "Organizational Unit", @@ -3181,120 +3012,6 @@ - // "profile.breadcrumbs": "Update Profile", - // TODO New key - Add a translation - "profile.breadcrumbs": "Update Profile", - - // "profile.card.identify": "Identify", - // TODO New key - Add a translation - "profile.card.identify": "Identify", - - // "profile.card.security": "Security", - // TODO New key - Add a translation - "profile.card.security": "Security", - - // "profile.form.submit": "Update Profile", - // TODO New key - Add a translation - "profile.form.submit": "Update Profile", - - // "profile.groups.head": "Authorization groups you belong to", - // TODO New key - Add a translation - "profile.groups.head": "Authorization groups you belong to", - - // "profile.head": "Update Profile", - // TODO New key - Add a translation - "profile.head": "Update Profile", - - // "profile.metadata.form.error.firstname.required": "First Name is required", - // TODO New key - Add a translation - "profile.metadata.form.error.firstname.required": "First Name is required", - - // "profile.metadata.form.error.lastname.required": "Last Name is required", - // TODO New key - Add a translation - "profile.metadata.form.error.lastname.required": "Last Name is required", - - // "profile.metadata.form.label.email": "Email Address", - // TODO New key - Add a translation - "profile.metadata.form.label.email": "Email Address", - - // "profile.metadata.form.label.firstname": "First Name", - // TODO New key - Add a translation - "profile.metadata.form.label.firstname": "First Name", - - // "profile.metadata.form.label.language": "Language", - // TODO New key - Add a translation - "profile.metadata.form.label.language": "Language", - - // "profile.metadata.form.label.lastname": "Last Name", - // TODO New key - Add a translation - "profile.metadata.form.label.lastname": "Last Name", - - // "profile.metadata.form.label.phone": "Contact Telephone", - // TODO New key - Add a translation - "profile.metadata.form.label.phone": "Contact Telephone", - - // "profile.metadata.form.notifications.success.content": "Your changes to the profile were saved.", - // TODO New key - Add a translation - "profile.metadata.form.notifications.success.content": "Your changes to the profile were saved.", - - // "profile.metadata.form.notifications.success.title": "Profile saved", - // TODO New key - Add a translation - "profile.metadata.form.notifications.success.title": "Profile saved", - - // "profile.notifications.warning.no-changes.content": "No changes were made to the Profile.", - // TODO New key - Add a translation - "profile.notifications.warning.no-changes.content": "No changes were made to the Profile.", - - // "profile.notifications.warning.no-changes.title": "No changes", - // TODO New key - Add a translation - "profile.notifications.warning.no-changes.title": "No changes", - - // "profile.security.form.error.matching-passwords": "The passwords do not match.", - // TODO New key - Add a translation - "profile.security.form.error.matching-passwords": "The passwords do not match.", - - // "profile.security.form.error.password-length": "The password should be at least 6 characters long.", - // TODO New key - Add a translation - "profile.security.form.error.password-length": "The password should be at least 6 characters long.", - - // "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.", - // TODO New key - Add a translation - "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.", - - // "profile.security.form.label.password": "Password", - // TODO New key - Add a translation - "profile.security.form.label.password": "Password", - - // "profile.security.form.label.passwordrepeat": "Retype to confirm", - // TODO New key - Add a translation - "profile.security.form.label.passwordrepeat": "Retype to confirm", - - // "profile.security.form.notifications.success.content": "Your changes to the password were saved.", - // TODO New key - Add a translation - "profile.security.form.notifications.success.content": "Your changes to the password were saved.", - - // "profile.security.form.notifications.success.title": "Password saved", - // TODO New key - Add a translation - "profile.security.form.notifications.success.title": "Password saved", - - // "profile.security.form.notifications.error.title": "Error changing passwords", - // TODO New key - Add a translation - "profile.security.form.notifications.error.title": "Error changing passwords", - - // "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", - // TODO New key - Add a translation - "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", - - // "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", - // TODO New key - Add a translation - "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", - - // "profile.title": "Update Profile", - // TODO New key - Add a translation - "profile.title": "Update Profile", - - - // "project.listelement.badge": "Research Project", "project.listelement.badge": "Projeto de Pesquisa", @@ -3399,192 +3116,6 @@ - // "resource-policies.add.button": "Add", - // TODO New key - Add a translation - "resource-policies.add.button": "Add", - - // "resource-policies.add.for.": "Add a new policy", - // TODO New key - Add a translation - "resource-policies.add.for.": "Add a new policy", - - // "resource-policies.add.for.bitstream": "Add a new Bitstream policy", - // TODO New key - Add a translation - "resource-policies.add.for.bitstream": "Add a new Bitstream policy", - - // "resource-policies.add.for.bundle": "Add a new Bundle policy", - // TODO New key - Add a translation - "resource-policies.add.for.bundle": "Add a new Bundle policy", - - // "resource-policies.add.for.item": "Add a new Item policy", - // TODO New key - Add a translation - "resource-policies.add.for.item": "Add a new Item policy", - - // "resource-policies.create.page.heading": "Create new resource policy for ", - // TODO New key - Add a translation - "resource-policies.create.page.heading": "Create new resource policy for ", - - // "resource-policies.create.page.failure.content": "An error occurred while creating the resource policy.", - // TODO New key - Add a translation - "resource-policies.create.page.failure.content": "An error occurred while creating the resource policy.", - - // "resource-policies.create.page.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.create.page.success.content": "Operation successful", - - // "resource-policies.create.page.title": "Create new resource policy", - // TODO New key - Add a translation - "resource-policies.create.page.title": "Create new resource policy", - - // "resource-policies.delete.btn": "Delete selected", - // TODO New key - Add a translation - "resource-policies.delete.btn": "Delete selected", - - // "resource-policies.delete.btn.title": "Delete selected resource policies", - // TODO New key - Add a translation - "resource-policies.delete.btn.title": "Delete selected resource policies", - - // "resource-policies.delete.failure.content": "An error occurred while deleting selected resource policies.", - // TODO New key - Add a translation - "resource-policies.delete.failure.content": "An error occurred while deleting selected resource policies.", - - // "resource-policies.delete.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.delete.success.content": "Operation successful", - - // "resource-policies.edit.page.heading": "Edit resource policy ", - // TODO New key - Add a translation - "resource-policies.edit.page.heading": "Edit resource policy ", - - // "resource-policies.edit.page.failure.content": "An error occurred while editing the resource policy.", - // TODO New key - Add a translation - "resource-policies.edit.page.failure.content": "An error occurred while editing the resource policy.", - - // "resource-policies.edit.page.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.edit.page.success.content": "Operation successful", - - // "resource-policies.edit.page.title": "Edit resource policy", - // TODO New key - Add a translation - "resource-policies.edit.page.title": "Edit resource policy", - - // "resource-policies.form.action-type.label": "Select the action type", - // TODO New key - Add a translation - "resource-policies.form.action-type.label": "Select the action type", - - // "resource-policies.form.action-type.required": "You must select the resource policy action.", - // TODO New key - Add a translation - "resource-policies.form.action-type.required": "You must select the resource policy action.", - - // "resource-policies.form.eperson-group-list.label": "The eperson or group that will be grant of the permission", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.label": "The eperson or group that will be grant of the permission", - - // "resource-policies.form.eperson-group-list.select.btn": "Select", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.select.btn": "Select", - - // "resource-policies.form.eperson-group-list.tab.eperson": "Search for a ePerson", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.tab.eperson": "Search for a ePerson", - - // "resource-policies.form.eperson-group-list.tab.group": "Search for a group", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.tab.group": "Search for a group", - - // "resource-policies.form.eperson-group-list.table.headers.action": "Action", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.action": "Action", - - // "resource-policies.form.eperson-group-list.table.headers.id": "ID", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.id": "ID", - - // "resource-policies.form.eperson-group-list.table.headers.name": "Name", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.name": "Name", - - // "resource-policies.form.date.end.label": "End Date", - // TODO New key - Add a translation - "resource-policies.form.date.end.label": "End Date", - - // "resource-policies.form.date.start.label": "Start Date", - // TODO New key - Add a translation - "resource-policies.form.date.start.label": "Start Date", - - // "resource-policies.form.description.label": "Description", - // TODO New key - Add a translation - "resource-policies.form.description.label": "Description", - - // "resource-policies.form.name.label": "Name", - // TODO New key - Add a translation - "resource-policies.form.name.label": "Name", - - // "resource-policies.form.policy-type.label": "Select the policy type", - // TODO New key - Add a translation - "resource-policies.form.policy-type.label": "Select the policy type", - - // "resource-policies.form.policy-type.required": "You must select the resource policy type.", - // TODO New key - Add a translation - "resource-policies.form.policy-type.required": "You must select the resource policy type.", - - // "resource-policies.table.headers.action": "Action", - // TODO New key - Add a translation - "resource-policies.table.headers.action": "Action", - - // "resource-policies.table.headers.date.end": "End Date", - // TODO New key - Add a translation - "resource-policies.table.headers.date.end": "End Date", - - // "resource-policies.table.headers.date.start": "Start Date", - // TODO New key - Add a translation - "resource-policies.table.headers.date.start": "Start Date", - - // "resource-policies.table.headers.edit": "Edit", - // TODO New key - Add a translation - "resource-policies.table.headers.edit": "Edit", - - // "resource-policies.table.headers.edit.group": "Edit group", - // TODO New key - Add a translation - "resource-policies.table.headers.edit.group": "Edit group", - - // "resource-policies.table.headers.edit.policy": "Edit policy", - // TODO New key - Add a translation - "resource-policies.table.headers.edit.policy": "Edit policy", - - // "resource-policies.table.headers.eperson": "EPerson", - // TODO New key - Add a translation - "resource-policies.table.headers.eperson": "EPerson", - - // "resource-policies.table.headers.group": "Group", - // TODO New key - Add a translation - "resource-policies.table.headers.group": "Group", - - // "resource-policies.table.headers.id": "ID", - // TODO New key - Add a translation - "resource-policies.table.headers.id": "ID", - - // "resource-policies.table.headers.name": "Name", - // TODO New key - Add a translation - "resource-policies.table.headers.name": "Name", - - // "resource-policies.table.headers.policyType": "type", - // TODO New key - Add a translation - "resource-policies.table.headers.policyType": "type", - - // "resource-policies.table.headers.title.for.bitstream": "Policies for Bitstream", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.bitstream": "Policies for Bitstream", - - // "resource-policies.table.headers.title.for.bundle": "Policies for Bundle", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.bundle": "Policies for Bundle", - - // "resource-policies.table.headers.title.for.item": "Policies for Item", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.item": "Policies for Item", - - - // "search.description": "", "search.description": "", @@ -4311,8 +3842,7 @@ // "submission.sections.upload.form.date-required": "Date is required.", "submission.sections.upload.form.date-required": "Data necessária.", - // "submission.sections.upload.form.from-label": "Grant access from", - // TODO Source message changed - Revise the translation + // "submission.sections.upload.form.from-label": "Access grant from", "submission.sections.upload.form.from-label": "Acesso permitido a partir de", // "submission.sections.upload.form.from-placeholder": "From", @@ -4324,8 +3854,7 @@ // "submission.sections.upload.form.group-required": "Group is required.", "submission.sections.upload.form.group-required": "Grupo é necessário.", - // "submission.sections.upload.form.until-label": "Grant access until", - // TODO Source message changed - Revise the translation + // "submission.sections.upload.form.until-label": "Access grant until", "submission.sections.upload.form.until-label": "Acesso permitido até", // "submission.sections.upload.form.until-placeholder": "Until", @@ -4493,78 +4022,5 @@ "virtual-metadata.delete-relationship.modal-head": "Select the items for which you want to save the virtual metadata as real metadata", - - // "workflowAdmin.search.results.head": "Administer Workflow", - // TODO New key - Add a translation - "workflowAdmin.search.results.head": "Administer Workflow", - - - - // "workflow-item.delete.notification.success.title": "Deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.success.title": "Deleted", - - // "workflow-item.delete.notification.success.content": "This workflow item was successfully deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.success.content": "This workflow item was successfully deleted", - - // "workflow-item.delete.notification.error.title": "Something went wrong", - // TODO New key - Add a translation - "workflow-item.delete.notification.error.title": "Something went wrong", - - // "workflow-item.delete.notification.error.content": "The workflow item could not be deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.error.content": "The workflow item could not be deleted", - - // "workflow-item.delete.title": "Delete workflow item", - // TODO New key - Add a translation - "workflow-item.delete.title": "Delete workflow item", - - // "workflow-item.delete.header": "Delete workflow item", - // TODO New key - Add a translation - "workflow-item.delete.header": "Delete workflow item", - - // "workflow-item.delete.button.cancel": "Cancel", - // TODO New key - Add a translation - "workflow-item.delete.button.cancel": "Cancel", - - // "workflow-item.delete.button.confirm": "Delete", - // TODO New key - Add a translation - "workflow-item.delete.button.confirm": "Delete", - - - // "workflow-item.send-back.notification.success.title": "Sent back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.success.title": "Sent back to submitter", - - // "workflow-item.send-back.notification.success.content": "This workflow item was successfully sent back to the submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.success.content": "This workflow item was successfully sent back to the submitter", - - // "workflow-item.send-back.notification.error.title": "Something went wrong", - // TODO New key - Add a translation - "workflow-item.send-back.notification.error.title": "Something went wrong", - - // "workflow-item.send-back.notification.error.content": "The workflow item could not be sent back to the submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.error.content": "The workflow item could not be sent back to the submitter", - - // "workflow-item.send-back.title": "Send workflow item back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.title": "Send workflow item back to submitter", - - // "workflow-item.send-back.header": "Send workflow item back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.header": "Send workflow item back to submitter", - - // "workflow-item.send-back.button.cancel": "Cancel", - // TODO New key - Add a translation - "workflow-item.send-back.button.cancel": "Cancel", - - // "workflow-item.send-back.button.confirm": "Send back", - // TODO New key - Add a translation - "workflow-item.send-back.button.confirm": "Send back", - - } \ No newline at end of file diff --git a/src/assets/i18n/sw.json5 b/src/assets/i18n/sw.json5 index 64a775dee8..d7afa97f08 100644 --- a/src/assets/i18n/sw.json5 +++ b/src/assets/i18n/sw.json5 @@ -332,22 +332,6 @@ - // "admin.access-control.epeople.actions.delete": "Delete EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.delete": "Delete EPerson", - - // "admin.access-control.epeople.actions.impersonate": "Impersonate EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.impersonate": "Impersonate EPerson", - - // "admin.access-control.epeople.actions.reset": "Reset password", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.reset": "Reset password", - - // "admin.access-control.epeople.actions.stop-impersonating": "Stop impersonating EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.stop-impersonating": "Stop impersonating EPerson", - // "admin.access-control.epeople.title": "DSpace Angular :: EPeople", // TODO New key - Add a translation "admin.access-control.epeople.title": "DSpace Angular :: EPeople", @@ -799,30 +783,6 @@ - - // "admin.workflow.breadcrumbs": "Administer Workflow", - // TODO New key - Add a translation - "admin.workflow.breadcrumbs": "Administer Workflow", - - // "admin.workflow.title": "Administer Workflow", - // TODO New key - Add a translation - "admin.workflow.title": "Administer Workflow", - - // "admin.workflow.item.workflow": "Workflow", - // TODO New key - Add a translation - "admin.workflow.item.workflow": "Workflow", - - // "admin.workflow.item.delete": "Delete", - // TODO New key - Add a translation - "admin.workflow.item.delete": "Delete", - - // "admin.workflow.item.send-back": "Send back", - // TODO New key - Add a translation - "admin.workflow.item.send-back": "Send back", - - - - // "auth.errors.invalid-user": "Invalid email address or password.", // TODO New key - Add a translation "auth.errors.invalid-user": "Invalid email address or password.", @@ -1515,104 +1475,6 @@ - // "comcol-role.edit.no-group": "None", - // TODO New key - Add a translation - "comcol-role.edit.no-group": "None", - - // "comcol-role.edit.create": "Create", - // TODO New key - Add a translation - "comcol-role.edit.create": "Create", - - // "comcol-role.edit.restrict": "Restrict", - // TODO New key - Add a translation - "comcol-role.edit.restrict": "Restrict", - - // "comcol-role.edit.delete": "Delete", - // TODO New key - Add a translation - "comcol-role.edit.delete": "Delete", - - - // "comcol-role.edit.community-admin.name": "Administrators", - // TODO New key - Add a translation - "comcol-role.edit.community-admin.name": "Administrators", - - // "comcol-role.edit.collection-admin.name": "Administrators", - // TODO New key - Add a translation - "comcol-role.edit.collection-admin.name": "Administrators", - - - // "comcol-role.edit.community-admin.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - // TODO New key - Add a translation - "comcol-role.edit.community-admin.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - - // "comcol-role.edit.collection-admin.description": "Collection administrators decide who can submit items to the collection, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization for that collection).", - // TODO New key - Add a translation - "comcol-role.edit.collection-admin.description": "Collection administrators decide who can submit items to the collection, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization for that collection).", - - - // "comcol-role.edit.submitters.name": "Submitters", - // TODO New key - Add a translation - "comcol-role.edit.submitters.name": "Submitters", - - // "comcol-role.edit.submitters.description": "The E-People and Groups that have permission to submit new items to this collection.", - // TODO New key - Add a translation - "comcol-role.edit.submitters.description": "The E-People and Groups that have permission to submit new items to this collection.", - - - // "comcol-role.edit.item_read.name": "Default item read access", - // TODO New key - Add a translation - "comcol-role.edit.item_read.name": "Default item read access", - - // "comcol-role.edit.item_read.description": "E-People and Groups that can read new items submitted to this collection. Changes to this role are not retroactive. Existing items in the system will still be viewable by those who had read access at the time of their addition.", - // TODO New key - Add a translation - "comcol-role.edit.item_read.description": "E-People and Groups that can read new items submitted to this collection. Changes to this role are not retroactive. Existing items in the system will still be viewable by those who had read access at the time of their addition.", - - // "comcol-role.edit.item_read.anonymous-group": "Default read for incoming items is currently set to Anonymous.", - // TODO New key - Add a translation - "comcol-role.edit.item_read.anonymous-group": "Default read for incoming items is currently set to Anonymous.", - - - // "comcol-role.edit.bitstream_read.name": "Default bitstream read access", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.name": "Default bitstream read access", - - // "comcol-role.edit.bitstream_read.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - - // "comcol-role.edit.bitstream_read.anonymous-group": "Default read for incoming bitstreams is currently set to Anonymous.", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.anonymous-group": "Default read for incoming bitstreams is currently set to Anonymous.", - - - // "comcol-role.edit.editor.name": "Editors", - // TODO New key - Add a translation - "comcol-role.edit.editor.name": "Editors", - - // "comcol-role.edit.editor.description": "Editors are able to edit the metadata of incoming submissions, and then accept or reject them.", - // TODO New key - Add a translation - "comcol-role.edit.editor.description": "Editors are able to edit the metadata of incoming submissions, and then accept or reject them.", - - - // "comcol-role.edit.finaleditor.name": "Final editors", - // TODO New key - Add a translation - "comcol-role.edit.finaleditor.name": "Final editors", - - // "comcol-role.edit.finaleditor.description": "Final editors are able to edit the metadata of incoming submissions, but will not be able to reject them.", - // TODO New key - Add a translation - "comcol-role.edit.finaleditor.description": "Final editors are able to edit the metadata of incoming submissions, but will not be able to reject them.", - - - // "comcol-role.edit.reviewer.name": "Reviewers", - // TODO New key - Add a translation - "comcol-role.edit.reviewer.name": "Reviewers", - - // "comcol-role.edit.reviewer.description": "Reviewers are able to accept or reject incoming submissions. However, they are not able to edit the submission's metadata.", - // TODO New key - Add a translation - "comcol-role.edit.reviewer.description": "Reviewers are able to accept or reject incoming submissions. However, they are not able to edit the submission's metadata.", - - - // "community.form.abstract": "Short Description", // TODO New key - Add a translation "community.form.abstract": "Short Description", @@ -1683,10 +1545,6 @@ // TODO New key - Add a translation "dso-selector.create.item.head": "New item", - // "dso-selector.create.submission.head": "New submission", - // TODO New key - Add a translation - "dso-selector.create.submission.head": "New submission", - // "dso-selector.edit.collection.head": "Edit collection", // TODO New key - Add a translation "dso-selector.edit.collection.head": "Edit collection", @@ -1892,9 +1750,9 @@ // TODO New key - Add a translation "form.search": "Search", - // "form.search-help": "Click here to look for an existing correspondence", + // "form.search-help": "Click here to looking for an existing correspondence", // TODO New key - Add a translation - "form.search-help": "Click here to look for an existing correspondence", + "form.search-help": "Click here to looking for an existing correspondence", // "form.submit": "Submit", // TODO New key - Add a translation @@ -1920,15 +1778,6 @@ - // "item.edit.authorizations.heading": "With this editor you can view and alter the policies of an item, plus alter policies of individual item components: bundles and bitstreams. Briefly, an item is a container of bundles, and bundles are containers of bitstreams. Containers usually have ADD/REMOVE/READ/WRITE policies, while bitstreams only have READ/WRITE policies.", - // TODO New key - Add a translation - "item.edit.authorizations.heading": "With this editor you can view and alter the policies of an item, plus alter policies of individual item components: bundles and bitstreams. Briefly, an item is a container of bundles, and bundles are containers of bitstreams. Containers usually have ADD/REMOVE/READ/WRITE policies, while bitstreams only have READ/WRITE policies.", - - // "item.edit.authorizations.title": "Edit item's Policies", - // TODO New key - Add a translation - "item.edit.authorizations.title": "Edit item's Policies", - - // "item.bitstreams.upload.bundle": "Bundle", // TODO New key - Add a translation @@ -3318,18 +3167,14 @@ "menu.section.toggle.statistics_task": "Toggle Statistics Task section", - // "menu.section.workflow": "Administer Workflow", - // TODO New key - Add a translation - "menu.section.workflow": "Administer Workflow", - // "mydspace.description": "", // TODO New key - Add a translation "mydspace.description": "", - // "mydspace.general.text-here": "here", + // "mydspace.general.text-here": "HERE", // TODO New key - Add a translation - "mydspace.general.text-here": "here", + "mydspace.general.text-here": "HERE", // "mydspace.messages.controller-help": "Select this option to send a message to item's submitter.", // TODO New key - Add a translation @@ -3459,14 +3304,6 @@ // TODO New key - Add a translation "mydspace.upload.upload-failed": "Error creating new workspace. Please verify the content uploaded before retry.", - // "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", - // TODO New key - Add a translation - "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", - - // "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", - // TODO New key - Add a translation - "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", - // "mydspace.upload.upload-multiple-successful": "{{qty}} new workspace items created.", // TODO New key - Add a translation "mydspace.upload.upload-multiple-successful": "{{qty}} new workspace items created.", @@ -3517,10 +3354,6 @@ // TODO New key - Add a translation "nav.statistics.header": "Statistics", - // "nav.stop-impersonating": "Stop impersonating EPerson", - // TODO New key - Add a translation - "nav.stop-impersonating": "Stop impersonating EPerson", - // "orgunit.listelement.badge": "Organizational Unit", @@ -3735,120 +3568,6 @@ - // "profile.breadcrumbs": "Update Profile", - // TODO New key - Add a translation - "profile.breadcrumbs": "Update Profile", - - // "profile.card.identify": "Identify", - // TODO New key - Add a translation - "profile.card.identify": "Identify", - - // "profile.card.security": "Security", - // TODO New key - Add a translation - "profile.card.security": "Security", - - // "profile.form.submit": "Update Profile", - // TODO New key - Add a translation - "profile.form.submit": "Update Profile", - - // "profile.groups.head": "Authorization groups you belong to", - // TODO New key - Add a translation - "profile.groups.head": "Authorization groups you belong to", - - // "profile.head": "Update Profile", - // TODO New key - Add a translation - "profile.head": "Update Profile", - - // "profile.metadata.form.error.firstname.required": "First Name is required", - // TODO New key - Add a translation - "profile.metadata.form.error.firstname.required": "First Name is required", - - // "profile.metadata.form.error.lastname.required": "Last Name is required", - // TODO New key - Add a translation - "profile.metadata.form.error.lastname.required": "Last Name is required", - - // "profile.metadata.form.label.email": "Email Address", - // TODO New key - Add a translation - "profile.metadata.form.label.email": "Email Address", - - // "profile.metadata.form.label.firstname": "First Name", - // TODO New key - Add a translation - "profile.metadata.form.label.firstname": "First Name", - - // "profile.metadata.form.label.language": "Language", - // TODO New key - Add a translation - "profile.metadata.form.label.language": "Language", - - // "profile.metadata.form.label.lastname": "Last Name", - // TODO New key - Add a translation - "profile.metadata.form.label.lastname": "Last Name", - - // "profile.metadata.form.label.phone": "Contact Telephone", - // TODO New key - Add a translation - "profile.metadata.form.label.phone": "Contact Telephone", - - // "profile.metadata.form.notifications.success.content": "Your changes to the profile were saved.", - // TODO New key - Add a translation - "profile.metadata.form.notifications.success.content": "Your changes to the profile were saved.", - - // "profile.metadata.form.notifications.success.title": "Profile saved", - // TODO New key - Add a translation - "profile.metadata.form.notifications.success.title": "Profile saved", - - // "profile.notifications.warning.no-changes.content": "No changes were made to the Profile.", - // TODO New key - Add a translation - "profile.notifications.warning.no-changes.content": "No changes were made to the Profile.", - - // "profile.notifications.warning.no-changes.title": "No changes", - // TODO New key - Add a translation - "profile.notifications.warning.no-changes.title": "No changes", - - // "profile.security.form.error.matching-passwords": "The passwords do not match.", - // TODO New key - Add a translation - "profile.security.form.error.matching-passwords": "The passwords do not match.", - - // "profile.security.form.error.password-length": "The password should be at least 6 characters long.", - // TODO New key - Add a translation - "profile.security.form.error.password-length": "The password should be at least 6 characters long.", - - // "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.", - // TODO New key - Add a translation - "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.", - - // "profile.security.form.label.password": "Password", - // TODO New key - Add a translation - "profile.security.form.label.password": "Password", - - // "profile.security.form.label.passwordrepeat": "Retype to confirm", - // TODO New key - Add a translation - "profile.security.form.label.passwordrepeat": "Retype to confirm", - - // "profile.security.form.notifications.success.content": "Your changes to the password were saved.", - // TODO New key - Add a translation - "profile.security.form.notifications.success.content": "Your changes to the password were saved.", - - // "profile.security.form.notifications.success.title": "Password saved", - // TODO New key - Add a translation - "profile.security.form.notifications.success.title": "Password saved", - - // "profile.security.form.notifications.error.title": "Error changing passwords", - // TODO New key - Add a translation - "profile.security.form.notifications.error.title": "Error changing passwords", - - // "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", - // TODO New key - Add a translation - "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", - - // "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", - // TODO New key - Add a translation - "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", - - // "profile.title": "Update Profile", - // TODO New key - Add a translation - "profile.title": "Update Profile", - - - // "project.listelement.badge": "Research Project", // TODO New key - Add a translation "project.listelement.badge": "Research Project", @@ -3983,192 +3702,6 @@ - // "resource-policies.add.button": "Add", - // TODO New key - Add a translation - "resource-policies.add.button": "Add", - - // "resource-policies.add.for.": "Add a new policy", - // TODO New key - Add a translation - "resource-policies.add.for.": "Add a new policy", - - // "resource-policies.add.for.bitstream": "Add a new Bitstream policy", - // TODO New key - Add a translation - "resource-policies.add.for.bitstream": "Add a new Bitstream policy", - - // "resource-policies.add.for.bundle": "Add a new Bundle policy", - // TODO New key - Add a translation - "resource-policies.add.for.bundle": "Add a new Bundle policy", - - // "resource-policies.add.for.item": "Add a new Item policy", - // TODO New key - Add a translation - "resource-policies.add.for.item": "Add a new Item policy", - - // "resource-policies.create.page.heading": "Create new resource policy for ", - // TODO New key - Add a translation - "resource-policies.create.page.heading": "Create new resource policy for ", - - // "resource-policies.create.page.failure.content": "An error occurred while creating the resource policy.", - // TODO New key - Add a translation - "resource-policies.create.page.failure.content": "An error occurred while creating the resource policy.", - - // "resource-policies.create.page.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.create.page.success.content": "Operation successful", - - // "resource-policies.create.page.title": "Create new resource policy", - // TODO New key - Add a translation - "resource-policies.create.page.title": "Create new resource policy", - - // "resource-policies.delete.btn": "Delete selected", - // TODO New key - Add a translation - "resource-policies.delete.btn": "Delete selected", - - // "resource-policies.delete.btn.title": "Delete selected resource policies", - // TODO New key - Add a translation - "resource-policies.delete.btn.title": "Delete selected resource policies", - - // "resource-policies.delete.failure.content": "An error occurred while deleting selected resource policies.", - // TODO New key - Add a translation - "resource-policies.delete.failure.content": "An error occurred while deleting selected resource policies.", - - // "resource-policies.delete.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.delete.success.content": "Operation successful", - - // "resource-policies.edit.page.heading": "Edit resource policy ", - // TODO New key - Add a translation - "resource-policies.edit.page.heading": "Edit resource policy ", - - // "resource-policies.edit.page.failure.content": "An error occurred while editing the resource policy.", - // TODO New key - Add a translation - "resource-policies.edit.page.failure.content": "An error occurred while editing the resource policy.", - - // "resource-policies.edit.page.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.edit.page.success.content": "Operation successful", - - // "resource-policies.edit.page.title": "Edit resource policy", - // TODO New key - Add a translation - "resource-policies.edit.page.title": "Edit resource policy", - - // "resource-policies.form.action-type.label": "Select the action type", - // TODO New key - Add a translation - "resource-policies.form.action-type.label": "Select the action type", - - // "resource-policies.form.action-type.required": "You must select the resource policy action.", - // TODO New key - Add a translation - "resource-policies.form.action-type.required": "You must select the resource policy action.", - - // "resource-policies.form.eperson-group-list.label": "The eperson or group that will be grant of the permission", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.label": "The eperson or group that will be grant of the permission", - - // "resource-policies.form.eperson-group-list.select.btn": "Select", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.select.btn": "Select", - - // "resource-policies.form.eperson-group-list.tab.eperson": "Search for a ePerson", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.tab.eperson": "Search for a ePerson", - - // "resource-policies.form.eperson-group-list.tab.group": "Search for a group", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.tab.group": "Search for a group", - - // "resource-policies.form.eperson-group-list.table.headers.action": "Action", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.action": "Action", - - // "resource-policies.form.eperson-group-list.table.headers.id": "ID", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.id": "ID", - - // "resource-policies.form.eperson-group-list.table.headers.name": "Name", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.name": "Name", - - // "resource-policies.form.date.end.label": "End Date", - // TODO New key - Add a translation - "resource-policies.form.date.end.label": "End Date", - - // "resource-policies.form.date.start.label": "Start Date", - // TODO New key - Add a translation - "resource-policies.form.date.start.label": "Start Date", - - // "resource-policies.form.description.label": "Description", - // TODO New key - Add a translation - "resource-policies.form.description.label": "Description", - - // "resource-policies.form.name.label": "Name", - // TODO New key - Add a translation - "resource-policies.form.name.label": "Name", - - // "resource-policies.form.policy-type.label": "Select the policy type", - // TODO New key - Add a translation - "resource-policies.form.policy-type.label": "Select the policy type", - - // "resource-policies.form.policy-type.required": "You must select the resource policy type.", - // TODO New key - Add a translation - "resource-policies.form.policy-type.required": "You must select the resource policy type.", - - // "resource-policies.table.headers.action": "Action", - // TODO New key - Add a translation - "resource-policies.table.headers.action": "Action", - - // "resource-policies.table.headers.date.end": "End Date", - // TODO New key - Add a translation - "resource-policies.table.headers.date.end": "End Date", - - // "resource-policies.table.headers.date.start": "Start Date", - // TODO New key - Add a translation - "resource-policies.table.headers.date.start": "Start Date", - - // "resource-policies.table.headers.edit": "Edit", - // TODO New key - Add a translation - "resource-policies.table.headers.edit": "Edit", - - // "resource-policies.table.headers.edit.group": "Edit group", - // TODO New key - Add a translation - "resource-policies.table.headers.edit.group": "Edit group", - - // "resource-policies.table.headers.edit.policy": "Edit policy", - // TODO New key - Add a translation - "resource-policies.table.headers.edit.policy": "Edit policy", - - // "resource-policies.table.headers.eperson": "EPerson", - // TODO New key - Add a translation - "resource-policies.table.headers.eperson": "EPerson", - - // "resource-policies.table.headers.group": "Group", - // TODO New key - Add a translation - "resource-policies.table.headers.group": "Group", - - // "resource-policies.table.headers.id": "ID", - // TODO New key - Add a translation - "resource-policies.table.headers.id": "ID", - - // "resource-policies.table.headers.name": "Name", - // TODO New key - Add a translation - "resource-policies.table.headers.name": "Name", - - // "resource-policies.table.headers.policyType": "type", - // TODO New key - Add a translation - "resource-policies.table.headers.policyType": "type", - - // "resource-policies.table.headers.title.for.bitstream": "Policies for Bitstream", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.bitstream": "Policies for Bitstream", - - // "resource-policies.table.headers.title.for.bundle": "Policies for Bundle", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.bundle": "Policies for Bundle", - - // "resource-policies.table.headers.title.for.item": "Policies for Item", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.item": "Policies for Item", - - - // "search.description": "", // TODO New key - Add a translation "search.description": "", @@ -5013,9 +4546,9 @@ // TODO New key - Add a translation "submission.sections.upload.form.date-required": "Date is required.", - // "submission.sections.upload.form.from-label": "Grant access from", + // "submission.sections.upload.form.from-label": "Access grant from", // TODO New key - Add a translation - "submission.sections.upload.form.from-label": "Grant access from", + "submission.sections.upload.form.from-label": "Access grant from", // "submission.sections.upload.form.from-placeholder": "From", // TODO New key - Add a translation @@ -5029,9 +4562,9 @@ // TODO New key - Add a translation "submission.sections.upload.form.group-required": "Group is required.", - // "submission.sections.upload.form.until-label": "Grant access until", + // "submission.sections.upload.form.until-label": "Access grant until", // TODO New key - Add a translation - "submission.sections.upload.form.until-label": "Grant access until", + "submission.sections.upload.form.until-label": "Access grant until", // "submission.sections.upload.form.until-placeholder": "Until", // TODO New key - Add a translation @@ -5241,78 +4774,5 @@ "virtual-metadata.delete-relationship.modal-head": "Select the items for which you want to save the virtual metadata as real metadata", - - // "workflowAdmin.search.results.head": "Administer Workflow", - // TODO New key - Add a translation - "workflowAdmin.search.results.head": "Administer Workflow", - - - - // "workflow-item.delete.notification.success.title": "Deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.success.title": "Deleted", - - // "workflow-item.delete.notification.success.content": "This workflow item was successfully deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.success.content": "This workflow item was successfully deleted", - - // "workflow-item.delete.notification.error.title": "Something went wrong", - // TODO New key - Add a translation - "workflow-item.delete.notification.error.title": "Something went wrong", - - // "workflow-item.delete.notification.error.content": "The workflow item could not be deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.error.content": "The workflow item could not be deleted", - - // "workflow-item.delete.title": "Delete workflow item", - // TODO New key - Add a translation - "workflow-item.delete.title": "Delete workflow item", - - // "workflow-item.delete.header": "Delete workflow item", - // TODO New key - Add a translation - "workflow-item.delete.header": "Delete workflow item", - - // "workflow-item.delete.button.cancel": "Cancel", - // TODO New key - Add a translation - "workflow-item.delete.button.cancel": "Cancel", - - // "workflow-item.delete.button.confirm": "Delete", - // TODO New key - Add a translation - "workflow-item.delete.button.confirm": "Delete", - - - // "workflow-item.send-back.notification.success.title": "Sent back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.success.title": "Sent back to submitter", - - // "workflow-item.send-back.notification.success.content": "This workflow item was successfully sent back to the submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.success.content": "This workflow item was successfully sent back to the submitter", - - // "workflow-item.send-back.notification.error.title": "Something went wrong", - // TODO New key - Add a translation - "workflow-item.send-back.notification.error.title": "Something went wrong", - - // "workflow-item.send-back.notification.error.content": "The workflow item could not be sent back to the submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.error.content": "The workflow item could not be sent back to the submitter", - - // "workflow-item.send-back.title": "Send workflow item back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.title": "Send workflow item back to submitter", - - // "workflow-item.send-back.header": "Send workflow item back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.header": "Send workflow item back to submitter", - - // "workflow-item.send-back.button.cancel": "Cancel", - // TODO New key - Add a translation - "workflow-item.send-back.button.cancel": "Cancel", - - // "workflow-item.send-back.button.confirm": "Send back", - // TODO New key - Add a translation - "workflow-item.send-back.button.confirm": "Send back", - - } \ No newline at end of file diff --git a/src/assets/i18n/tr.json5 b/src/assets/i18n/tr.json5 index 64a775dee8..d7afa97f08 100644 --- a/src/assets/i18n/tr.json5 +++ b/src/assets/i18n/tr.json5 @@ -332,22 +332,6 @@ - // "admin.access-control.epeople.actions.delete": "Delete EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.delete": "Delete EPerson", - - // "admin.access-control.epeople.actions.impersonate": "Impersonate EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.impersonate": "Impersonate EPerson", - - // "admin.access-control.epeople.actions.reset": "Reset password", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.reset": "Reset password", - - // "admin.access-control.epeople.actions.stop-impersonating": "Stop impersonating EPerson", - // TODO New key - Add a translation - "admin.access-control.epeople.actions.stop-impersonating": "Stop impersonating EPerson", - // "admin.access-control.epeople.title": "DSpace Angular :: EPeople", // TODO New key - Add a translation "admin.access-control.epeople.title": "DSpace Angular :: EPeople", @@ -799,30 +783,6 @@ - - // "admin.workflow.breadcrumbs": "Administer Workflow", - // TODO New key - Add a translation - "admin.workflow.breadcrumbs": "Administer Workflow", - - // "admin.workflow.title": "Administer Workflow", - // TODO New key - Add a translation - "admin.workflow.title": "Administer Workflow", - - // "admin.workflow.item.workflow": "Workflow", - // TODO New key - Add a translation - "admin.workflow.item.workflow": "Workflow", - - // "admin.workflow.item.delete": "Delete", - // TODO New key - Add a translation - "admin.workflow.item.delete": "Delete", - - // "admin.workflow.item.send-back": "Send back", - // TODO New key - Add a translation - "admin.workflow.item.send-back": "Send back", - - - - // "auth.errors.invalid-user": "Invalid email address or password.", // TODO New key - Add a translation "auth.errors.invalid-user": "Invalid email address or password.", @@ -1515,104 +1475,6 @@ - // "comcol-role.edit.no-group": "None", - // TODO New key - Add a translation - "comcol-role.edit.no-group": "None", - - // "comcol-role.edit.create": "Create", - // TODO New key - Add a translation - "comcol-role.edit.create": "Create", - - // "comcol-role.edit.restrict": "Restrict", - // TODO New key - Add a translation - "comcol-role.edit.restrict": "Restrict", - - // "comcol-role.edit.delete": "Delete", - // TODO New key - Add a translation - "comcol-role.edit.delete": "Delete", - - - // "comcol-role.edit.community-admin.name": "Administrators", - // TODO New key - Add a translation - "comcol-role.edit.community-admin.name": "Administrators", - - // "comcol-role.edit.collection-admin.name": "Administrators", - // TODO New key - Add a translation - "comcol-role.edit.collection-admin.name": "Administrators", - - - // "comcol-role.edit.community-admin.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - // TODO New key - Add a translation - "comcol-role.edit.community-admin.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - - // "comcol-role.edit.collection-admin.description": "Collection administrators decide who can submit items to the collection, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization for that collection).", - // TODO New key - Add a translation - "comcol-role.edit.collection-admin.description": "Collection administrators decide who can submit items to the collection, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization for that collection).", - - - // "comcol-role.edit.submitters.name": "Submitters", - // TODO New key - Add a translation - "comcol-role.edit.submitters.name": "Submitters", - - // "comcol-role.edit.submitters.description": "The E-People and Groups that have permission to submit new items to this collection.", - // TODO New key - Add a translation - "comcol-role.edit.submitters.description": "The E-People and Groups that have permission to submit new items to this collection.", - - - // "comcol-role.edit.item_read.name": "Default item read access", - // TODO New key - Add a translation - "comcol-role.edit.item_read.name": "Default item read access", - - // "comcol-role.edit.item_read.description": "E-People and Groups that can read new items submitted to this collection. Changes to this role are not retroactive. Existing items in the system will still be viewable by those who had read access at the time of their addition.", - // TODO New key - Add a translation - "comcol-role.edit.item_read.description": "E-People and Groups that can read new items submitted to this collection. Changes to this role are not retroactive. Existing items in the system will still be viewable by those who had read access at the time of their addition.", - - // "comcol-role.edit.item_read.anonymous-group": "Default read for incoming items is currently set to Anonymous.", - // TODO New key - Add a translation - "comcol-role.edit.item_read.anonymous-group": "Default read for incoming items is currently set to Anonymous.", - - - // "comcol-role.edit.bitstream_read.name": "Default bitstream read access", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.name": "Default bitstream read access", - - // "comcol-role.edit.bitstream_read.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", - - // "comcol-role.edit.bitstream_read.anonymous-group": "Default read for incoming bitstreams is currently set to Anonymous.", - // TODO New key - Add a translation - "comcol-role.edit.bitstream_read.anonymous-group": "Default read for incoming bitstreams is currently set to Anonymous.", - - - // "comcol-role.edit.editor.name": "Editors", - // TODO New key - Add a translation - "comcol-role.edit.editor.name": "Editors", - - // "comcol-role.edit.editor.description": "Editors are able to edit the metadata of incoming submissions, and then accept or reject them.", - // TODO New key - Add a translation - "comcol-role.edit.editor.description": "Editors are able to edit the metadata of incoming submissions, and then accept or reject them.", - - - // "comcol-role.edit.finaleditor.name": "Final editors", - // TODO New key - Add a translation - "comcol-role.edit.finaleditor.name": "Final editors", - - // "comcol-role.edit.finaleditor.description": "Final editors are able to edit the metadata of incoming submissions, but will not be able to reject them.", - // TODO New key - Add a translation - "comcol-role.edit.finaleditor.description": "Final editors are able to edit the metadata of incoming submissions, but will not be able to reject them.", - - - // "comcol-role.edit.reviewer.name": "Reviewers", - // TODO New key - Add a translation - "comcol-role.edit.reviewer.name": "Reviewers", - - // "comcol-role.edit.reviewer.description": "Reviewers are able to accept or reject incoming submissions. However, they are not able to edit the submission's metadata.", - // TODO New key - Add a translation - "comcol-role.edit.reviewer.description": "Reviewers are able to accept or reject incoming submissions. However, they are not able to edit the submission's metadata.", - - - // "community.form.abstract": "Short Description", // TODO New key - Add a translation "community.form.abstract": "Short Description", @@ -1683,10 +1545,6 @@ // TODO New key - Add a translation "dso-selector.create.item.head": "New item", - // "dso-selector.create.submission.head": "New submission", - // TODO New key - Add a translation - "dso-selector.create.submission.head": "New submission", - // "dso-selector.edit.collection.head": "Edit collection", // TODO New key - Add a translation "dso-selector.edit.collection.head": "Edit collection", @@ -1892,9 +1750,9 @@ // TODO New key - Add a translation "form.search": "Search", - // "form.search-help": "Click here to look for an existing correspondence", + // "form.search-help": "Click here to looking for an existing correspondence", // TODO New key - Add a translation - "form.search-help": "Click here to look for an existing correspondence", + "form.search-help": "Click here to looking for an existing correspondence", // "form.submit": "Submit", // TODO New key - Add a translation @@ -1920,15 +1778,6 @@ - // "item.edit.authorizations.heading": "With this editor you can view and alter the policies of an item, plus alter policies of individual item components: bundles and bitstreams. Briefly, an item is a container of bundles, and bundles are containers of bitstreams. Containers usually have ADD/REMOVE/READ/WRITE policies, while bitstreams only have READ/WRITE policies.", - // TODO New key - Add a translation - "item.edit.authorizations.heading": "With this editor you can view and alter the policies of an item, plus alter policies of individual item components: bundles and bitstreams. Briefly, an item is a container of bundles, and bundles are containers of bitstreams. Containers usually have ADD/REMOVE/READ/WRITE policies, while bitstreams only have READ/WRITE policies.", - - // "item.edit.authorizations.title": "Edit item's Policies", - // TODO New key - Add a translation - "item.edit.authorizations.title": "Edit item's Policies", - - // "item.bitstreams.upload.bundle": "Bundle", // TODO New key - Add a translation @@ -3318,18 +3167,14 @@ "menu.section.toggle.statistics_task": "Toggle Statistics Task section", - // "menu.section.workflow": "Administer Workflow", - // TODO New key - Add a translation - "menu.section.workflow": "Administer Workflow", - // "mydspace.description": "", // TODO New key - Add a translation "mydspace.description": "", - // "mydspace.general.text-here": "here", + // "mydspace.general.text-here": "HERE", // TODO New key - Add a translation - "mydspace.general.text-here": "here", + "mydspace.general.text-here": "HERE", // "mydspace.messages.controller-help": "Select this option to send a message to item's submitter.", // TODO New key - Add a translation @@ -3459,14 +3304,6 @@ // TODO New key - Add a translation "mydspace.upload.upload-failed": "Error creating new workspace. Please verify the content uploaded before retry.", - // "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", - // TODO New key - Add a translation - "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", - - // "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", - // TODO New key - Add a translation - "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", - // "mydspace.upload.upload-multiple-successful": "{{qty}} new workspace items created.", // TODO New key - Add a translation "mydspace.upload.upload-multiple-successful": "{{qty}} new workspace items created.", @@ -3517,10 +3354,6 @@ // TODO New key - Add a translation "nav.statistics.header": "Statistics", - // "nav.stop-impersonating": "Stop impersonating EPerson", - // TODO New key - Add a translation - "nav.stop-impersonating": "Stop impersonating EPerson", - // "orgunit.listelement.badge": "Organizational Unit", @@ -3735,120 +3568,6 @@ - // "profile.breadcrumbs": "Update Profile", - // TODO New key - Add a translation - "profile.breadcrumbs": "Update Profile", - - // "profile.card.identify": "Identify", - // TODO New key - Add a translation - "profile.card.identify": "Identify", - - // "profile.card.security": "Security", - // TODO New key - Add a translation - "profile.card.security": "Security", - - // "profile.form.submit": "Update Profile", - // TODO New key - Add a translation - "profile.form.submit": "Update Profile", - - // "profile.groups.head": "Authorization groups you belong to", - // TODO New key - Add a translation - "profile.groups.head": "Authorization groups you belong to", - - // "profile.head": "Update Profile", - // TODO New key - Add a translation - "profile.head": "Update Profile", - - // "profile.metadata.form.error.firstname.required": "First Name is required", - // TODO New key - Add a translation - "profile.metadata.form.error.firstname.required": "First Name is required", - - // "profile.metadata.form.error.lastname.required": "Last Name is required", - // TODO New key - Add a translation - "profile.metadata.form.error.lastname.required": "Last Name is required", - - // "profile.metadata.form.label.email": "Email Address", - // TODO New key - Add a translation - "profile.metadata.form.label.email": "Email Address", - - // "profile.metadata.form.label.firstname": "First Name", - // TODO New key - Add a translation - "profile.metadata.form.label.firstname": "First Name", - - // "profile.metadata.form.label.language": "Language", - // TODO New key - Add a translation - "profile.metadata.form.label.language": "Language", - - // "profile.metadata.form.label.lastname": "Last Name", - // TODO New key - Add a translation - "profile.metadata.form.label.lastname": "Last Name", - - // "profile.metadata.form.label.phone": "Contact Telephone", - // TODO New key - Add a translation - "profile.metadata.form.label.phone": "Contact Telephone", - - // "profile.metadata.form.notifications.success.content": "Your changes to the profile were saved.", - // TODO New key - Add a translation - "profile.metadata.form.notifications.success.content": "Your changes to the profile were saved.", - - // "profile.metadata.form.notifications.success.title": "Profile saved", - // TODO New key - Add a translation - "profile.metadata.form.notifications.success.title": "Profile saved", - - // "profile.notifications.warning.no-changes.content": "No changes were made to the Profile.", - // TODO New key - Add a translation - "profile.notifications.warning.no-changes.content": "No changes were made to the Profile.", - - // "profile.notifications.warning.no-changes.title": "No changes", - // TODO New key - Add a translation - "profile.notifications.warning.no-changes.title": "No changes", - - // "profile.security.form.error.matching-passwords": "The passwords do not match.", - // TODO New key - Add a translation - "profile.security.form.error.matching-passwords": "The passwords do not match.", - - // "profile.security.form.error.password-length": "The password should be at least 6 characters long.", - // TODO New key - Add a translation - "profile.security.form.error.password-length": "The password should be at least 6 characters long.", - - // "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.", - // TODO New key - Add a translation - "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.", - - // "profile.security.form.label.password": "Password", - // TODO New key - Add a translation - "profile.security.form.label.password": "Password", - - // "profile.security.form.label.passwordrepeat": "Retype to confirm", - // TODO New key - Add a translation - "profile.security.form.label.passwordrepeat": "Retype to confirm", - - // "profile.security.form.notifications.success.content": "Your changes to the password were saved.", - // TODO New key - Add a translation - "profile.security.form.notifications.success.content": "Your changes to the password were saved.", - - // "profile.security.form.notifications.success.title": "Password saved", - // TODO New key - Add a translation - "profile.security.form.notifications.success.title": "Password saved", - - // "profile.security.form.notifications.error.title": "Error changing passwords", - // TODO New key - Add a translation - "profile.security.form.notifications.error.title": "Error changing passwords", - - // "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", - // TODO New key - Add a translation - "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", - - // "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", - // TODO New key - Add a translation - "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", - - // "profile.title": "Update Profile", - // TODO New key - Add a translation - "profile.title": "Update Profile", - - - // "project.listelement.badge": "Research Project", // TODO New key - Add a translation "project.listelement.badge": "Research Project", @@ -3983,192 +3702,6 @@ - // "resource-policies.add.button": "Add", - // TODO New key - Add a translation - "resource-policies.add.button": "Add", - - // "resource-policies.add.for.": "Add a new policy", - // TODO New key - Add a translation - "resource-policies.add.for.": "Add a new policy", - - // "resource-policies.add.for.bitstream": "Add a new Bitstream policy", - // TODO New key - Add a translation - "resource-policies.add.for.bitstream": "Add a new Bitstream policy", - - // "resource-policies.add.for.bundle": "Add a new Bundle policy", - // TODO New key - Add a translation - "resource-policies.add.for.bundle": "Add a new Bundle policy", - - // "resource-policies.add.for.item": "Add a new Item policy", - // TODO New key - Add a translation - "resource-policies.add.for.item": "Add a new Item policy", - - // "resource-policies.create.page.heading": "Create new resource policy for ", - // TODO New key - Add a translation - "resource-policies.create.page.heading": "Create new resource policy for ", - - // "resource-policies.create.page.failure.content": "An error occurred while creating the resource policy.", - // TODO New key - Add a translation - "resource-policies.create.page.failure.content": "An error occurred while creating the resource policy.", - - // "resource-policies.create.page.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.create.page.success.content": "Operation successful", - - // "resource-policies.create.page.title": "Create new resource policy", - // TODO New key - Add a translation - "resource-policies.create.page.title": "Create new resource policy", - - // "resource-policies.delete.btn": "Delete selected", - // TODO New key - Add a translation - "resource-policies.delete.btn": "Delete selected", - - // "resource-policies.delete.btn.title": "Delete selected resource policies", - // TODO New key - Add a translation - "resource-policies.delete.btn.title": "Delete selected resource policies", - - // "resource-policies.delete.failure.content": "An error occurred while deleting selected resource policies.", - // TODO New key - Add a translation - "resource-policies.delete.failure.content": "An error occurred while deleting selected resource policies.", - - // "resource-policies.delete.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.delete.success.content": "Operation successful", - - // "resource-policies.edit.page.heading": "Edit resource policy ", - // TODO New key - Add a translation - "resource-policies.edit.page.heading": "Edit resource policy ", - - // "resource-policies.edit.page.failure.content": "An error occurred while editing the resource policy.", - // TODO New key - Add a translation - "resource-policies.edit.page.failure.content": "An error occurred while editing the resource policy.", - - // "resource-policies.edit.page.success.content": "Operation successful", - // TODO New key - Add a translation - "resource-policies.edit.page.success.content": "Operation successful", - - // "resource-policies.edit.page.title": "Edit resource policy", - // TODO New key - Add a translation - "resource-policies.edit.page.title": "Edit resource policy", - - // "resource-policies.form.action-type.label": "Select the action type", - // TODO New key - Add a translation - "resource-policies.form.action-type.label": "Select the action type", - - // "resource-policies.form.action-type.required": "You must select the resource policy action.", - // TODO New key - Add a translation - "resource-policies.form.action-type.required": "You must select the resource policy action.", - - // "resource-policies.form.eperson-group-list.label": "The eperson or group that will be grant of the permission", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.label": "The eperson or group that will be grant of the permission", - - // "resource-policies.form.eperson-group-list.select.btn": "Select", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.select.btn": "Select", - - // "resource-policies.form.eperson-group-list.tab.eperson": "Search for a ePerson", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.tab.eperson": "Search for a ePerson", - - // "resource-policies.form.eperson-group-list.tab.group": "Search for a group", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.tab.group": "Search for a group", - - // "resource-policies.form.eperson-group-list.table.headers.action": "Action", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.action": "Action", - - // "resource-policies.form.eperson-group-list.table.headers.id": "ID", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.id": "ID", - - // "resource-policies.form.eperson-group-list.table.headers.name": "Name", - // TODO New key - Add a translation - "resource-policies.form.eperson-group-list.table.headers.name": "Name", - - // "resource-policies.form.date.end.label": "End Date", - // TODO New key - Add a translation - "resource-policies.form.date.end.label": "End Date", - - // "resource-policies.form.date.start.label": "Start Date", - // TODO New key - Add a translation - "resource-policies.form.date.start.label": "Start Date", - - // "resource-policies.form.description.label": "Description", - // TODO New key - Add a translation - "resource-policies.form.description.label": "Description", - - // "resource-policies.form.name.label": "Name", - // TODO New key - Add a translation - "resource-policies.form.name.label": "Name", - - // "resource-policies.form.policy-type.label": "Select the policy type", - // TODO New key - Add a translation - "resource-policies.form.policy-type.label": "Select the policy type", - - // "resource-policies.form.policy-type.required": "You must select the resource policy type.", - // TODO New key - Add a translation - "resource-policies.form.policy-type.required": "You must select the resource policy type.", - - // "resource-policies.table.headers.action": "Action", - // TODO New key - Add a translation - "resource-policies.table.headers.action": "Action", - - // "resource-policies.table.headers.date.end": "End Date", - // TODO New key - Add a translation - "resource-policies.table.headers.date.end": "End Date", - - // "resource-policies.table.headers.date.start": "Start Date", - // TODO New key - Add a translation - "resource-policies.table.headers.date.start": "Start Date", - - // "resource-policies.table.headers.edit": "Edit", - // TODO New key - Add a translation - "resource-policies.table.headers.edit": "Edit", - - // "resource-policies.table.headers.edit.group": "Edit group", - // TODO New key - Add a translation - "resource-policies.table.headers.edit.group": "Edit group", - - // "resource-policies.table.headers.edit.policy": "Edit policy", - // TODO New key - Add a translation - "resource-policies.table.headers.edit.policy": "Edit policy", - - // "resource-policies.table.headers.eperson": "EPerson", - // TODO New key - Add a translation - "resource-policies.table.headers.eperson": "EPerson", - - // "resource-policies.table.headers.group": "Group", - // TODO New key - Add a translation - "resource-policies.table.headers.group": "Group", - - // "resource-policies.table.headers.id": "ID", - // TODO New key - Add a translation - "resource-policies.table.headers.id": "ID", - - // "resource-policies.table.headers.name": "Name", - // TODO New key - Add a translation - "resource-policies.table.headers.name": "Name", - - // "resource-policies.table.headers.policyType": "type", - // TODO New key - Add a translation - "resource-policies.table.headers.policyType": "type", - - // "resource-policies.table.headers.title.for.bitstream": "Policies for Bitstream", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.bitstream": "Policies for Bitstream", - - // "resource-policies.table.headers.title.for.bundle": "Policies for Bundle", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.bundle": "Policies for Bundle", - - // "resource-policies.table.headers.title.for.item": "Policies for Item", - // TODO New key - Add a translation - "resource-policies.table.headers.title.for.item": "Policies for Item", - - - // "search.description": "", // TODO New key - Add a translation "search.description": "", @@ -5013,9 +4546,9 @@ // TODO New key - Add a translation "submission.sections.upload.form.date-required": "Date is required.", - // "submission.sections.upload.form.from-label": "Grant access from", + // "submission.sections.upload.form.from-label": "Access grant from", // TODO New key - Add a translation - "submission.sections.upload.form.from-label": "Grant access from", + "submission.sections.upload.form.from-label": "Access grant from", // "submission.sections.upload.form.from-placeholder": "From", // TODO New key - Add a translation @@ -5029,9 +4562,9 @@ // TODO New key - Add a translation "submission.sections.upload.form.group-required": "Group is required.", - // "submission.sections.upload.form.until-label": "Grant access until", + // "submission.sections.upload.form.until-label": "Access grant until", // TODO New key - Add a translation - "submission.sections.upload.form.until-label": "Grant access until", + "submission.sections.upload.form.until-label": "Access grant until", // "submission.sections.upload.form.until-placeholder": "Until", // TODO New key - Add a translation @@ -5241,78 +4774,5 @@ "virtual-metadata.delete-relationship.modal-head": "Select the items for which you want to save the virtual metadata as real metadata", - - // "workflowAdmin.search.results.head": "Administer Workflow", - // TODO New key - Add a translation - "workflowAdmin.search.results.head": "Administer Workflow", - - - - // "workflow-item.delete.notification.success.title": "Deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.success.title": "Deleted", - - // "workflow-item.delete.notification.success.content": "This workflow item was successfully deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.success.content": "This workflow item was successfully deleted", - - // "workflow-item.delete.notification.error.title": "Something went wrong", - // TODO New key - Add a translation - "workflow-item.delete.notification.error.title": "Something went wrong", - - // "workflow-item.delete.notification.error.content": "The workflow item could not be deleted", - // TODO New key - Add a translation - "workflow-item.delete.notification.error.content": "The workflow item could not be deleted", - - // "workflow-item.delete.title": "Delete workflow item", - // TODO New key - Add a translation - "workflow-item.delete.title": "Delete workflow item", - - // "workflow-item.delete.header": "Delete workflow item", - // TODO New key - Add a translation - "workflow-item.delete.header": "Delete workflow item", - - // "workflow-item.delete.button.cancel": "Cancel", - // TODO New key - Add a translation - "workflow-item.delete.button.cancel": "Cancel", - - // "workflow-item.delete.button.confirm": "Delete", - // TODO New key - Add a translation - "workflow-item.delete.button.confirm": "Delete", - - - // "workflow-item.send-back.notification.success.title": "Sent back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.success.title": "Sent back to submitter", - - // "workflow-item.send-back.notification.success.content": "This workflow item was successfully sent back to the submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.success.content": "This workflow item was successfully sent back to the submitter", - - // "workflow-item.send-back.notification.error.title": "Something went wrong", - // TODO New key - Add a translation - "workflow-item.send-back.notification.error.title": "Something went wrong", - - // "workflow-item.send-back.notification.error.content": "The workflow item could not be sent back to the submitter", - // TODO New key - Add a translation - "workflow-item.send-back.notification.error.content": "The workflow item could not be sent back to the submitter", - - // "workflow-item.send-back.title": "Send workflow item back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.title": "Send workflow item back to submitter", - - // "workflow-item.send-back.header": "Send workflow item back to submitter", - // TODO New key - Add a translation - "workflow-item.send-back.header": "Send workflow item back to submitter", - - // "workflow-item.send-back.button.cancel": "Cancel", - // TODO New key - Add a translation - "workflow-item.send-back.button.cancel": "Cancel", - - // "workflow-item.send-back.button.confirm": "Send back", - // TODO New key - Add a translation - "workflow-item.send-back.button.confirm": "Send back", - - } \ No newline at end of file From 2238599a7d695a20a06463c6693e0ae15e14d31a Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 2 Jul 2020 17:57:31 +0200 Subject: [PATCH 039/170] [CST-3088] remove duplicated test --- .../vocabularies/vocabulary.service.spec.ts | 103 +----------------- 1 file changed, 1 insertion(+), 102 deletions(-) diff --git a/src/app/core/submission/vocabularies/vocabulary.service.spec.ts b/src/app/core/submission/vocabularies/vocabulary.service.spec.ts index 962507ad94..91eda41df1 100644 --- a/src/app/core/submission/vocabularies/vocabulary.service.spec.ts +++ b/src/app/core/submission/vocabularies/vocabulary.service.spec.ts @@ -9,7 +9,7 @@ import { RemoteDataBuildService } from '../../cache/builders/remote-data-build.s import { ObjectCacheService } from '../../cache/object-cache.service'; import { HALEndpointService } from '../../shared/hal-endpoint.service'; import { RequestService } from '../../data/request.service'; -import { FindListOptions, VocabularyEntriesRequest } from '../../data/request.models'; +import { VocabularyEntriesRequest } from '../../data/request.models'; import { RequestParam } from '../../cache/models/request-param.model'; import { PageInfo } from '../../shared/page-info.model'; import { PaginatedList } from '../../data/paginated-list'; @@ -67,55 +67,6 @@ describe('VocabularyService', () => { } }; - const vocabularyEntry: any = { - display: 'testValue1', - value: 'testValue1', - otherInformation: {}, - type: 'vocabularyEntry' - }; - - const vocabularyEntryWithAuthority: any = { - authority: 'authorityId1', - display: 'testValue1', - value: 'testValue1', - otherInformation: { - id: 'VR131402', - parent: 'Research Subject Categories::SOCIAL SCIENCES::Social sciences::Social work', - hasChildren: 'false', - note: 'Familjeforskning' - }, - type: 'vocabularyEntry', - _links: { - vocabularyEntryDetail: { - href: 'https://rest.api/rest/api/submission/vocabularyEntryDetails/srsc:VR131402' - } - } - }; - - const vocabularyEntryDetail: any = { - authority: 'authorityId1', - display: 'testValue1', - value: 'testValue1', - otherInformation: { - id: 'VR131402', - parent: 'Research Subject Categories::SOCIAL SCIENCES::Social sciences::Social work', - hasChildren: 'true', - note: 'Familjeforskning' - }, - type: 'vocabularyEntryDetail', - _links: { - self: { - href: 'https://rest.api/rest/api/submission/vocabularyEntryDetails/srsc:VR131402' - }, - parent: { - href: 'https://rest.api/rest/api/submission/vocabularyEntryDetails/srsc:parent' - }, - children: { - href: 'https://rest.api/rest/api/submission/vocabularyEntryDetails/srsc:children' - } - } - }; - const vocabularyEntryParentDetail: any = { authority: 'authorityId2', display: 'testParent', @@ -185,27 +136,6 @@ describe('VocabularyService', () => { } }; - const anotherVocabularyEntryDetail: any = { - authority: 'authorityId1', - display: 'children', - value: 'children', - otherInformation: { - id: 'VR131402', - parent: 'Research Subject Categories::SOCIAL SCIENCES::Social sciences::Social work', - hasChildren: 'false', - note: 'Familjeforskning' - }, - type: 'vocabularyEntryDetail', - _links: { - self: { - href: 'https://rest.api/rest/api/submission/vocabularyEntryDetails/srsc:children' - }, - parent: { - href: 'https://rest.api/rest/api/submission/vocabularyEntryDetails/srsc:testValue1' - } - } - }; - const endpointURL = `https://rest.api/rest/api/submission/vocabularies`; const requestURL = `https://rest.api/rest/api/submission/vocabularies/${vocabulary.id}`; const entryDetailEndpointURL = `https://rest.api/rest/api/submission/vocabularyEntryDetails`; @@ -230,17 +160,13 @@ describe('VocabularyService', () => { } const pageInfo = new PageInfo(); const array = [vocabulary, hierarchicalVocabulary]; - const arrayEntries = [vocabularyEntryDetail, anotherVocabularyEntryDetail]; const childrenEntries = [vocabularyEntryChildDetail, vocabularyEntryChild2Detail]; const paginatedList = new PaginatedList(pageInfo, array); - const entriesPaginatedList = new PaginatedList(pageInfo, arrayEntries); const childrenPaginatedList = new PaginatedList(pageInfo, childrenEntries); const vocabularyRD = createSuccessfulRemoteDataObject(vocabulary); - const vocabularyEntryDetailRD = createSuccessfulRemoteDataObject(vocabularyEntryDetail); const vocabularyEntryDetailParentRD = createSuccessfulRemoteDataObject(vocabularyEntryParentDetail); const vocabularyEntryChildrenRD = createSuccessfulRemoteDataObject(childrenPaginatedList); const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); - const entriesPaginatedListRD = createSuccessfulRemoteDataObject(entriesPaginatedList); const getRequestEntry$ = (successful: boolean) => { return observableOf({ response: { isSuccessful: successful, payload: vocabulary } as any @@ -375,33 +301,6 @@ describe('VocabularyService', () => { }); - describe('getVocabularyEntries', () => { - - beforeEach(() => { - requestService = getMockRequestService(getRequestEntry$(true)); - rdbService = getMockRemoteDataBuildService(); - spyOn(rdbService, 'toRemoteDataObservable').and.callThrough(); - service = initTestService(); - }); - - it('should configure a new VocabularyEntriesRequest', () => { - const expected = new VocabularyEntriesRequest(requestService.generateRequestId(), entriesRequestURL); - - scheduler.schedule(() => service.getVocabularyEntries(vocabularyOptions, pageInfo).subscribe()); - scheduler.flush(); - - expect(requestService.configure).toHaveBeenCalledWith(expected); - }); - - it('should call RemoteDataBuildService to create the RemoteData Observable', () => { - service.getVocabularyEntries(vocabularyOptions, pageInfo); - - expect(rdbService.toRemoteDataObservable).toHaveBeenCalled(); - - }); - - }); - describe('', () => { beforeEach(() => { From 2da96aac25a06b7d178ed7481ecb2a672f8d21ea Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Fri, 3 Jul 2020 15:43:08 +0200 Subject: [PATCH 040/170] initialized submission object's sections properly on submission submit --- .../submission/submit/submission-submit.component.html | 1 + .../submission/submit/submission-submit.component.spec.ts | 1 + src/app/submission/submit/submission-submit.component.ts | 8 ++++++++ 3 files changed, 10 insertions(+) diff --git a/src/app/submission/submit/submission-submit.component.html b/src/app/submission/submit/submission-submit.component.html index c9e8c6b51a..25f397bf4e 100644 --- a/src/app/submission/submit/submission-submit.component.html +++ b/src/app/submission/submit/submission-submit.component.html @@ -1,6 +1,7 @@
diff --git a/src/app/submission/submit/submission-submit.component.spec.ts b/src/app/submission/submit/submission-submit.component.spec.ts index d0a2291ba9..19cd6d55dd 100644 --- a/src/app/submission/submit/submission-submit.component.spec.ts +++ b/src/app/submission/submit/submission-submit.component.spec.ts @@ -69,6 +69,7 @@ describe('SubmissionSubmitComponent Component', () => { expect(comp.submissionId.toString()).toEqual(submissionId); expect(comp.collectionId).toBe(submissionObject.collection.id); expect(comp.selfUrl).toBe(submissionObject._links.self.href); + expect(comp.sections).toBe(submissionObject.sections); expect(comp.submissionDefinition).toBe(submissionObject.submissionDefinition); })); diff --git a/src/app/submission/submit/submission-submit.component.ts b/src/app/submission/submit/submission-submit.component.ts index d3d3ca4e66..30612c9560 100644 --- a/src/app/submission/submit/submission-submit.component.ts +++ b/src/app/submission/submit/submission-submit.component.ts @@ -10,6 +10,7 @@ import { NotificationsService } from '../../shared/notifications/notifications.s import { SubmissionService } from '../submission.service'; import { SubmissionObject } from '../../core/submission/models/submission-object.model'; import { Collection } from '../../core/shared/collection.model'; +import { WorkspaceitemSectionsObject } from '../../core/submission/models/workspaceitem-sections.model'; /** * This component allows to submit a new workspaceitem. @@ -33,6 +34,12 @@ export class SubmissionSubmitComponent implements OnDestroy, OnInit { */ public collectionParam: string; + /** + * The list of submission's sections + * @type {WorkspaceitemSectionsObject} + */ + public sections: WorkspaceitemSectionsObject; + /** * The submission self url * @type {string} @@ -95,6 +102,7 @@ export class SubmissionSubmitComponent implements OnDestroy, OnInit { this.router.navigate(['/mydspace']); } else { this.collectionId = (submissionObject.collection as Collection).id; + this.sections = submissionObject.sections; this.selfUrl = submissionObject._links.self.href; this.submissionDefinition = (submissionObject.submissionDefinition as SubmissionDefinitionsModel); this.submissionId = submissionObject.id; From 58f18737f70742a5d1d12701b49cb635831d8a4b Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Fri, 3 Jul 2020 15:53:29 +0200 Subject: [PATCH 041/170] [CST-3088] tried to resolve travis fail --- .../vocabularies/vocabulary.service.spec.ts | 175 +++++++++--------- 1 file changed, 92 insertions(+), 83 deletions(-) diff --git a/src/app/core/submission/vocabularies/vocabulary.service.spec.ts b/src/app/core/submission/vocabularies/vocabulary.service.spec.ts index 91eda41df1..0998b64579 100644 --- a/src/app/core/submission/vocabularies/vocabulary.service.spec.ts +++ b/src/app/core/submission/vocabularies/vocabulary.service.spec.ts @@ -198,107 +198,115 @@ describe('VocabularyService', () => { halService = jasmine.createSpyObj('halService', { getEndpoint: cold('a', { a: endpointURL }) }); - - responseCacheEntry = new RequestEntry(); - responseCacheEntry.response = new RestResponse(true, 200, 'Success'); - - requestService = jasmine.createSpyObj('requestService', { - generateRequestId: requestUUID, - configure: true, - removeByHrefSubstring: {}, - getByHref: observableOf(responseCacheEntry), - getByUUID: observableOf(responseCacheEntry), - }); - rdbService = jasmine.createSpyObj('rdbService', { - buildSingle: hot('a|', { - a: vocabularyRD - }), - buildList: hot('a|', { - a: paginatedListRD - }), - }); - - service = initTestService(); - - spyOn((service as any).vocabularyDataService, 'findById').and.callThrough(); - spyOn((service as any).vocabularyDataService, 'findAll').and.callThrough(); - spyOn((service as any).vocabularyDataService, 'findByHref').and.callThrough(); - spyOn((service as any).vocabularyDataService, 'searchBy').and.callThrough(); - spyOn((service as any).vocabularyDataService, 'getSearchByHref').and.returnValue(observableOf(searchRequestURL)); - spyOn((service as any).vocabularyDataService, 'getFindAllHref').and.returnValue(observableOf(entriesRequestURL)); }); afterEach(() => { service = null; }); - describe('findVocabularyById', () => { - it('should proxy the call to vocabularyDataService.findVocabularyById', () => { - scheduler.schedule(() => service.findVocabularyById(vocabularyId)); - scheduler.flush(); + describe('', () => { + beforeEach(() => { + responseCacheEntry = new RequestEntry(); + responseCacheEntry.response = new RestResponse(true, 200, 'Success'); - expect((service as any).vocabularyDataService.findById).toHaveBeenCalledWith(vocabularyId); - }); - - it('should return a RemoteData for the object with the given id', () => { - const result = service.findVocabularyById(vocabularyId); - const expected = cold('a|', { - a: vocabularyRD + requestService = jasmine.createSpyObj('requestService', { + generateRequestId: requestUUID, + configure: true, + removeByHrefSubstring: {}, + getByHref: observableOf(responseCacheEntry), + getByUUID: observableOf(responseCacheEntry), }); - expect(result).toBeObservable(expected); - }); - }); - - describe('findVocabularyByHref', () => { - it('should proxy the call to vocabularyDataService.findVocabularyByHref', () => { - scheduler.schedule(() => service.findVocabularyByHref(requestURL)); - scheduler.flush(); - - expect((service as any).vocabularyDataService.findByHref).toHaveBeenCalledWith(requestURL); - }); - - it('should return a RemoteData for the object with the given URL', () => { - const result = service.findVocabularyByHref(requestURL); - const expected = cold('a|', { - a: vocabularyRD + rdbService = jasmine.createSpyObj('rdbService', { + buildSingle: hot('a|', { + a: vocabularyRD + }), + buildList: hot('a|', { + a: paginatedListRD + }), }); - expect(result).toBeObservable(expected); - }); - }); - describe('findAllVocabularies', () => { - it('should proxy the call to vocabularyDataService.findAllVocabularies', () => { - scheduler.schedule(() => service.findAllVocabularies()); - scheduler.flush(); + service = initTestService(); - expect((service as any).vocabularyDataService.findAll).toHaveBeenCalled(); + spyOn((service as any).vocabularyDataService, 'findById').and.callThrough(); + spyOn((service as any).vocabularyDataService, 'findAll').and.callThrough(); + spyOn((service as any).vocabularyDataService, 'findByHref').and.callThrough(); + spyOn((service as any).vocabularyDataService, 'searchBy').and.callThrough(); + spyOn((service as any).vocabularyDataService, 'getSearchByHref').and.returnValue(observableOf(searchRequestURL)); + spyOn((service as any).vocabularyDataService, 'getFindAllHref').and.returnValue(observableOf(entriesRequestURL)); }); - it('should return a RemoteData>', () => { - const result = service.findAllVocabularies(); - const expected = cold('a|', { - a: paginatedListRD + afterEach(() => { + service = null; + }); + + describe('findVocabularyById', () => { + it('should proxy the call to vocabularyDataService.findVocabularyById', () => { + scheduler.schedule(() => service.findVocabularyById(vocabularyId)); + scheduler.flush(); + + expect((service as any).vocabularyDataService.findById).toHaveBeenCalledWith(vocabularyId); }); - expect(result).toBeObservable(expected); - }); - }); - describe('searchVocabularyByMetadataAndCollection', () => { - it('should proxy the call to vocabularyDataService.findVocabularyByHref', () => { - scheduler.schedule(() => service.searchVocabularyByMetadataAndCollection(vocabularyOptions).subscribe()); - scheduler.flush(); - - expect((service as any).vocabularyDataService.findByHref).toHaveBeenCalledWith(searchRequestURL); - }); - - it('should return a RemoteData for the search', () => { - const result = service.searchVocabularyByMetadataAndCollection(vocabularyOptions); - const expected = cold('a|', { - a: vocabularyRD + it('should return a RemoteData for the object with the given id', () => { + const result = service.findVocabularyById(vocabularyId); + const expected = cold('a|', { + a: vocabularyRD + }); + expect(result).toBeObservable(expected); }); - expect(result).toBeObservable(expected); }); + describe('findVocabularyByHref', () => { + it('should proxy the call to vocabularyDataService.findVocabularyByHref', () => { + scheduler.schedule(() => service.findVocabularyByHref(requestURL)); + scheduler.flush(); + + expect((service as any).vocabularyDataService.findByHref).toHaveBeenCalledWith(requestURL); + }); + + it('should return a RemoteData for the object with the given URL', () => { + const result = service.findVocabularyByHref(requestURL); + const expected = cold('a|', { + a: vocabularyRD + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('findAllVocabularies', () => { + it('should proxy the call to vocabularyDataService.findAllVocabularies', () => { + scheduler.schedule(() => service.findAllVocabularies()); + scheduler.flush(); + + expect((service as any).vocabularyDataService.findAll).toHaveBeenCalled(); + }); + + it('should return a RemoteData>', () => { + const result = service.findAllVocabularies(); + const expected = cold('a|', { + a: paginatedListRD + }); + expect(result).toBeObservable(expected); + }); + }); + + describe('searchVocabularyByMetadataAndCollection', () => { + it('should proxy the call to vocabularyDataService.findVocabularyByHref', () => { + scheduler.schedule(() => service.searchVocabularyByMetadataAndCollection(vocabularyOptions).subscribe()); + scheduler.flush(); + + expect((service as any).vocabularyDataService.findByHref).toHaveBeenCalledWith(searchRequestURL); + }); + + it('should return a RemoteData for the search', () => { + const result = service.searchVocabularyByMetadataAndCollection(vocabularyOptions); + const expected = cold('a|', { + a: vocabularyRD + }); + expect(result).toBeObservable(expected); + }); + + }); }); describe('', () => { @@ -383,6 +391,7 @@ describe('VocabularyService', () => { }); }); + }); describe('vocabularyEntryDetails endpoint', () => { From d6a5d9d1ddf96bb792a5fd3db23534acd9a7dad2 Mon Sep 17 00:00:00 2001 From: Matteo Perelli Date: Mon, 6 Jul 2020 09:12:18 +0200 Subject: [PATCH 042/170] CI test fix, buttons and searchbar style fix and service methods removed --- .../my-dspace-new-submission.component.html | 10 ++++--- ...my-dspace-new-submission.component.spec.ts | 5 +++- .../my-dspace-new-submission.component.ts | 15 ++++++++-- .../core/data/external-source.service.spec.ts | 17 ----------- src/app/core/data/external-source.service.ts | 28 ------------------- .../mocks/external-source.service.mock.ts | 2 +- ...-import-external-preview.component.spec.ts | 7 ++++- ...n-import-external-searchbar.component.html | 9 ++++-- ...mport-external-searchbar.component.spec.ts | 5 +++- ...ion-import-external-searchbar.component.ts | 14 ++++++++-- src/assets/i18n/en.json5 | 6 ++-- 11 files changed, 55 insertions(+), 63 deletions(-) diff --git a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html index da5519eb07..248909b215 100644 --- a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html +++ b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html @@ -7,11 +7,13 @@
- - - {{'mydspace.new-submission-external' | translate}} +
+ diff --git a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.spec.ts b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.spec.ts index 16b50d18f0..f2687e452c 100644 --- a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.spec.ts +++ b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.spec.ts @@ -23,6 +23,8 @@ import { getMockScrollToService } from '../../shared/mocks/scroll-to-service.moc import { UploaderService } from '../../shared/uploader/uploader.service'; import { By } from '@angular/platform-browser'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { HostWindowService } from '../../shared/host-window.service'; +import { HostWindowServiceStub } from '../../shared/testing/host-window-service.stub'; describe('MyDSpaceNewSubmissionComponent test', () => { @@ -63,7 +65,8 @@ describe('MyDSpaceNewSubmissionComponent test', () => { }, ChangeDetectorRef, MyDSpaceNewSubmissionComponent, - UploaderService + UploaderService, + { provide: HostWindowService, useValue: new HostWindowServiceStub(800) }, ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); diff --git a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts index 8d20a5736a..e3cf19bf8a 100644 --- a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts +++ b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts @@ -1,6 +1,6 @@ import { ChangeDetectorRef, Component, EventEmitter, OnDestroy, OnInit, Output } from '@angular/core'; -import { Subscription } from 'rxjs'; +import { Subscription, Observable } from 'rxjs'; import { first } from 'rxjs/operators'; import { Store } from '@ngrx/store'; import { TranslateService } from '@ngx-translate/core'; @@ -18,6 +18,7 @@ import { SearchResult } from '../../shared/search/search-result.model'; import { Router } from '@angular/router'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { CreateItemParentSelectorComponent } from 'src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component'; +import { HostWindowService } from '../../shared/host-window.service'; /** * This component represents the whole mydspace page header @@ -38,6 +39,11 @@ export class MyDSpaceNewSubmissionComponent implements OnDestroy, OnInit { */ public uploadFilesOptions: UploaderOptions = new UploaderOptions(); + /** + * Emits true if were on a small screen + */ + public isXsOrSm$: Observable; + /** * Subscription to unsubscribe from */ @@ -52,6 +58,9 @@ export class MyDSpaceNewSubmissionComponent implements OnDestroy, OnInit { * @param {NotificationsService} notificationsService * @param {Store} store * @param {TranslateService} translate + * @param {Router} router + * @param {NgbModal} modalService + * @param {HostWindowService} windowService */ constructor(private authService: AuthService, private changeDetectorRef: ChangeDetectorRef, @@ -60,7 +69,8 @@ export class MyDSpaceNewSubmissionComponent implements OnDestroy, OnInit { private store: Store, private translate: TranslateService, private router: Router, - private modalService: NgbModal) { + private modalService: NgbModal, + protected windowService: HostWindowService) { } /** @@ -73,6 +83,7 @@ export class MyDSpaceNewSubmissionComponent implements OnDestroy, OnInit { this.changeDetectorRef.detectChanges(); } ); + this.isXsOrSm$ = this.windowService.isXsOrSm(); } /** diff --git a/src/app/core/data/external-source.service.spec.ts b/src/app/core/data/external-source.service.spec.ts index 2fc4589bed..7c7d676bc7 100644 --- a/src/app/core/data/external-source.service.spec.ts +++ b/src/app/core/data/external-source.service.spec.ts @@ -74,21 +74,4 @@ describe('ExternalSourceService', () => { }); }); }); - - describe('getAllExternalSources', () => { - it('should call findAll', () => { - spyOn(service, 'findAll'); - service.getAllExternalSources(); - expect(service.findAll).toHaveBeenCalled(); - }); - }); - - describe('getExternalSource', () => { - it('should call findById', () => { - const externalSourceId = 'orcidV2'; - spyOn(service, 'findById'); - service.getExternalSource(externalSourceId); - expect(service.findById).toHaveBeenCalledWith(externalSourceId); - }); - }); }); diff --git a/src/app/core/data/external-source.service.ts b/src/app/core/data/external-source.service.ts index 0d84639a40..edc538a39b 100644 --- a/src/app/core/data/external-source.service.ts +++ b/src/app/core/data/external-source.service.ts @@ -60,34 +60,6 @@ export class ExternalSourceService extends DataService { ); } - /** - * Return a single external source. - * - * @param id - * The external source id. - * @param linksToFollow - * List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved. - * @return Observable> - * The list of the external sources. - */ - getExternalSource(id: string, ...linksToFollow: Array>): Observable> { - return this.findById(id, ...linksToFollow); - } - - /** - * Return the list of external sources. - * - * @param options - * Find list options object. - * @param linksToFollow - * List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved. - * @return Observable>> - * The list of the external sources. - */ - getAllExternalSources(options: FindListOptions = {}, ...linksToFollow: Array>): Observable>> { - return this.findAll(options, ...linksToFollow); - } - /** * Get the entries for an external source * @param externalSourceId The id of the external source to fetch entries for diff --git a/src/app/shared/mocks/external-source.service.mock.ts b/src/app/shared/mocks/external-source.service.mock.ts index 3e96eb508e..85d63189e5 100644 --- a/src/app/shared/mocks/external-source.service.mock.ts +++ b/src/app/shared/mocks/external-source.service.mock.ts @@ -53,7 +53,7 @@ export const externalSourceMyStaffDb: ExternalSource = { export function getMockExternalSourceService(): ExternalSourceService { return jasmine.createSpyObj('ExternalSourceService', { - getAllExternalSources: jasmine.createSpy('getAllExternalSources'), + findAll: jasmine.createSpy('findAll'), getExternalSourceEntries: jasmine.createSpy('getExternalSourceEntries'), }); } diff --git a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts index 3bb6a19645..29b0094b69 100644 --- a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts +++ b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts @@ -3,7 +3,9 @@ import { async, TestBed, ComponentFixture, inject } from '@angular/core/testing' import { TranslateModule } from '@ngx-translate/core'; import { Router } from '@angular/router'; import { NgbModal, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { TestScheduler } from 'rxjs/testing'; import { of as observableOf, of } from 'rxjs/internal/observable/of'; +import { getTestScheduler } from 'jasmine-marbles'; import { SubmissionImportExternalPreviewComponent } from './submission-import-external-preview.component'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; import { RouterStub } from '../../../shared/testing/router.stub'; @@ -21,6 +23,7 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { let compAsAny: any; let fixture: ComponentFixture; let submissionServiceStub: SubmissionServiceStub; + let scheduler: TestScheduler; const ngbActiveModal = jasmine.createSpyObj('modal', ['close', 'dismiss']); const ngbModal = jasmine.createSpyObj('modal', ['open']); const externalEntry = Object.assign(new ExternalSourceEntry(), { @@ -38,6 +41,7 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { }); beforeEach(async (() => { + scheduler = getTestScheduler(); TestBed.configureTestingModule({ imports: [ TranslateModule.forRoot() @@ -134,7 +138,8 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { spyOn(comp, 'closeMetadataModal'); submissionServiceStub.createSubmissionFromExternalSource.and.returnValue(observableOf(submissionObjects)); spyOn(compAsAny.router, 'navigateByUrl'); - comp.import(); + scheduler.schedule(() => comp.import()); + scheduler.flush(); expect(compAsAny.modalService.open).toHaveBeenCalledWith(SubmissionImportExternalCollectionComponent, { size: 'lg' }); expect(comp.closeMetadataModal).toHaveBeenCalled(); diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html index a63828568d..fe70299e4e 100644 --- a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html @@ -1,6 +1,9 @@ -
+
-
+
+
+ +
- +
diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.spec.ts b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.spec.ts index 285581560b..25f12c6e38 100644 --- a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.spec.ts +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.spec.ts @@ -11,6 +11,8 @@ import { PaginatedList } from '../../../core/data/paginated-list'; import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils'; import { ExternalSource } from '../../../core/shared/external-source.model'; import { FindListOptions } from '../../../core/data/request.models'; +import { HostWindowService } from '../../../shared/host-window.service'; +import { HostWindowServiceStub } from '../../../shared/testing/host-window-service.stub'; describe('SubmissionImportExternalSearchbarComponent test suite', () => { let comp: SubmissionImportExternalSearchbarComponent; @@ -29,6 +31,7 @@ describe('SubmissionImportExternalSearchbarComponent test suite', () => { providers: [ { provide: ExternalSourceService, useClass: getMockExternalSourceService }, ChangeDetectorRef, + { provide: HostWindowService, useValue: new HostWindowServiceStub(800) }, SubmissionImportExternalSearchbarComponent ], schemas: [NO_ERRORS_SCHEMA] @@ -68,7 +71,7 @@ describe('SubmissionImportExternalSearchbarComponent test suite', () => { const pageInfo = new PageInfo(); paginatedList = new PaginatedList(pageInfo, [externalSourceOrcid, externalSourceCiencia, externalSourceMyStaffDb]); const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); - compAsAny.externalService.getAllExternalSources.and.returnValue(observableOf(paginatedListRD)); + compAsAny.externalService.findAll.and.returnValue(observableOf(paginatedListRD)); sourceList = [ {id: 'orcid', name: 'orcid'}, {id: 'ciencia', name: 'ciencia'}, diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts index efbcbad60c..bb156e1878 100644 --- a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts @@ -1,6 +1,6 @@ import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import { of as observableOf } from 'rxjs'; +import { of as observableOf, Observable } from 'rxjs'; import { catchError, tap } from 'rxjs/operators'; import { ExternalSourceService } from '../../../core/data/external-source.service'; @@ -11,6 +11,7 @@ import { PageInfo } from '../../../core/shared/page-info.model'; import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils'; import { FindListOptions } from '../../../core/data/request.models'; import { getFirstSucceededRemoteDataPayload } from '../../../core/shared/operators'; +import { HostWindowService } from '../../../shared/host-window.service'; /** * Interface for the selected external source element. @@ -57,6 +58,10 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { * The external sources loading status. */ public sourceListLoading = false; + /** + * Emits true if were on a small screen + */ + public isXsOrSm$: Observable; /** * The external source data to use to perform the search. */ @@ -75,10 +80,12 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { * Initialize the component variables. * @param {ExternalSourceService} externalService * @param {ChangeDetectorRef} cdr + * @param {HostWindowService} windowService */ constructor( private externalService: ExternalSourceService, private cdr: ChangeDetectorRef, + protected windowService: HostWindowService ) { } @@ -96,7 +103,7 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { elementsPerPage: 5, currentPage: 0, }); - this.externalService.getAllExternalSources(this.findListOptions).pipe( + this.externalService.findAll(this.findListOptions).pipe( catchError(() => { const pageInfo = new PageInfo(); const paginatedList = new PaginatedList(pageInfo, []); @@ -118,6 +125,7 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { this.pageInfo = externalSource.pageInfo; this.cdr.detectChanges(); }); + this.isXsOrSm$ = this.windowService.isXsOrSm(); } /** @@ -137,7 +145,7 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit { elementsPerPage: 5, currentPage: this.findListOptions.currentPage + 1, }); - this.externalService.getAllExternalSources(this.findListOptions).pipe( + this.externalService.findAll(this.findListOptions).pipe( catchError(() => { const pageInfo = new PageInfo(); const paginatedList = new PaginatedList(pageInfo, []); diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index cc21874672..75cf73339d 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1859,7 +1859,9 @@ "mydspace.new-submission": "New submission", - "mydspace.new-submission-external": "Import from external source", + "mydspace.new-submission-external": "Import metadata from external source", + + "mydspace.new-submission-external-short": "Import metadata", "mydspace.results.head": "Your submissions", @@ -2562,7 +2564,7 @@ "submission.import-external.title": "Import metadata from an external source", - "submission.import-external.page.hint": "Search items using external sources.", + "submission.import-external.page.hint": "No search performed yet. Search items using external sources.", "submission.import-external.back-to-my-dspace": "Back to MyDSpace", From 9ec57094100a5e88d67865c0e63b1b5a7ec60957 Mon Sep 17 00:00:00 2001 From: Matteo Perelli Date: Mon, 6 Jul 2020 10:28:17 +0200 Subject: [PATCH 043/170] CI test fix using TestScheduler --- .../submission-import-external-preview.component.spec.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts index 29b0094b69..58488dd5ab 100644 --- a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts +++ b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts @@ -79,7 +79,7 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { testFixture.destroy(); }); - it('should create SubmissionImportExternalComponent', inject([SubmissionImportExternalPreviewComponent], (app: SubmissionImportExternalPreviewComponent) => { + it('should create SubmissionImportExternalPreviewComponent', inject([SubmissionImportExternalPreviewComponent], (app: SubmissionImportExternalPreviewComponent) => { expect(app).toBeDefined(); })); }); @@ -103,14 +103,16 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { const expected = [ { key: 'dc.identifier.uri', value: Metadata.first(comp.externalSourceEntry.metadata, 'dc.identifier.uri') } ]; - fixture.detectChanges(); + scheduler.schedule(() => comp.ngOnInit()); + scheduler.flush(); expect(comp.metadataList).toEqual(expected); }); it('Should close the modal calling \'activeModal.dismiss\'', () => { comp.modalRef = jasmine.createSpyObj('modal', ['close', 'dismiss']); - comp.closeMetadataModal(); + scheduler.schedule(() => comp.closeMetadataModal()); + scheduler.flush(); expect(compAsAny.activeModal.dismiss).toHaveBeenCalled(); }); From aa265c02a522e4d8c7f75cc370c004471d0ffed1 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Mon, 6 Jul 2020 10:28:23 +0200 Subject: [PATCH 044/170] [CST-3088] Fixed travis failure --- .../onebox/dynamic-onebox.component.spec.ts | 37 +++++++++++++------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.spec.ts index f43d779ae3..5bbae9c98c 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.spec.ts @@ -3,7 +3,10 @@ import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/c import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { async, ComponentFixture, fakeAsync, inject, TestBed, tick, } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; +import { CdkTreeModule } from '@angular/cdk/tree'; +import { TestScheduler } from 'rxjs/testing'; +import { getTestScheduler } from 'jasmine-marbles'; import { of as observableOf } from 'rxjs'; import { NgbModal, NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { DynamicFormLayoutService, DynamicFormsCoreModule, DynamicFormValidationService } from '@ng-dynamic-forms/core'; @@ -22,14 +25,23 @@ import { ObjNgFor } from '../../../../../utils/object-ngfor.pipe'; import { VocabularyEntry } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry.model'; import { createSuccessfulRemoteDataObject$ } from '../../../../../remote-data.utils'; import { VocabularyTreeviewComponent } from '../../../../../vocabulary-treeview/vocabulary-treeview.component'; -import { CdkTreeModule } from '@angular/cdk/tree'; -import { TestScheduler } from 'rxjs/testing'; -import { getTestScheduler } from 'jasmine-marbles'; export let ONEBOX_TEST_GROUP; export let ONEBOX_TEST_MODEL_CONFIG; +/* tslint:disable:max-classes-per-file */ + +// Mock class for NgbModalRef +export class MockNgbModalRef { + componentInstance = { + vocabularyOptions: undefined, + preloadLevel: undefined, + selectedItem: undefined + }; + result: Promise = new Promise((resolve, reject) => resolve(true)); +} + function init() { ONEBOX_TEST_GROUP = new FormGroup({ onebox: new FormControl(), @@ -63,6 +75,7 @@ describe('DsDynamicOneboxComponent test suite', () => { let testFixture: ComponentFixture; let oneboxCompFixture: ComponentFixture; let vocabularyServiceStub: any; + let modalService: any; let html; let modal; const vocabulary = { @@ -102,14 +115,14 @@ describe('DsDynamicOneboxComponent test suite', () => { // async beforeEach beforeEach(async(() => { vocabularyServiceStub = new VocabularyServiceStub(); - modal = jasmine.createSpyObj('modal', ['open', 'close', 'dismiss']); -/* jasmine.createSpyObj('modal', + // modal = jasmine.createSpyObj('modal', ['open', 'close', 'dismiss']); + modal = jasmine.createSpyObj('modal', { - open: jasmine.createSpy('open'), + open: jasmine.createSpy('open').and.returnValue(new MockNgbModalRef()), close: jasmine.createSpy('close'), dismiss: jasmine.createSpy('dismiss'), } - );*/ + ); init(); TestBed.configureTestingModule({ imports: [ @@ -365,13 +378,13 @@ describe('DsDynamicOneboxComponent test suite', () => { beforeEach(() => { scheduler = getTestScheduler(); spyOn(vocabularyServiceStub, 'findVocabularyById').and.returnValue(createSuccessfulRemoteDataObject$(hierarchicalVocabulary)); + oneboxCompFixture = TestBed.createComponent(DsDynamicOneboxComponent); + oneboxComponent = oneboxCompFixture.componentInstance; // FormComponent test instance + modalService = TestBed.get(NgbModal); }); describe('when init model value is empty', () => { beforeEach(() => { - - oneboxCompFixture = TestBed.createComponent(DsDynamicOneboxComponent); - oneboxComponent = oneboxCompFixture.componentInstance; // FormComponent test instance oneboxComponent.group = ONEBOX_TEST_GROUP; oneboxComponent.model = new DynamicOneboxModel(ONEBOX_TEST_MODEL_CONFIG); oneboxCompFixture.detectChanges(); @@ -396,8 +409,6 @@ describe('DsDynamicOneboxComponent test suite', () => { describe('when init model value is not empty', () => { beforeEach(() => { - oneboxCompFixture = TestBed.createComponent(DsDynamicOneboxComponent); - oneboxComponent = oneboxCompFixture.componentInstance; // FormComponent test instance oneboxComponent.group = ONEBOX_TEST_GROUP; oneboxComponent.model = new DynamicOneboxModel(ONEBOX_TEST_MODEL_CONFIG); const entry = observableOf(Object.assign(new VocabularyEntry(), { @@ -445,3 +456,5 @@ class TestComponent { model = new DynamicOneboxModel(ONEBOX_TEST_MODEL_CONFIG); } + +/* tslint:enable:max-classes-per-file */ From 7c36051fccd12383e5959ca4e5c9cc276c1aac10 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Mon, 6 Jul 2020 11:24:21 +0200 Subject: [PATCH 045/170] fixed travis failure --- ...ission-import-external-preview.component.spec.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts index 58488dd5ab..aa4413637c 100644 --- a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts +++ b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts @@ -4,7 +4,7 @@ import { TranslateModule } from '@ngx-translate/core'; import { Router } from '@angular/router'; import { NgbModal, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { TestScheduler } from 'rxjs/testing'; -import { of as observableOf, of } from 'rxjs/internal/observable/of'; +import { of as observableOf } from 'rxjs/internal/observable/of'; import { getTestScheduler } from 'jasmine-marbles'; import { SubmissionImportExternalPreviewComponent } from './submission-import-external-preview.component'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; @@ -103,16 +103,14 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { const expected = [ { key: 'dc.identifier.uri', value: Metadata.first(comp.externalSourceEntry.metadata, 'dc.identifier.uri') } ]; - scheduler.schedule(() => comp.ngOnInit()); - scheduler.flush(); + fixture.detectChanges(); expect(comp.metadataList).toEqual(expected); }); it('Should close the modal calling \'activeModal.dismiss\'', () => { comp.modalRef = jasmine.createSpyObj('modal', ['close', 'dismiss']); - scheduler.schedule(() => comp.closeMetadataModal()); - scheduler.flush(); + comp.closeMetadataModal(); expect(compAsAny.activeModal.dismiss).toHaveBeenCalled(); }); @@ -136,7 +134,10 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { { id: 'jk11k13o-9v4z-632i-sr88-wq071n0h1d47' } ]; comp.externalSourceEntry = externalEntry; - ngbModal.open.and.returnValue({componentInstance: { selectedEvent: observableOf(emittedEvent)}}); + ngbModal.open.and.returnValue({ + componentInstance: { selectedEvent: observableOf(emittedEvent)}, + close: (): void => { /* empty */ } + }); spyOn(comp, 'closeMetadataModal'); submissionServiceStub.createSubmissionFromExternalSource.and.returnValue(observableOf(submissionObjects)); spyOn(compAsAny.router, 'navigateByUrl'); From a38e5cf632f75a98b8bbfdc02dec673df4511ca9 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Mon, 6 Jul 2020 12:30:53 +0200 Subject: [PATCH 046/170] fixed travis failure --- ...mport-external-searchbar.component.spec.ts | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.spec.ts b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.spec.ts index 25f12c6e38..10cc122624 100644 --- a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.spec.ts +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.spec.ts @@ -1,5 +1,5 @@ import { Component, NO_ERRORS_SCHEMA, ChangeDetectorRef } from '@angular/core'; -import { async, TestBed, ComponentFixture, inject } from '@angular/core/testing'; +import { async, TestBed, ComponentFixture, inject, fakeAsync, tick } from '@angular/core/testing'; import { TranslateModule } from '@ngx-translate/core'; import { of as observableOf } from 'rxjs'; import { SubmissionImportExternalSearchbarComponent, SourceElement } from './submission-import-external-searchbar.component'; @@ -13,13 +13,17 @@ import { ExternalSource } from '../../../core/shared/external-source.model'; import { FindListOptions } from '../../../core/data/request.models'; import { HostWindowService } from '../../../shared/host-window.service'; import { HostWindowServiceStub } from '../../../shared/testing/host-window-service.stub'; +import { getTestScheduler } from 'jasmine-marbles'; +import { TestScheduler } from 'rxjs/testing'; describe('SubmissionImportExternalSearchbarComponent test suite', () => { let comp: SubmissionImportExternalSearchbarComponent; let compAsAny: any; let fixture: ComponentFixture; + let scheduler: TestScheduler; beforeEach(async (() => { + scheduler = getTestScheduler(); TestBed.configureTestingModule({ imports: [ TranslateModule.forRoot(), @@ -85,23 +89,25 @@ describe('SubmissionImportExternalSearchbarComponent test suite', () => { compAsAny = null; }); - it('Should init component properly (without initExternalSourceData)', () => { + it('Should init component properly (without initExternalSourceData)', fakeAsync(() => { comp.initExternalSourceData = { sourceId: '', query: '' }; fixture.detectChanges(); + tick(); expect(comp.selectedElement).toEqual(sourceList[0]); expect(compAsAny.pageInfo).toEqual(paginatedList.pageInfo); expect(comp.sourceList).toEqual(sourceList); - }); + })); - it('Should init component properly (with initExternalSourceData populated)', () => { + it('Should init component properly (with initExternalSourceData populated)', fakeAsync(() => { comp.initExternalSourceData = { query: 'dummy', sourceId: 'ciencia' }; fixture.detectChanges(); + tick(); expect(comp.selectedElement).toEqual(sourceList[1]); expect(compAsAny.pageInfo).toEqual(paginatedList.pageInfo); expect(comp.sourceList).toEqual(sourceList); - }); + })); it('Variable \'selectedElement\' should be assigned', () => { const selectedElement = {id: 'orcid', name: 'orcid'}; @@ -123,7 +129,9 @@ describe('SubmissionImportExternalSearchbarComponent test suite', () => { }); comp.sourceList = sourceList; const expected = sourceList.concat(sourceList); - comp.onScroll(); + + scheduler.schedule(() => comp.onScroll()); + scheduler.flush(); expect(comp.sourceList).toEqual(expected); }); From a2834764035265cb537891cee289656ed1cc8445 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 16 Jul 2020 13:08:17 +0200 Subject: [PATCH 047/170] [CST-3088] Fixed travis failure --- .../form/process-form.component.spec.ts | 3 ++- .../onebox/dynamic-onebox.component.spec.ts | 24 +++++++++++-------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/app/process-page/form/process-form.component.spec.ts b/src/app/process-page/form/process-form.component.spec.ts index 12326111da..d32405d8bf 100644 --- a/src/app/process-page/form/process-form.component.spec.ts +++ b/src/app/process-page/form/process-form.component.spec.ts @@ -75,8 +75,9 @@ describe('ProcessFormComponent', () => { fixture.detectChanges(); }); - it('should create', () => { + it('should create', (done) => { expect(component).toBeTruthy(); + done(); }); it('should call invoke on the scriptService on submit', () => { diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.spec.ts index 5bbae9c98c..e94d3a208c 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.spec.ts @@ -1,7 +1,7 @@ // Load the implementations that should be tested import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { async, ComponentFixture, fakeAsync, inject, TestBed, tick, } from '@angular/core/testing'; +import { ComponentFixture, fakeAsync, inject, TestBed, tick, } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { CdkTreeModule } from '@angular/cdk/tree'; @@ -113,12 +113,12 @@ describe('DsDynamicOneboxComponent test suite', () => { } // async beforeEach - beforeEach(async(() => { + beforeEach(() => { vocabularyServiceStub = new VocabularyServiceStub(); - // modal = jasmine.createSpyObj('modal', ['open', 'close', 'dismiss']); + modal = jasmine.createSpyObj('modal', { - open: jasmine.createSpy('open').and.returnValue(new MockNgbModalRef()), + open: jasmine.createSpy('open'), close: jasmine.createSpy('close'), dismiss: jasmine.createSpy('dismiss'), } @@ -150,9 +150,9 @@ describe('DsDynamicOneboxComponent test suite', () => { { provide: NgbModal, useValue: modal } ], schemas: [CUSTOM_ELEMENTS_SCHEMA] - }); + }).compileComponents(); - })); + }); describe('', () => { // synchronous beforeEach @@ -381,6 +381,7 @@ describe('DsDynamicOneboxComponent test suite', () => { oneboxCompFixture = TestBed.createComponent(DsDynamicOneboxComponent); oneboxComponent = oneboxCompFixture.componentInstance; // FormComponent test instance modalService = TestBed.get(NgbModal); + modalService.open.and.returnValue(new MockNgbModalRef()); }); describe('when init model value is empty', () => { @@ -395,15 +396,17 @@ describe('DsDynamicOneboxComponent test suite', () => { oneboxComponent = null; }); - it('should init component properly', () => { + it('should init component properly', fakeAsync(() => { + tick(); expect(oneboxComponent.currentValue).not.toBeDefined(); - }); + })); - it('should open tree properly', () => { + it('should open tree properly', (done) => { scheduler.schedule(() => oneboxComponent.openTree(new Event('click'))); scheduler.flush(); expect((oneboxComponent as any).modalService.open).toHaveBeenCalled(); + done(); }); }); @@ -433,11 +436,12 @@ describe('DsDynamicOneboxComponent test suite', () => { expect((oneboxComponent as any).vocabularyService.getVocabularyEntryByValue).toHaveBeenCalled(); })); - it('should open tree properly', () => { + it('should open tree properly', (done) => { scheduler.schedule(() => oneboxComponent.openTree(new Event('click'))); scheduler.flush(); expect((oneboxComponent as any).modalService.open).toHaveBeenCalled(); + done(); }); }); From c33a63aa90480f6235bdbeaa1df91b620cc06ae9 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 16 Jul 2020 13:13:24 +0200 Subject: [PATCH 048/170] [CST-3088] Removed metadata and collection params when making vocabulary requests --- .../models/vocabulary-find-options.model.ts | 11 +--- .../vocabularies/vocabulary.service.spec.ts | 59 +++++++++++++------ .../vocabularies/vocabulary.service.ts | 10 ---- 3 files changed, 43 insertions(+), 37 deletions(-) diff --git a/src/app/core/submission/vocabularies/models/vocabulary-find-options.model.ts b/src/app/core/submission/vocabularies/models/vocabulary-find-options.model.ts index 9dc12fad57..bd9bd55b95 100644 --- a/src/app/core/submission/vocabularies/models/vocabulary-find-options.model.ts +++ b/src/app/core/submission/vocabularies/models/vocabulary-find-options.model.ts @@ -8,9 +8,7 @@ import { isNotEmpty } from '../../../../shared/empty.util'; */ export class VocabularyFindOptions extends FindListOptions { - constructor(public collection, - public metadata, - public query: string = '', + constructor(public query: string = '', public filter?: string, public exact?: boolean, public entryID?: string, @@ -21,12 +19,7 @@ export class VocabularyFindOptions extends FindListOptions { super(); const searchParams = []; - if (isNotEmpty(metadata)) { - searchParams.push(new RequestParam('metadata', metadata)) - } - if (isNotEmpty(collection)) { - searchParams.push(new RequestParam('collection', collection)) - } + if (isNotEmpty(query)) { searchParams.push(new RequestParam('query', query)) } diff --git a/src/app/core/submission/vocabularies/vocabulary.service.spec.ts b/src/app/core/submission/vocabularies/vocabulary.service.spec.ts index 0998b64579..682cc215e0 100644 --- a/src/app/core/submission/vocabularies/vocabulary.service.spec.ts +++ b/src/app/core/submission/vocabularies/vocabulary.service.spec.ts @@ -13,7 +13,7 @@ import { VocabularyEntriesRequest } from '../../data/request.models'; import { RequestParam } from '../../cache/models/request-param.model'; import { PageInfo } from '../../shared/page-info.model'; import { PaginatedList } from '../../data/paginated-list'; -import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils'; +import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; import { RequestEntry } from '../../data/request.reducer'; import { RestResponse } from '../../cache/response.models'; import { VocabularyService } from './vocabulary.service'; @@ -67,6 +67,27 @@ describe('VocabularyService', () => { } }; + const vocabularyEntry: any = { + display: 'testValue1', + value: 'testValue1', + otherInformation: {}, + type: 'vocabularyEntry' + }; + + const vocabularyEntry2: any = { + display: 'testValue2', + value: 'testValue2', + otherInformation: {}, + type: 'vocabularyEntry' + }; + + const vocabularyEntry3: any = { + display: 'testValue3', + value: 'testValue3', + otherInformation: {}, + type: 'vocabularyEntry' + }; + const vocabularyEntryParentDetail: any = { authority: 'authorityId2', display: 'testParent', @@ -148,10 +169,10 @@ describe('VocabularyService', () => { const collectionUUID = '8b39g7ya-5a4b-438b-851f-be1d5b4a1c5a'; const entryID = 'dsfsfsdf-5a4b-438b-851f-be1d5b4a1c5a'; const searchRequestURL = `https://rest.api/rest/api/submission/vocabularies/search/byMetadataAndCollection?metadata=${metadata}&collection=${collectionUUID}`; - const entriesRequestURL = `https://rest.api/rest/api/submission/vocabularies/${vocabulary.id}/entries?metadata=${metadata}&collection=${collectionUUID}`; - const entriesByValueRequestURL = `https://rest.api/rest/api/submission/vocabularies/${vocabulary.id}/entries?metadata=${metadata}&collection=${collectionUUID}&filter=test&exact=false`; - const entryByValueRequestURL = `https://rest.api/rest/api/submission/vocabularies/${vocabulary.id}/entries?metadata=${metadata}&collection=${collectionUUID}&filter=test&exact=true`; - const entryByIDRequestURL = `https://rest.api/rest/api/submission/vocabularies/${vocabulary.id}/entries?metadata=${metadata}&collection=${collectionUUID}&entryID=${entryID}`; + const entriesRequestURL = `https://rest.api/rest/api/submission/vocabularies/${vocabulary.id}/entries`; + const entriesByValueRequestURL = `https://rest.api/rest/api/submission/vocabularies/${vocabulary.id}/entries?filter=test&exact=false`; + const entryByValueRequestURL = `https://rest.api/rest/api/submission/vocabularies/${vocabulary.id}/entries?filter=test&exact=true`; + const entryByIDRequestURL = `https://rest.api/rest/api/submission/vocabularies/${vocabulary.id}/entries?entryID=${entryID}`; const vocabularyOptions: VocabularyOptions = { name: vocabularyId, metadata: metadata, @@ -160,16 +181,19 @@ describe('VocabularyService', () => { } const pageInfo = new PageInfo(); const array = [vocabulary, hierarchicalVocabulary]; + const arrayEntries = [vocabularyEntry, vocabularyEntry2, vocabularyEntry3]; const childrenEntries = [vocabularyEntryChildDetail, vocabularyEntryChild2Detail]; const paginatedList = new PaginatedList(pageInfo, array); + const paginatedListEntries = new PaginatedList(pageInfo, arrayEntries); const childrenPaginatedList = new PaginatedList(pageInfo, childrenEntries); const vocabularyRD = createSuccessfulRemoteDataObject(vocabulary); + const vocabularyEntriesRD = createSuccessfulRemoteDataObject$(paginatedListEntries); const vocabularyEntryDetailParentRD = createSuccessfulRemoteDataObject(vocabularyEntryParentDetail); const vocabularyEntryChildrenRD = createSuccessfulRemoteDataObject(childrenPaginatedList); const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); - const getRequestEntry$ = (successful: boolean) => { + const getRequestEntries$ = (successful: boolean) => { return observableOf({ - response: { isSuccessful: successful, payload: vocabulary } as any + response: { isSuccessful: successful, payload: arrayEntries } as any } as RequestEntry) }; objectCache = {} as ObjectCacheService; @@ -312,8 +336,8 @@ describe('VocabularyService', () => { describe('', () => { beforeEach(() => { - requestService = getMockRequestService(getRequestEntry$(true)); - rdbService = getMockRemoteDataBuildService(); + requestService = getMockRequestService(getRequestEntries$(true)); + rdbService = getMockRemoteDataBuildService(undefined, vocabularyEntriesRD); spyOn(rdbService, 'toRemoteDataObservable').and.callThrough(); service = initTestService(); }); @@ -329,10 +353,10 @@ describe('VocabularyService', () => { }); it('should call RemoteDataBuildService to create the RemoteData Observable', () => { - service.getVocabularyEntries(vocabularyOptions, pageInfo); + scheduler.schedule(() => service.getVocabularyEntries(vocabularyOptions, pageInfo)); + scheduler.flush(); expect(rdbService.toRemoteDataObservable).toHaveBeenCalled(); - }); }); @@ -347,7 +371,8 @@ describe('VocabularyService', () => { }); it('should call RemoteDataBuildService to create the RemoteData Observable', () => { - service.getVocabularyEntriesByValue('test', false, vocabularyOptions, pageInfo); + scheduler.schedule(() => service.getVocabularyEntriesByValue('test', false, vocabularyOptions, pageInfo)); + scheduler.flush(); expect(rdbService.toRemoteDataObservable).toHaveBeenCalled(); @@ -365,7 +390,8 @@ describe('VocabularyService', () => { }); it('should call RemoteDataBuildService to create the RemoteData Observable', () => { - service.getVocabularyEntryByValue('test', vocabularyOptions); + scheduler.schedule(() => service.getVocabularyEntryByValue('test', vocabularyOptions)); + scheduler.flush(); expect(rdbService.toRemoteDataObservable).toHaveBeenCalled(); @@ -383,7 +409,8 @@ describe('VocabularyService', () => { }); it('should call RemoteDataBuildService to create the RemoteData Observable', () => { - service.getVocabularyEntryByID('test', vocabularyOptions); + scheduler.schedule(() => service.getVocabularyEntryByID('test', vocabularyOptions)); + scheduler.flush(); expect(rdbService.toRemoteDataObservable).toHaveBeenCalled(); @@ -495,8 +522,6 @@ describe('VocabularyService', () => { null, null, null, - null, - null, pageInfo.elementsPerPage, pageInfo.currentPage ); @@ -522,8 +547,6 @@ describe('VocabularyService', () => { null, null, null, - null, - null, pageInfo.elementsPerPage, pageInfo.currentPage ); diff --git a/src/app/core/submission/vocabularies/vocabulary.service.ts b/src/app/core/submission/vocabularies/vocabulary.service.ts index 1dac3b56a6..648f4744d3 100644 --- a/src/app/core/submission/vocabularies/vocabulary.service.ts +++ b/src/app/core/submission/vocabularies/vocabulary.service.ts @@ -150,8 +150,6 @@ export class VocabularyService { getVocabularyEntries(vocabularyOptions: VocabularyOptions, pageInfo: PageInfo): Observable>> { const options: VocabularyFindOptions = new VocabularyFindOptions( - vocabularyOptions.scope, - vocabularyOptions.metadata, null, null, null, @@ -179,8 +177,6 @@ export class VocabularyService { */ getVocabularyEntriesByValue(value: string, exact: boolean, vocabularyOptions: VocabularyOptions, pageInfo: PageInfo): Observable>> { const options: VocabularyFindOptions = new VocabularyFindOptions( - vocabularyOptions.scope, - vocabularyOptions.metadata, null, value, exact, @@ -229,8 +225,6 @@ export class VocabularyService { getVocabularyEntryByID(ID: string, vocabularyOptions: VocabularyOptions): Observable { const pageInfo = new PageInfo() const options: VocabularyFindOptions = new VocabularyFindOptions( - vocabularyOptions.scope, - vocabularyOptions.metadata, null, null, null, @@ -335,8 +329,6 @@ export class VocabularyService { null, null, null, - null, - null, pageInfo.elementsPerPage, pageInfo.currentPage ); @@ -358,8 +350,6 @@ export class VocabularyService { null, null, null, - null, - null, pageInfo.elementsPerPage, pageInfo.currentPage ); From c7ef818454c9c6cf671c3f5b310619ff75365b44 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 16 Jul 2020 14:35:57 +0200 Subject: [PATCH 049/170] [CST-3088] fix ProcessFormComponent test --- .../form/process-form.component.spec.ts | 36 +++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/src/app/process-page/form/process-form.component.spec.ts b/src/app/process-page/form/process-form.component.spec.ts index d32405d8bf..97423c8617 100644 --- a/src/app/process-page/form/process-form.component.spec.ts +++ b/src/app/process-page/form/process-form.component.spec.ts @@ -1,4 +1,4 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; import { FormsModule } from '@angular/forms'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; @@ -14,6 +14,8 @@ import { NotificationsServiceStub } from '../../shared/testing/notifications-ser import { TranslateLoaderMock } from '../../shared/mocks/translate-loader.mock'; import { RequestService } from '../../core/data/request.service'; import { Router } from '@angular/router'; +import { TestScheduler } from 'rxjs/testing'; +import { getTestScheduler } from 'jasmine-marbles'; describe('ProcessFormComponent', () => { let component: ProcessFormComponent; @@ -21,6 +23,9 @@ describe('ProcessFormComponent', () => { let scriptService; let parameterValues; let script; + let scheduler: TestScheduler; + let requestService: RequestService; + let router: Router; function init() { const param1 = new ScriptParameter(); @@ -41,10 +46,18 @@ describe('ProcessFormComponent', () => { } }) } - ) + ); + + requestService = jasmine.createSpyObj('requestService', { + removeByHrefSubstring: jasmine.createSpy('removeByHrefSubstring') + }); + + router = jasmine.createSpyObj('requestService', { + navigateByUrl: jasmine.createSpy('navigateByUrl') + }); } - beforeEach(async(() => { + beforeEach(() => { init(); TestBed.configureTestingModule({ imports: [ @@ -59,15 +72,16 @@ describe('ProcessFormComponent', () => { providers: [ { provide: ScriptDataService, useValue: scriptService }, { provide: NotificationsService, useClass: NotificationsServiceStub }, - { provide: RequestService, useValue: jasmine.createSpyObj('requestService', ['removeBySubstring']) }, - { provide: Router, useValue: {} }, + { provide: RequestService, useValue: requestService }, + { provide: Router, useValue: router }, ], schemas: [NO_ERRORS_SCHEMA] }) .compileComponents(); - })); + }); beforeEach(() => { + scheduler = getTestScheduler(); fixture = TestBed.createComponent(ProcessFormComponent); component = fixture.componentInstance; component.parameters = parameterValues; @@ -75,13 +89,15 @@ describe('ProcessFormComponent', () => { fixture.detectChanges(); }); - it('should create', (done) => { + it('should create', () => { expect(component).toBeTruthy(); - done(); }); - it('should call invoke on the scriptService on submit', () => { - component.submitForm({ controls: {} } as any); + it('should call invoke on the scriptService on submit', (done) => { + scheduler.schedule(() => component.submitForm({ controls: {} } as any)); + scheduler.flush(); + expect(scriptService.invoke).toHaveBeenCalled(); + done(); }); }); From b8abedb5d6eaa6f78b9c68ab36513177fe263aa1 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 16 Jul 2020 14:49:03 +0200 Subject: [PATCH 050/170] Fixed test --- ...-import-external-preview.component.spec.ts | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts index 58488dd5ab..5467d9e7b7 100644 --- a/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts +++ b/src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts @@ -1,10 +1,10 @@ import { Component, NO_ERRORS_SCHEMA } from '@angular/core'; -import { async, TestBed, ComponentFixture, inject } from '@angular/core/testing'; +import { async, ComponentFixture, inject, TestBed } from '@angular/core/testing'; import { TranslateModule } from '@ngx-translate/core'; import { Router } from '@angular/router'; -import { NgbModal, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { TestScheduler } from 'rxjs/testing'; -import { of as observableOf, of } from 'rxjs/internal/observable/of'; +import { of as observableOf } from 'rxjs/internal/observable/of'; import { getTestScheduler } from 'jasmine-marbles'; import { SubmissionImportExternalPreviewComponent } from './submission-import-external-preview.component'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; @@ -40,7 +40,7 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { _links: { self: { href: 'http://test-rest.com/server/api/integration/externalSources/orcidV2/entryValues/0000-0003-4851-8004' } } }); - beforeEach(async (() => { + beforeEach(async(() => { scheduler = getTestScheduler(); TestBed.configureTestingModule({ imports: [ @@ -117,7 +117,7 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { expect(compAsAny.activeModal.dismiss).toHaveBeenCalled(); }); - it('Should start the import process opening a modal', () => { + it('Should start the import process opening a modal', (done) => { const emittedEvent: CollectionListEntry = { communities: [ { @@ -133,10 +133,15 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { } }; const submissionObjects = [ - { id: 'jk11k13o-9v4z-632i-sr88-wq071n0h1d47' } + { id: 'jk11k13o-9v4z-632i-sr88-wq071n0h1d47' } ]; comp.externalSourceEntry = externalEntry; - ngbModal.open.and.returnValue({componentInstance: { selectedEvent: observableOf(emittedEvent)}}); + ngbModal.open.and.returnValue({ + componentInstance: { selectedEvent: observableOf(emittedEvent) }, + close: () => { + return; + } + }); spyOn(comp, 'closeMetadataModal'); submissionServiceStub.createSubmissionFromExternalSource.and.returnValue(observableOf(submissionObjects)); spyOn(compAsAny.router, 'navigateByUrl'); @@ -147,6 +152,7 @@ describe('SubmissionImportExternalPreviewComponent test suite', () => { expect(comp.closeMetadataModal).toHaveBeenCalled(); expect(compAsAny.submissionService.createSubmissionFromExternalSource).toHaveBeenCalledWith(externalEntry._links.self.href, emittedEvent.collection.id); expect(compAsAny.router.navigateByUrl).toHaveBeenCalledWith('/workspaceitems/' + submissionObjects[0].id + '/edit'); + done(); }); }); }); From 92258190467e2e4fc023fdd48b5caeb18e9b1a28 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 16 Jul 2020 17:00:14 +0200 Subject: [PATCH 051/170] [CST-3092] Removed label from New submission and Import buttons --- .../my-dspace-new-submission.component.html | 4 ++-- .../my-dspace-new-submission.component.ts | 19 +++++-------------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html index 248909b215..4cb58012bc 100644 --- a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html +++ b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.html @@ -8,12 +8,12 @@
diff --git a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts index e3cf19bf8a..5659c442ad 100644 --- a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts +++ b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts @@ -1,9 +1,11 @@ import { ChangeDetectorRef, Component, EventEmitter, OnDestroy, OnInit, Output } from '@angular/core'; +import { Router } from '@angular/router'; -import { Subscription, Observable } from 'rxjs'; +import { Subscription } from 'rxjs'; import { first } from 'rxjs/operators'; import { Store } from '@ngrx/store'; import { TranslateService } from '@ngx-translate/core'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { SubmissionState } from '../../submission/submission.reducers'; import { AuthService } from '../../core/auth/auth.service'; @@ -15,10 +17,7 @@ import { HALEndpointService } from '../../core/shared/hal-endpoint.service'; import { NotificationType } from '../../shared/notifications/models/notification-type'; import { hasValue } from '../../shared/empty.util'; import { SearchResult } from '../../shared/search/search-result.model'; -import { Router } from '@angular/router'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; -import { CreateItemParentSelectorComponent } from 'src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component'; -import { HostWindowService } from '../../shared/host-window.service'; +import { CreateItemParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component'; /** * This component represents the whole mydspace page header @@ -39,11 +38,6 @@ export class MyDSpaceNewSubmissionComponent implements OnDestroy, OnInit { */ public uploadFilesOptions: UploaderOptions = new UploaderOptions(); - /** - * Emits true if were on a small screen - */ - public isXsOrSm$: Observable; - /** * Subscription to unsubscribe from */ @@ -60,7 +54,6 @@ export class MyDSpaceNewSubmissionComponent implements OnDestroy, OnInit { * @param {TranslateService} translate * @param {Router} router * @param {NgbModal} modalService - * @param {HostWindowService} windowService */ constructor(private authService: AuthService, private changeDetectorRef: ChangeDetectorRef, @@ -69,8 +62,7 @@ export class MyDSpaceNewSubmissionComponent implements OnDestroy, OnInit { private store: Store, private translate: TranslateService, private router: Router, - private modalService: NgbModal, - protected windowService: HostWindowService) { + private modalService: NgbModal) { } /** @@ -83,7 +75,6 @@ export class MyDSpaceNewSubmissionComponent implements OnDestroy, OnInit { this.changeDetectorRef.detectChanges(); } ); - this.isXsOrSm$ = this.windowService.isXsOrSm(); } /** From 1c31deb3dfde1ae866f7b5b87786863f8f42cad5 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 16 Jul 2020 17:01:06 +0200 Subject: [PATCH 052/170] [CST-3092] fixed style issue with external source search bar --- .../submission-import-external-searchbar.component.scss | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.scss b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.scss index 562b5b5613..0d2a79b056 100644 --- a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.scss +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.scss @@ -1,7 +1,6 @@ -.input-group-append .btn { +.input-group-append:last-child > .btn:not(:last-child):not(.dropdown-toggle) { margin-left: -1px; - border-top-left-radius: 0; - border-bottom-left-radius: 0; + border-radius: 0 0.25rem 0.25rem 0; } .input-group-append .dropdown-toggle { From c48b817c2da6de75c54f6c9962214b4e72dd4a0b Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 16 Jul 2020 17:02:12 +0200 Subject: [PATCH 053/170] [CST-3092] Changed start message from external source page --- .../import-external/submission-import-external.component.html | 4 ++-- src/assets/i18n/en.json5 | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/submission/import-external/submission-import-external.component.html b/src/app/submission/import-external/submission-import-external.component.html index 2aac8557aa..9f52969635 100644 --- a/src/app/submission/import-external/submission-import-external.component.html +++ b/src/app/submission/import-external/submission-import-external.component.html @@ -30,9 +30,9 @@
-
+

{{'submission.import-external.page.hint' | translate}}

-
+
diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 6aee58458f..23f72646c6 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -2683,7 +2683,7 @@ "submission.import-external.title": "Import metadata from an external source", - "submission.import-external.page.hint": "No search performed yet. Search items using external sources.", + "submission.import-external.page.hint": "Enter a query above to find items from the web to import in to DSpace.", "submission.import-external.back-to-my-dspace": "Back to MyDSpace", From 607318f6c5cfdb8ef1e517b968264c33648b74a2 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Mon, 13 Jul 2020 15:42:52 +0200 Subject: [PATCH 054/170] Fix CommunityDataService's topLinkPath --- src/app/core/data/community-data.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/core/data/community-data.service.ts b/src/app/core/data/community-data.service.ts index 123c3eccd1..474bdef44a 100644 --- a/src/app/core/data/community-data.service.ts +++ b/src/app/core/data/community-data.service.ts @@ -24,7 +24,7 @@ import { RequestService } from './request.service'; @dataService(COMMUNITY) export class CommunityDataService extends ComColDataService { protected linkPath = 'communities'; - protected topLinkPath = 'communities/search/top'; + protected topLinkPath = 'search/top'; protected cds = this; constructor( From 6fecdfadb2521a1d6269170579ec3025eeff4090 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Tue, 21 Jul 2020 18:53:09 +0200 Subject: [PATCH 055/170] Fixed issue that redirect always to home page after checking authentication on CSR --- src/app/core/auth/auth.service.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/core/auth/auth.service.ts b/src/app/core/auth/auth.service.ts index 85e5eebb9e..7f61bec9f3 100644 --- a/src/app/core/auth/auth.service.ts +++ b/src/app/core/auth/auth.service.ts @@ -423,6 +423,7 @@ export class AuthService { } else { // If redirectUrl is empty use history. this.routeService.getHistory().pipe( + filter((history) => history.length > 0), take(1) ).subscribe((history) => { let redirUrl; From 47ab023e7a090523246f76cc83b90d9aeb003caa Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Wed, 22 Jul 2020 17:03:52 +0200 Subject: [PATCH 056/170] fixed VocabularyTreeviewComponent selector --- .../vocabulary-treeview/vocabulary-treeview.component.spec.ts | 2 +- .../shared/vocabulary-treeview/vocabulary-treeview.component.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.spec.ts b/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.spec.ts index 9af00b6be7..16ee2a55dd 100644 --- a/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.spec.ts +++ b/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.spec.ts @@ -79,7 +79,7 @@ describe('VocabularyTreeviewComponent test suite', () => { // synchronous beforeEach beforeEach(() => { const html = ` - `; + `; testFixture = createTestComponent(html, TestComponent) as ComponentFixture; testComp = testFixture.componentInstance; diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts b/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts index 8c7543849d..6de1a11e00 100644 --- a/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts +++ b/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts @@ -22,7 +22,7 @@ import { VocabularyEntry } from '../../core/submission/vocabularies/models/vocab * Component that show a hierarchical vocabulary in a tree view */ @Component({ - selector: 'ds-authority-treeview', + selector: 'ds-vocabulary-treeview', templateUrl: './vocabulary-treeview.component.html', styleUrls: ['./vocabulary-treeview.component.scss'] }) From d88a863a0d8b1041f01bcf0b9d698b3440e21529 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Wed, 22 Jul 2020 17:40:03 +0200 Subject: [PATCH 057/170] fixed issue that didn't allow to select tree node after a search --- .../vocabulary-treeview-node.model.ts | 1 + .../vocabulary-treeview.component.ts | 5 ++- .../vocabulary-treeview.service.spec.ts | 33 ++++++++++++----- .../vocabulary-treeview.service.ts | 36 ++++++++++--------- 4 files changed, 48 insertions(+), 27 deletions(-) diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview-node.model.ts b/src/app/shared/vocabulary-treeview/vocabulary-treeview-node.model.ts index 60473c77ca..2ed21cbdf0 100644 --- a/src/app/shared/vocabulary-treeview/vocabulary-treeview-node.model.ts +++ b/src/app/shared/vocabulary-treeview/vocabulary-treeview-node.model.ts @@ -34,6 +34,7 @@ export class TreeviewFlatNode { constructor(public item: VocabularyEntryDetail, public level = 1, public expandable = false, + public childrenLoaded = false, public pageInfo: PageInfo = new PageInfo(), public loadMoreParentItem: VocabularyEntryDetail | null = null, public isSearchNode = false, diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts b/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts index 6de1a11e00..cbd9c25a9b 100644 --- a/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts +++ b/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts @@ -143,6 +143,7 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit { node.item, level, node.hasChildren, + (node.hasChildren && isNotEmpty(node.children)), node.pageInfo, node.loadMoreParentItem, node.isSearchNode, @@ -150,7 +151,9 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit { ); this.nodeMap.set(node.item.id, newNode); - if ((((level + 1) < this.preloadLevel) && newNode.expandable) || newNode.isSearchNode || newNode.isInInitValueHierarchy) { + if ((((level + 1) < this.preloadLevel) && newNode.childrenLoaded) + || (newNode.isSearchNode && newNode.childrenLoaded) + || newNode.isInInitValueHierarchy) { if (!newNode.isSearchNode) { this.loadChildren(newNode); } diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.spec.ts b/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.spec.ts index 2f03549898..944ca0bfb0 100644 --- a/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.spec.ts +++ b/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.spec.ts @@ -13,6 +13,7 @@ import { PageInfo } from '../../core/shared/page-info.model'; import { VocabularyEntryDetail } from '../../core/submission/vocabularies/models/vocabulary-entry-detail.model'; import { PaginatedList } from '../../core/data/paginated-list'; import { createSuccessfulRemoteDataObject } from '../remote-data.utils'; +import { VocabularyEntry } from '../../core/submission/vocabularies/models/vocabulary-entry.model'; describe('VocabularyTreeviewService test suite', () => { @@ -34,6 +35,7 @@ describe('VocabularyTreeviewService test suite', () => { let childNode: TreeviewNode; let child2: VocabularyEntryDetail; let childNode2: TreeviewNode; + let childEntry3: VocabularyEntry; let child3: VocabularyEntryDetail; let childNode3: TreeviewNode; let searchItemNode: TreeviewNode; @@ -71,37 +73,46 @@ describe('VocabularyTreeviewService test suite', () => { }); loadMoreNode = new TreeviewNode(LOAD_MORE_NODE, false, new PageInfo(), item); loadMoreRootNode = new TreeviewNode(LOAD_MORE_ROOT_NODE, false, new PageInfo(), null); - loadMoreRootFlatNode = new TreeviewFlatNode(LOAD_MORE_ROOT_NODE, 1, false, new PageInfo(), null); + loadMoreRootFlatNode = new TreeviewFlatNode(LOAD_MORE_ROOT_NODE, 1, false, false, new PageInfo(), null); item = new VocabularyEntryDetail(); - item.id = item.value = item.display = 'root1'; + item.id = 'vocabularyTest:root1'; + item.value = item.display = 'root1'; item.otherInformation = { hasChildren: 'true', id: 'root1' }; itemNode = new TreeviewNode(item, true, pageInfo); searchItemNode = new TreeviewNode(item, true, new PageInfo(), null, true); item2 = new VocabularyEntryDetail(); - item2.id = item2.value = item2.display = 'root2'; + item2.id = 'vocabularyTest:root2'; + item2.value = item2.display = 'root2'; item2.otherInformation = { id: 'root2' }; itemNode2 = new TreeviewNode(item2, false, pageInfo); item3 = new VocabularyEntryDetail(); - item3.id = item3.value = item3.display = 'root3'; + item3.id = 'vocabularyTest:root3'; + item3.value = item3.display = 'root3'; item3.otherInformation = { id: 'root3' }; itemNode3 = new TreeviewNode(item3, false, pageInfo); child = new VocabularyEntryDetail(); - child.id = child.value = child.display = 'root1-child1'; + child.id = 'vocabularyTest:root1-child1'; + child.value = child.display = 'root1-child1'; child.otherInformation = { parent: 'root1', hasChildren: 'true', id: 'root1-child1' }; childNode = new TreeviewNode(child); searchChildNode = new TreeviewNode(child, true, new PageInfo(), item, true); + childEntry3 = new VocabularyEntry(); + childEntry3.value = childEntry3.display = 'root1-child1-child1'; + childEntry3.otherInformation = { parent: 'root1-child1', id: 'root1-child1-child1' }; child3 = new VocabularyEntryDetail(); - child3.id = child3.value = child3.display = 'root1-child1-child1'; + child3.id = 'vocabularyTest:root1-child1-child1'; + child3.value = child3.display = 'root1-child1-child1'; child3.otherInformation = { parent: 'root1-child1', id: 'root1-child1-child1' }; childNode3 = new TreeviewNode(child3); searchChildNode3 = new TreeviewNode(child3, false, new PageInfo(), child, true); child2 = new VocabularyEntryDetail(); - child2.id = child2.value = child2.display = 'root1-child2'; + child2.id = 'vocabularyTest:root1-child2'; + child2.value = child2.display = 'root1-child2'; child2.otherInformation = { parent: 'root1', id: 'root1-child2' }; childNode2 = new TreeviewNode(child2, true); initValueChildNode2 = new TreeviewNode(child2, false, new PageInfo(), item, false, true); @@ -184,7 +195,6 @@ describe('VocabularyTreeviewService test suite', () => { expect(serviceAsAny.vocabularyName).toEqual(vocabularyOptions.name); expect(serviceAsAny.pageInfo).toEqual(pageInfo); - console.log(serviceAsAny.dataChange.value[0].pageInfo, itemNode.pageInfo); expect(serviceAsAny.dataChange.value).toEqual([itemNode, itemNode2, itemNode3]); }); @@ -290,7 +300,11 @@ describe('VocabularyTreeviewService test suite', () => { currentPage: 1 }); serviceAsAny.vocabularyService.getVocabularyEntriesByValue.and.returnValue(hot('-a', { - a: createSuccessfulRemoteDataObject(new PaginatedList(pageInfo, [child3])) + a: createSuccessfulRemoteDataObject(new PaginatedList(pageInfo, [childEntry3])) + })); + + serviceAsAny.vocabularyService.findEntryDetailByValue.and.returnValue(hot('-a', { + a: createSuccessfulRemoteDataObject(child3) })); serviceAsAny.vocabularyService.getEntryDetailParent.and.returnValues( @@ -305,6 +319,7 @@ describe('VocabularyTreeviewService test suite', () => { scheduler.schedule(() => service.searchByQuery(vocabularyOptions)); scheduler.flush(); + searchChildNode.childrenChange.next([searchChildNode3]); searchItemNode.childrenChange.next([searchChildNode]); expect(serviceAsAny.dataChange.value.length).toEqual(1); diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.ts b/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.ts index 836ce7672a..698f5bb0d2 100644 --- a/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.ts +++ b/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.ts @@ -134,13 +134,13 @@ export class VocabularyTreeviewService { * @param onlyFirstTime */ loadMore(item: VocabularyEntryDetail, onlyFirstTime = false) { - if (!this.nodeMap.has(item.id)) { + if (!this.nodeMap.has(item.otherInformation.id)) { return; } - const parent: TreeviewNode = this.nodeMap.get(item.id)!; - const children = this.nodeMap.get(item.id)!.children || []; + const parent: TreeviewNode = this.nodeMap.get(item.otherInformation.id)!; + const children = this.nodeMap.get(item.otherInformation.id)!.children || []; children.pop(); - this.getChildrenNodesByParent(item.id, parent.pageInfo).subscribe((list: PaginatedList) => { + this.getChildrenNodesByParent(item.otherInformation.id, parent.pageInfo).subscribe((list: PaginatedList) => { if (onlyFirstTime && parent.children!.length > 0) { return; @@ -187,9 +187,14 @@ export class VocabularyTreeviewService { this.vocabularyService.getVocabularyEntriesByValue(query, false, this.vocabularyOptions, new PageInfo()).pipe( getFirstSucceededRemoteListPayload(), flatMap((result: VocabularyEntry[]) => (result.length > 0) ? result : observableOf(null)), - flatMap((entry: VocabularyEntry) => this.getNodeHierarchy(entry)), + flatMap((entry: VocabularyEntry) => + this.vocabularyService.findEntryDetailByValue(entry.otherInformation.id, this.vocabularyName).pipe( + getFirstSucceededRemoteDataPayload() + ) + ), + flatMap((entry: VocabularyEntryDetail) => this.getNodeHierarchy(entry)), scan((acc: TreeviewNode[], value: TreeviewNode) => { - if (isEmpty(value) || findIndex(acc, (node) => node.item.id === value.item.id) !== -1) { + if (isEmpty(value) || findIndex(acc, (node) => node.item.otherInformation.id === value.item.otherInformation.id) !== -1) { return acc; } else { return [...acc, value] @@ -217,24 +222,21 @@ export class VocabularyTreeviewService { /** * Generate a {@link TreeviewNode} object from vocabulary entry * - * @param entry The vocabulary entry + * @param entry The vocabulary entry detail * @param isSearchNode A Boolean representing if given entry is the result of a search * @param toStore A Boolean representing if the node created is to store or not * @return TreeviewNode */ - private _generateNode(entry: VocabularyEntry, isSearchNode = false, toStore = true): TreeviewNode { + private _generateNode(entry: VocabularyEntryDetail, isSearchNode = false, toStore = true): TreeviewNode { const entryId = entry.otherInformation.id; if (this.nodeMap.has(entryId)) { return this.nodeMap.get(entryId)!; } - const entryDetail: VocabularyEntryDetail = Object.assign(new VocabularyEntryDetail(), entry, { - id: entryId - }); const hasChildren = entry.hasOtherInformation() && (entry.otherInformation as any)!.hasChildren === 'true'; const pageInfo: PageInfo = this.pageInfo; const isInInitValueHierarchy = this.initValueHierarchy.includes(entryId); const result = new TreeviewNode( - entryDetail, + entry, hasChildren, pageInfo, null, @@ -328,7 +330,7 @@ export class VocabularyTreeviewService { * @param toStore A Boolean representing if the node created is to store or not * @return Observable */ - private getNodeHierarchy(item: VocabularyEntry, children?: TreeviewNode[], toStore = true): Observable { + private getNodeHierarchy(item: VocabularyEntryDetail, children?: TreeviewNode[], toStore = true): Observable { if (isEmpty(item)) { return observableOf(null); } @@ -337,7 +339,7 @@ export class VocabularyTreeviewService { if (isNotEmpty(children)) { const newChildren = children .filter((entry: TreeviewNode) => { - return findIndex(node.children, (nodeEntry) => nodeEntry.item.id === entry.item.id) === -1; + return findIndex(node.children, (nodeEntry) => nodeEntry.item.otherInformation.id === entry.item.otherInformation.id) === -1; }); newChildren.forEach((entry: TreeviewNode) => { entry.loadMoreParentItem = node.item @@ -346,7 +348,7 @@ export class VocabularyTreeviewService { } if (node.item.hasOtherInformation() && isNotEmpty(node.item.otherInformation.parent)) { - return this.getParentNode(node.item.id).pipe( + return this.getParentNode(node.item.otherInformation.id).pipe( flatMap((parentItem: VocabularyEntryDetail) => this.getNodeHierarchy(parentItem, [node], toStore)) ) } else { @@ -362,8 +364,8 @@ export class VocabularyTreeviewService { * @return string[] */ private getNodeHierarchyIds(node: TreeviewNode, hierarchyIds: string[] = []): string[] { - if (!hierarchyIds.includes(node.item.id)) { - hierarchyIds.push(node.item.id); + if (!hierarchyIds.includes(node.item.otherInformation.id)) { + hierarchyIds.push(node.item.otherInformation.id); } if (isNotEmpty(node.children)) { return this.getNodeHierarchyIds(node.children[0], hierarchyIds); From fb1b6c7a7abf0f79337d0fce64ad8752a6e92344 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Wed, 22 Jul 2020 17:49:36 +0200 Subject: [PATCH 058/170] Changed findEntryDetailByValue method name to a properly findEntryDetailById --- .../submission/vocabularies/vocabulary.service.spec.ts | 6 +++--- .../core/submission/vocabularies/vocabulary.service.ts | 8 ++++---- .../relation-group/dynamic-relation-group.components.ts | 2 +- .../vocabulary-treeview.service.spec.ts | 6 +++--- .../vocabulary-treeview/vocabulary-treeview.service.ts | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/app/core/submission/vocabularies/vocabulary.service.spec.ts b/src/app/core/submission/vocabularies/vocabulary.service.spec.ts index 682cc215e0..16e0eaf844 100644 --- a/src/app/core/submission/vocabularies/vocabulary.service.spec.ts +++ b/src/app/core/submission/vocabularies/vocabulary.service.spec.ts @@ -481,16 +481,16 @@ describe('VocabularyService', () => { }); }); - describe('findEntryDetailByValue', () => { + describe('findEntryDetailById', () => { it('should proxy the call to vocabularyDataService.findVocabularyById', () => { - scheduler.schedule(() => service.findEntryDetailByValue('testValue', hierarchicalVocabulary.id)); + scheduler.schedule(() => service.findEntryDetailById('testValue', hierarchicalVocabulary.id)); scheduler.flush(); const expectedId = `${hierarchicalVocabulary.id}:testValue` expect((service as any).vocabularyEntryDetailDataService.findById).toHaveBeenCalledWith(expectedId); }); it('should return a RemoteData for the object with the given id', () => { - const result = service.findEntryDetailByValue('testValue', hierarchicalVocabulary.id); + const result = service.findEntryDetailById('testValue', hierarchicalVocabulary.id); const expected = cold('a|', { a: vocabularyEntryDetailParentRD }); diff --git a/src/app/core/submission/vocabularies/vocabulary.service.ts b/src/app/core/submission/vocabularies/vocabulary.service.ts index 648f4744d3..5200d703b9 100644 --- a/src/app/core/submission/vocabularies/vocabulary.service.ts +++ b/src/app/core/submission/vocabularies/vocabulary.service.ts @@ -283,15 +283,15 @@ export class VocabularyService { /** * Returns an observable of {@link RemoteData} of a {@link VocabularyEntryDetail}, based on its ID, with a list of {@link FollowLinkConfig}, * to automatically resolve {@link HALLink}s of the object - * @param value The entry value for which to provide detailed information. + * @param id The entry id for which to provide detailed information. * @param name The name of {@link Vocabulary} to which the entry belongs * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved * @return {Observable>} * Return an observable that emits VocabularyEntryDetail object */ - findEntryDetailByValue(value: string, name: string, ...linksToFollow: Array>): Observable> { - const id = `${name}:${value}`; - return this.vocabularyEntryDetailDataService.findById(id, ...linksToFollow); + findEntryDetailById(id: string, name: string, ...linksToFollow: Array>): Observable> { + const findId = `${name}:${id}`; + return this.vocabularyEntryDetailDataService.findById(findId, ...linksToFollow); } /** diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.components.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.components.ts index 51cf69d560..5c2616dd34 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.components.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.components.ts @@ -233,7 +233,7 @@ export class DsDynamicRelationGroupComponent extends DynamicFormControlComponent if (isObject(valueObj[fieldName]) && valueObj[fieldName].hasAuthority() && isNotEmpty(valueObj[fieldName].authority)) { const fieldId = fieldName.replace(/\./g, '_'); const model = this.formBuilderService.findById(fieldId, this.formModel); - return$ = this.vocabularyService.findEntryDetailByValue( + return$ = this.vocabularyService.findEntryDetailById( valueObj[fieldName].authority, (model as any).vocabularyOptions.name ).pipe( diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.spec.ts b/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.spec.ts index 944ca0bfb0..f45478f82b 100644 --- a/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.spec.ts +++ b/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.spec.ts @@ -57,7 +57,7 @@ describe('VocabularyTreeviewService test suite', () => { const vocabularyServiceStub = jasmine.createSpyObj('VocabularyService', { getVocabularyEntriesByValue: jasmine.createSpy('getVocabularyEntriesByValue'), getEntryDetailParent: jasmine.createSpy('getEntryDetailParent'), - findEntryDetailByValue: jasmine.createSpy('findEntryDetailByValue'), + findEntryDetailById: jasmine.createSpy('findEntryDetailById'), searchTopEntries: jasmine.createSpy('searchTopEntries'), getEntryDetailChildren: jasmine.createSpy('getEntryDetailChildren'), clearSearchTopRequests: jasmine.createSpy('clearSearchTopRequests') @@ -202,7 +202,7 @@ describe('VocabularyTreeviewService test suite', () => { serviceAsAny.vocabularyService.searchTopEntries.and.returnValue(hot('-c', { a: createSuccessfulRemoteDataObject(new PaginatedList(pageInfo, [item, item2, item3])) })); - serviceAsAny.vocabularyService.findEntryDetailByValue.and.returnValue( + serviceAsAny.vocabularyService.findEntryDetailById.and.returnValue( hot('-a', { a: createSuccessfulRemoteDataObject(child2) }) @@ -303,7 +303,7 @@ describe('VocabularyTreeviewService test suite', () => { a: createSuccessfulRemoteDataObject(new PaginatedList(pageInfo, [childEntry3])) })); - serviceAsAny.vocabularyService.findEntryDetailByValue.and.returnValue(hot('-a', { + serviceAsAny.vocabularyService.findEntryDetailById.and.returnValue(hot('-a', { a: createSuccessfulRemoteDataObject(child3) })); diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.ts b/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.ts index 698f5bb0d2..dd58a6aede 100644 --- a/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.ts +++ b/src/app/shared/vocabulary-treeview/vocabulary-treeview.service.ts @@ -188,7 +188,7 @@ export class VocabularyTreeviewService { getFirstSucceededRemoteListPayload(), flatMap((result: VocabularyEntry[]) => (result.length > 0) ? result : observableOf(null)), flatMap((entry: VocabularyEntry) => - this.vocabularyService.findEntryDetailByValue(entry.otherInformation.id, this.vocabularyName).pipe( + this.vocabularyService.findEntryDetailById(entry.otherInformation.id, this.vocabularyName).pipe( getFirstSucceededRemoteDataPayload() ) ), @@ -289,7 +289,7 @@ export class VocabularyTreeviewService { * @return Observable */ private getById(entryId: string): Observable { - return this.vocabularyService.findEntryDetailByValue(entryId, this.vocabularyName).pipe( + return this.vocabularyService.findEntryDetailById(entryId, this.vocabularyName).pipe( getFirstSucceededRemoteDataPayload() ); } From 3f77ffa1e689f1538bc4800f481d8c1d9cd3e01b Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Mon, 27 Jul 2020 11:14:56 +0200 Subject: [PATCH 059/170] [CST-3092] remove margin bottom --- .../import-external/submission-import-external.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/submission/import-external/submission-import-external.component.html b/src/app/submission/import-external/submission-import-external.component.html index 9f52969635..c4de97b934 100644 --- a/src/app/submission/import-external/submission-import-external.component.html +++ b/src/app/submission/import-external/submission-import-external.component.html @@ -31,7 +31,7 @@
-

{{'submission.import-external.page.hint' | translate}}

+

{{'submission.import-external.page.hint' | translate}}

From 4779dd209ec4c0ab2a6504ca4b21aaa1455e504b Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Mon, 27 Jul 2020 11:15:15 +0200 Subject: [PATCH 060/170] [CST-3092] fix context --- .../import-external/submission-import-external.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/submission/import-external/submission-import-external.component.ts b/src/app/submission/import-external/submission-import-external.component.ts index e23dce9719..a369863a74 100644 --- a/src/app/submission/import-external/submission-import-external.component.ts +++ b/src/app/submission/import-external/submission-import-external.component.ts @@ -94,7 +94,7 @@ export class SubmissionImportExternalComponent implements OnInit { ngOnInit(): void { this.label = 'Journal'; this.listId = 'list-submission-external-sources'; - this.context = Context.SubmissionModal; + this.context = Context.EntitySearchModalWithNameVariants; this.repeatable = false; this.routeData = { sourceId: '', query: '' }; this.importConfig = { From 7e7ce7b06e0e8b7347ee146f31d6a33e302936ab Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 30 Jul 2020 18:37:45 +0200 Subject: [PATCH 061/170] Added check for VocabularyEntry when initializing a controlled vocabulary component's init model --- .../models/dynamic-vocabulary.component.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-vocabulary.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-vocabulary.component.ts index 5e6acf8581..d3263f1584 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-vocabulary.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-vocabulary.component.ts @@ -70,6 +70,13 @@ export abstract class DsDynamicVocabularyComponent extends DynamicFormControlCom return this.model.value as any; } })); + } else if (isNotEmpty(this.model.value) && (this.model.value instanceof VocabularyEntry)) { + initValue$ = observableOf(Object.assign(new FormFieldMetadataValueObject(), this.model.value, { + value: this.model.value.value, + authority: this.model.value.authority, + display: this.model.value.display, + otherInformation: this.model.value.otherInformation || null + })); } else { initValue$ = observableOf(new FormFieldMetadataValueObject(this.model.value)); } From 7dae82cbbd54034510db2dcd79b6d15210ad49ad Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 30 Jul 2020 18:41:04 +0200 Subject: [PATCH 062/170] added virtualValue property to FormFieldMetadataValueObject --- .../models/form-field-metadata-value.model.ts | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/app/shared/form/builder/models/form-field-metadata-value.model.ts b/src/app/shared/form/builder/models/form-field-metadata-value.model.ts index 2b451a7217..752db8bd5c 100644 --- a/src/app/shared/form/builder/models/form-field-metadata-value.model.ts +++ b/src/app/shared/form/builder/models/form-field-metadata-value.model.ts @@ -51,26 +51,53 @@ export class FormFieldMetadataValueObject implements MetadataValueInterface { this.otherInformation = otherInformation; } + /** + * Returns true if this this object has an authority value + */ hasAuthority(): boolean { return isNotEmpty(this.authority); } + /** + * Returns true if this this object has a value + */ hasValue(): boolean { return isNotEmpty(this.value); } + /** + * Returns true if this this object has otherInformation property with value + */ hasOtherInformation(): boolean { return isNotEmpty(this.otherInformation); } + /** + * Returns true if this object value contains a placeholder + */ hasPlaceholder() { return this.hasValue() && this.value === PLACEHOLDER_PARENT_METADATA; } + /** + * Returns true if this Metadatum's authority key starts with 'virtual::' + */ get isVirtual(): boolean { return hasValue(this.authority) && this.authority.startsWith(VIRTUAL_METADATA_PREFIX); } + /** + * If this is a virtual Metadatum, it returns everything in the authority key after 'virtual::'. + * Returns undefined otherwise. + */ + get virtualValue(): string { + if (this.isVirtual) { + return this.authority.substring(this.authority.indexOf(VIRTUAL_METADATA_PREFIX) + VIRTUAL_METADATA_PREFIX.length); + } else { + return undefined; + } + } + toString() { return this.display || this.value; } From 1a9d20161c0cf0d8f618e72e2c7c9d6f12d27356 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 30 Jul 2020 18:43:19 +0200 Subject: [PATCH 063/170] Fixed issue while preparing json patch value in case of array in the JsonPatchOperationsBuilder --- .../builder/json-patch-operations-builder.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/app/core/json-patch/builder/json-patch-operations-builder.ts b/src/app/core/json-patch/builder/json-patch-operations-builder.ts index 7ce0358ab2..3755821bf9 100644 --- a/src/app/core/json-patch/builder/json-patch-operations-builder.ts +++ b/src/app/core/json-patch/builder/json-patch-operations-builder.ts @@ -1,9 +1,14 @@ import { Store } from '@ngrx/store'; import { CoreState } from '../../core.reducers'; -import { NewPatchAddOperationAction, NewPatchMoveOperationAction, NewPatchRemoveOperationAction, NewPatchReplaceOperationAction } from '../json-patch-operations.actions'; +import { + NewPatchAddOperationAction, + NewPatchMoveOperationAction, + NewPatchRemoveOperationAction, + NewPatchReplaceOperationAction +} from '../json-patch-operations.actions'; import { JsonPatchOperationPathObject } from './json-patch-operation-path-combiner'; import { Injectable } from '@angular/core'; -import { hasNoValue, isEmpty, isNotEmpty } from '../../../shared/empty.util'; +import { hasNoValue, hasValue, isEmpty, isNotEmpty } from '../../../shared/empty.util'; import { dateToISOFormat } from '../../../shared/date.util'; import { VocabularyEntry } from '../../submission/vocabularies/models/vocabulary-entry.model'; import { FormFieldMetadataValueObject } from '../../../shared/form/builder/models/form-field-metadata-value.model'; @@ -96,7 +101,7 @@ export class JsonPatchOperationsBuilder { protected prepareValue(value: any, plain: boolean, first: boolean) { let operationValue: any = null; - if (isNotEmpty(value)) { + if (hasValue(value)) { if (plain) { operationValue = value; } else { From 85506238b36a9eaaba3d5804e40aa2e2cbc9f23d Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 30 Jul 2020 18:46:17 +0200 Subject: [PATCH 064/170] Fixed issue with form dropdown field which didn't close menu after entry selection --- .../dynamic-scrollable-dropdown.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.html index 7a35287a99..f40d58bb0e 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.html @@ -26,7 +26,7 @@ [scrollWindow]="false"> -

{{'form.loading' | translate}}

From 090fb94c4da57df2dbe415f520d5cd0e4ae32f85 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 30 Jul 2020 18:50:47 +0200 Subject: [PATCH 065/170] Normalized submission section data when retrieving them from item object --- ...ynamic-form-control-container.component.ts | 5 +- .../models/ds-dynamic-input.model.ts | 12 ++- .../objects/submission-objects.actions.ts | 9 ++- .../submission-objects.effects.spec.ts | 2 +- .../objects/submission-objects.effects.ts | 74 ++++++++++++++----- .../objects/submission-objects.reducer.ts | 2 +- 6 files changed, 76 insertions(+), 28 deletions(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts index edc6efc5f9..7873f3a86e 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts @@ -116,6 +116,7 @@ import { followLink } from '../../../utils/follow-link-config.model'; import { paginatedRelationsToItems } from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; import { RelationshipOptions } from '../models/relationship-options.model'; import { FormBuilderService } from '../form-builder.service'; +import { FormFieldMetadataValueObject } from '../models/form-field-metadata-value.model'; export function dsDynamicFormControlMapFn(model: DynamicFormControlModel): Type | null { switch (model.type) { @@ -303,9 +304,9 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo } if (hasValue(this.model.metadataValue)) { - this.value = Object.assign(new MetadataValue(), this.model.metadataValue); + this.value = Object.assign(new FormFieldMetadataValueObject(), this.model.metadataValue); } else { - this.value = Object.assign(new MetadataValue(), this.model.value); + this.value = Object.assign(new FormFieldMetadataValueObject(), this.model.value); } if (hasValue(this.value) && this.value.isVirtual) { diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model.ts index c91a0aea54..290e29dc65 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model.ts @@ -1,4 +1,9 @@ -import { DynamicFormControlLayout, DynamicInputModel, DynamicInputModelConfig, serializable } from '@ng-dynamic-forms/core'; +import { + DynamicFormControlLayout, + DynamicInputModel, + DynamicInputModelConfig, + serializable +} from '@ng-dynamic-forms/core'; import { Subject } from 'rxjs'; import { LanguageCode } from '../../models/form-field-language-value.model'; @@ -6,7 +11,6 @@ import { VocabularyOptions } from '../../../../../core/submission/vocabularies/m import { hasValue } from '../../../../empty.util'; import { FormFieldMetadataValueObject } from '../../models/form-field-metadata-value.model'; import { RelationshipOptions } from '../../models/relationship-options.model'; -import { MetadataValue } from '../../../../../core/shared/metadata.models'; export interface DsDynamicInputModelConfig extends DynamicInputModelConfig { vocabularyOptions?: VocabularyOptions; @@ -19,7 +23,7 @@ export interface DsDynamicInputModelConfig extends DynamicInputModelConfig { metadataFields: string[]; submissionId: string; hasSelectableMetadata: boolean; - metadataValue?: MetadataValue; + metadataValue?: FormFieldMetadataValueObject; } @@ -34,7 +38,7 @@ export class DsDynamicInputModel extends DynamicInputModel { @serializable() metadataFields: string[]; @serializable() submissionId: string; @serializable() hasSelectableMetadata: boolean; - @serializable() metadataValue: MetadataValue; + @serializable() metadataValue: FormFieldMetadataValueObject; constructor(config: DsDynamicInputModelConfig, layout?: DynamicFormControlLayout) { super(config, layout); diff --git a/src/app/submission/objects/submission-objects.actions.ts b/src/app/submission/objects/submission-objects.actions.ts index 1e3e44aba9..73c070846c 100644 --- a/src/app/submission/objects/submission-objects.actions.ts +++ b/src/app/submission/objects/submission-objects.actions.ts @@ -42,7 +42,8 @@ export const SubmissionObjectActionTypes = { DISABLE_SECTION: type('dspace/submission/DISABLE_SECTION'), SECTION_STATUS_CHANGE: type('dspace/submission/SECTION_STATUS_CHANGE'), SECTION_LOADING_STATUS_CHANGE: type('dspace/submission/SECTION_LOADING_STATUS_CHANGE'), - UPLOAD_SECTION_DATA: type('dspace/submission/UPLOAD_SECTION_DATA'), + UPDATE_SECTION_DATA: type('dspace/submission/UPDATE_SECTION_DATA'), + UPDATE_SECTION_DATA_SUCCESS: type('dspace/submission/UPDATE_SECTION_DATA_SUCCESS'), SAVE_AND_DEPOSIT_SUBMISSION: type('dspace/submission/SAVE_AND_DEPOSIT_SUBMISSION'), DEPOSIT_SUBMISSION: type('dspace/submission/DEPOSIT_SUBMISSION'), DEPOSIT_SUBMISSION_SUCCESS: type('dspace/submission/DEPOSIT_SUBMISSION_SUCCESS'), @@ -199,7 +200,7 @@ export class DisableSectionAction implements Action { } export class UpdateSectionDataAction implements Action { - type = SubmissionObjectActionTypes.UPLOAD_SECTION_DATA; + type = SubmissionObjectActionTypes.UPDATE_SECTION_DATA; payload: { submissionId: string; sectionId: string; @@ -227,6 +228,10 @@ export class UpdateSectionDataAction implements Action { } } +export class UpdateSectionDataSuccessAction implements Action { + type = SubmissionObjectActionTypes.UPDATE_SECTION_DATA_SUCCESS; +} + export class RemoveSectionErrorsAction implements Action { type = SubmissionObjectActionTypes.REMOVE_SECTION_ERRORS; payload: { diff --git a/src/app/submission/objects/submission-objects.effects.spec.ts b/src/app/submission/objects/submission-objects.effects.spec.ts index 6c2e9eefc6..c35968c0a0 100644 --- a/src/app/submission/objects/submission-objects.effects.spec.ts +++ b/src/app/submission/objects/submission-objects.effects.spec.ts @@ -276,7 +276,7 @@ describe('SubmissionObjectEffects test suite', () => { describe('saveSubmissionSuccess$', () => { - it('should return a UPLOAD_SECTION_DATA action for each updated section', () => { + it('should return a UPDATE_SECTION_DATA action for each updated section', () => { store.nextState({ submission: { objects: submissionState diff --git a/src/app/submission/objects/submission-objects.effects.ts b/src/app/submission/objects/submission-objects.effects.ts index 2dfed9ee47..ecda75759e 100644 --- a/src/app/submission/objects/submission-objects.effects.ts +++ b/src/app/submission/objects/submission-objects.effects.ts @@ -2,7 +2,7 @@ import { Injectable } from '@angular/core'; import { Actions, Effect, ofType } from '@ngrx/effects'; import { Store } from '@ngrx/store'; import { TranslateService } from '@ngx-translate/core'; -import { isEqual, union } from 'lodash'; +import { union } from 'lodash'; import { from as observableFrom, Observable, of as observableOf } from 'rxjs'; import { catchError, filter, map, mergeMap, switchMap, take, tap, withLatestFrom } from 'rxjs/operators'; @@ -40,7 +40,8 @@ import { SaveSubmissionSectionFormSuccessAction, SubmissionObjectAction, SubmissionObjectActionTypes, - UpdateSectionDataAction + UpdateSectionDataAction, + UpdateSectionDataSuccessAction } from './submission-objects.actions'; import { SubmissionObjectEntry, SubmissionSectionObject } from './submission-objects.reducer'; import { Item } from '../../core/shared/item.model'; @@ -48,6 +49,8 @@ import { RemoteData } from '../../core/data/remote-data'; import { getFirstSucceededRemoteDataPayload } from '../../core/shared/operators'; import { SubmissionObjectDataService } from '../../core/submission/submission-object-data.service'; import { followLink } from '../../shared/utils/follow-link-config.model'; +import { normalizeSectionData } from '../../core/submission/submission-response-parsing.service'; +import { difference } from '../../shared/object.util'; @Injectable() export class SubmissionObjectEffects { @@ -69,7 +72,7 @@ export class SubmissionObjectEffects { if (sectionDefinition.sectionType !== SectionsType.SubmissionForm) { sectionData = (isNotUndefined(action.payload.sections) && isNotUndefined(action.payload.sections[sectionId])) ? action.payload.sections[sectionId] : Object.create(null); } else { - sectionData = action.payload.item.metadata; + sectionData = normalizeSectionData(action.payload.item.metadata); } const sectionErrors = null; mappedActions.push( @@ -246,28 +249,37 @@ export class SubmissionObjectEffects { * Adds all metadata an item to the SubmissionForm sections of the submission */ @Effect() addAllMetadataToSectionData = this.actions$.pipe( - ofType(SubmissionObjectActionTypes.UPLOAD_SECTION_DATA), + ofType(SubmissionObjectActionTypes.UPDATE_SECTION_DATA), switchMap((action: UpdateSectionDataAction) => { return this.sectionService.getSectionState(action.payload.submissionId, action.payload.sectionId) .pipe(map((section: SubmissionSectionObject) => [action, section]), take(1)); }), filter(([action, section]: [UpdateSectionDataAction, SubmissionSectionObject]) => section.sectionType === SectionsType.SubmissionForm), switchMap(([action, section]: [UpdateSectionDataAction, SubmissionSectionObject]) => { - const submissionObject$ = this.submissionObjectService - .findById(action.payload.submissionId, followLink('item')).pipe( - getFirstSucceededRemoteDataPayload() + if (section.sectionType === SectionsType.SubmissionForm) { + const submissionObject$ = this.submissionObjectService + .findById(action.payload.submissionId, followLink('item')).pipe( + getFirstSucceededRemoteDataPayload() + ); + + const item$ = submissionObject$.pipe( + switchMap((submissionObject: SubmissionObject) => (submissionObject.item as Observable>).pipe( + getFirstSucceededRemoteDataPayload(), + ))); + + return item$.pipe( + map((item: Item) => item.metadata), + map((metadata: any) => { + if (!this.isEqual(action.payload.data, normalizeSectionData(metadata))) { + return new UpdateSectionDataAction(action.payload.submissionId, action.payload.sectionId, normalizeSectionData(metadata), action.payload.errors) + } else { + return new UpdateSectionDataSuccessAction(); + } + }) ); - - const item$ = submissionObject$.pipe( - switchMap((submissionObject: SubmissionObject) => (submissionObject.item as Observable>).pipe( - getFirstSucceededRemoteDataPayload(), - ))); - - return item$.pipe( - map((item: Item) => item.metadata), - filter((metadata) => !isEqual(action.payload.data, metadata)), - map((metadata: any) => new UpdateSectionDataAction(action.payload.submissionId, action.payload.sectionId, metadata, action.payload.errors)) - ); + } else { + return observableOf(new UpdateSectionDataSuccessAction()); + } }), ); @@ -382,4 +394,30 @@ export class SubmissionObjectEffects { return mappedActions; } + /** + * Check if the section data has been enriched by the server + * + * @param sectionData + * the section metadata retrieved from the server + * @param itemData + * the item data retrieved from the server + */ + isEqual(sectionData: any, itemData: any): boolean { + const diffResult = []; + + // compare current form data state with section data retrieved from store + const diffObj = difference(sectionData, itemData); + + // iterate over differences to check whether they are actually different + Object.keys(diffObj) + .forEach((key) => { + diffObj[key].forEach((value) => { + if (value.hasOwnProperty('value')) { + diffResult.push(value); + } + }); + }); + return isEmpty(diffResult); + } + } diff --git a/src/app/submission/objects/submission-objects.reducer.ts b/src/app/submission/objects/submission-objects.reducer.ts index e0aeefd7b6..098160c737 100644 --- a/src/app/submission/objects/submission-objects.reducer.ts +++ b/src/app/submission/objects/submission-objects.reducer.ts @@ -262,7 +262,7 @@ export function submissionObjectReducer(state = initialState, action: Submission return changeSectionState(state, action as EnableSectionAction, true); } - case SubmissionObjectActionTypes.UPLOAD_SECTION_DATA: { + case SubmissionObjectActionTypes.UPDATE_SECTION_DATA: { return updateSectionData(state, action as UpdateSectionDataAction); } From 9ced3530abc3fcbb541687e45f4bca678101b4d8 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 30 Jul 2020 19:13:59 +0200 Subject: [PATCH 066/170] Added inline comments --- src/app/submission/objects/submission-objects.effects.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/app/submission/objects/submission-objects.effects.ts b/src/app/submission/objects/submission-objects.effects.ts index ecda75759e..0f4158a760 100644 --- a/src/app/submission/objects/submission-objects.effects.ts +++ b/src/app/submission/objects/submission-objects.effects.ts @@ -72,6 +72,8 @@ export class SubmissionObjectEffects { if (sectionDefinition.sectionType !== SectionsType.SubmissionForm) { sectionData = (isNotUndefined(action.payload.sections) && isNotUndefined(action.payload.sections[sectionId])) ? action.payload.sections[sectionId] : Object.create(null); } else { + // Normalize item metadata before to init section + // TODO to review after https://github.com/DSpace/dspace-angular/issues/818 is resolved sectionData = normalizeSectionData(action.payload.item.metadata); } const sectionErrors = null; @@ -271,6 +273,8 @@ export class SubmissionObjectEffects { map((item: Item) => item.metadata), map((metadata: any) => { if (!this.isEqual(action.payload.data, normalizeSectionData(metadata))) { + // Normalize item metadata before to update section + // TODO to review after https://github.com/DSpace/dspace-angular/issues/818 is resolved return new UpdateSectionDataAction(action.payload.submissionId, action.payload.sectionId, normalizeSectionData(metadata), action.payload.errors) } else { return new UpdateSectionDataSuccessAction(); From c9519f44fbc93be7305c13a02532e4391cf54567 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Fri, 31 Jul 2020 13:30:23 +0200 Subject: [PATCH 067/170] Retrieve entries url from vocabulary's link --- src/app/core/data/data.service.ts | 2 +- .../vocabularies/vocabulary.service.spec.ts | 5 +++++ .../vocabularies/vocabulary.service.ts | 17 ++++++++++++----- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index bb1a65cc3a..3b4e5f7d42 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -112,7 +112,7 @@ export abstract class DataService implements UpdateDa * Return an observable that emits created HREF * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved */ - protected buildHrefFromFindOptions(href: string, options: FindListOptions, extraArgs: string[] = [], ...linksToFollow: Array>): string { + public buildHrefFromFindOptions(href: string, options: FindListOptions, extraArgs: string[] = [], ...linksToFollow: Array>): string { let args = [...extraArgs]; if (hasValue(options.currentPage) && typeof options.currentPage === 'number') { diff --git a/src/app/core/submission/vocabularies/vocabulary.service.spec.ts b/src/app/core/submission/vocabularies/vocabulary.service.spec.ts index ca7711637e..a172ae2a45 100644 --- a/src/app/core/submission/vocabularies/vocabulary.service.spec.ts +++ b/src/app/core/submission/vocabularies/vocabulary.service.spec.ts @@ -187,6 +187,7 @@ describe('VocabularyService', () => { const paginatedListEntries = new PaginatedList(pageInfo, arrayEntries); const childrenPaginatedList = new PaginatedList(pageInfo, childrenEntries); const vocabularyRD = createSuccessfulRemoteDataObject(vocabulary); + const vocabularyRD$ = createSuccessfulRemoteDataObject$(vocabulary); const vocabularyEntriesRD = createSuccessfulRemoteDataObject$(paginatedListEntries); const vocabularyEntryDetailParentRD = createSuccessfulRemoteDataObject(vocabularyEntryParentDetail); const vocabularyEntryChildrenRD = createSuccessfulRemoteDataObject(childrenPaginatedList); @@ -342,9 +343,11 @@ describe('VocabularyService', () => { rdbService = getMockRemoteDataBuildService(undefined, vocabularyEntriesRD); spyOn(rdbService, 'toRemoteDataObservable').and.callThrough(); service = initTestService(); + spyOn(service, 'findVocabularyById').and.returnValue(vocabularyRD$); }); describe('getVocabularyEntries', () => { + it('should configure a new VocabularyEntriesRequest', () => { const expected = new VocabularyEntriesRequest(requestService.generateRequestId(), entriesRequestURL); @@ -363,6 +366,7 @@ describe('VocabularyService', () => { }); describe('getVocabularyEntriesByValue', () => { + it('should configure a new VocabularyEntriesRequest', () => { const expected = new VocabularyEntriesRequest(requestService.generateRequestId(), entriesByValueRequestURL); @@ -382,6 +386,7 @@ describe('VocabularyService', () => { }); describe('getVocabularyEntryByValue', () => { + it('should configure a new VocabularyEntriesRequest', () => { const expected = new VocabularyEntriesRequest(requestService.generateRequestId(), entryByValueRequestURL); diff --git a/src/app/core/submission/vocabularies/vocabulary.service.ts b/src/app/core/submission/vocabularies/vocabulary.service.ts index 5200d703b9..90438e77e9 100644 --- a/src/app/core/submission/vocabularies/vocabulary.service.ts +++ b/src/app/core/submission/vocabularies/vocabulary.service.ts @@ -26,6 +26,7 @@ import { hasValue, isNotEmpty, isNotEmptyOperator } from '../../../shared/empty. import { configureRequest, filterSuccessfulResponses, + getFirstSucceededRemoteDataPayload, getFirstSucceededRemoteListPayload, getRequestFromRequestHref } from '../../shared/operators'; @@ -158,11 +159,13 @@ export class VocabularyService { pageInfo.currentPage ); - return this.vocabularyDataService.getFindAllHref(options, `${vocabularyOptions.name}/entries`).pipe( + return this.findVocabularyById(vocabularyOptions.name).pipe( + getFirstSucceededRemoteDataPayload(), + map((vocabulary: Vocabulary) => this.vocabularyDataService.buildHrefFromFindOptions(vocabulary._links.entries.href, options)), isNotEmptyOperator(), distinctUntilChanged(), getVocabularyEntriesFor(this.requestService, this.rdbService) - ); + ) } /** @@ -185,11 +188,13 @@ export class VocabularyService { pageInfo.currentPage ); - return this.vocabularyDataService.getFindAllHref(options, `${vocabularyOptions.name}/entries`).pipe( + return this.findVocabularyById(vocabularyOptions.name).pipe( + getFirstSucceededRemoteDataPayload(), + map((vocabulary: Vocabulary) => this.vocabularyDataService.buildHrefFromFindOptions(vocabulary._links.entries.href, options)), isNotEmptyOperator(), distinctUntilChanged(), getVocabularyEntriesFor(this.requestService, this.rdbService) - ); + ) } /** @@ -233,7 +238,9 @@ export class VocabularyService { pageInfo.currentPage ); - return this.vocabularyDataService.getFindAllHref(options, `${vocabularyOptions.name}/entries`).pipe( + return this.findVocabularyById(vocabularyOptions.name).pipe( + getFirstSucceededRemoteDataPayload(), + map((vocabulary: Vocabulary) => this.vocabularyDataService.buildHrefFromFindOptions(vocabulary._links.entries.href, options)), isNotEmptyOperator(), distinctUntilChanged(), getVocabularyEntriesFor(this.requestService, this.rdbService), From 2ed144bd1c04e29785abc3ed177af42a3d3f5dfa Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Fri, 31 Jul 2020 13:37:26 +0200 Subject: [PATCH 068/170] Fixed wrong links in mock object --- .../vocabulary-entries-response-parsing.service.spec.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/core/submission/vocabularies/vocabulary-entries-response-parsing.service.spec.ts b/src/app/core/submission/vocabularies/vocabulary-entries-response-parsing.service.spec.ts index 9f28ccea17..7d4ec8be7c 100644 --- a/src/app/core/submission/vocabularies/vocabulary-entries-response-parsing.service.spec.ts +++ b/src/app/core/submission/vocabularies/vocabulary-entries-response-parsing.service.spec.ts @@ -60,16 +60,16 @@ describe('VocabularyEntriesResponseParsingService', () => { }, _links: { first: { - href: 'https://rest.api/discover/browses/author/entries?page=0&size=5' + href: 'https://rest.api/discover/browses/author/entries/first?page=0&size=5' }, self: { href: 'https://rest.api/discover/browses/author/entries' }, next: { - href: 'https://rest.api/discover/browses/author/entries?page=1&size=5' + href: 'https://rest.api/discover/browses/author/entries/next?page=1&size=5' }, last: { - href: 'https://rest.api/discover/browses/author/entries?page=9&size=5' + href: 'https://rest.api/discover/browses/author/entries/last?page=9&size=5' } }, page: { From 79db49043f7573831fd391429fbfc170ca0c6f53 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Fri, 31 Jul 2020 14:16:20 +0200 Subject: [PATCH 069/170] Make metadata and scope properties as optional in the VocabularyOptions --- .../vocabularies/models/vocabulary-options.model.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/core/submission/vocabularies/models/vocabulary-options.model.ts b/src/app/core/submission/vocabularies/models/vocabulary-options.model.ts index c28d8504bd..bdbd19f85f 100644 --- a/src/app/core/submission/vocabularies/models/vocabulary-options.model.ts +++ b/src/app/core/submission/vocabularies/models/vocabulary-options.model.ts @@ -11,12 +11,12 @@ export class VocabularyOptions { /** * The metadata field name (e.g. "dc.type") for which the vocabulary is used: */ - metadata: string; + metadata?: string; /** * The uuid of the collection where the item is being submitted */ - scope: string; + scope?: string; /** * A boolean representing if value is closely related to a vocabulary entry or not @@ -24,8 +24,8 @@ export class VocabularyOptions { closed: boolean; constructor(name: string, - metadata: string, - scope: string, + metadata?: string, + scope?: string, closed: boolean = false) { this.name = name; this.metadata = metadata; From 0582bc56222863f55453b36d77a527e0f688e930 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Fri, 31 Jul 2020 15:17:51 +0200 Subject: [PATCH 070/170] Fixed issue when adding repeatable onebox field with vocabulary --- .../models/onebox/dynamic-onebox.component.ts | 4 +++- src/app/shared/form/form.component.ts | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.ts index fa9fe2103a..0cc9f66ef7 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.ts @@ -46,7 +46,7 @@ export class DsDynamicOneboxComponent extends DsDynamicVocabularyComponent imple @ViewChild('instance', { static: false }) instance: NgbTypeahead; - pageInfo: PageInfo; + pageInfo: PageInfo = new PageInfo(); searching = false; searchFailed = false; hideSearchingWhenUnsubscribed$ = new Observable(() => () => this.changeSearchingStatus(false)); @@ -247,6 +247,7 @@ export class DsDynamicOneboxComponent extends DsDynamicVocabularyComponent imple this.getInitValueFromModel() .subscribe((formValue: FormFieldMetadataValueObject) => { this.currentValue = formValue; + this.cdr.detectChanges(); }); } else { if (isEmpty(value)) { @@ -258,6 +259,7 @@ export class DsDynamicOneboxComponent extends DsDynamicVocabularyComponent imple } this.currentValue = result; + this.cdr.detectChanges(); } } diff --git a/src/app/shared/form/form.component.ts b/src/app/shared/form/form.component.ts index dee06c29b2..286f2673de 100644 --- a/src/app/shared/form/form.component.ts +++ b/src/app/shared/form/form.component.ts @@ -11,6 +11,7 @@ import { FormService } from './form.service'; import { FormEntry, FormError } from './form.reducer'; import { DYNAMIC_FORM_CONTROL_TYPE_SCROLLABLE_DROPDOWN } from './builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.model'; import { QUALDROP_GROUP_SUFFIX } from './builder/ds-dynamic-form-ui/models/ds-dynamic-qualdrop.model'; +import { DYNAMIC_FORM_CONTROL_TYPE_ONEBOX } from './builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.model'; const QUALDROP_GROUP_REGEX = new RegExp(`${QUALDROP_GROUP_SUFFIX}_\\d+$`); @@ -316,7 +317,7 @@ export class FormComponent implements OnDestroy, OnInit { // set that field to the new value const model = arrayContext.groups[arrayContext.groups.length - 1].group[0] as any; - if (model.type === DYNAMIC_FORM_CONTROL_TYPE_SCROLLABLE_DROPDOWN) { + if (model.type === DYNAMIC_FORM_CONTROL_TYPE_SCROLLABLE_DROPDOWN || model.type === DYNAMIC_FORM_CONTROL_TYPE_ONEBOX) { model.value = Object.values(value)[0]; } else if (this.formBuilderService.isQualdropGroup(model)) { const ctrl = formArrayControl.controls[formArrayControl.length - 1]; From 34da1dc0550d1fe80933c9124e515b7919282ff9 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Fri, 31 Jul 2020 15:18:41 +0200 Subject: [PATCH 071/170] Removed angular material dependency --- package.json | 1 - .../vocabulary-tree-flat-data-source.ts | 51 ++++++++ .../vocabulary-tree-flattener.ts | 111 ++++++++++++++++++ .../vocabulary-treeview.component.ts | 11 +- yarn.lock | 7 -- 5 files changed, 168 insertions(+), 13 deletions(-) create mode 100644 src/app/shared/vocabulary-treeview/vocabulary-tree-flat-data-source.ts create mode 100644 src/app/shared/vocabulary-treeview/vocabulary-tree-flattener.ts diff --git a/package.json b/package.json index 69ca11b82d..c1e5b05010 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,6 @@ "@angular/compiler": "~8.2.14", "@angular/core": "~8.2.14", "@angular/forms": "~8.2.14", - "@angular/material": "8.2.3", "@angular/platform-browser": "~8.2.14", "@angular/platform-browser-dynamic": "~8.2.14", "@angular/platform-server": "~8.2.14", diff --git a/src/app/shared/vocabulary-treeview/vocabulary-tree-flat-data-source.ts b/src/app/shared/vocabulary-treeview/vocabulary-tree-flat-data-source.ts new file mode 100644 index 0000000000..2340d477b6 --- /dev/null +++ b/src/app/shared/vocabulary-treeview/vocabulary-tree-flat-data-source.ts @@ -0,0 +1,51 @@ +import { CollectionViewer, DataSource } from '@angular/cdk/collections'; +import { FlatTreeControl } from '@angular/cdk/tree'; + +import { BehaviorSubject, merge, Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { VocabularyTreeFlattener } from './vocabulary-tree-flattener'; + +/** + * Data source for flat tree. + * The data source need to handle expansion/collapsion of the tree node and change the data feed + * to `MatTree`. + * The nested tree nodes of type `T` are flattened through `MatTreeFlattener`, and converted + * to type `F` for `MatTree` to consume. + */ +export class VocabularyTreeFlatDataSource extends DataSource { + _flattenedData = new BehaviorSubject([]); + + _expandedData = new BehaviorSubject([]); + + _data: BehaviorSubject; + get data() { return this._data.value; } + set data(value: T[]) { + this._data.next(value); + this._flattenedData.next(this._treeFlattener.flattenNodes(this.data)); + this._treeControl.dataNodes = this._flattenedData.value; + } + + constructor(private _treeControl: FlatTreeControl, + private _treeFlattener: VocabularyTreeFlattener, + initialData: T[] = []) { + super(); + this._data = new BehaviorSubject(initialData); + } + + connect(collectionViewer: CollectionViewer): Observable { + const changes = [ + collectionViewer.viewChange, + this._treeControl.expansionModel.onChange, + this._flattenedData + ]; + return merge(...changes).pipe(map(() => { + this._expandedData.next( + this._treeFlattener.expandFlattenedNodes(this._flattenedData.value, this._treeControl)); + return this._expandedData.value; + })); + } + + disconnect() { + // no op + } +} diff --git a/src/app/shared/vocabulary-treeview/vocabulary-tree-flattener.ts b/src/app/shared/vocabulary-treeview/vocabulary-tree-flattener.ts new file mode 100644 index 0000000000..419f48d222 --- /dev/null +++ b/src/app/shared/vocabulary-treeview/vocabulary-tree-flattener.ts @@ -0,0 +1,111 @@ +import { TreeControl } from '@angular/cdk/tree'; + +import { Observable } from 'rxjs'; +import { take } from 'rxjs/operators'; + +/** + * Tree flattener to convert a normal type of node to node with children & level information. + * Transform nested nodes of type `T` to flattened nodes of type `F`. + * + * For example, the input data of type `T` is nested, and contains its children data: + * SomeNode: { + * key: 'Fruits', + * children: [ + * NodeOne: { + * key: 'Apple', + * }, + * NodeTwo: { + * key: 'Pear', + * } + * ] + * } + * After flattener flatten the tree, the structure will become + * SomeNode: { + * key: 'Fruits', + * expandable: true, + * level: 1 + * }, + * NodeOne: { + * key: 'Apple', + * expandable: false, + * level: 2 + * }, + * NodeTwo: { + * key: 'Pear', + * expandable: false, + * level: 2 + * } + * and the output flattened type is `F` with additional information. + */ +export class VocabularyTreeFlattener { + + constructor(public transformFunction: (node: T, level: number) => F, + public getLevel: (node: F) => number, + public isExpandable: (node: F) => boolean, + public getChildren: (node: T) => + Observable | T[] | undefined | null) {} + + _flattenNode(node: T, level: number, + resultNodes: F[], parentMap: boolean[]): F[] { + const flatNode = this.transformFunction(node, level); + resultNodes.push(flatNode); + + if (this.isExpandable(flatNode)) { + const childrenNodes = this.getChildren(node); + if (childrenNodes) { + if (Array.isArray(childrenNodes)) { + this._flattenChildren(childrenNodes, level, resultNodes, parentMap); + } else { + childrenNodes.pipe(take(1)).subscribe((children) => { + this._flattenChildren(children, level, resultNodes, parentMap); + }); + } + } + } + return resultNodes; + } + + _flattenChildren(children: T[], level: number, + resultNodes: F[], parentMap: boolean[]): void { + children.forEach((child, index) => { + const childParentMap: boolean[] = parentMap.slice(); + childParentMap.push(index !== children.length - 1); + this._flattenNode(child, level + 1, resultNodes, childParentMap); + }); + } + + /** + * Flatten a list of node type T to flattened version of node F. + * Please note that type T may be nested, and the length of `structuredData` may be different + * from that of returned list `F[]`. + */ + flattenNodes(structuredData: T[]): F[] { + const resultNodes: F[] = []; + structuredData.forEach((node) => this._flattenNode(node, 0, resultNodes, [])); + return resultNodes; + } + + /** + * Expand flattened node with current expansion status. + * The returned list may have different length. + */ + expandFlattenedNodes(nodes: F[], treeControl: TreeControl): F[] { + const results: F[] = []; + const currentExpand: boolean[] = []; + currentExpand[0] = true; + + nodes.forEach((node) => { + let expand = true; + for (let i = 0; i <= this.getLevel(node); i++) { + expand = expand && currentExpand[i]; + } + if (expand) { + results.push(node); + } + if (this.isExpandable(node)) { + currentExpand[this.getLevel(node) + 1] = treeControl.isExpanded(node); + } + }); + return results; + } +} diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts b/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts index cbd9c25a9b..9eb4bb860c 100644 --- a/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts +++ b/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts @@ -1,6 +1,5 @@ import { FlatTreeControl } from '@angular/cdk/tree'; import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'; -import { MatTreeFlatDataSource, MatTreeFlattener } from '@angular/material/tree'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { filter, find, startWith } from 'rxjs/operators'; @@ -17,6 +16,8 @@ import { LOAD_MORE, LOAD_MORE_ROOT, TreeviewFlatNode, TreeviewNode } from './voc 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'; /** * Component that show a hierarchical vocabulary in a tree view @@ -66,12 +67,12 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit { /** * Tree flattener object. Able to convert a normal type of node to node with children and level information. */ - treeFlattener: MatTreeFlattener; + treeFlattener: VocabularyTreeFlattener; /** * Flat tree data source */ - dataSource: MatTreeFlatDataSource; + dataSource: VocabularyTreeFlatDataSource; /** * The content of the search box used to search for a vocabulary entry @@ -113,12 +114,12 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit { private store: Store, private translate: TranslateService ) { - this.treeFlattener = new MatTreeFlattener(this.transformer, this.getLevel, + this.treeFlattener = new VocabularyTreeFlattener(this.transformer, this.getLevel, this.isExpandable, this.getChildren); this.treeControl = new FlatTreeControl(this.getLevel, this.isExpandable); - this.dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener); + this.dataSource = new VocabularyTreeFlatDataSource(this.treeControl, this.treeFlattener); } /** diff --git a/yarn.lock b/yarn.lock index 1dd1bb6673..3a36e692d7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -211,13 +211,6 @@ resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-8.2.14.tgz#e18b27a6841577ce489ad31540150da5a444ca37" integrity sha512-7EhN9JJbAJcH2xCa+rIOmekjiEuB0qwPdHuD5qn/wwMfRzMZo+Db4hHbR9KHrLH6H82PTwYKye/LLpDaZqoHOA== -"@angular/material@8.2.3": - version "8.2.3" - resolved "https://registry.yarnpkg.com/@angular/material/-/material-8.2.3.tgz#16543e4e06a3fde2651a25cfe126e88e714ae105" - integrity sha512-SOczkIaqes+r+9XF/UUiokidfFKBpHkOPIaFK857sFD0FBNPvPEpOr5oHKCG3feERRwAFqHS7Wo2ohVEWypb5A== - dependencies: - tslib "^1.7.1" - "@angular/platform-browser-dynamic@~8.2.14": version "8.2.14" resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-8.2.14.tgz#4439a79fe10ec45170e6940a28835e9ff0918950" From 902d4c2330304ee48597118ea1ea91d50db26fd3 Mon Sep 17 00:00:00 2001 From: Marie Verdonck Date: Mon, 6 Jul 2020 19:18:40 +0200 Subject: [PATCH 072/170] 71712: Export metadata CSV; WIP --- .../admin-sidebar/admin-sidebar.component.ts | 149 +++++++++++------- src/app/app.component.ts | 1 - .../data/processes/script-data.service.ts | 21 +++ .../core/shared/dspace-object-type.model.ts | 1 + .../dso-selector/dso-selector.component.ts | 2 +- .../dso-selector-modal-wrapper.component.ts | 7 +- .../edit-item-selector.component.spec.ts | 2 - .../export-metadata-selector.component.ts | 79 ++++++++++ src/app/shared/shared.module.ts | 5 +- src/assets/i18n/en.json5 | 4 + 10 files changed, 205 insertions(+), 66 deletions(-) create mode 100644 src/app/shared/dso-selector/modal-wrappers/export-metadata-selector/export-metadata-selector.component.ts diff --git a/src/app/+admin/admin-sidebar/admin-sidebar.component.ts b/src/app/+admin/admin-sidebar/admin-sidebar.component.ts index eb86de5f3c..2a911f6097 100644 --- a/src/app/+admin/admin-sidebar/admin-sidebar.component.ts +++ b/src/app/+admin/admin-sidebar/admin-sidebar.component.ts @@ -2,8 +2,13 @@ import { Component, Injector, OnInit } from '@angular/core'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { combineLatest as combineLatestObservable } from 'rxjs'; import { Observable } from 'rxjs/internal/Observable'; -import { first, map } from 'rxjs/operators'; +import { of } from 'rxjs/internal/observable/of'; +import { first, map, take } from 'rxjs/operators'; import { AuthService } from '../../core/auth/auth.service'; +import { ProcessDataService } from '../../core/data/processes/process-data.service'; +import { ScriptDataService } from '../../core/data/processes/script-data.service'; +import { RemoteData } from '../../core/data/remote-data'; +import { Script } from '../../process-page/scripts/script.model'; import { slideHorizontal, slideSidebar } from '../../shared/animations/slide'; import { CreateCollectionParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component'; import { CreateCommunityParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component'; @@ -11,6 +16,10 @@ import { CreateItemParentSelectorComponent } from '../../shared/dso-selector/mod import { EditCollectionSelectorComponent } from '../../shared/dso-selector/modal-wrappers/edit-collection-selector/edit-collection-selector.component'; import { EditCommunitySelectorComponent } from '../../shared/dso-selector/modal-wrappers/edit-community-selector/edit-community-selector.component'; import { EditItemSelectorComponent } from '../../shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component'; +import { + ExportMetadataSelectorComponent, + METADATA_EXPORT_SCRIPT_NAME +} from '../../shared/dso-selector/modal-wrappers/export-metadata-selector/export-metadata-selector.component'; import { MenuID, MenuItemType } from '../../shared/menu/initial-menus-state'; import { LinkMenuItemModel } from '../../shared/menu/menu-item/models/link.model'; import { OnClickMenuItemModel } from '../../shared/menu/menu-item/models/onclick.model'; @@ -64,7 +73,8 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { private variableService: CSSVariableService, private authService: AuthService, private modalService: NgbModal, - private authorizationService: AuthorizationDataService + private authorizationService: AuthorizationDataService, + private scriptDataService: ScriptDataService, ) { super(menuService, injector); } @@ -75,6 +85,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { ngOnInit(): void { this.createMenu(); this.createSiteAdministratorMenuSections(); + this.createExportMenuSections(); super.ngOnInit(); this.sidebarWidth = this.variableService.getVariable('sidebarItemsWidth'); this.authService.isAuthenticated() @@ -259,61 +270,6 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { link: '' } as LinkMenuItemModel, }, - /* Export */ - { - id: 'export', - active: false, - visible: true, - model: { - type: MenuItemType.TEXT, - text: 'menu.section.export' - } as TextMenuItemModel, - icon: 'sign-out-alt', - index: 3 - }, - { - id: 'export_community', - parentID: 'export', - active: false, - visible: true, - model: { - type: MenuItemType.LINK, - text: 'menu.section.export_community', - link: '' - } as LinkMenuItemModel, - }, - { - id: 'export_collection', - parentID: 'export', - active: false, - visible: true, - model: { - type: MenuItemType.LINK, - text: 'menu.section.export_collection', - link: '' - } as LinkMenuItemModel, - }, - { - id: 'export_item', - parentID: 'export', - active: false, - visible: true, - model: { - type: MenuItemType.LINK, - text: 'menu.section.export_item', - link: '' - } as LinkMenuItemModel, - }, { - id: 'export_metadata', - parentID: 'export', - active: false, - visible: true, - model: { - type: MenuItemType.LINK, - text: 'menu.section.export_metadata', - link: '' - } as LinkMenuItemModel, - }, /* Statistics */ { @@ -362,6 +318,85 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit { }))); } + /** + * Create menu sections dependent on whether or not the current user is a site administrator and on whether or not + * the export scripts exist and the current user is allowed to execute them + */ + createExportMenuSections() { + const isAuthorized$: Observable = this.authorizationService.isAuthorized(FeatureID.AdministratorOf); + isAuthorized$.subscribe((authorized: boolean) => { + if (authorized) { + const metadataExportScriptExists$ = this.scriptDataService.scripWithNameExistsAndCanExecute(METADATA_EXPORT_SCRIPT_NAME); + metadataExportScriptExists$.subscribe((metadataExportScriptExists: boolean) => { + const menuList = [ + /* Export */ + { + id: 'export', + active: false, + visible: true, + model: { + type: MenuItemType.TEXT, + text: 'menu.section.export' + } as TextMenuItemModel, + icon: 'sign-out-alt', + index: 3 + }, + { + id: 'export_community', + parentID: 'export', + active: false, + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.export_community', + link: '' + } as LinkMenuItemModel, + }, + { + id: 'export_collection', + parentID: 'export', + active: false, + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.export_collection', + link: '' + } as LinkMenuItemModel, + }, + { + id: 'export_item', + parentID: 'export', + active: false, + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.export_item', + link: '' + } as LinkMenuItemModel, + }, + { + id: 'export_metadata', + parentID: 'export', + active: true, + visible: authorized && metadataExportScriptExists, + model: { + type: MenuItemType.ONCLICK, + text: 'menu.section.export_metadata', + function: () => { + this.modalService.open(ExportMetadataSelectorComponent); + } + } as OnClickMenuItemModel, + }, + ]; + menuList.forEach((menuSection) => this.menuService.addSection(this.menuID, Object.assign(menuSection, { + shouldPersistOnRouteChange: true + }))); + }); + } + }); + + } + /** * Create menu sections dependent on whether or not the current user is a site administrator */ diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 35ca4db131..10f81a9adc 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -21,7 +21,6 @@ import { HostWindowState } from './shared/search/host-window.reducer'; import { NativeWindowRef, NativeWindowService } from './core/services/window.service'; import { isAuthenticated } from './core/auth/selectors'; import { AuthService } from './core/auth/auth.service'; -import variables from '../styles/_exposed_variables.scss'; import { CSSVariableService } from './shared/sass-helper/sass-helper.service'; import { MenuService } from './shared/menu/menu.service'; import { MenuID } from './shared/menu/initial-menus-state'; diff --git a/src/app/core/data/processes/script-data.service.ts b/src/app/core/data/processes/script-data.service.ts index 6600444ea0..2dcc6e364d 100644 --- a/src/app/core/data/processes/script-data.service.ts +++ b/src/app/core/data/processes/script-data.service.ts @@ -1,4 +1,5 @@ import { Injectable } from '@angular/core'; +import { getRemoteDataPayload, getSucceededRemoteData } from '../../shared/operators'; import { DataService } from '../data.service'; import { RemoteDataBuildService } from '../../cache/builders/remote-data-build.service'; import { Store } from '@ngrx/store'; @@ -12,6 +13,7 @@ import { Script } from '../../../process-page/scripts/script.model'; import { ProcessParameter } from '../../../process-page/processes/process-parameter.model'; import { find, map, switchMap } from 'rxjs/operators'; import { URLCombiner } from '../../url-combiner/url-combiner'; +import { PaginatedList } from '../paginated-list'; import { MultipartPostRequest, RestRequest } from '../request.models'; import { RequestService } from '../request.service'; import { Observable } from 'rxjs'; @@ -58,4 +60,23 @@ export class ScriptDataService extends DataService` - }); - } - } - if (environment.universal.preboot) { // If preboot is enabled, create a new zone for SSR, and // register the error handler for when it throws an error - Zone.current.fork({ name: 'CSR fallback', onHandleError }).run(() => { - res.render(DIST_FOLDER + '/index.html', { + res.render(DIST_FOLDER + '/index.html', { req, res, + preboot: environment.universal.preboot, async: environment.universal.async, time: environment.universal.time, baseUrl: environment.ui.nameSpace, originUrl: environment.ui.baseUrl, requestUrl: req.originalUrl - }); - }); + }, (err) => { + console.warn('Error in SSR, serving for direct CSR. Error details : ', err); + res.sendFile(DIST_FOLDER + '/index.html'); + } + ); } else { // If preboot is disabled, just serve the client side ejs template and pass it the required // variables console.log('Universal off, serving for direct CSR'); - res.render('index-csr.ejs', { - root: DIST_FOLDER, - scripts: `` - }); + res.sendFile(DIST_FOLDER + '/index.html'); } } diff --git a/src/config/universal-config.interface.ts b/src/config/universal-config.interface.ts index d3bbf9d17c..c088dcd657 100644 --- a/src/config/universal-config.interface.ts +++ b/src/config/universal-config.interface.ts @@ -1,6 +1,7 @@ import { Config } from './config.interface'; export interface UniversalConfig extends Config { + preboot: boolean; async: boolean; time: boolean; } diff --git a/src/environments/environment.common.ts b/src/environments/environment.common.ts index c665e6d3db..32ae2f54b0 100644 --- a/src/environments/environment.common.ts +++ b/src/environments/environment.common.ts @@ -121,6 +121,7 @@ export const environment: GlobalConfig = { }, // Angular Universal settings universal: { + preboot: true, async: true, time: false }, diff --git a/src/environments/mock-environment.ts b/src/environments/mock-environment.ts index f2253e307f..6e4d60e268 100644 --- a/src/environments/mock-environment.ts +++ b/src/environments/mock-environment.ts @@ -105,6 +105,7 @@ export const environment: Partial = { }, // Angular Universal settings universal: { + preboot: true, async: true, time: false }, diff --git a/src/main.browser.ts b/src/main.browser.ts index 70f13be6cc..5149014d88 100644 --- a/src/main.browser.ts +++ b/src/main.browser.ts @@ -45,7 +45,7 @@ function addGoogleAnalytics() { } // support async tag or hmr -if (environment.production === false) { +if (hasValue(environment.universal) && environment.universal.preboot === false) { bootloader(main); } else { document.addEventListener('DOMContentLoaded', () => bootloader(main)); From a6dd87f78c84289fe269ef3f99b7064410a3c210 Mon Sep 17 00:00:00 2001 From: lotte Date: Wed, 9 Sep 2020 16:04:42 +0200 Subject: [PATCH 162/170] updated server.ts to latest fixes --- server.ts | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/server.ts b/server.ts index ca79215206..99e2b25e1e 100644 --- a/server.ts +++ b/server.ts @@ -15,7 +15,6 @@ * import for `ngExpressEngine`. */ -import 'zone.js/dist/zone-node'; import 'reflect-metadata'; import 'rxjs'; @@ -34,6 +33,7 @@ import { enableProdMode, NgModuleFactory, Type } from '@angular/core'; import { REQUEST, RESPONSE } from '@nguniversal/express-engine/tokens'; import { environment } from './src/environments/environment'; import { createProxyMiddleware } from 'http-proxy-middleware'; +import { hasValue } from './src/app/shared/empty.util'; /* * Set path for the browser application's dist folder @@ -131,25 +131,24 @@ app.get('*.*', cacheControl, express.static(DIST_FOLDER, { index: false })); */ function ngApp(req, res) { if (environment.universal.preboot) { - // If preboot is enabled, create a new zone for SSR, and - // register the error handler for when it throws an error res.render(DIST_FOLDER + '/index.html', { - req, - res, - preboot: environment.universal.preboot, - async: environment.universal.async, - time: environment.universal.time, - baseUrl: environment.ui.nameSpace, - originUrl: environment.ui.baseUrl, - requestUrl: req.originalUrl - }, (err) => { - console.warn('Error in SSR, serving for direct CSR. Error details : ', err); - res.sendFile(DIST_FOLDER + '/index.html'); + req, + res, + preboot: environment.universal.preboot, + async: environment.universal.async, + time: environment.universal.time, + baseUrl: environment.ui.nameSpace, + originUrl: environment.ui.baseUrl, + requestUrl: req.originalUrl + }, (err) => { + console.warn('Error in SSR, serving for direct CSR.'); + if (hasValue(err)) { + console.warn('Error details : ', err); } - ); + res.sendFile(DIST_FOLDER + '/index.html'); + }) } else { - // If preboot is disabled, just serve the client side ejs template and pass it the required - // variables + // If preboot is disabled, just serve the client console.log('Universal off, serving for direct CSR'); res.sendFile(DIST_FOLDER + '/index.html'); } From 1e8669a73812e807e6656e474be8395ab337f2ce Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Fri, 11 Sep 2020 15:30:38 +0200 Subject: [PATCH 163/170] Fixed issue with change not detected --- .../ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts index 90319ee64d..ff3279e108 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts @@ -290,6 +290,7 @@ export class DsDynamicLookupComponent extends DsDynamicVocabularyComponent imple } else { this.firstInputValue = displayValue || ''; } + this.cdr.detectChanges(); } } From fab0a09727420c0e30c3930150f1620f9f24c589 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Fri, 11 Sep 2020 15:33:05 +0200 Subject: [PATCH 164/170] Fixed issue with adding lookup repeatable fields --- src/app/shared/form/form.component.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/app/shared/form/form.component.ts b/src/app/shared/form/form.component.ts index b6813afdfb..7a5d3932c8 100644 --- a/src/app/shared/form/form.component.ts +++ b/src/app/shared/form/form.component.ts @@ -2,16 +2,20 @@ import { distinctUntilChanged, filter, map } from 'rxjs/operators'; import { ChangeDetectorRef, Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'; import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms'; -import { DynamicFormArrayModel, DynamicFormControlEvent, DynamicFormControlModel, DynamicFormGroupModel, DynamicFormLayout, } from '@ng-dynamic-forms/core'; +import { + DynamicFormArrayModel, + DynamicFormControlEvent, + DynamicFormControlModel, + DynamicFormGroupModel, + DynamicFormLayout, +} from '@ng-dynamic-forms/core'; import { findIndex } from 'lodash'; import { FormBuilderService } from './builder/form-builder.service'; import { Observable, Subscription } from 'rxjs'; import { hasValue, isNotEmpty, isNotNull, isNull } from '../empty.util'; import { FormService } from './form.service'; import { FormEntry, FormError } from './form.reducer'; -import { DYNAMIC_FORM_CONTROL_TYPE_SCROLLABLE_DROPDOWN } from './builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.model'; import { QUALDROP_GROUP_SUFFIX } from './builder/ds-dynamic-form-ui/models/ds-dynamic-qualdrop.model'; -import { DYNAMIC_FORM_CONTROL_TYPE_ONEBOX } from './builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.model'; const QUALDROP_GROUP_REGEX = new RegExp(`${QUALDROP_GROUP_SUFFIX}_\\d+$`); @@ -151,8 +155,8 @@ export class FormComponent implements OnDestroy, OnInit { this.formValid = this.getFormGroupValidStatus(); this.subs.push(this.formGroup.statusChanges.pipe( - filter((currentStatus) => this.formValid !== this.getFormGroupValidStatus())) - .subscribe((currentStatus) => { + filter(() => this.formValid !== this.getFormGroupValidStatus())) + .subscribe(() => { this.formService.setStatusChanged(this.formId, this.getFormGroupValidStatus()); this.formValid = this.getFormGroupValidStatus(); })); @@ -317,7 +321,7 @@ export class FormComponent implements OnDestroy, OnInit { // set that field to the new value const model = arrayContext.groups[arrayContext.groups.length - 1].group[0] as any; - if (model.type === DYNAMIC_FORM_CONTROL_TYPE_SCROLLABLE_DROPDOWN || model.type === DYNAMIC_FORM_CONTROL_TYPE_ONEBOX) { + if (model.hasAuthority) { model.value = Object.values(value)[0]; const ctrl = formArrayControl.controls[formArrayControl.length - 1]; const ctrlValue = ctrl.value; From a178e215f00e13468568f39717c0c268cc8c94d7 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Fri, 11 Sep 2020 15:35:50 +0200 Subject: [PATCH 165/170] Fixed issue with preparing patch operation's value when value has an authority id but is not an instance of VocabularyEntry or FormFieldMetadataValueObject --- .../json-patch/builder/json-patch-operations-builder.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/app/core/json-patch/builder/json-patch-operations-builder.ts b/src/app/core/json-patch/builder/json-patch-operations-builder.ts index 3755821bf9..ced3750834 100644 --- a/src/app/core/json-patch/builder/json-patch-operations-builder.ts +++ b/src/app/core/json-patch/builder/json-patch-operations-builder.ts @@ -134,6 +134,8 @@ export class JsonPatchOperationsBuilder { operationValue = this.prepareAuthorityValue(value); } else if (value instanceof FormFieldLanguageValueObject) { operationValue = new FormFieldMetadataValueObject(value.value, value.language); + } else if (value.hasOwnProperty('authority')) { + operationValue = new FormFieldMetadataValueObject(value.value, value.language, value.authority); } else if (value.hasOwnProperty('value')) { operationValue = new FormFieldMetadataValueObject(value.value); } else { @@ -149,8 +151,8 @@ export class JsonPatchOperationsBuilder { return operationValue; } - protected prepareAuthorityValue(value: any) { - let operationValue: any = null; + protected prepareAuthorityValue(value: any): FormFieldMetadataValueObject { + let operationValue: FormFieldMetadataValueObject; if (isNotEmpty(value.authority)) { operationValue = new FormFieldMetadataValueObject(value.value, value.language, value.authority); } else { From c5cb1a2837d4738fe0d133255013d34d2a415865 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Tue, 8 Sep 2020 11:10:17 +0200 Subject: [PATCH 166/170] [CSTPER-75] Fixed confidence status for linked metadata with authority --- .../models/onebox/dynamic-onebox.component.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.ts index 11002204f5..43ea03228d 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.ts @@ -259,10 +259,8 @@ export class DsDynamicOneboxComponent extends DsDynamicVocabularyComponent imple } else { if (isEmpty(value)) { result = ''; - } else if (typeof value === 'string') { - result = value; } else { - result = value.display; + result = value.value; } this.currentValue = result; From b77dce25cef94b238345f8a54b59f6f9d5cf9f2e Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Thu, 17 Sep 2020 10:44:10 +0200 Subject: [PATCH 167/170] 72699: Shibboleth login redirect fix --- .../shibboleth/log-in-shibboleth.component.ts | 45 +++++++++++-------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/src/app/shared/log-in/methods/shibboleth/log-in-shibboleth.component.ts b/src/app/shared/log-in/methods/shibboleth/log-in-shibboleth.component.ts index 5cc50e46c6..b0704d5cb1 100644 --- a/src/app/shared/log-in/methods/shibboleth/log-in-shibboleth.component.ts +++ b/src/app/shared/log-in/methods/shibboleth/log-in-shibboleth.component.ts @@ -11,9 +11,11 @@ import { CoreState } from '../../../../core/core.reducers'; import { isAuthenticated, isAuthenticationLoading } from '../../../../core/auth/selectors'; import { RouteService } from '../../../../core/services/route.service'; import { NativeWindowRef, NativeWindowService } from '../../../../core/services/window.service'; -import { isNotNull } from '../../../empty.util'; +import { isNotNull, isEmpty } from '../../../empty.util'; import { AuthService } from '../../../../core/auth/auth.service'; import { HardRedirectService } from '../../../../core/services/hard-redirect.service'; +import { take } from 'rxjs/operators'; +import { URLCombiner } from '../../../../core/url-combiner/url-combiner'; @Component({ selector: 'ds-log-in-shibboleth', @@ -83,26 +85,31 @@ export class LogInShibbolethComponent implements OnInit { } redirectToShibboleth() { - if (!this.isStandalonePage) { - this.authService.setRedirectUrl(this.hardRedirectService.getCurrentRoute()); - } else { - this.authService.setRedirectUrlIfNotSet('/'); - } - let newLocationUrl = this.location; - const currentUrl = this._window.nativeWindow.location.href; - const myRegexp = /\?redirectUrl=(.*)/g; - const match = myRegexp.exec(this.location); - const redirectUrl = (match && match[1]) ? match[1] : null; - // Check whether the current page is different from the redirect url received from rest - if (isNotNull(redirectUrl) && redirectUrl !== currentUrl) { - // change the redirect url with the current page url - const newRedirectUrl = `?redirectUrl=${currentUrl}`; - newLocationUrl = this.location.replace(/\?redirectUrl=(.*)/g, newRedirectUrl); - } + this.authService.getRedirectUrl().pipe(take(1)).subscribe((redirectRoute) => { + if (!this.isStandalonePage) { + redirectRoute = this.hardRedirectService.getCurrentRoute(); + } else if (isEmpty(redirectRoute)) { + redirectRoute = '/'; + } + const correctRedirectUrl = new URLCombiner(this._window.nativeWindow.origin, redirectRoute).toString(); + + let shibbolethServerUrl = this.location; + const myRegexp = /\?redirectUrl=(.*)/g; + const match = myRegexp.exec(this.location); + const redirectUrlFromServer = (match && match[1]) ? match[1] : null; + + // Check whether the current page is different from the redirect url received from rest + if (isNotNull(redirectUrlFromServer) && redirectUrlFromServer !== correctRedirectUrl) { + // change the redirect url with the current page url + const newRedirectUrl = `?redirectUrl=${correctRedirectUrl}`; + shibbolethServerUrl = this.location.replace(/\?redirectUrl=(.*)/g, newRedirectUrl); + } + + // redirect to shibboleth authentication url + this.hardRedirectService.redirect(shibbolethServerUrl); + }); - // redirect to shibboleth authentication url - this._window.nativeWindow.location.href = newLocationUrl; } } From d5927a76fc3980eb7a3c48c4cab4f605bcd86e30 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Thu, 17 Sep 2020 10:49:24 +0200 Subject: [PATCH 168/170] 72699: Test fix --- .../methods/shibboleth/log-in-shibboleth.component.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/shared/log-in/methods/shibboleth/log-in-shibboleth.component.spec.ts b/src/app/shared/log-in/methods/shibboleth/log-in-shibboleth.component.spec.ts index 1c5698031d..23c279d148 100644 --- a/src/app/shared/log-in/methods/shibboleth/log-in-shibboleth.component.spec.ts +++ b/src/app/shared/log-in/methods/shibboleth/log-in-shibboleth.component.spec.ts @@ -107,7 +107,7 @@ describe('LogInShibbolethComponent', () => { component.redirectToShibboleth(); - expect(setHrefSpy).toHaveBeenCalledWith(shibbolethBaseUrl + currentUrl) + expect(setHrefSpy).toHaveBeenCalledWith(currentUrl) }); @@ -122,7 +122,7 @@ describe('LogInShibbolethComponent', () => { component.redirectToShibboleth(); - expect(setHrefSpy).toHaveBeenCalledWith(shibbolethBaseUrl + currentUrl) + expect(setHrefSpy).toHaveBeenCalledWith(currentUrl) }); From b68fe233108068dbbea26d45483f5f74f5f10e75 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Thu, 17 Sep 2020 11:40:30 +0200 Subject: [PATCH 169/170] 72699: Additional test fix --- .../methods/shibboleth/log-in-shibboleth.component.spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app/shared/log-in/methods/shibboleth/log-in-shibboleth.component.spec.ts b/src/app/shared/log-in/methods/shibboleth/log-in-shibboleth.component.spec.ts index 23c279d148..e8b18fa409 100644 --- a/src/app/shared/log-in/methods/shibboleth/log-in-shibboleth.component.spec.ts +++ b/src/app/shared/log-in/methods/shibboleth/log-in-shibboleth.component.spec.ts @@ -45,7 +45,8 @@ describe('LogInShibbolethComponent', () => { }; hardRedirectService = jasmine.createSpyObj('hardRedirectService', { - getCurrentRoute: {} + getCurrentRoute: {}, + redirect: {} }); }); From 4e10db8a53c45541ec43f407ac4337818f22f783 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Thu, 17 Sep 2020 11:31:16 +0200 Subject: [PATCH 170/170] 72541: user-agreement update to patch --- src/app/core/data/data.service.ts | 3 ++- .../end-user-agreement.service.spec.ts | 14 ++++---------- .../end-user-agreement.service.ts | 18 ++++++++++-------- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index 3b4e5f7d42..528889cd83 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -3,7 +3,7 @@ import { Store } from '@ngrx/store'; import { Operation } from 'fast-json-patch'; import { Observable } from 'rxjs'; import { distinctUntilChanged, filter, find, first, map, mergeMap, switchMap, take } from 'rxjs/operators'; -import { hasValue, isNotEmpty, isNotEmptyOperator } from '../../shared/empty.util'; +import { hasValue, hasValueOperator, isNotEmpty, isNotEmptyOperator } from '../../shared/empty.util'; import { NotificationOptions } from '../../shared/notifications/models/notification-options.model'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; @@ -376,6 +376,7 @@ export abstract class DataService implements UpdateDa ).subscribe(); return this.requestService.getByUUID(requestId).pipe( + hasValueOperator(), find((request: RequestEntry) => request.completed), map((request: RequestEntry) => request.response) ); diff --git a/src/app/core/end-user-agreement/end-user-agreement.service.spec.ts b/src/app/core/end-user-agreement/end-user-agreement.service.spec.ts index 4b0a37a94f..d50c730d28 100644 --- a/src/app/core/end-user-agreement/end-user-agreement.service.spec.ts +++ b/src/app/core/end-user-agreement/end-user-agreement.service.spec.ts @@ -7,6 +7,7 @@ import { CookieServiceMock } from '../../shared/mocks/cookie.service.mock'; import { of as observableOf } from 'rxjs'; import { EPerson } from '../eperson/models/eperson.model'; import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; +import { RestResponse } from '../cache/response.models'; describe('EndUserAgreementService', () => { let service: EndUserAgreementService; @@ -36,7 +37,8 @@ describe('EndUserAgreementService', () => { getAuthenticatedUserFromStore: observableOf(userWithMetadata) }); ePersonService = jasmine.createSpyObj('ePersonService', { - update: createSuccessfulRemoteDataObject$(userWithMetadata) + update: createSuccessfulRemoteDataObject$(userWithMetadata), + patch: observableOf(new RestResponse(true, 200, 'OK')) }); service = new EndUserAgreementService(cookie, authService, ePersonService); @@ -98,15 +100,7 @@ describe('EndUserAgreementService', () => { it('setUserAcceptedAgreement should update the user with new metadata', (done) => { service.setUserAcceptedAgreement(true).subscribe(() => { - expect(ePersonService.update).toHaveBeenCalledWith(jasmine.objectContaining({ - metadata: jasmine.objectContaining({ - [END_USER_AGREEMENT_METADATA_FIELD]: [ - { - value: 'true' - } - ] - }) - })); + expect(ePersonService.patch).toHaveBeenCalled(); done(); }); }); diff --git a/src/app/core/end-user-agreement/end-user-agreement.service.ts b/src/app/core/end-user-agreement/end-user-agreement.service.ts index 31b606cfb4..23bda89169 100644 --- a/src/app/core/end-user-agreement/end-user-agreement.service.ts +++ b/src/app/core/end-user-agreement/end-user-agreement.service.ts @@ -5,10 +5,7 @@ import { Observable } from 'rxjs/internal/Observable'; import { of as observableOf } from 'rxjs'; import { map, switchMap, take } from 'rxjs/operators'; import { hasValue } from '../../shared/empty.util'; -import { cloneDeep } from 'lodash'; -import { Metadata } from '../shared/metadata.utils'; import { EPersonDataService } from '../eperson/eperson-data.service'; -import { getSucceededRemoteData } from '../shared/operators'; export const END_USER_AGREEMENT_COOKIE = 'hasAgreedEndUser'; export const END_USER_AGREEMENT_METADATA_FIELD = 'dspace.agreements.end-user'; @@ -67,13 +64,18 @@ export class EndUserAgreementService { switchMap((authenticated) => { if (authenticated) { return this.authService.getAuthenticatedUserFromStore().pipe( + take(1), switchMap((user) => { - const updatedUser = cloneDeep(user); - Metadata.setFirstValue(updatedUser.metadata, END_USER_AGREEMENT_METADATA_FIELD, String(accepted)); - return this.ePersonService.update(updatedUser); + const newValue = { value: String(accepted) }; + let operation; + if (user.hasMetadata(END_USER_AGREEMENT_METADATA_FIELD)) { + operation = { op: 'replace', path: `/metadata/${END_USER_AGREEMENT_METADATA_FIELD}/0`, value: newValue }; + } else { + operation = { op: 'add', path: `/metadata/${END_USER_AGREEMENT_METADATA_FIELD}`, value: [ newValue ] }; + } + return this.ePersonService.patch(user, [operation]); }), - getSucceededRemoteData(), - map((rd) => hasValue(rd.payload)) + map((response) => response.isSuccessful) ); } else { this.setCookieAccepted(accepted);