diff --git a/config/config.example.yml b/config/config.example.yml index 4fbc98fea2..8b010ba6ea 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -424,3 +424,12 @@ comcolSelectionSort: # suggestion: # - collectionId: 8f7df5ca-f9c2-47a4-81ec-8a6393d6e5af # source: "openaire" + + +# Search settings +search: + # Settings to enable/disable or configure advanced search filters. + advancedFilters: + enabled: false + # List of filters to enable in "Advanced Search" dropdown + filter: [ 'title', 'author', 'subject', 'entityType' ] diff --git a/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts b/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts new file mode 100644 index 0000000000..c94083d3ba --- /dev/null +++ b/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts @@ -0,0 +1,47 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { LdnServicesOverviewComponent } from './ldn-services-directory/ldn-services-directory.component'; +import { NavigationBreadcrumbResolver } from '../../core/breadcrumbs/navigation-breadcrumb.resolver'; +import { I18nBreadcrumbResolver } from '../../core/breadcrumbs/i18n-breadcrumb.resolver'; +import { LdnServiceFormComponent } from './ldn-service-form/ldn-service-form.component'; + + +const moduleRoutes: Routes = [ + { + path: '', + pathMatch: 'full', + component: LdnServicesOverviewComponent, + resolve: {breadcrumb: I18nBreadcrumbResolver}, + data: {title: 'ldn-registered-services.title', breadcrumbKey: 'ldn-registered-services.new'}, + }, + { + path: 'new', + resolve: {breadcrumb: NavigationBreadcrumbResolver}, + component: LdnServiceFormComponent, + data: {title: 'ldn-register-new-service.title', breadcrumbKey: 'ldn-register-new-service'} + }, + { + path: 'edit/:serviceId', + resolve: {breadcrumb: NavigationBreadcrumbResolver}, + component: LdnServiceFormComponent, + data: {title: 'ldn-edit-service.title', breadcrumbKey: 'ldn-edit-service'} + }, +]; + + +@NgModule({ + imports: [ + RouterModule.forChild(moduleRoutes.map(route => { + return {...route, data: { + ...route.data, + relatedRoutes: moduleRoutes.filter(relatedRoute => relatedRoute.path !== route.path) + .map((relatedRoute) => { + return {path: relatedRoute.path, data: relatedRoute.data}; + }) + }}; + })) + ] +}) +export class AdminLdnServicesRoutingModule { + +} diff --git a/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts b/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts new file mode 100644 index 0000000000..45ec696cd3 --- /dev/null +++ b/src/app/admin/admin-ldn-services/admin-ldn-services.module.ts @@ -0,0 +1,25 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { AdminLdnServicesRoutingModule } from './admin-ldn-services-routing.module'; +import { LdnServicesOverviewComponent } from './ldn-services-directory/ldn-services-directory.component'; +import { SharedModule } from '../../shared/shared.module'; +import { LdnServiceFormComponent } from './ldn-service-form/ldn-service-form.component'; +import { FormsModule } from '@angular/forms'; +import { LdnItemfiltersService } from './ldn-services-data/ldn-itemfilters-data.service'; + + +@NgModule({ + imports: [ + CommonModule, + SharedModule, + AdminLdnServicesRoutingModule, + FormsModule + ], + declarations: [ + LdnServicesOverviewComponent, + LdnServiceFormComponent, + ], + providers: [LdnItemfiltersService] +}) +export class AdminLdnServicesModule { +} diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html new file mode 100644 index 0000000000..c11a41d887 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.html @@ -0,0 +1,310 @@ +
+
+
+

{{ isNewService ? ('ldn-create-service.title' | translate) : ('ldn-edit-registered-service.title' | translate) }}

+
+ +
+ +
+ +
+
+
+
+
+ +
+ + +
+ {{ 'ldn-new-service.form.error.name' | translate }} +
+
+ + +
+ + +
+ +
+ +
+
+ + +
+ {{ 'ldn-new-service.form.error.url' | translate }} +
+
+ +
+ + +
+ {{ 'ldn-new-service.form.error.score' | translate }} +
+
+
+
+ + +
+ +
+ + +
+
+ {{ 'ldn-new-service.form.error.ipRange' | translate }} +
+
+ {{ 'ldn-new-service.form.hint.ipRange' | translate }} +
+
+ + +
+ + +
+ {{ 'ldn-new-service.form.error.ldnurl' | translate }} +
+
+ + + +
+
+ +
+ +
+ +
+
+ +
+
+
+
+
+ + +
+
+ + + + +
+
+
+ +
+
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+
+ + +
+
+ + + + +
+
+
+
+
+
+ + {{ 'ldn-new-service.form.label.addPattern' | translate }} + + +
+
+ + + + + + + + diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss new file mode 100644 index 0000000000..afd5c80d1c --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.scss @@ -0,0 +1,143 @@ +@import '../../../shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.scss'; +@import '../../../shared/form/form.component.scss'; + +form { + font-size: 14px; + position: relative; +} + +input, +select { + max-width: 100%; + width: 100%; + padding: 8px; + font-size: 14px; +} + +option:not(:first-child) { + font-weight: bold; +} + +.trash-button { + width: 40px; + height: 40px; +} + +textarea { + height: 200px; + resize: none; +} + +.add-pattern-link { + color: #0048ff; + cursor: pointer; +} + +.remove-pattern-link { + color: #e34949; + cursor: pointer; + margin-left: 10px; +} + +.status-checkbox { + margin-top: 5px; +} + + +.invalid-field { + border: 1px solid red; + color: #000000; +} + +.error-text { + color: red; + font-size: 0.8em; + margin-top: 5px; +} + +.toggle-switch { + display: flex; + align-items: center; + opacity: 0.8; + position: relative; + width: 60px; + height: 30px; + background-color: #ccc; + border-radius: 15px; + cursor: pointer; + transition: background-color 0.3s; +} + +.toggle-switch.checked { + background-color: #24cc9a; +} + +.slider { + position: absolute; + width: 30px; + height: 30px; + border-radius: 50%; + background-color: #fff; + transition: transform 0.3s; +} + + +.toggle-switch .slider { + width: 22px; + height: 22px; + border-radius: 50%; + margin: 0 auto; +} + +.toggle-switch.checked .slider { + transform: translateX(30px); +} + +.toggle-switch-container { + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: flex-end; + margin-top: 10px; +} + +.small-text { + font-size: 0.7em; + color: #888; +} + +.toggle-switch { + cursor: pointer; + margin-top: 3px; + margin-right: 3px +} + +.label-box { + margin-left: 11px; +} + +.label-box-2 { + margin-left: 14px; +} + +.label-box-3 { + margin-left: 5px; +} + +.submission-form-footer { + border-radius: var(--bs-card-border-radius); + bottom: 0; + background-color: var(--bs-gray-400); + padding: calc(var(--bs-spacer) / 2); + z-index: calc(var(--ds-submission-footer-z-index) + 1); +} + +.marked-for-deletion { + background-color: lighten($red, 30%); +} + +.dropdown-menu-top, .scrollable-dropdown-menu { + z-index: var(--ds-submission-footer-z-index); +} + + diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.spec.ts b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.spec.ts new file mode 100644 index 0000000000..e16ff49b7e --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.spec.ts @@ -0,0 +1,241 @@ +import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; + +import {NgbDropdownModule, NgbModal} from '@ng-bootstrap/ng-bootstrap'; +import {LdnServiceFormComponent} from './ldn-service-form.component'; +import {ChangeDetectorRef, EventEmitter} from '@angular/core'; +import { FormArray, FormBuilder, FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import {ActivatedRoute, Router} from '@angular/router'; +import {TranslateModule, TranslateService} from '@ngx-translate/core'; +import {PaginationService} from 'ngx-pagination'; +import {NotificationsService} from '../../../shared/notifications/notifications.service'; +import {LdnItemfiltersService} from '../ldn-services-data/ldn-itemfilters-data.service'; +import {LdnServicesService} from '../ldn-services-data/ldn-services-data.service'; +import {RouterStub} from '../../../shared/testing/router.stub'; +import {MockActivatedRoute} from '../../../shared/mocks/active-router.mock'; +import {NotificationsServiceStub} from '../../../shared/testing/notifications-service.stub'; +import { of as observableOf, of } from 'rxjs'; +import {RouteService} from '../../../core/services/route.service'; +import {provideMockStore} from '@ngrx/store/testing'; +import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; +import { By } from '@angular/platform-browser'; + +describe('LdnServiceFormEditComponent', () => { + let component: LdnServiceFormComponent; + let fixture: ComponentFixture; + + let ldnServicesService: LdnServicesService; + let ldnItemfiltersService: any; + let cdRefStub: any; + let modalService: any; + let activatedRoute: MockActivatedRoute; + + const testId = '1234'; + const routeParams = { + serviceId: testId, + }; + const routeUrlSegments = [{path: 'path'}]; + const formMockValue = { + 'id': '', + 'name': 'name', + 'description': 'description', + 'url': 'www.test.com', + 'ldnUrl': 'https://test.com', + 'lowerIp': '127.0.0.1', + 'upperIp': '100.100.100.100', + 'score': 1, + 'inboundPattern': '', + 'constraintPattern': '', + 'enabled': '', + 'type': 'ldnservice', + 'notifyServiceInboundPatterns': [ + { + 'pattern': '', + 'patternLabel': 'Select a pattern', + 'constraint': '', + 'automatic': false + } + ] + }; + + + const translateServiceStub = { + get: () => of('translated-text'), + instant: () => 'translated-text', + onLangChange: new EventEmitter(), + onTranslationChange: new EventEmitter(), + onDefaultLangChange: new EventEmitter() + }; + + beforeEach(async () => { + ldnServicesService = jasmine.createSpyObj('ldnServicesService', { + create: observableOf(null), + update: observableOf(null), + findById: createSuccessfulRemoteDataObject$({}), + }); + + ldnItemfiltersService = { + findAll: () => of(['item1', 'item2']), + }; + cdRefStub = Object.assign({ + detectChanges: () => fixture.detectChanges() + }); + modalService = { + open: () => {/*comment*/ + } + }; + + + activatedRoute = new MockActivatedRoute(routeParams, routeUrlSegments); + + await TestBed.configureTestingModule({ + imports: [ReactiveFormsModule, TranslateModule.forRoot(), NgbDropdownModule], + declarations: [LdnServiceFormComponent], + providers: [ + {provide: LdnServicesService, useValue: ldnServicesService}, + {provide: LdnItemfiltersService, useValue: ldnItemfiltersService}, + {provide: Router, useValue: new RouterStub()}, + {provide: ActivatedRoute, useValue: activatedRoute}, + {provide: ChangeDetectorRef, useValue: cdRefStub}, + {provide: NgbModal, useValue: modalService}, + {provide: NotificationsService, useValue: new NotificationsServiceStub()}, + {provide: TranslateService, useValue: translateServiceStub}, + {provide: PaginationService, useValue: {}}, + FormBuilder, + RouteService, + provideMockStore({}), + ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(LdnServiceFormComponent); + component = fixture.componentInstance; + spyOn(component, 'filterPatternObjectsAndAssignLabel').and.callFake((a) => a); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + expect(component.formModel instanceof FormGroup).toBeTruthy(); + }); + + it('should init properties correctly', fakeAsync(() => { + spyOn(component, 'fetchServiceData'); + spyOn(component, 'setItemfilters'); + component.ngOnInit(); + tick(100); + expect((component as any).serviceId).toEqual(testId); + expect(component.isNewService).toBeFalsy(); + expect(component.areControlsInitialized).toBeTruthy(); + expect(component.formModel.controls.notifyServiceInboundPatterns).toBeDefined(); + expect(component.fetchServiceData).toHaveBeenCalledWith(testId); + expect(component.setItemfilters).toHaveBeenCalled(); + })); + + it('should unsubscribe on destroy', () => { + spyOn((component as any).routeSubscription, 'unsubscribe'); + component.ngOnDestroy(); + expect((component as any).routeSubscription.unsubscribe).toHaveBeenCalled(); + }); + + it('should handle create service with valid form', () => { + spyOn(component, 'fetchServiceData').and.callFake((a) => a); + component.formModel.addControl('notifyServiceInboundPatterns', (component as any).formBuilder.array([{pattern: 'patternValue'}])); + const nameInput = fixture.debugElement.query(By.css('#name')); + const descriptionInput = fixture.debugElement.query(By.css('#description')); + const urlInput = fixture.debugElement.query(By.css('#url')); + const scoreInput = fixture.debugElement.query(By.css('#score')); + const lowerIpInput = fixture.debugElement.query(By.css('#lowerIp')); + const upperIpInput = fixture.debugElement.query(By.css('#upperIp')); + const ldnUrlInput = fixture.debugElement.query(By.css('#ldnUrl')); + component.formModel.patchValue(formMockValue); + + nameInput.nativeElement.value = 'testName'; + descriptionInput.nativeElement.value = 'testDescription'; + urlInput.nativeElement.value = 'tetsUrl.com'; + ldnUrlInput.nativeElement.value = 'tetsLdnUrl.com'; + scoreInput.nativeElement.value = 1; + lowerIpInput.nativeElement.value = '127.0.0.1'; + upperIpInput.nativeElement.value = '127.0.0.1'; + + fixture.detectChanges(); + + expect(component.formModel.valid).toBeTruthy(); + }); + + it('should handle create service with invalid form', () => { + const nameInput = fixture.debugElement.query(By.css('#name')); + + nameInput.nativeElement.value = 'testName'; + fixture.detectChanges(); + + expect(component.formModel.valid).toBeFalsy(); + }); + + it('should not create service with invalid form', () => { + spyOn(component.formModel, 'markAllAsTouched'); + spyOn(component, 'closeModal'); + component.createService(); + + expect(component.formModel.markAllAsTouched).toHaveBeenCalled(); + expect(component.closeModal).toHaveBeenCalled(); + }); + + it('should create service with valid form', () => { + spyOn(component.formModel, 'markAllAsTouched'); + spyOn(component, 'closeModal'); + spyOn(component, 'checkPatterns').and.callFake(() => true); + component.formModel.addControl('notifyServiceInboundPatterns', (component as any).formBuilder.array([{pattern: 'patternValue'}])); + component.formModel.patchValue(formMockValue); + component.createService(); + + expect(component.formModel.markAllAsTouched).toHaveBeenCalled(); + expect(component.closeModal).not.toHaveBeenCalled(); + expect(ldnServicesService.create).toHaveBeenCalled(); + }); + + it('should check patterns', () => { + const arrValid = new FormArray([ + new FormGroup({ + pattern: new FormControl('pattern') + }), + ]); + + const arrInvalid = new FormArray([ + new FormGroup({ + pattern: new FormControl('') + }), + ]); + + expect(component.checkPatterns(arrValid)).toBeTruthy(); + expect(component.checkPatterns(arrInvalid)).toBeFalsy(); + }); + + it('should fetch service data', () => { + component.fetchServiceData(testId); + expect(ldnServicesService.findById).toHaveBeenCalledWith(testId); + expect(component.filterPatternObjectsAndAssignLabel).toHaveBeenCalled(); + expect((component as any).ldnService).toEqual({}); + }); + + it('should generate patch operations', () => { + spyOn(component as any, 'createReplaceOperation'); + spyOn(component as any, 'handlePatterns'); + component.generatePatchOperations(); + expect((component as any).createReplaceOperation).toHaveBeenCalledTimes(7); + expect((component as any).handlePatterns).toHaveBeenCalled(); + }); + + it('should open modal on submit', () => { + spyOn(component, 'openConfirmModal'); + component.onSubmit(); + expect(component.openConfirmModal).toHaveBeenCalled(); + }); + + + it('should reset form and leave', () => { + spyOn(component as any, 'sendBack'); + + component.resetFormAndLeave(); + expect((component as any).sendBack).toHaveBeenCalled(); + }); +}); diff --git a/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts new file mode 100644 index 0000000000..0a08264bda --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts @@ -0,0 +1,557 @@ +import { + ChangeDetectorRef, + Component, + OnDestroy, + OnInit, + TemplateRef, + ViewChild +} from '@angular/core'; +import {FormArray, FormBuilder, FormGroup, Validators} from '@angular/forms'; +import {LDN_SERVICE} from '../ldn-services-model/ldn-service.resource-type'; +import {ActivatedRoute, Router} from '@angular/router'; +import {LdnServicesService} from '../ldn-services-data/ldn-services-data.service'; +import {notifyPatterns} from '../ldn-services-patterns/ldn-service-coar-patterns'; +import {animate, state, style, transition, trigger} from '@angular/animations'; +import {NgbModal} from '@ng-bootstrap/ng-bootstrap'; +import {NotificationsService} from '../../../shared/notifications/notifications.service'; +import {TranslateService} from '@ngx-translate/core'; +import {LdnService} from '../ldn-services-model/ldn-services.model'; +import {RemoteData} from 'src/app/core/data/remote-data'; +import {Operation} from 'fast-json-patch'; +import {getFirstCompletedRemoteData} from '../../../core/shared/operators'; +import {LdnItemfiltersService} from '../ldn-services-data/ldn-itemfilters-data.service'; +import {Itemfilter} from '../ldn-services-model/ldn-service-itemfilters'; +import {PaginatedList} from '../../../core/data/paginated-list.model'; +import {combineLatestWith, Observable, Subscription} from 'rxjs'; +import {PaginationService} from '../../../core/pagination/pagination.service'; +import {FindListOptions} from '../../../core/data/find-list-options.model'; +import {NotifyServicePattern} from '../ldn-services-model/ldn-service-patterns.model'; +import { IpV4Validator } from '../../../shared/utils/ipV4.validator'; + + +/** + * Component for editing LDN service through a form that allows to create or edit the properties of a service + */ +@Component({ + selector: 'ds-ldn-service-form', + templateUrl: './ldn-service-form.component.html', + styleUrls: ['./ldn-service-form.component.scss'], + animations: [ + trigger('toggleAnimation', [ + state('true', style({})), + state('false', style({})), + transition('true <=> false', animate('300ms ease-in')), + ]), + ], +}) +export class LdnServiceFormComponent implements OnInit, OnDestroy { + formModel: FormGroup; + + @ViewChild('confirmModal', {static: true}) confirmModal: TemplateRef; + @ViewChild('resetFormModal', {static: true}) resetFormModal: TemplateRef; + + public inboundPatterns: string[] = notifyPatterns; + public isNewService: boolean; + public areControlsInitialized: boolean; + public itemfiltersRD$: Observable>>; + public config: FindListOptions = Object.assign(new FindListOptions(), { + elementsPerPage: 20 + }); + public markedForDeletionInboundPattern: number[] = []; + public selectedInboundPatterns: string[]; + + protected serviceId: string; + + private deletedInboundPatterns: number[] = []; + private modalRef: any; + private ldnService: LdnService; + private selectPatternDefaultLabeli18Key = 'ldn-service.form.label.placeholder.default-select'; + private routeSubscription: Subscription; + + constructor( + protected ldnServicesService: LdnServicesService, + private ldnItemfiltersService: LdnItemfiltersService, + private formBuilder: FormBuilder, + private router: Router, + private route: ActivatedRoute, + private cdRef: ChangeDetectorRef, + protected modalService: NgbModal, + private notificationService: NotificationsService, + private translateService: TranslateService, + protected paginationService: PaginationService + ) { + + this.formModel = this.formBuilder.group({ + id: [''], + name: ['', Validators.required], + description: [''], + url: ['', Validators.required], + ldnUrl: ['', Validators.required], + lowerIp: ['', [Validators.required, new IpV4Validator()]], + upperIp: ['', [Validators.required, new IpV4Validator()]], + score: ['', [Validators.required, Validators.pattern('^0*(\.[0-9]+)?$|^1(\.0+)?$')]], inboundPattern: [''], + constraintPattern: [''], + enabled: [''], + type: LDN_SERVICE.value, + }); + } + + ngOnInit(): void { + this.routeSubscription = this.route.params.pipe( + combineLatestWith(this.route.url) + ).subscribe(([params, segment]) => { + this.serviceId = params.serviceId; + this.isNewService = segment[0].path === 'new'; + this.formModel.addControl('notifyServiceInboundPatterns', this.formBuilder.array([this.createInboundPatternFormGroup()])); + this.areControlsInitialized = true; + if (this.serviceId && !this.isNewService) { + this.fetchServiceData(this.serviceId); + } + }); + this.setItemfilters(); + } + + ngOnDestroy(): void { + this.routeSubscription.unsubscribe(); + } + + /** + * Sets item filters using LDN item filters service + */ + setItemfilters() { + this.itemfiltersRD$ = this.ldnItemfiltersService.findAll().pipe( + getFirstCompletedRemoteData()); + } + + /** + * Handles the creation of an LDN service by retrieving and validating form fields, + * and submitting the form data to the LDN services endpoint. + */ + createService() { + this.formModel.markAllAsTouched(); + const notifyServiceInboundPatterns = this.formModel.get('notifyServiceInboundPatterns') as FormArray; + const hasInboundPattern = notifyServiceInboundPatterns?.length > 0 ? this.checkPatterns(notifyServiceInboundPatterns) : false; + + if (this.formModel.invalid) { + this.closeModal(); + return; + } + + if (!hasInboundPattern) { + this.notificationService.warning(this.translateService.get('ldn-service-notification.created.warning.title')); + this.closeModal(); + return; + } + + + this.formModel.value.notifyServiceInboundPatterns = this.formModel.value.notifyServiceInboundPatterns.map((pattern: { + pattern: string; + patternLabel: string, + constraintFormatted: string; + }) => { + const {patternLabel, ...rest} = pattern; + delete rest.constraintFormatted; + return rest; + }); + + const values = {...this.formModel.value, enabled: true}; + + const ldnServiceData = this.ldnServicesService.create(values); + + ldnServiceData.pipe( + getFirstCompletedRemoteData() + ).subscribe((rd: RemoteData) => { + if (rd.hasSucceeded) { + this.notificationService.success(this.translateService.get('ldn-service-notification.created.success.title'), + this.translateService.get('ldn-service-notification.created.success.body')); + this.closeModal(); + this.sendBack(); + } else { + this.notificationService.error(this.translateService.get('ldn-service-notification.created.failure.title'), + this.translateService.get('ldn-service-notification.created.failure.body')); + this.closeModal(); + } + }); + } + + /** + * Checks if at least one pattern in the specified form array has a value. + * + * @param {FormArray} formArray - The form array containing patterns to check. + * @returns {boolean} - True if at least one pattern has a value, otherwise false. + */ + checkPatterns(formArray: FormArray): boolean { + for (let i = 0; i < formArray.length; i++) { + const pattern = formArray.at(i).get('pattern').value; + if (pattern) { + return true; + } + } + return false; + } + + /** + * Fetches LDN service data by ID and updates the form + * @param serviceId - The ID of the LDN service + */ + fetchServiceData(serviceId: string): void { + this.ldnServicesService.findById(serviceId).pipe( + getFirstCompletedRemoteData() + ).subscribe( + (data: RemoteData) => { + if (data.hasSucceeded) { + this.ldnService = data.payload; + this.formModel.patchValue({ + id: this.ldnService.id, + name: this.ldnService.name, + description: this.ldnService.description, + url: this.ldnService.url, + score: this.ldnService.score, + ldnUrl: this.ldnService.ldnUrl, + type: this.ldnService.type, + enabled: this.ldnService.enabled, + lowerIp: this.ldnService.lowerIp, + upperIp: this.ldnService.upperIp + }); + this.filterPatternObjectsAndAssignLabel('notifyServiceInboundPatterns'); + let notifyServiceInboundPatternsFormArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; + notifyServiceInboundPatternsFormArray.controls.forEach( + control => { + const controlFormGroup = control as FormGroup; + const controlConstraint = controlFormGroup.get('constraint').value; + controlFormGroup.patchValue({ + constraintFormatted: controlConstraint ? this.translateService.instant((controlConstraint as string) + '.label') : '' + }); + } + ); + } + }, + ); + } + + /** + * Filters pattern objects, initializes form groups, assigns labels, and adds them to the specified form array so the correct string is shown in the dropdown.. + * @param formArrayName - The name of the form array to be populated + */ + filterPatternObjectsAndAssignLabel(formArrayName: string) { + const PatternsArray = this.formModel.get(formArrayName) as FormArray; + PatternsArray.clear(); + + let servicesToUse = this.ldnService.notifyServiceInboundPatterns; + + servicesToUse.forEach((patternObj: NotifyServicePattern) => { + let patternFormGroup; + patternFormGroup = this.initializeInboundPatternFormGroup(); + const newPatternObjWithLabel = Object.assign(new NotifyServicePattern(), { + ...patternObj, + patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternObj?.pattern + '.label') + }); + patternFormGroup.patchValue(newPatternObjWithLabel); + + PatternsArray.push(patternFormGroup); + this.cdRef.detectChanges(); + }); + } + + /** + * Generates an array of patch operations based on form changes + * @returns Array of patch operations + */ + generatePatchOperations(): any[] { + const patchOperations: any[] = []; + + this.createReplaceOperation(patchOperations, 'name', '/name'); + this.createReplaceOperation(patchOperations, 'description', '/description'); + this.createReplaceOperation(patchOperations, 'ldnUrl', '/ldnurl'); + this.createReplaceOperation(patchOperations, 'url', '/url'); + this.createReplaceOperation(patchOperations, 'score', '/score'); + this.createReplaceOperation(patchOperations, 'lowerIp', '/lowerIp'); + this.createReplaceOperation(patchOperations, 'upperIp', '/upperIp'); + + this.handlePatterns(patchOperations, 'notifyServiceInboundPatterns'); + this.deletedInboundPatterns.forEach(index => { + const removeOperation: Operation = { + op: 'remove', + path: `notifyServiceInboundPatterns[${index}]` + }; + patchOperations.push(removeOperation); + }); + + return patchOperations; + } + + /** + * Submits the form by opening the confirmation modal + */ + onSubmit() { + this.openConfirmModal(this.confirmModal); + } + + /** + * Adds a new inbound pattern form group to the array of inbound patterns in the form + */ + addInboundPattern() { + const notifyServiceInboundPatternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; + notifyServiceInboundPatternsArray.push(this.createInboundPatternFormGroup()); + } + + /** + * Selects an inbound pattern by updating its values based on the provided pattern value and index + * @param patternValue - The selected pattern value + * @param index - The index of the inbound pattern in the array + */ + selectInboundPattern(patternValue: string, index: number): void { + const patternArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray); + patternArray.controls[index].patchValue({pattern: patternValue}); + patternArray.controls[index].patchValue({patternLabel: this.translateService.instant('ldn-service.form.pattern.' + patternValue + '.label')}); + } + + /** + * Selects an inbound item filter by updating its value based on the provided filter value and index + * @param filterValue - The selected filter value + * @param index - The index of the inbound pattern in the array + */ + selectInboundItemFilter(filterValue: string, index: number): void { + const filterArray = (this.formModel.get('notifyServiceInboundPatterns') as FormArray); + filterArray.controls[index].patchValue({ + constraint: filterValue, + constraintFormatted: this.translateService.instant((filterValue !== '' ? filterValue : 'ldn.no-filter') + '.label') + }); + filterArray.markAllAsTouched(); + } + + /** + * Toggles the automatic property of an inbound pattern at the specified index + * @param i - The index of the inbound pattern in the array + */ + toggleAutomatic(i: number) { + const automaticControl = this.formModel.get(`notifyServiceInboundPatterns.${i}.automatic`); + if (automaticControl) { + automaticControl.markAsTouched(); + automaticControl.setValue(!automaticControl.value); + } + } + + /** + * Toggles the enabled status of the LDN service by sending a patch request + */ + toggleEnabled() { + const newStatus = !this.formModel.get('enabled').value; + + const patchOperation: Operation = { + op: 'replace', + path: '/enabled', + value: newStatus, + }; + + this.ldnServicesService.patch(this.ldnService, [patchOperation]).pipe( + getFirstCompletedRemoteData() + ).subscribe( + () => { + this.formModel.get('enabled').setValue(newStatus); + this.cdRef.detectChanges(); + } + ); + } + + /** + * Closes the modal + */ + closeModal() { + this.modalRef.close(); + this.cdRef.detectChanges(); + } + + /** + * Opens a confirmation modal with the specified content + * @param content - The content to be displayed in the modal + */ + openConfirmModal(content) { + this.modalRef = this.modalService.open(content); + } + + /** + * Patches the LDN service by retrieving and sending patch operations geenrated in generatePatchOperations() + */ + patchService() { + this.deleteMarkedInboundPatterns(); + + const patchOperations = this.generatePatchOperations(); + this.formModel.markAllAsTouched(); + // If the form is invalid, close the modal and return + if (this.formModel.invalid) { + this.closeModal(); + return; + } + + const notifyServiceInboundPatterns = this.formModel.get('notifyServiceInboundPatterns') as FormArray; + const deletedInboundPatternsLength = this.deletedInboundPatterns.length; + // If no inbound patterns are specified, close the modal and return + // notify the user that no patterns are specified + if (notifyServiceInboundPatterns.length === deletedInboundPatternsLength) { + this.notificationService.warning(this.translateService.get('ldn-service-notification.created.warning.title')); + this.deletedInboundPatterns = []; + this.closeModal(); + return; + } + + this.ldnServicesService.patch(this.ldnService, patchOperations).pipe( + getFirstCompletedRemoteData() + ).subscribe( + (rd: RemoteData) => { + if (rd.hasSucceeded) { + this.closeModal(); + this.sendBack(); + this.notificationService.success(this.translateService.get('admin.registries.services-formats.modify.success.head'), + this.translateService.get('admin.registries.services-formats.modify.success.content')); + } else { + this.notificationService.error(this.translateService.get('admin.registries.services-formats.modify.failure.head'), + this.translateService.get('admin.registries.services-formats.modify.failure.content')); + this.closeModal(); + } + }); + } + + /** + * Resets the form and navigates back to the LDN services page + */ + resetFormAndLeave() { + this.sendBack(); + } + + /** + * Marks the specified inbound pattern for deletion + * @param index - The index of the inbound pattern in the array + */ + markForInboundPatternDeletion(index: number) { + if (!this.markedForDeletionInboundPattern.includes(index)) { + this.markedForDeletionInboundPattern.push(index); + } + } + + /** + * Unmarks the specified inbound pattern for deletion + * @param index - The index of the inbound pattern in the array + */ + unmarkForInboundPatternDeletion(index: number) { + const i = this.markedForDeletionInboundPattern.indexOf(index); + if (i !== -1) { + this.markedForDeletionInboundPattern.splice(i, 1); + } + } + + /** + * Deletes marked inbound patterns from the form model + */ + deleteMarkedInboundPatterns() { + this.markedForDeletionInboundPattern.sort((a, b) => b - a); + const patternsArray = this.formModel.get('notifyServiceInboundPatterns') as FormArray; + + for (const index of this.markedForDeletionInboundPattern) { + if (index >= 0 && index < patternsArray.length) { + const patternGroup = patternsArray.at(index) as FormGroup; + const patternValue = patternGroup.value; + if (patternValue.isNew) { + patternsArray.removeAt(index); + } else { + this.deletedInboundPatterns.push(index); + } + } + } + + this.markedForDeletionInboundPattern = []; + } + + /** + * Creates a replace operation and adds it to the patch operations if the form control is dirty + * @param patchOperations - The array to store patch operations + * @param formControlName - The name of the form control + * @param path - The JSON Patch path for the operation + */ + private createReplaceOperation(patchOperations: any[], formControlName: string, path: string): void { + if (this.formModel.get(formControlName).dirty) { + patchOperations.push({ + op: 'replace', + path, + value: this.formModel.get(formControlName).value.toString(), + }); + } + } + + /** + * Handles patterns in the form array, checking if an add or replace operations is required + * @param patchOperations - The array to store patch operations + * @param formArrayName - The name of the form array + */ + private handlePatterns(patchOperations: any[], formArrayName: string): void { + const patternsArray = this.formModel.get(formArrayName) as FormArray; + + for (let i = 0; i < patternsArray.length; i++) { + const patternGroup = patternsArray.at(i) as FormGroup; + + const patternValue = patternGroup.value; + delete patternValue.constraintFormatted; + if (patternGroup.touched && patternGroup.valid) { + delete patternValue?.patternLabel; + if (patternValue.isNew) { + delete patternValue.isNew; + const addOperation = { + op: 'add', + path: `${formArrayName}/-`, + value: patternValue, + }; + patchOperations.push(addOperation); + } else { + const replaceOperation = { + op: 'replace', + path: `${formArrayName}[${i}]`, + value: patternValue, + }; + patchOperations.push(replaceOperation); + } + } + } + } + + /** + * Navigates back to the LDN services page + */ + private sendBack() { + this.router.navigateByUrl('admin/ldn/services'); + } + + /** + * Creates a form group for inbound patterns + * @returns The form group for inbound patterns + */ + private createInboundPatternFormGroup(): FormGroup { + const inBoundFormGroup = { + pattern: '', + patternLabel: this.translateService.instant(this.selectPatternDefaultLabeli18Key), + constraint: '', + constraintFormatted: '', + automatic: false, + isNew: true + }; + + if (this.isNewService) { + delete inBoundFormGroup.isNew; + } + + return this.formBuilder.group(inBoundFormGroup); + } + + /** + * Initializes an existing form group for inbound patterns + * @returns The initialized form group for inbound patterns + */ + private initializeInboundPatternFormGroup(): FormGroup { + return this.formBuilder.group({ + pattern: '', + patternLabel: '', + constraint: '', + constraintFormatted: '', + automatic: '', + }); + } +} diff --git a/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts b/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts new file mode 100644 index 0000000000..d8534dde03 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-service-serviceMock/ldnServicesRD$-mock.ts @@ -0,0 +1,111 @@ +import {LdnService} from '../ldn-services-model/ldn-services.model'; +import {LDN_SERVICE} from '../ldn-services-model/ldn-service.resource-type'; +import {RemoteData} from '../../../core/data/remote-data'; +import {PaginatedList} from '../../../core/data/paginated-list.model'; +import {Observable, of} from 'rxjs'; +import {createSuccessfulRemoteDataObject$} from '../../../shared/remote-data.utils'; + +export const mockLdnService: LdnService = { + uuid: '1', + enabled: false, + score: 0, + id: 1, + lowerIp: '192.0.2.146', + upperIp: '192.0.2.255', + name: 'Service Name', + description: 'Service Description', + url: 'Service URL', + ldnUrl: 'Service LDN URL', + notifyServiceInboundPatterns: [ + { + pattern: 'patternA', + constraint: 'itemFilterA', + automatic: 'false', + }, + { + pattern: 'patternB', + constraint: 'itemFilterB', + automatic: 'true', + }, + ], + type: LDN_SERVICE, + _links: { + self: { + href: 'http://localhost/api/ldn/ldnservices/1' + }, + }, + get self(): string { + return ''; + }, +}; + +export const mockLdnServiceRD$ = createSuccessfulRemoteDataObject$(mockLdnService); + + +export const mockLdnServices: LdnService[] = [{ + uuid: '1', + enabled: false, + score: 0, + id: 1, + lowerIp: '192.0.2.146', + upperIp: '192.0.2.255', + name: 'Service Name', + description: 'Service Description', + url: 'Service URL', + ldnUrl: 'Service LDN URL', + notifyServiceInboundPatterns: [ + { + pattern: 'patternA', + constraint: 'itemFilterA', + automatic: 'false', + }, + { + pattern: 'patternB', + constraint: 'itemFilterB', + automatic: 'true', + }, + ], + type: LDN_SERVICE, + _links: { + self: { + href: 'http://localhost/api/ldn/ldnservices/1' + }, + }, + get self(): string { + return ''; + }, +}, { + uuid: '2', + enabled: false, + score: 0, + id: 2, + lowerIp: '192.0.2.146', + upperIp: '192.0.2.255', + name: 'Service Name', + description: 'Service Description', + url: 'Service URL', + ldnUrl: 'Service LDN URL', + notifyServiceInboundPatterns: [ + { + pattern: 'patternA', + constraint: 'itemFilterA', + automatic: 'false', + }, + { + pattern: 'patternB', + constraint: 'itemFilterB', + automatic: 'true', + }, + ], + type: LDN_SERVICE, + _links: { + self: { + href: 'http://localhost/api/ldn/ldnservices/1' + }, + }, + get self(): string { + return ''; + }, +} +]; +export const mockLdnServicesRD$: Observable>> = of((mockLdnServices as unknown) as RemoteData>); diff --git a/src/app/admin/admin-ldn-services/ldn-services-data/ldn-itemfilter-data.service.spec.ts b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-itemfilter-data.service.spec.ts new file mode 100644 index 0000000000..b5b0881727 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-itemfilter-data.service.spec.ts @@ -0,0 +1,89 @@ +import { TestScheduler } from 'rxjs/testing'; +import { LdnItemfiltersService } from './ldn-itemfilters-data.service'; +import { RequestService } from '../../../core/data/request.service'; +import { RemoteDataBuildService } from '../../../core/cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../../../core/cache/object-cache.service'; +import { HALEndpointService } from '../../../core/shared/hal-endpoint.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { RequestEntry } from '../../../core/data/request-entry.model'; +import { RemoteData } from '../../../core/data/remote-data'; +import { RequestEntryState } from '../../../core/data/request-entry-state.model'; +import { cold, getTestScheduler } from 'jasmine-marbles'; +import { RestResponse } from '../../../core/cache/response.models'; +import { of } from 'rxjs'; +import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; +import { FindAllData } from '../../../core/data/base/find-all-data'; +import { testFindAllDataImplementation } from '../../../core/data/base/find-all-data.spec'; + +describe('LdnItemfiltersService test', () => { + let scheduler: TestScheduler; + let service: LdnItemfiltersService; + let requestService: RequestService; + let rdbService: RemoteDataBuildService; + let objectCache: ObjectCacheService; + let halService: HALEndpointService; + let notificationsService: NotificationsService; + let responseCacheEntry: RequestEntry; + + const endpointURL = `https://rest.api/rest/api/ldn/itemfilters`; + const requestUUID = '8b3c613a-5a4b-438b-9686-be1d5b4a1c5a'; + + const remoteDataMocks = { + Success: new RemoteData(null, null, null, RequestEntryState.Success, null, null, 200), + }; + + function initTestService() { + return new LdnItemfiltersService( + requestService, + rdbService, + objectCache, + halService, + notificationsService, + ); + } + + beforeEach(() => { + scheduler = getTestScheduler(); + + objectCache = {} as ObjectCacheService; + notificationsService = {} as NotificationsService; + responseCacheEntry = new RequestEntry(); + responseCacheEntry.request = { href: 'https://rest.api/' } as any; + responseCacheEntry.response = new RestResponse(true, 200, 'Success'); + + requestService = jasmine.createSpyObj('requestService', { + generateRequestId: requestUUID, + send: true, + removeByHrefSubstring: {}, + getByHref: of(responseCacheEntry), + getByUUID: of(responseCacheEntry), + }); + + halService = jasmine.createSpyObj('halService', { + getEndpoint: of(endpointURL) + }); + + rdbService = jasmine.createSpyObj('rdbService', { + buildSingle: createSuccessfulRemoteDataObject$({}, 500), + buildList: cold('a', { a: remoteDataMocks.Success }) + }); + + + service = initTestService(); + }); + + describe('composition', () => { + const initFindAllService = () => new LdnItemfiltersService(null, null, null, null, null) as unknown as FindAllData; + testFindAllDataImplementation(initFindAllService); + }); + + describe('get endpoint', () => { + it('should retrieve correct endpoint', (done) => { + service.getEndpoint().subscribe(() => { + expect(halService.getEndpoint).toHaveBeenCalledWith('itemfilters'); + done(); + }); + }); + }); + +}); diff --git a/src/app/admin/admin-ldn-services/ldn-services-data/ldn-itemfilters-data.service.ts b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-itemfilters-data.service.ts new file mode 100644 index 0000000000..15a7bcccda --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-itemfilters-data.service.ts @@ -0,0 +1,61 @@ +import {Injectable} from '@angular/core'; +import {dataService} from '../../../core/data/base/data-service.decorator'; +import {LDN_SERVICE_CONSTRAINT_FILTERS} from '../ldn-services-model/ldn-service.resource-type'; +import {IdentifiableDataService} from '../../../core/data/base/identifiable-data.service'; +import {FindAllData, FindAllDataImpl} from '../../../core/data/base/find-all-data'; + +import {RequestService} from '../../../core/data/request.service'; +import {RemoteDataBuildService} from '../../../core/cache/builders/remote-data-build.service'; +import {ObjectCacheService} from '../../../core/cache/object-cache.service'; +import {HALEndpointService} from '../../../core/shared/hal-endpoint.service'; +import {NotificationsService} from '../../../shared/notifications/notifications.service'; +import {FindListOptions} from '../../../core/data/find-list-options.model'; +import {FollowLinkConfig} from '../../../shared/utils/follow-link-config.model'; +import {Observable} from 'rxjs'; +import {RemoteData} from '../../../core/data/remote-data'; +import {Itemfilter} from '../ldn-services-model/ldn-service-itemfilters'; +import {PaginatedList} from '../../../core/data/paginated-list.model'; + + +/** + * A service responsible for fetching/sending data from/to the REST API on the itemfilters endpoint + */ +@Injectable() +@dataService(LDN_SERVICE_CONSTRAINT_FILTERS) +export class LdnItemfiltersService extends IdentifiableDataService implements FindAllData { + private findAllData: FindAllDataImpl; + + constructor( + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected notificationsService: NotificationsService, + ) { + super('itemfilters', requestService, rdbService, objectCache, halService); + + this.findAllData = new FindAllDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive); + } + + /** + * Gets the endpoint URL for the itemfilters. + * + * @returns {string} - The endpoint URL. + */ + getEndpoint() { + return this.halService.getEndpoint(this.linkPath); + } + + /** + * Finds all itemfilters based on the provided options and link configurations. + * + * @param {FindListOptions} options - The options for finding a list of itemfilters. + * @param {boolean} useCachedVersionIfAvailable - Whether to use the cached version if available. + * @param {boolean} reRequestOnStale - Whether to re-request the data if it's stale. + * @param {...FollowLinkConfig[]} linksToFollow - Configurations for following specific links. + * @returns {Observable>>} - An observable of remote data containing a paginated list of itemfilters. + */ + findAll(options?: FindListOptions, useCachedVersionIfAvailable?: boolean, reRequestOnStale?: boolean, ...linksToFollow: FollowLinkConfig[]): Observable>> { + return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + } +} diff --git a/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.spec.ts b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.spec.ts new file mode 100644 index 0000000000..9d17fc244c --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.spec.ts @@ -0,0 +1,116 @@ +import { TestScheduler } from 'rxjs/testing'; +import { RequestService } from '../../../core/data/request.service'; +import { RemoteDataBuildService } from '../../../core/cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../../../core/cache/object-cache.service'; +import { HALEndpointService } from '../../../core/shared/hal-endpoint.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { RequestEntry } from '../../../core/data/request-entry.model'; +import { RemoteData } from '../../../core/data/remote-data'; +import { RequestEntryState } from '../../../core/data/request-entry-state.model'; +import { cold, getTestScheduler } from 'jasmine-marbles'; +import { RestResponse } from '../../../core/cache/response.models'; +import { of as observableOf } from 'rxjs'; +import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; +import { FindAllData } from '../../../core/data/base/find-all-data'; +import { testFindAllDataImplementation } from '../../../core/data/base/find-all-data.spec'; +import { LdnServicesService } from './ldn-services-data.service'; +import { testDeleteDataImplementation } from '../../../core/data/base/delete-data.spec'; +import { DeleteData } from '../../../core/data/base/delete-data'; +import { testSearchDataImplementation } from '../../../core/data/base/search-data.spec'; +import { SearchData } from '../../../core/data/base/search-data'; +import { testPatchDataImplementation } from '../../../core/data/base/patch-data.spec'; +import { PatchData } from '../../../core/data/base/patch-data'; +import { CreateData } from '../../../core/data/base/create-data'; +import { testCreateDataImplementation } from '../../../core/data/base/create-data.spec'; +import { FindListOptions } from '../../../core/data/find-list-options.model'; +import { RequestParam } from '../../../core/cache/models/request-param.model'; +import { mockLdnService } from '../ldn-service-serviceMock/ldnServicesRD$-mock'; +import { createPaginatedList } from '../../../shared/testing/utils.test'; + + +describe('LdnServicesService test', () => { + let scheduler: TestScheduler; + let service: LdnServicesService; + let requestService: RequestService; + let rdbService: RemoteDataBuildService; + let objectCache: ObjectCacheService; + let halService: HALEndpointService; + let notificationsService: NotificationsService; + let responseCacheEntry: RequestEntry; + + const endpointURL = `https://rest.api/rest/api/ldn/ldnservices`; + const requestUUID = '8b3c613a-5a4b-438b-9686-be1d5b4a1c5a'; + + const remoteDataMocks = { + Success: new RemoteData(null, null, null, RequestEntryState.Success, null, null, 200), + }; + + function initTestService() { + return new LdnServicesService( + requestService, + rdbService, + objectCache, + halService, + notificationsService, + ); + } + + beforeEach(() => { + scheduler = getTestScheduler(); + + objectCache = {} as ObjectCacheService; + notificationsService = {} as NotificationsService; + responseCacheEntry = new RequestEntry(); + responseCacheEntry.request = { href: 'https://rest.api/' } as any; + responseCacheEntry.response = new RestResponse(true, 200, 'Success'); + + requestService = jasmine.createSpyObj('requestService', { + generateRequestId: requestUUID, + send: true, + removeByHrefSubstring: {}, + getByHref: observableOf(responseCacheEntry), + getByUUID: observableOf(responseCacheEntry), + }); + + halService = jasmine.createSpyObj('halService', { + getEndpoint: observableOf(endpointURL) + }); + + rdbService = jasmine.createSpyObj('rdbService', { + buildSingle: createSuccessfulRemoteDataObject$({}, 500), + buildList: cold('a', { a: remoteDataMocks.Success }) + }); + + + service = initTestService(); + }); + + describe('composition', () => { + const initFindAllService = () => new LdnServicesService(null, null, null, null, null) as unknown as FindAllData; + const initDeleteService = () => new LdnServicesService(null, null, null, null, null) as unknown as DeleteData; + const initSearchService = () => new LdnServicesService(null, null, null, null, null) as unknown as SearchData; + const initPatchService = () => new LdnServicesService(null, null, null, null, null) as unknown as PatchData; + const initCreateService = () => new LdnServicesService(null, null, null, null, null) as unknown as CreateData; + + testFindAllDataImplementation(initFindAllService); + testDeleteDataImplementation(initDeleteService); + testSearchDataImplementation(initSearchService); + testPatchDataImplementation(initPatchService); + testCreateDataImplementation(initCreateService); + }); + + describe('custom methods', () => { + it('should find service by inbound pattern', (done) => { + const params = [new RequestParam('pattern', 'testPattern')]; + const findListOptions = Object.assign(new FindListOptions(), {}, {searchParams: params}); + spyOn(service, 'searchBy').and.returnValue(observableOf(null)); + spyOn((service as any).searchData, 'searchBy').and.returnValue(createSuccessfulRemoteDataObject$(createPaginatedList([mockLdnService]))); + + service.findByInboundPattern('testPattern').subscribe(() => { + expect(service.searchBy).toHaveBeenCalledWith('byInboundPattern', findListOptions, undefined, undefined ); + done(); + }); + }); + }); + +}); diff --git a/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts new file mode 100644 index 0000000000..d1541e6bd8 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service.ts @@ -0,0 +1,217 @@ +import {Injectable} from '@angular/core'; +import {dataService} from '../../../core/data/base/data-service.decorator'; +import {LDN_SERVICE} from '../ldn-services-model/ldn-service.resource-type'; +import {IdentifiableDataService} from '../../../core/data/base/identifiable-data.service'; +import {FindAllData, FindAllDataImpl} from '../../../core/data/base/find-all-data'; +import {DeleteData, DeleteDataImpl} from '../../../core/data/base/delete-data'; +import {RequestService} from '../../../core/data/request.service'; +import {RemoteDataBuildService} from '../../../core/cache/builders/remote-data-build.service'; +import {ObjectCacheService} from '../../../core/cache/object-cache.service'; +import {HALEndpointService} from '../../../core/shared/hal-endpoint.service'; +import {NotificationsService} from '../../../shared/notifications/notifications.service'; +import {FindListOptions} from '../../../core/data/find-list-options.model'; +import {FollowLinkConfig} from '../../../shared/utils/follow-link-config.model'; +import {Observable} from 'rxjs'; +import {RemoteData} from '../../../core/data/remote-data'; +import {PaginatedList} from '../../../core/data/paginated-list.model'; +import {NoContent} from '../../../core/shared/NoContent.model'; +import {map, take} from 'rxjs/operators'; +import {URLCombiner} from '../../../core/url-combiner/url-combiner'; +import {MultipartPostRequest} from '../../../core/data/request.models'; +import {RestRequest} from '../../../core/data/rest-request.model'; + + +import {LdnService} from '../ldn-services-model/ldn-services.model'; + +import {PatchData, PatchDataImpl} from '../../../core/data/base/patch-data'; +import {ChangeAnalyzer} from '../../../core/data/change-analyzer'; +import {Operation} from 'fast-json-patch'; +import {RestRequestMethod} from '../../../core/data/rest-request-method'; +import {CreateData, CreateDataImpl} from '../../../core/data/base/create-data'; +import {LdnServiceConstrain} from '../ldn-services-model/ldn-service.constrain.model'; +import {SearchDataImpl} from '../../../core/data/base/search-data'; +import {RequestParam} from '../../../core/cache/models/request-param.model'; + +/** + * Injectable service responsible for fetching/sending data from/to the REST API on the ldnservices endpoint. + * + * @export + * @class LdnServicesService + * @extends {IdentifiableDataService} + * @implements {FindAllData} + * @implements {DeleteData} + * @implements {PatchData} + * @implements {CreateData} + */ +@Injectable() +@dataService(LDN_SERVICE) +export class LdnServicesService extends IdentifiableDataService implements FindAllData, DeleteData, PatchData, CreateData { + createData: CreateDataImpl; + private findAllData: FindAllDataImpl; + private deleteData: DeleteDataImpl; + private patchData: PatchDataImpl; + private comparator: ChangeAnalyzer; + private searchData: SearchDataImpl; + + private findByPatternEndpoint = 'byInboundPattern'; + + constructor( + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected notificationsService: NotificationsService, + ) { + super('ldnservices', requestService, rdbService, objectCache, halService); + + this.findAllData = new FindAllDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive); + this.searchData = new SearchDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive); + this.deleteData = new DeleteDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, notificationsService, this.responseMsToLive, this.constructIdEndpoint); + this.patchData = new PatchDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.comparator, this.responseMsToLive, this.constructIdEndpoint); + this.createData = new CreateDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, notificationsService, this.responseMsToLive); + } + + /** + * Creates an LDN service by sending a POST request to the REST API. + * + * @param {LdnService} object - The LDN service object to be created. + * @param params Array with additional params to combine with query string + * @returns {Observable>} - Observable containing the result of the creation operation. + */ + create(object: LdnService, ...params: RequestParam[]): Observable> { + return this.createData.create(object, ...params); + } + + /** + * Updates an LDN service by applying a set of operations through a PATCH request to the REST API. + * + * @param {LdnService} object - The LDN service object to be updated. + * @param {Operation[]} operations - The patch operations to be applied. + * @returns {Observable>} - Observable containing the result of the update operation. + */ + patch(object: LdnService, operations: Operation[]): Observable> { + return this.patchData.patch(object, operations); + } + + /** + * Updates an LDN service by sending a PUT request to the REST API. + * + * @param {LdnService} object - The LDN service object to be updated. + * @returns {Observable>} - Observable containing the result of the update operation. + */ + update(object: LdnService): Observable> { + return this.patchData.update(object); + } + + /** + * Commits pending updates by sending a PATCH request to the REST API. + * + * @param {RestRequestMethod} [method] - The HTTP method to be used for the request. + */ + commitUpdates(method?: RestRequestMethod): void { + return this.patchData.commitUpdates(method); + } + + /** + * Creates a patch representing the changes made to the LDN service in the cache. + * + * @param {LdnService} object - The LDN service object for which to create the patch. + * @returns {Observable} - Observable containing the patch operations. + */ + createPatchFromCache(object: LdnService): Observable { + return this.patchData.createPatchFromCache(object); + } + + /** + * Retrieves all LDN services from the REST API based on the provided options. + * + * @param {FindListOptions} [options] - The options to be applied to the request. + * @param {boolean} [useCachedVersionIfAvailable] - Flag indicating whether to use cached data if available. + * @param {boolean} [reRequestOnStale] - Flag indicating whether to re-request data if it's stale. + * @param {...FollowLinkConfig[]} linksToFollow - Optional links to follow during the request. + * @returns {Observable>>} - Observable containing the result of the request. + */ + findAll(options?: FindListOptions, useCachedVersionIfAvailable?: boolean, reRequestOnStale?: boolean, ...linksToFollow: FollowLinkConfig[]): Observable>> { + return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + } + + /** + * Retrieves LDN services based on the inbound pattern from the REST API. + * + * @param {string} pattern - The inbound pattern to be used in the search. + * @param {FindListOptions} [options] - The options to be applied to the request. + * @param {boolean} [useCachedVersionIfAvailable] - Flag indicating whether to use cached data if available. + * @param {boolean} [reRequestOnStale] - Flag indicating whether to re-request data if it's stale. + * @param {...FollowLinkConfig[]} linksToFollow - Optional links to follow during the request. + * @returns {Observable>>} - Observable containing the result of the request. + */ + findByInboundPattern(pattern: string, options?: FindListOptions, useCachedVersionIfAvailable?: boolean, reRequestOnStale?: boolean, ...linksToFollow: FollowLinkConfig[]): Observable>> { + const params = [new RequestParam('pattern', pattern)]; + const findListOptions = Object.assign(new FindListOptions(), options, {searchParams: params}); + return this.searchBy(this.findByPatternEndpoint, findListOptions, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + } + + /** + * Deletes an LDN service by sending a DELETE request to the REST API. + * + * @param {string} objectId - The ID of the LDN service to be deleted. + * @param {string[]} [copyVirtualMetadata] - Optional virtual metadata to be copied during the deletion. + * @returns {Observable>} - Observable containing the result of the deletion operation. + */ + public delete(objectId: string, copyVirtualMetadata?: string[]): Observable> { + return this.deleteData.delete(objectId, copyVirtualMetadata); + } + + /** + * Deletes an LDN service by its HATEOAS link. + * + * @param {string} href - The HATEOAS link of the LDN service to be deleted. + * @param {string[]} [copyVirtualMetadata] - Optional virtual metadata to be copied during the deletion. + * @returns {Observable>} - Observable containing the result of the deletion operation. + */ + public deleteByHref(href: string, copyVirtualMetadata?: string[]): Observable> { + return this.deleteData.deleteByHref(href, copyVirtualMetadata); + } + + + /** + * Make a new FindListRequest with given search method + * + * @param searchMethod The search method for the object + * @param options The [[FindListOptions]] object + * @param useCachedVersionIfAvailable If this is true, the request will only be sent if there's + * no valid cached version. Defaults to true + * @param reRequestOnStale Whether or not the request should automatically be re- + * requested after the response becomes stale + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which + * {@link HALLink}s should be automatically resolved + * @return {Observable>} + * Return an observable that emits response from the server + */ + public searchBy(searchMethod: string, options?: FindListOptions, useCachedVersionIfAvailable?: boolean, reRequestOnStale?: boolean, ...linksToFollow: FollowLinkConfig[]): Observable>> { + return this.searchData.searchBy(searchMethod, options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + } + + public invoke(serviceName: string, serviceId: string, parameters: LdnServiceConstrain[], files: File[]): Observable> { + const requestId = this.requestService.generateRequestId(); + this.getBrowseEndpoint().pipe( + take(1), + map((endpoint: string) => new URLCombiner(endpoint, serviceName, 'processes', serviceId).toString()), + map((endpoint: string) => { + const body = this.getInvocationFormData(parameters, files); + return new MultipartPostRequest(requestId, endpoint, body); + }) + ).subscribe((request: RestRequest) => this.requestService.send(request)); + + return this.rdbService.buildFromRequestUUID(requestId); + } + + private getInvocationFormData(constrain: LdnServiceConstrain[], files: File[]): FormData { + const form: FormData = new FormData(); + form.set('properties', JSON.stringify(constrain)); + files.forEach((file: File) => { + form.append('file', file); + }); + return form; + } +} diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html new file mode 100644 index 0000000000..0aaa39bda2 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.html @@ -0,0 +1,99 @@ +
+
+

{{ 'ldn-registered-services.title' | translate }}

+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + +
{{ 'service.overview.table.name' | translate }}{{ 'service.overview.table.description' | translate }}{{ 'service.overview.table.status' | translate }}{{ 'service.overview.table.actions' | translate }}
{{ ldnService.name }} + + +
+ {{ ldnService.description }} +
+
+
+
+ + {{ ldnService.enabled ? ('ldn-service.overview.table.enabled' | translate) : ('ldn-service.overview.table.disabled' | translate) }} + + +
+ + +
+
+
+
+
+ + + +
+ + + + +
+
+ diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.scss b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.scss new file mode 100644 index 0000000000..07377d63d5 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.scss @@ -0,0 +1,29 @@ +.status-indicator { + padding: 2.5px 25px 2.5px 25px; + border-radius: 4px; + cursor: pointer; + transition: background-color 0.5s; +} + +.status-enabled { + background-color: #daf7a6; + color: #4f5359; + font-size: 85%; + font-weight: bold; + +} + +.status-enabled:hover { + background-color: #faa0a0; +} + +.status-disabled { + background-color: #faa0a0; + color: #4f5359; + font-size: 85%; + font-weight: bold; +} + +.status-disabled:hover { + background-color: #daf7a6; +} diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts new file mode 100644 index 0000000000..664edcb27d --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts @@ -0,0 +1,144 @@ +import {ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing'; +import {ChangeDetectorRef, EventEmitter} from '@angular/core'; +import {NotificationsService} from '../../../shared/notifications/notifications.service'; +import {NotificationsServiceStub} from '../../../shared/testing/notifications-service.stub'; +import {TranslateModule, TranslateService} from '@ngx-translate/core'; +import {NgbModal} from '@ng-bootstrap/ng-bootstrap'; +import {LdnServicesService} from '../ldn-services-data/ldn-services-data.service'; +import {PaginationService} from '../../../core/pagination/pagination.service'; +import {PaginationServiceStub} from '../../../shared/testing/pagination-service.stub'; +import {of} from 'rxjs'; +import {LdnService} from '../ldn-services-model/ldn-services.model'; +import {PaginatedList} from '../../../core/data/paginated-list.model'; +import {RemoteData} from '../../../core/data/remote-data'; +import {LdnServicesOverviewComponent} from './ldn-services-directory.component'; +import {createSuccessfulRemoteDataObject$} from '../../../shared/remote-data.utils'; +import {createPaginatedList} from '../../../shared/testing/utils.test'; + +describe('LdnServicesOverviewComponent', () => { + let component: LdnServicesOverviewComponent; + let fixture: ComponentFixture; + let ldnServicesService; + let paginationService; + let modalService: NgbModal; + let notificationsService: NotificationsService; + let translateService: TranslateService; + + const translateServiceStub = { + get: () => of('translated-text'), + onLangChange: new EventEmitter(), + onTranslationChange: new EventEmitter(), + onDefaultLangChange: new EventEmitter() + }; + + beforeEach(async () => { + paginationService = new PaginationServiceStub(); + ldnServicesService = jasmine.createSpyObj('LdnServicesService', ['findAll', 'delete', 'patch']); + await TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + declarations: [LdnServicesOverviewComponent], + providers: [ + { + provide: LdnServicesService, + useValue: ldnServicesService + }, + {provide: PaginationService, useValue: paginationService}, + { + provide: NgbModal, useValue: { + open: () => { /*comment*/ + } + } + }, + {provide: ChangeDetectorRef, useValue: {}}, + {provide: NotificationsService, useValue: NotificationsServiceStub}, + {provide: TranslateService, useValue: translateServiceStub}, + ] + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(LdnServicesOverviewComponent); + component = fixture.componentInstance; + ldnServicesService = TestBed.inject(LdnServicesService); + paginationService = TestBed.inject(PaginationService); + modalService = TestBed.inject(NgbModal); + notificationsService = TestBed.inject(NotificationsService); + translateService = TestBed.inject(TranslateService); + component.modalRef = jasmine.createSpyObj({close: null}); + component.isProcessingSub = jasmine.createSpyObj({unsubscribe: null}); + component.ldnServicesRD$ = of({} as RemoteData>); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnInit', () => { + it('should call setLdnServices', fakeAsync(() => { + spyOn(component, 'setLdnServices').and.callThrough(); + component.ngOnInit(); + tick(); + expect(component.setLdnServices).toHaveBeenCalled(); + })); + + it('should set ldnServicesRD$ with mock data', fakeAsync(() => { + spyOn(component, 'setLdnServices').and.callThrough(); + const testData: LdnService[] = Object.assign([new LdnService()], [ + {id: 1, name: 'Service 1', description: 'Description 1', enabled: true}, + {id: 2, name: 'Service 2', description: 'Description 2', enabled: false}, + {id: 3, name: 'Service 3', description: 'Description 3', enabled: true}]); + + const mockLdnServicesRD = createPaginatedList(testData); + component.ldnServicesRD$ = createSuccessfulRemoteDataObject$(mockLdnServicesRD); + fixture.detectChanges(); + + const tableRows = fixture.debugElement.nativeElement.querySelectorAll('tbody tr'); + expect(tableRows.length).toBe(testData.length); + const firstRowContent = tableRows[0].textContent; + expect(firstRowContent).toContain('Service 1'); + expect(firstRowContent).toContain('Description 1'); + })); + }); + + describe('ngOnDestroy', () => { + it('should call paginationService.clearPagination and unsubscribe', () => { + // spyOn(paginationService, 'clearPagination'); + // spyOn(component.isProcessingSub, 'unsubscribe'); + component.ngOnDestroy(); + expect(paginationService.clearPagination).toHaveBeenCalledWith(component.pageConfig.id); + expect(component.isProcessingSub.unsubscribe).toHaveBeenCalled(); + }); + }); + + describe('openDeleteModal', () => { + it('should open delete modal', () => { + spyOn(modalService, 'open'); + component.openDeleteModal(component.deleteModal); + expect(modalService.open).toHaveBeenCalledWith(component.deleteModal); + }); + }); + + describe('closeModal', () => { + it('should close modal and detect changes', () => { + // spyOn(component.modalRef, 'close'); + spyOn(component.cdRef, 'detectChanges'); + component.closeModal(); + expect(component.modalRef.close).toHaveBeenCalled(); + expect(component.cdRef.detectChanges).toHaveBeenCalled(); + }); + }); + + describe('deleteSelected', () => { + it('should delete selected service and update data', fakeAsync(() => { + const serviceId = '123'; + const mockRemoteData = { /* just an empty object to retrieve as as RemoteData> */}; + spyOn(component, 'setLdnServices').and.callThrough(); + const deleteSpy = ldnServicesService.delete.and.returnValue(of(mockRemoteData as RemoteData>)); + component.selectedServiceId = serviceId; + component.deleteSelected(serviceId, ldnServicesService); + tick(); + expect(deleteSpy).toHaveBeenCalledWith(serviceId); + })); + }); +}); diff --git a/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts new file mode 100644 index 0000000000..b36d102cb0 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts @@ -0,0 +1,176 @@ +import { + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + OnDestroy, + OnInit, + TemplateRef, + ViewChild +} from '@angular/core'; +import {Observable, Subscription} from 'rxjs'; +import {RemoteData} from '../../../core/data/remote-data'; +import {PaginatedList} from '../../../core/data/paginated-list.model'; +import {FindListOptions} from '../../../core/data/find-list-options.model'; +import {LdnService} from '../ldn-services-model/ldn-services.model'; +import {PaginationComponentOptions} from '../../../shared/pagination/pagination-component-options.model'; +import {map, switchMap} from 'rxjs/operators'; +import {LdnServicesService} from 'src/app/admin/admin-ldn-services/ldn-services-data/ldn-services-data.service'; +import {PaginationService} from 'src/app/core/pagination/pagination.service'; +import {NgbModal} from '@ng-bootstrap/ng-bootstrap'; +import {hasValue} from '../../../shared/empty.util'; +import {Operation} from 'fast-json-patch'; +import {getFirstCompletedRemoteData} from '../../../core/shared/operators'; +import {NotificationsService} from '../../../shared/notifications/notifications.service'; +import {TranslateService} from '@ngx-translate/core'; + + +/** + * The `LdnServicesOverviewComponent` is a component that provides an overview of LDN (Linked Data Notifications) services. + * It displays a paginated list of LDN services, allows users to edit and delete services, + * toggle the status of each service directly form the page and allows for creation of new services redirecting the user on the creation/edit form + */ +@Component({ + selector: 'ds-ldn-services-directory', + templateUrl: './ldn-services-directory.component.html', + styleUrls: ['./ldn-services-directory.component.scss'], + changeDetection: ChangeDetectionStrategy.Default +}) +export class LdnServicesOverviewComponent implements OnInit, OnDestroy { + + selectedServiceId: string | number | null = null; + servicesData: any[] = []; + @ViewChild('deleteModal', {static: true}) deleteModal: TemplateRef; + ldnServicesRD$: Observable>>; + config: FindListOptions = Object.assign(new FindListOptions(), { + elementsPerPage: 10 + }); + pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { + id: 'po', + pageSize: 10 + }); + isProcessingSub: Subscription; + modalRef: any; + + + constructor( + protected ldnServicesService: LdnServicesService, + protected paginationService: PaginationService, + protected modalService: NgbModal, + public cdRef: ChangeDetectorRef, + private notificationService: NotificationsService, + private translateService: TranslateService, + ) { + } + + ngOnInit(): void { + this.setLdnServices(); + } + + /** + * Sets up the LDN services by fetching and observing the paginated list of services. + */ + setLdnServices() { + this.ldnServicesRD$ = this.paginationService.getFindListOptions(this.pageConfig.id, this.config).pipe( + switchMap((config) => this.ldnServicesService.findAll(config, false, false).pipe( + getFirstCompletedRemoteData() + )) + ); + } + + ngOnDestroy(): void { + this.paginationService.clearPagination(this.pageConfig.id); + if (hasValue(this.isProcessingSub)) { + this.isProcessingSub.unsubscribe(); + } + } + + /** + * Opens the delete confirmation modal. + * + * @param {any} content - The content of the modal. + */ + openDeleteModal(content) { + this.modalRef = this.modalService.open(content); + } + + /** + * Closes the currently open modal and triggers change detection. + */ + closeModal() { + this.modalRef.close(); + this.cdRef.detectChanges(); + } + + /** + * Sets the selected LDN service ID for deletion and opens the delete confirmation modal. + * + * @param {number} serviceId - The ID of the service to be deleted. + */ + selectServiceToDelete(serviceId: number) { + this.selectedServiceId = serviceId; + this.openDeleteModal(this.deleteModal); + } + + /** + * Deletes the selected LDN service. + * + * @param {string} serviceId - The ID of the service to be deleted. + * @param {LdnServicesService} ldnServicesService - The service for managing LDN services. + */ + deleteSelected(serviceId: string, ldnServicesService: LdnServicesService): void { + if (this.selectedServiceId !== null) { + ldnServicesService.delete(serviceId).pipe(getFirstCompletedRemoteData()).subscribe((rd: RemoteData) => { + if (rd.hasSucceeded) { + this.servicesData = this.servicesData.filter(service => service.id !== serviceId); + this.ldnServicesRD$ = this.ldnServicesRD$.pipe( + map((remoteData: RemoteData>) => { + if (remoteData.hasSucceeded) { + remoteData.payload.page = remoteData.payload.page.filter(service => service.id.toString() !== serviceId); + } + return remoteData; + }) + ); + this.cdRef.detectChanges(); + this.closeModal(); + this.notificationService.success(this.translateService.get('ldn-service-delete.notification.success.title'), + this.translateService.get('ldn-service-delete.notification.success.content')); + } else { + this.notificationService.error(this.translateService.get('ldn-service-delete.notification.error.title'), + this.translateService.get('ldn-service-delete.notification.error.content')); + this.cdRef.detectChanges(); + } + }); + } + } + + /** + * Toggles the status (enabled/disabled) of an LDN service. + * + * @param {any} ldnService - The LDN service object. + * @param {LdnServicesService} ldnServicesService - The service for managing LDN services. + */ + toggleStatus(ldnService: any, ldnServicesService: LdnServicesService): void { + const newStatus = !ldnService.enabled; + const originalStatus = ldnService.enabled; + + const patchOperation: Operation = { + op: 'replace', + path: '/enabled', + value: newStatus, + }; + + ldnServicesService.patch(ldnService, [patchOperation]).pipe(getFirstCompletedRemoteData()).subscribe( + (rd: RemoteData) => { + if (rd.hasSucceeded) { + ldnService.enabled = newStatus; + this.notificationService.success(this.translateService.get('ldn-enable-service.notification.success.title'), + this.translateService.get('ldn-enable-service.notification.success.content')); + } else { + ldnService.enabled = originalStatus; + this.notificationService.error(this.translateService.get('ldn-enable-service.notification.error.title'), + this.translateService.get('ldn-enable-service.notification.error.content')); + } + } + ); + } +} diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-itemfilters.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-itemfilters.ts new file mode 100644 index 0000000000..55b7ad8b98 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-itemfilters.ts @@ -0,0 +1,31 @@ +import {autoserialize, deserialize, inheritSerialization} from 'cerialize'; +import {LDN_SERVICE_CONSTRAINT_FILTER} from './ldn-service.resource-type'; +import {CacheableObject} from '../../../core/cache/cacheable-object.model'; +import {typedObject} from '../../../core/cache/builders/build-decorators'; +import {excludeFromEquals} from '../../../core/utilities/equals.decorators'; +import {ResourceType} from '../../../core/shared/resource-type'; + +/** A single filter value and its properties. */ +@typedObject +@inheritSerialization(CacheableObject) +export class Itemfilter extends CacheableObject { + static type = LDN_SERVICE_CONSTRAINT_FILTER; + + @excludeFromEquals + @autoserialize + type: ResourceType; + + @autoserialize + id: string; + + @deserialize + _links: { + self: { + href: string; + }; + }; + + get self(): string { + return this._links.self.href; + } +} diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-patterns.model.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-patterns.model.ts new file mode 100644 index 0000000000..295426ba87 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-patterns.model.ts @@ -0,0 +1,13 @@ +import {autoserialize} from 'cerialize'; + +/** + * A single notify service pattern and his properties + */ +export class NotifyServicePattern { + @autoserialize + pattern: string; + @autoserialize + constraint: string; + @autoserialize + automatic: string; +} diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-status.model.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-status.model.ts new file mode 100644 index 0000000000..040e4d37b8 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service-status.model.ts @@ -0,0 +1,8 @@ +/** + * List of services statuses + */ +export enum LdnServiceStatus { + UNKOWN, + DISABLED, + ENABLED, +} diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.constrain.model.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.constrain.model.ts new file mode 100644 index 0000000000..5121e47f69 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.constrain.model.ts @@ -0,0 +1,3 @@ +export class LdnServiceConstrain { + void: any; +} diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts new file mode 100644 index 0000000000..4fb510c032 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-service.resource-type.ts @@ -0,0 +1,12 @@ +/** + * The resource type for Ldn-Services + * + * Needs to be in a separate file to prevent circular + * dependencies in webpack. + */ +import {ResourceType} from '../../../core/shared/resource-type'; + +export const LDN_SERVICE = new ResourceType('ldnservice'); +export const LDN_SERVICE_CONSTRAINT_FILTERS = new ResourceType('itemfilters'); + +export const LDN_SERVICE_CONSTRAINT_FILTER = new ResourceType('itemfilter'); diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/ldn-services.model.ts b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-services.model.ts new file mode 100644 index 0000000000..9e803fbc01 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-model/ldn-services.model.ts @@ -0,0 +1,72 @@ +import {ResourceType} from '../../../core/shared/resource-type'; +import {CacheableObject} from '../../../core/cache/cacheable-object.model'; +import {autoserialize, deserialize, deserializeAs, inheritSerialization} from 'cerialize'; +import {LDN_SERVICE} from './ldn-service.resource-type'; +import {excludeFromEquals} from '../../../core/utilities/equals.decorators'; +import {typedObject} from '../../../core/cache/builders/build-decorators'; +import {NotifyServicePattern} from './ldn-service-patterns.model'; + + +/** + * LDN Services bounded to each selected pattern, relation set in service creation + */ + +export interface LdnServiceByPattern { + allowsMultipleRequests: boolean; + services: LdnService[]; +} + +/** An LdnService and its properties. */ +@typedObject +@inheritSerialization(CacheableObject) +export class LdnService extends CacheableObject { + static type = LDN_SERVICE; + + @excludeFromEquals + @autoserialize + type: ResourceType; + + @autoserialize + id: number; + + @deserializeAs('id') + uuid: string; + + @autoserialize + name: string; + + @autoserialize + description: string; + + @autoserialize + url: string; + + @autoserialize + score: number; + + @autoserialize + enabled: boolean; + + @autoserialize + ldnUrl: string; + + @autoserialize + lowerIp: string; + + @autoserialize + upperIp: string; + + @autoserialize + notifyServiceInboundPatterns?: NotifyServicePattern[]; + + @deserialize + _links: { + self: { + href: string; + }; + }; + + get self(): string { + return this._links.self.href; + } +} diff --git a/src/app/admin/admin-ldn-services/ldn-services-model/service-constrain-type.model.ts b/src/app/admin/admin-ldn-services/ldn-services-model/service-constrain-type.model.ts new file mode 100644 index 0000000000..c734503d95 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-model/service-constrain-type.model.ts @@ -0,0 +1,10 @@ +/** + * List of parameter types used for scripts + */ +export enum LdnServiceConstrainType { + STRING = 'String', + DATE = 'date', + BOOLEAN = 'boolean', + FILE = 'InputStream', + OUTPUT = 'OutputStream' +} diff --git a/src/app/admin/admin-ldn-services/ldn-services-patterns/ldn-service-coar-patterns.ts b/src/app/admin/admin-ldn-services/ldn-services-patterns/ldn-service-coar-patterns.ts new file mode 100644 index 0000000000..faa7dc82d7 --- /dev/null +++ b/src/app/admin/admin-ldn-services/ldn-services-patterns/ldn-service-coar-patterns.ts @@ -0,0 +1,16 @@ +/** + * All available patterns for LDN service creation. + * They are used to populate a dropdown in the LDN service form creation + */ + +export const notifyPatterns = [ + + 'request-endorsement', + + 'request-ingest', + + 'request-review', + +]; + + diff --git a/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page-resolver.service.ts b/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page-resolver.service.ts index add9a504dd..f524cd56c2 100644 --- a/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page-resolver.service.ts +++ b/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page-resolver.service.ts @@ -4,7 +4,7 @@ import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/r /** * Interface for the route parameters. */ -export interface AdminNotificationsPublicationClaimPageParams { +export interface NotificationsSuggestionTargetsPageParams { pageId?: string; pageSize?: number; currentPage?: number; @@ -14,7 +14,7 @@ export interface AdminNotificationsPublicationClaimPageParams { * This class represents a resolver that retrieve the route data before the route is activated. */ @Injectable() -export class AdminNotificationsPublicationClaimPageResolver implements Resolve { +export class NotificationsSuggestionTargetsPageResolver implements Resolve { /** * Method for resolving the parameters in the current route. @@ -22,7 +22,7 @@ export class AdminNotificationsPublicationClaimPageResolver implements Resolve { - let component: AdminNotificationsPublicationClaimPageComponent; - let fixture: ComponentFixture; +describe('NotificationsSuggestionTargetsPageComponent', () => { + let component: NotificationsSuggestionTargetsPageComponent; + let fixture: ComponentFixture; beforeEach(async(() => { TestBed.configureTestingModule({ @@ -16,10 +18,10 @@ describe('AdminNotificationsPublicationClaimPageComponent', () => { TranslateModule.forRoot() ], declarations: [ - AdminNotificationsPublicationClaimPageComponent + NotificationsSuggestionTargetsPageComponent ], providers: [ - AdminNotificationsPublicationClaimPageComponent + NotificationsSuggestionTargetsPageComponent ], schemas: [NO_ERRORS_SCHEMA] }) @@ -27,7 +29,7 @@ describe('AdminNotificationsPublicationClaimPageComponent', () => { })); beforeEach(() => { - fixture = TestBed.createComponent(AdminNotificationsPublicationClaimPageComponent); + fixture = TestBed.createComponent(NotificationsSuggestionTargetsPageComponent); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/src/app/admin/admin-notifications/admin-notifications-routing-paths.ts b/src/app/admin/admin-notifications/admin-notifications-routing-paths.ts index f92a96d242..9fcabedd64 100644 --- a/src/app/admin/admin-notifications/admin-notifications-routing-paths.ts +++ b/src/app/admin/admin-notifications/admin-notifications-routing-paths.ts @@ -1,9 +1,7 @@ -import { URLCombiner } from '../../core/url-combiner/url-combiner'; -import { getNotificationsModuleRoute } from '../admin-routing-paths'; export const QUALITY_ASSURANCE_EDIT_PATH = 'quality-assurance'; export const PUBLICATION_CLAIMS_PATH = 'publication-claim'; -export function getQualityAssuranceRoute(id: string) { - return new URLCombiner(getNotificationsModuleRoute(), QUALITY_ASSURANCE_EDIT_PATH, id).toString(); +export function getQualityAssuranceEditRoute() { + return `/${QUALITY_ASSURANCE_EDIT_PATH}`; } diff --git a/src/app/admin/admin-notifications/admin-notifications-routing.module.ts b/src/app/admin/admin-notifications/admin-notifications-routing.module.ts index 07a98aa080..c82c91233e 100644 --- a/src/app/admin/admin-notifications/admin-notifications-routing.module.ts +++ b/src/app/admin/admin-notifications/admin-notifications-routing.module.ts @@ -6,19 +6,37 @@ import { I18nBreadcrumbResolver } from '../../core/breadcrumbs/i18n-breadcrumb.r import { I18nBreadcrumbsService } from '../../core/breadcrumbs/i18n-breadcrumbs.service'; import { PUBLICATION_CLAIMS_PATH } from './admin-notifications-routing-paths'; import { AdminNotificationsPublicationClaimPageComponent } from './admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component'; -import { AdminNotificationsPublicationClaimPageResolver } from './admin-notifications-publication-claim-page/admin-notifications-publication-claim-page-resolver.service'; import { QUALITY_ASSURANCE_EDIT_PATH } from './admin-notifications-routing-paths'; -import { AdminQualityAssuranceTopicsPageComponent } from './admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component'; -import { AdminQualityAssuranceEventsPageComponent } from './admin-quality-assurance-events-page/admin-quality-assurance-events-page.component'; -import { AdminQualityAssuranceTopicsPageResolver } from './admin-quality-assurance-topics-page/admin-quality-assurance-topics-page-resolver.service'; -import { AdminQualityAssuranceEventsPageResolver } from './admin-quality-assurance-events-page/admin-quality-assurance-events-page.resolver'; -import { AdminQualityAssuranceSourcePageComponent } from './admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component'; -import { AdminQualityAssuranceSourcePageResolver } from './admin-quality-assurance-source-page-component/admin-quality-assurance-source-page-resolver.service'; +import { + SiteAdministratorGuard +} from '../../core/data/feature-authorization/feature-authorization-guard/site-administrator.guard'; import { QualityAssuranceBreadcrumbResolver } from '../../core/breadcrumbs/quality-assurance-breadcrumb.resolver'; import { QualityAssuranceBreadcrumbService } from '../../core/breadcrumbs/quality-assurance-breadcrumb.service'; +import { + QualityAssuranceEventsPageResolver +} from '../../quality-assurance-notifications-pages/quality-assurance-events-page/quality-assurance-events-page.resolver'; +import { + AdminNotificationsPublicationClaimPageResolver +} from '../../quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page-resolver.service'; +import { + QualityAssuranceTopicsPageComponent +} from '../../quality-assurance-notifications-pages/quality-assurance-topics-page/quality-assurance-topics-page.component'; +import { + QualityAssuranceTopicsPageResolver +} from '../../quality-assurance-notifications-pages/quality-assurance-topics-page/quality-assurance-topics-page-resolver.service'; +import { + QualityAssuranceSourcePageComponent +} from '../../quality-assurance-notifications-pages/quality-assurance-source-page-component/quality-assurance-source-page.component'; +import { + QualityAssuranceSourcePageResolver +} from '../../quality-assurance-notifications-pages/quality-assurance-source-page-component/quality-assurance-source-page-resolver.service'; import { SourceDataResolver -} from './admin-quality-assurance-source-page-component/admin-quality-assurance-source-data.resolver'; +} from '../../quality-assurance-notifications-pages/quality-assurance-source-page-component/quality-assurance-source-data.resolver'; +import { + QualityAssuranceEventsPageComponent +} from '../../quality-assurance-notifications-pages/quality-assurance-events-page/quality-assurance-events-page.component'; + @NgModule({ imports: [ @@ -41,11 +59,11 @@ import { { canActivate: [ AuthenticatedGuard ], path: `${QUALITY_ASSURANCE_EDIT_PATH}/:sourceId`, - component: AdminQualityAssuranceTopicsPageComponent, + component: QualityAssuranceTopicsPageComponent, pathMatch: 'full', resolve: { breadcrumb: QualityAssuranceBreadcrumbResolver, - openaireQualityAssuranceTopicsParams: AdminQualityAssuranceTopicsPageResolver + openaireQualityAssuranceTopicsParams: QualityAssuranceTopicsPageResolver }, data: { title: 'admin.quality-assurance.page.title', @@ -55,12 +73,27 @@ import { }, { canActivate: [ AuthenticatedGuard ], - path: `${QUALITY_ASSURANCE_EDIT_PATH}`, - component: AdminQualityAssuranceSourcePageComponent, + path: `${QUALITY_ASSURANCE_EDIT_PATH}/:sourceId/target/:targetId`, + component: QualityAssuranceTopicsPageComponent, pathMatch: 'full', resolve: { breadcrumb: I18nBreadcrumbResolver, - openaireQualityAssuranceSourceParams: AdminQualityAssuranceSourcePageResolver, + openaireQualityAssuranceTopicsParams: QualityAssuranceTopicsPageResolver + }, + data: { + title: 'admin.quality-assurance.page.title', + breadcrumbKey: 'admin.quality-assurance', + showBreadcrumbsFluid: false + } + }, + { + canActivate: [ SiteAdministratorGuard ], + path: `${QUALITY_ASSURANCE_EDIT_PATH}`, + component: QualityAssuranceSourcePageComponent, + pathMatch: 'full', + resolve: { + breadcrumb: I18nBreadcrumbResolver, + openaireQualityAssuranceSourceParams: QualityAssuranceSourcePageResolver, sourceData: SourceDataResolver }, data: { @@ -72,11 +105,11 @@ import { { canActivate: [ AuthenticatedGuard ], path: `${QUALITY_ASSURANCE_EDIT_PATH}/:sourceId/:topicId`, - component: AdminQualityAssuranceEventsPageComponent, + component: QualityAssuranceEventsPageComponent, pathMatch: 'full', resolve: { breadcrumb: QualityAssuranceBreadcrumbResolver, - openaireQualityAssuranceEventsParams: AdminQualityAssuranceEventsPageResolver + openaireQualityAssuranceEventsParams: QualityAssuranceEventsPageResolver }, data: { title: 'admin.notifications.event.page.title', @@ -91,10 +124,10 @@ import { I18nBreadcrumbsService, AdminNotificationsPublicationClaimPageResolver, SourceDataResolver, - AdminQualityAssuranceSourcePageResolver, - AdminQualityAssuranceTopicsPageResolver, - AdminQualityAssuranceEventsPageResolver, - AdminQualityAssuranceSourcePageResolver, + QualityAssuranceSourcePageResolver, + QualityAssuranceTopicsPageResolver, + QualityAssuranceEventsPageResolver, + QualityAssuranceSourcePageResolver, QualityAssuranceBreadcrumbResolver, QualityAssuranceBreadcrumbService ] diff --git a/src/app/admin/admin-notifications/admin-notifications.module.ts b/src/app/admin/admin-notifications/admin-notifications.module.ts index d9efb4c288..ea670d222c 100644 --- a/src/app/admin/admin-notifications/admin-notifications.module.ts +++ b/src/app/admin/admin-notifications/admin-notifications.module.ts @@ -4,11 +4,14 @@ import { CoreModule } from '../../core/core.module'; import { SharedModule } from '../../shared/shared.module'; import { AdminNotificationsRoutingModule } from './admin-notifications-routing.module'; import { AdminNotificationsPublicationClaimPageComponent } from './admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component'; -import { AdminQualityAssuranceTopicsPageComponent } from './admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component'; -import { AdminQualityAssuranceEventsPageComponent } from './admin-quality-assurance-events-page/admin-quality-assurance-events-page.component'; -import { AdminQualityAssuranceSourcePageComponent } from './admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component'; import { NotificationsModule } from '../../notifications/notifications.module'; + + + + + + @NgModule({ imports: [ CommonModule, @@ -19,9 +22,6 @@ import { NotificationsModule } from '../../notifications/notifications.module'; ], declarations: [ AdminNotificationsPublicationClaimPageComponent, - AdminQualityAssuranceTopicsPageComponent, - AdminQualityAssuranceEventsPageComponent, - AdminQualityAssuranceSourcePageComponent ], entryComponents: [] }) diff --git a/src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component.spec.ts b/src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component.spec.ts deleted file mode 100644 index 451c911c4c..0000000000 --- a/src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component.spec.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { NO_ERRORS_SCHEMA } from '@angular/core'; -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { AdminQualityAssuranceSourcePageComponent } from './admin-quality-assurance-source-page.component'; - -describe('AdminQualityAssuranceSourcePageComponent', () => { - let component: AdminQualityAssuranceSourcePageComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ AdminQualityAssuranceSourcePageComponent ], - schemas: [NO_ERRORS_SCHEMA] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(AdminQualityAssuranceSourcePageComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create AdminQualityAssuranceSourcePageComponent', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component.ts b/src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component.ts deleted file mode 100644 index 447e5a2e55..0000000000 --- a/src/app/admin/admin-notifications/admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component } from '@angular/core'; - -/** - * Component for the page that show the QA sources. - */ -@Component({ - selector: 'ds-admin-quality-assurance-source-page-component', - templateUrl: './admin-quality-assurance-source-page.component.html', -}) -export class AdminQualityAssuranceSourcePageComponent {} diff --git a/src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component.spec.ts b/src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component.spec.ts deleted file mode 100644 index a32f60f017..0000000000 --- a/src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component.spec.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { NO_ERRORS_SCHEMA } from '@angular/core'; -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { AdminQualityAssuranceTopicsPageComponent } from './admin-quality-assurance-topics-page.component'; - -describe('AdminQualityAssuranceTopicsPageComponent', () => { - let component: AdminQualityAssuranceTopicsPageComponent; - let fixture: ComponentFixture; - - beforeEach(async(() => { - TestBed.configureTestingModule({ - declarations: [ AdminQualityAssuranceTopicsPageComponent ], - schemas: [NO_ERRORS_SCHEMA] - }) - .compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(AdminQualityAssuranceTopicsPageComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create AdminQualityAssuranceTopicsPageComponent', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/admin/admin-reports/admin-reports-routing.module.ts b/src/app/admin/admin-reports/admin-reports-routing.module.ts new file mode 100644 index 0000000000..9022429502 --- /dev/null +++ b/src/app/admin/admin-reports/admin-reports-routing.module.ts @@ -0,0 +1,37 @@ +import { FilteredCollectionsComponent } from './filtered-collections/filtered-collections.component'; +import { FilteredItemsComponent } from './filtered-items/filtered-items.component'; +import { RouterModule } from '@angular/router'; +import { NgModule } from '@angular/core'; +import { I18nBreadcrumbResolver } from '../../core/breadcrumbs/i18n-breadcrumb.resolver'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + { + path: 'collections', + resolve: { breadcrumb: I18nBreadcrumbResolver }, + data: {title: 'admin.reports.collections.title', breadcrumbKey: 'admin.reports.collections'}, + children: [ + { + path: '', + component: FilteredCollectionsComponent + } + ] + }, + { + path: 'queries', + resolve: { breadcrumb: I18nBreadcrumbResolver }, + data: {title: 'admin.reports.items.title', breadcrumbKey: 'admin.reports.items'}, + children: [ + { + path: '', + component: FilteredItemsComponent + } + ] + } + ]) + ] +}) +export class AdminReportsRoutingModule { + +} diff --git a/src/app/admin/admin-reports/admin-reports.module.ts b/src/app/admin/admin-reports/admin-reports.module.ts new file mode 100644 index 0000000000..70dfba8a07 --- /dev/null +++ b/src/app/admin/admin-reports/admin-reports.module.ts @@ -0,0 +1,28 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FilteredCollectionsComponent } from './filtered-collections/filtered-collections.component'; +import { RouterModule } from '@angular/router'; +import { SharedModule } from '../../shared/shared.module'; +import { FormModule } from '../../shared/form/form.module'; +import { FilteredItemsComponent } from './filtered-items/filtered-items.component'; +import { AdminReportsRoutingModule } from './admin-reports-routing.module'; +import { NgbAccordionModule } from '@ng-bootstrap/ng-bootstrap'; +import { FiltersComponent } from './filters-section/filters-section.component'; + +@NgModule({ + imports: [ + CommonModule, + SharedModule, + RouterModule, + FormModule, + AdminReportsRoutingModule, + NgbAccordionModule + ], + declarations: [ + FilteredCollectionsComponent, + FilteredItemsComponent, + FiltersComponent + ] +}) +export class AdminReportsModule { +} diff --git a/src/app/admin/admin-reports/filtered-collections/filtered-collection.model.ts b/src/app/admin/admin-reports/filtered-collections/filtered-collection.model.ts new file mode 100644 index 0000000000..a48b1e02fa --- /dev/null +++ b/src/app/admin/admin-reports/filtered-collections/filtered-collection.model.ts @@ -0,0 +1,36 @@ +export class FilteredCollection { + + public label: string; + public handle: string; + public communityLabel: string; + public communityHandle: string; + public nbTotalItems: number; + public values = {}; + public allFiltersValue: number; + + public clear() { + this.label = ''; + this.handle = ''; + this.communityLabel = ''; + this.communityHandle = ''; + this.nbTotalItems = 0; + this.values = {}; + this.allFiltersValue = 0; + } + + public deserialize(object: any) { + this.clear(); + this.label = object.label; + this.handle = object.handle; + this.communityLabel = object.community_label; + this.communityHandle = object.community_handle; + this.nbTotalItems = object.nb_total_items; + let valuesPerFilter = object.values; + for (let filter in valuesPerFilter) { + if (valuesPerFilter.hasOwnProperty(filter)) { + this.values[filter] = valuesPerFilter[filter]; + } + } + this.allFiltersValue = object.all_filters_value; + } +} diff --git a/src/app/admin/admin-reports/filtered-collections/filtered-collections.component.html b/src/app/admin/admin-reports/filtered-collections/filtered-collections.component.html new file mode 100644 index 0000000000..5199a115a6 --- /dev/null +++ b/src/app/admin/admin-reports/filtered-collections/filtered-collections.component.html @@ -0,0 +1,64 @@ +
+ +
diff --git a/src/app/admin/admin-reports/filtered-collections/filtered-collections.component.scss b/src/app/admin/admin-reports/filtered-collections/filtered-collections.component.scss new file mode 100644 index 0000000000..73ce5275e5 --- /dev/null +++ b/src/app/admin/admin-reports/filtered-collections/filtered-collections.component.scss @@ -0,0 +1,3 @@ +.num { + text-align: center; +} diff --git a/src/app/admin/admin-reports/filtered-collections/filtered-collections.component.spec.ts b/src/app/admin/admin-reports/filtered-collections/filtered-collections.component.spec.ts new file mode 100644 index 0000000000..fe5dc612ca --- /dev/null +++ b/src/app/admin/admin-reports/filtered-collections/filtered-collections.component.spec.ts @@ -0,0 +1,83 @@ +import { waitForAsync, ComponentFixture, TestBed} from '@angular/core/testing'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { TranslateLoaderMock } from 'src/app/shared/mocks/translate-loader.mock'; +import { FormBuilder } from '@angular/forms'; +import { FilteredCollectionsComponent } from './filtered-collections.component'; +import { DspaceRestService } from 'src/app/core/dspace-rest/dspace-rest.service'; +import { NgbAccordion, NgbAccordionModule } from '@ng-bootstrap/ng-bootstrap'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { of as observableOf } from 'rxjs'; +import { RawRestResponse } from 'src/app/core/dspace-rest/raw-rest-response.model'; + +describe('FiltersComponent', () => { + let component: FilteredCollectionsComponent; + let fixture: ComponentFixture; + let formBuilder: FormBuilder; + + const expected = { + payload: { + collections: [], + summary: { + label: 'Test' + } + }, + statusCode: 200, + statusText: 'OK' + } as RawRestResponse; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [FilteredCollectionsComponent], + imports: [ + NgbAccordionModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateLoaderMock + } + }), + HttpClientTestingModule + ], + providers: [ + FormBuilder, + DspaceRestService + ], + schemas: [NO_ERRORS_SCHEMA] + }); + })); + + beforeEach(waitForAsync(() => { + formBuilder = TestBed.inject(FormBuilder); + + fixture = TestBed.createComponent(FilteredCollectionsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + })); + + it('should create the component', () => { + expect(component).toBeTruthy(); + }); + + it('should be displaying the filters panel initially', () => { + let accordion: NgbAccordion = component.accordionComponent; + expect(accordion.isExpanded('filters')).toBeTrue(); + }); + + describe('toggle', () => { + beforeEach(() => { + spyOn(component, 'getFilteredCollections').and.returnValue(observableOf(expected)); + spyOn(component.results, 'deserialize'); + spyOn(component.accordionComponent, 'expand').and.callThrough(); + component.submit(); + fixture.detectChanges(); + }); + + it('should be displaying the collections panel after submitting', waitForAsync(() => { + fixture.whenStable().then(() => { + expect(component.accordionComponent.expand).toHaveBeenCalledWith('collections'); + expect(component.accordionComponent.isExpanded('collections')).toBeTrue(); + }); + })); + }); +}); diff --git a/src/app/admin/admin-reports/filtered-collections/filtered-collections.component.ts b/src/app/admin/admin-reports/filtered-collections/filtered-collections.component.ts new file mode 100644 index 0000000000..23fde05278 --- /dev/null +++ b/src/app/admin/admin-reports/filtered-collections/filtered-collections.component.ts @@ -0,0 +1,70 @@ +import { Component, ViewChild } from '@angular/core'; +import { FormBuilder, FormGroup } from '@angular/forms'; +import { NgbAccordion } from '@ng-bootstrap/ng-bootstrap'; +import { Observable } from 'rxjs'; +import { RestRequestMethod } from 'src/app/core/data/rest-request-method'; +import { DspaceRestService } from 'src/app/core/dspace-rest/dspace-rest.service'; +import { RawRestResponse } from 'src/app/core/dspace-rest/raw-rest-response.model'; +import { environment } from 'src/environments/environment'; +import { FiltersComponent } from '../filters-section/filters-section.component'; +import { FilteredCollections } from './filtered-collections.model'; + +/** + * Component representing the Filtered Collections content report + */ +@Component({ + selector: 'ds-report-filtered-collections', + templateUrl: './filtered-collections.component.html', + styleUrls: ['./filtered-collections.component.scss'] +}) +export class FilteredCollectionsComponent { + + queryForm: FormGroup; + results: FilteredCollections = new FilteredCollections(); + @ViewChild('acc') accordionComponent: NgbAccordion; + + constructor( + private formBuilder: FormBuilder, + private restService: DspaceRestService) {} + + ngOnInit() { + this.queryForm = this.formBuilder.group({ + filters: FiltersComponent.formGroup(this.formBuilder) + }); + } + + filtersFormGroup(): FormGroup { + return this.queryForm.get('filters') as FormGroup; + } + + getGroup(filterId: string): string { + return FiltersComponent.getGroup(filterId).id; + } + + submit() { + this + .getFilteredCollections() + .subscribe( + response => { + this.results.deserialize(response.payload); + this.accordionComponent.expand('collections'); + } + ); + } + + getFilteredCollections(): Observable { + let params = this.toQueryString(); + if (params.length > 0) { + params = `?${params}`; + } + let scheme = environment.rest.ssl ? 'https' : 'http'; + let urlRestApp = `${scheme}://${environment.rest.host}:${environment.rest.port}${environment.rest.nameSpace}`; + return this.restService.request(RestRequestMethod.GET, `${urlRestApp}/api/contentreport/filteredcollections${params}`); + } + + private toQueryString(): string { + let params = FiltersComponent.toQueryString(this.queryForm.value.filters); + return params; + } + +} diff --git a/src/app/admin/admin-reports/filtered-collections/filtered-collections.model.ts b/src/app/admin/admin-reports/filtered-collections/filtered-collections.model.ts new file mode 100644 index 0000000000..6ea5a2fc80 --- /dev/null +++ b/src/app/admin/admin-reports/filtered-collections/filtered-collections.model.ts @@ -0,0 +1,26 @@ +import { FilteredCollection } from './filtered-collection.model'; + +export class FilteredCollections { + + public collections: Array = []; + public summary: FilteredCollection = new FilteredCollection(); + + public clear() { + this.collections.splice(0, this.collections.length); + this.summary.clear(); + } + + public deserialize(object: any) { + this.clear(); + let summary = object.summary; + this.summary.deserialize(summary); + let collections = object.collections; + for (let i = 0; i < collections.length; i++) { + let collection = collections[i]; + let coll = new FilteredCollection(); + coll.deserialize(collection); + this.collections.push(coll); + } + } + +} diff --git a/src/app/admin/admin-reports/filtered-items/filtered-items-model.ts b/src/app/admin/admin-reports/filtered-items/filtered-items-model.ts new file mode 100644 index 0000000000..2c384fe39c --- /dev/null +++ b/src/app/admin/admin-reports/filtered-items/filtered-items-model.ts @@ -0,0 +1,23 @@ +import { Item } from 'src/app/core/shared/item.model'; + +export class FilteredItems { + + public items: Item[] = []; + public itemCount: number; + + public clear() { + this.items.splice(0, this.items.length); + } + + public deserialize(object: any, offset: number = 0) { + this.clear(); + this.itemCount = object.itemCount; + let items = object.items; + for (let i = 0; i < items.length; i++) { + let item = items[i]; + item.index = this.items.length + offset + 1; + this.items.push(item); + } + } + +} diff --git a/src/app/admin/admin-reports/filtered-items/filtered-items.component.html b/src/app/admin/admin-reports/filtered-items/filtered-items.component.html new file mode 100644 index 0000000000..4b6679bdbc --- /dev/null +++ b/src/app/admin/admin-reports/filtered-items/filtered-items.component.html @@ -0,0 +1,175 @@ +
+ +
diff --git a/src/app/admin/admin-reports/filtered-items/filtered-items.component.scss b/src/app/admin/admin-reports/filtered-items/filtered-items.component.scss new file mode 100644 index 0000000000..73ce5275e5 --- /dev/null +++ b/src/app/admin/admin-reports/filtered-items/filtered-items.component.scss @@ -0,0 +1,3 @@ +.num { + text-align: center; +} diff --git a/src/app/suggestion-notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.scss b/src/app/admin/admin-reports/filtered-items/filtered-items.component.spec.ts similarity index 100% rename from src/app/suggestion-notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.scss rename to src/app/admin/admin-reports/filtered-items/filtered-items.component.spec.ts diff --git a/src/app/admin/admin-reports/filtered-items/filtered-items.component.ts b/src/app/admin/admin-reports/filtered-items/filtered-items.component.ts new file mode 100644 index 0000000000..48fcfe1faa --- /dev/null +++ b/src/app/admin/admin-reports/filtered-items/filtered-items.component.ts @@ -0,0 +1,338 @@ +import { Component, ViewChild } from '@angular/core'; +import { FormArray, FormBuilder, FormControl, FormGroup } from '@angular/forms'; +import { NgbAccordion } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateService } from '@ngx-translate/core'; +import { map, Observable } from 'rxjs'; +import { CollectionDataService } from 'src/app/core/data/collection-data.service'; +import { CommunityDataService } from 'src/app/core/data/community-data.service'; +import { MetadataFieldDataService } from 'src/app/core/data/metadata-field-data.service'; +import { MetadataSchemaDataService } from 'src/app/core/data/metadata-schema-data.service'; +import { RestRequestMethod } from 'src/app/core/data/rest-request-method'; +import { DspaceRestService } from 'src/app/core/dspace-rest/dspace-rest.service'; +import { RawRestResponse } from 'src/app/core/dspace-rest/raw-rest-response.model'; +import { MetadataField } from 'src/app/core/metadata/metadata-field.model'; +import { MetadataSchema } from 'src/app/core/metadata/metadata-schema.model'; +import { Collection } from 'src/app/core/shared/collection.model'; +import { Community } from 'src/app/core/shared/community.model'; +import { Item } from 'src/app/core/shared/item.model'; +import { getFirstSucceededRemoteListPayload } from 'src/app/core/shared/operators'; +import { isEmpty } from 'src/app/shared/empty.util'; +import { environment } from 'src/environments/environment'; +import { FiltersComponent } from '../filters-section/filters-section.component'; +import { FilteredItems } from './filtered-items-model'; +import { OptionVO } from './option-vo.model'; +import { PresetQuery } from './preset-query.model'; +import { QueryPredicate } from './query-predicate.model'; + +/** + * Component representing the Filtered Items content report. + */ +@Component({ + selector: 'ds-report-filtered-items', + templateUrl: './filtered-items.component.html', + styleUrls: ['./filtered-items.component.scss'] +}) +export class FilteredItemsComponent { + + collections: OptionVO[]; + presetQueries: PresetQuery[]; + metadataFields: OptionVO[]; + metadataFieldsWithAny: OptionVO[]; + predicates: OptionVO[]; + pageLimits: OptionVO[]; + + queryForm: FormGroup; + currentPage = 0; + results: FilteredItems = new FilteredItems(); + results$: Observable; + @ViewChild('acc') accordionComponent: NgbAccordion; + + constructor( + private communityService: CommunityDataService, + private collectionService: CollectionDataService, + private metadataSchemaService: MetadataSchemaDataService, + private metadataFieldService: MetadataFieldDataService, + private translateService: TranslateService, + private formBuilder: FormBuilder, + private restService: DspaceRestService) {} + + ngOnInit() { + this.loadCollections(); + this.loadPresetQueries(); + this.loadMetadataFields(); + this.loadPredicates(); + this.loadPageLimits(); + + let formQueryPredicates: FormGroup[] = [ + new QueryPredicate().toFormGroup(this.formBuilder) + ]; + + this.queryForm = this.formBuilder.group({ + collections: this.formBuilder.control([''], []), + presetQuery: this.formBuilder.control('new', []), + queryPredicates: this.formBuilder.array(formQueryPredicates), + pageLimit: this.formBuilder.control('100', []), + filters: FiltersComponent.formGroup(this.formBuilder), + additionalFields: this.formBuilder.control([], []) + }); + } + + loadCollections(): void { + this.collections = []; + let wholeRepo$ = this.translateService.stream('admin.reports.items.wholeRepo'); + this.collections.push(OptionVO.collectionLoc('', wholeRepo$)); + + this.communityService.findAll({ elementsPerPage: 10000, currentPage: 1 }).pipe( + getFirstSucceededRemoteListPayload() + ).subscribe( + (communitiesRest: Community[]) => { + communitiesRest.forEach(community => { + let commVO = OptionVO.collection(community.uuid, community.name, true); + this.collections.push(commVO); + + this.collectionService.findByParent(community.uuid, { elementsPerPage: 10000, currentPage: 1 }).pipe( + getFirstSucceededRemoteListPayload() + ).subscribe( + (collectionsRest: Collection[]) => { + collectionsRest.filter(collection => collection.firstMetadataValue('dspace.entity.type') === 'Publication') + .forEach(collection => { + let collVO = OptionVO.collection(collection.uuid, '–' + collection.name); + this.collections.push(collVO); + }); + } + ); + }); + } + ); + } + + loadPresetQueries(): void { + this.presetQueries = [ + PresetQuery.of('new', 'admin.reports.items.preset.new', []), + PresetQuery.of('q1', 'admin.reports.items.preset.hasNoTitle', [ + QueryPredicate.of('dc.title', QueryPredicate.DOES_NOT_EXIST) + ]), + PresetQuery.of('q2', 'admin.reports.items.preset.hasNoIdentifierUri', [ + QueryPredicate.of('dc.identifier.uri', QueryPredicate.DOES_NOT_EXIST) + ]), + PresetQuery.of('q3', 'admin.reports.items.preset.hasCompoundSubject', [ + QueryPredicate.of('dc.subject.*', QueryPredicate.LIKE, '%;%') + ]), + PresetQuery.of('q4', 'admin.reports.items.preset.hasCompoundAuthor', [ + QueryPredicate.of('dc.contributor.author', QueryPredicate.LIKE, '% and %') + ]), + PresetQuery.of('q5', 'admin.reports.items.preset.hasCompoundCreator', [ + QueryPredicate.of('dc.creator', QueryPredicate.LIKE, '% and %') + ]), + PresetQuery.of('q6', 'admin.reports.items.preset.hasUrlInDescription', [ + QueryPredicate.of('dc.description', QueryPredicate.MATCHES, '^.*(http://|https://|mailto:).*$') + ]), + PresetQuery.of('q7', 'admin.reports.items.preset.hasFullTextInProvenance', [ + QueryPredicate.of('dc.description.provenance', QueryPredicate.MATCHES, '^.*No\. of bitstreams(.|\r|\n|\r\n)*\.(PDF|pdf|DOC|doc|PPT|ppt|DOCX|docx|PPTX|pptx).*$') + ]), + PresetQuery.of('q8', 'admin.reports.items.preset.hasNonFullTextInProvenance', [ + QueryPredicate.of('dc.description.provenance', QueryPredicate.DOES_NOT_MATCH, '^.*No\. of bitstreams(.|\r|\n|\r\n)*\.(PDF|pdf|DOC|doc|PPT|ppt|DOCX|docx|PPTX|pptx).*$') + ]), + PresetQuery.of('q9', 'admin.reports.items.preset.hasEmptyMetadata', [ + QueryPredicate.of('*', QueryPredicate.MATCHES, '^\s*$') + ]), + PresetQuery.of('q10', 'admin.reports.items.preset.hasUnbreakingDataInDescription', [ + QueryPredicate.of('dc.description.*', QueryPredicate.MATCHES, '^.*[^\s]{50,}.*$') + ]), + PresetQuery.of('q12', 'admin.reports.items.preset.hasXmlEntityInMetadata', [ + QueryPredicate.of('*', QueryPredicate.MATCHES, '^.*&#.*$') + ]), + PresetQuery.of('q13', 'admin.reports.items.preset.hasNonAsciiCharInMetadata', [ + QueryPredicate.of('*', QueryPredicate.MATCHES, '^.*[^[:ascii:]].*$') + ]) + ]; + } + + loadMetadataFields(): void { + this.metadataFields = []; + this.metadataFieldsWithAny = []; + let anyField$ = this.translateService.stream('admin.reports.items.anyField'); + this.metadataFieldsWithAny.push(OptionVO.itemLoc('*', anyField$)); + this.metadataSchemaService.findAll({ elementsPerPage: 10000, currentPage: 1 }).pipe( + getFirstSucceededRemoteListPayload() + ).subscribe( + (schemasRest: MetadataSchema[]) => { + schemasRest.forEach(schema => { + this.metadataFieldService.findBySchema(schema, { elementsPerPage: 10000, currentPage: 1 }).pipe( + getFirstSucceededRemoteListPayload() + ).subscribe( + (fieldsRest: MetadataField[]) => { + fieldsRest.forEach(field => { + let fieldName = schema.prefix + '.' + field.toString(); + let fieldVO = OptionVO.item(fieldName, fieldName); + this.metadataFields.push(fieldVO); + this.metadataFieldsWithAny.push(fieldVO); + if (isEmpty(field.qualifier)) { + fieldName = schema.prefix + '.' + field.element + '.*'; + fieldVO = OptionVO.item(fieldName, fieldName); + this.metadataFieldsWithAny.push(fieldVO); + } + }); + } + ); + }); + } + ); + } + + loadPredicates(): void { + this.predicates = [ + OptionVO.item(QueryPredicate.EXISTS, 'admin.reports.items.predicate.exists'), + OptionVO.item(QueryPredicate.DOES_NOT_EXIST, 'admin.reports.items.predicate.doesNotExist'), + OptionVO.item(QueryPredicate.EQUALS, 'admin.reports.items.predicate.equals'), + OptionVO.item(QueryPredicate.DOES_NOT_EQUAL, 'admin.reports.items.predicate.doesNotEqual'), + OptionVO.item(QueryPredicate.LIKE, 'admin.reports.items.predicate.like'), + OptionVO.item(QueryPredicate.NOT_LIKE, 'admin.reports.items.predicate.notLike'), + OptionVO.item(QueryPredicate.CONTAINS, 'admin.reports.items.predicate.contains'), + OptionVO.item(QueryPredicate.DOES_NOT_CONTAIN, 'admin.reports.items.predicate.doesNotContain'), + OptionVO.item(QueryPredicate.MATCHES, 'admin.reports.items.predicate.matches'), + OptionVO.item(QueryPredicate.DOES_NOT_MATCH, 'admin.reports.items.predicate.doesNotMatch') + ]; + } + + loadPageLimits(): void { + this.pageLimits = [ + OptionVO.item('10', '10'), + OptionVO.item('25', '25'), + OptionVO.item('50', '50'), + OptionVO.item('100', '100'), + OptionVO.item('250', '250'), + OptionVO.item('1000', '1000') + ]; + } + + queryPredicatesArray(): FormArray { + return (this.queryForm.get('queryPredicates') as FormArray); + } + + addQueryPredicate(newItem: FormGroup = new QueryPredicate().toFormGroup(this.formBuilder)) { + this.queryPredicatesArray().push(newItem); + } + + deleteQueryPredicateDisabled(): boolean { + return this.queryPredicatesArray().length < 2; + } + + deleteQueryPredicate(index: number, nbToDelete: number = 1) { + if (index > -1) { + this.queryPredicatesArray().removeAt(index); + } + } + + setPresetQuery() { + let queryField = this.queryForm.controls.presetQuery as FormControl; + let value = queryField.value; + let query = this.presetQueries.find(q => q.id === value); + if (query !== undefined) { + this.queryPredicatesArray().clear(); + query.predicates + .map(qp => qp.toFormGroup(this.formBuilder)) + .forEach(qp => this.addQueryPredicate(qp)); + if (query.predicates.length === 0) { + this.addQueryPredicate(new QueryPredicate().toFormGroup(this.formBuilder)); + } + } + } + + filtersFormGroup(): FormGroup { + return this.queryForm.get('filters') as FormGroup; + } + + private pageSize() { + let form = this.queryForm.value; + return form.pageLimit; + } + + canNavigatePrevious(): boolean { + return this.currentPage > 0; + } + + prevPage() { + if (this.canNavigatePrevious()) { + this.currentPage--; + this.resubmit(); + } + } + + pageCount(): number { + let total = this.results.itemCount || 0; + return Math.ceil(total / this.pageSize()); + } + + canNavigateNext(): boolean { + return this.currentPage + 1 < this.pageCount(); + } + + nextPage() { + if (this.canNavigateNext()) { + this.currentPage++; + this.resubmit(); + } + } + + submit() { + this.accordionComponent.expand('itemResults'); + this.currentPage = 0; + this.resubmit(); + } + + resubmit() { + this.results$ = this + .getFilteredItems() + .pipe( + map(response => { + let offset = this.currentPage * this.pageSize(); + this.results.deserialize(response.payload, offset); + return this.results.items; + }) + ); + } + + getFilteredItems(): Observable { + let params = this.toQueryString(); + if (params.length > 0) { + params = `?${params}`; + } + let scheme = environment.rest.ssl ? 'https' : 'http'; + let urlRestApp = `${scheme}://${environment.rest.host}:${environment.rest.port}${environment.rest.nameSpace}`; + return this.restService.request(RestRequestMethod.GET, `${urlRestApp}/api/contentreport/filtereditems${params}`); + } + + private toQueryString(): string { + let params = `pageNumber=${this.currentPage}&pageLimit=${this.pageSize()}`; + + let colls = this.queryForm.value.collections; + for (let i = 0; i < colls.length; i++) { + params += `&collections=${colls[i]}`; + } + + let preds = this.queryForm.value.queryPredicates; + for (let i = 0; i < preds.length; i++) { + const field = preds[i].field; + const op = preds[i].operator; + const value = preds[i].value; + params += `&queryPredicates=${field}:${op}`; + if (value) { + params += `:${value}`; + } + } + + let filters = FiltersComponent.toQueryString(this.queryForm.value.filters); + if (filters.length > 0) { + params += `&${filters}`; + } + + let addFlds = this.queryForm.value.additionalFields; + for (let i = 0; i < addFlds.length; i++) { + params += `&additionalFields=${addFlds[i]}`; + } + + return params; + } + +} diff --git a/src/app/admin/admin-reports/filtered-items/option-vo.model.ts b/src/app/admin/admin-reports/filtered-items/option-vo.model.ts new file mode 100644 index 0000000000..0aee34d070 --- /dev/null +++ b/src/app/admin/admin-reports/filtered-items/option-vo.model.ts @@ -0,0 +1,50 @@ +import { Observable } from 'rxjs'; + +/** + * Component representing an option in each selectable list of values + * used in the Filtered Items report query interface + */ +export class OptionVO { + + id: string; + name$: Observable; + disabled = false; + + static collection(id: string, name: string, disabled: boolean = false): OptionVO { + let opt = new OptionVO(); + opt.id = id; + opt.name$ = OptionVO.toObservable(name); + opt.disabled = disabled; + return opt; + } + + static collectionLoc(id: string, name$: Observable, disabled: boolean = false): OptionVO { + let opt = new OptionVO(); + opt.id = id; + opt.name$ = name$; + opt.disabled = disabled; + return opt; + } + + static item(id: string, name: string): OptionVO { + let opt = new OptionVO(); + opt.id = id; + opt.name$ = OptionVO.toObservable(name); + return opt; + } + + static itemLoc(id: string, name$: Observable): OptionVO { + let opt = new OptionVO(); + opt.id = id; + opt.name$ = name$; + return opt; + } + + private static toObservable(value: T): Observable { + return new Observable(subscriber => { + subscriber.next(value); + subscriber.complete(); + }); + + } +} diff --git a/src/app/admin/admin-reports/filtered-items/preset-query.model.ts b/src/app/admin/admin-reports/filtered-items/preset-query.model.ts new file mode 100644 index 0000000000..73522f02cf --- /dev/null +++ b/src/app/admin/admin-reports/filtered-items/preset-query.model.ts @@ -0,0 +1,17 @@ +import { QueryPredicate } from './query-predicate.model'; + +export class PresetQuery { + + id: string; + label: string; + predicates: QueryPredicate[]; + + static of(id: string, label: string, predicates: QueryPredicate[]) { + let query = new PresetQuery(); + query.id = id; + query.label = label; + query.predicates = predicates; + return query; + } + +} diff --git a/src/app/admin/admin-reports/filtered-items/query-predicate.model.ts b/src/app/admin/admin-reports/filtered-items/query-predicate.model.ts new file mode 100644 index 0000000000..c5f323ed2c --- /dev/null +++ b/src/app/admin/admin-reports/filtered-items/query-predicate.model.ts @@ -0,0 +1,36 @@ +import { FormBuilder, FormControl, FormGroup } from '@angular/forms'; + +export class QueryPredicate { + + static EXISTS = 'exists'; + static DOES_NOT_EXIST = 'doesnt_exist'; + static EQUALS = 'equals'; + static DOES_NOT_EQUAL = 'not_equals'; + static LIKE = 'like'; + static NOT_LIKE = 'not_like'; + static CONTAINS = 'contains'; + static DOES_NOT_CONTAIN = 'doesnt_contain'; + static MATCHES = 'matches'; + static DOES_NOT_MATCH = 'doesnt_match'; + + field = '*'; + operator: string; + value: string; + + static of(field: string, operator: string, value: string = '') { + let pred = new QueryPredicate(); + pred.field = field; + pred.operator = operator; + pred.value = value; + return pred; + } + + toFormGroup(formBuilder: FormBuilder): FormGroup { + return formBuilder.group({ + field: new FormControl(this.field), + operator: new FormControl(this.operator), + value: new FormControl(this.value) + }); + } + +} diff --git a/src/app/admin/admin-reports/filters-section/filter-group.model.ts b/src/app/admin/admin-reports/filters-section/filter-group.model.ts new file mode 100644 index 0000000000..975b43a986 --- /dev/null +++ b/src/app/admin/admin-reports/filters-section/filter-group.model.ts @@ -0,0 +1,19 @@ +import { Filter } from './filter.model'; + +export class FilterGroup { + + id: string; + key: string; + + constructor(id: string, public filters: Filter[]) { + this.id = id; + this.key = 'admin.reports.commons.filters.' + id; + filters.forEach(filter => { + filter.key = this.key + '.' + filter.id; + if (filter.hasTooltip) { + filter.tooltipKey = filter.key + '.tooltip'; + } + }); + } + +} diff --git a/src/app/admin/admin-reports/filters-section/filter.model.ts b/src/app/admin/admin-reports/filters-section/filter.model.ts new file mode 100644 index 0000000000..63eeb114cd --- /dev/null +++ b/src/app/admin/admin-reports/filters-section/filter.model.ts @@ -0,0 +1,8 @@ +export class Filter { + + key: string; + tooltipKey: string; + + constructor(public id: string, public hasTooltip: boolean = false) {} + +} diff --git a/src/app/admin/admin-reports/filters-section/filters-section.component.html b/src/app/admin/admin-reports/filters-section/filters-section.component.html new file mode 100644 index 0000000000..1e7856f09c --- /dev/null +++ b/src/app/admin/admin-reports/filters-section/filters-section.component.html @@ -0,0 +1,19 @@ +
+ +   +   + +   + +   +   + +
+
+ {{group.key | translate}} + +
+ +
+
+
diff --git a/src/app/suggestion-notifications/suggestion-targets/publication-claim/publication-claim.component.scss b/src/app/admin/admin-reports/filters-section/filters-section.component.scss similarity index 100% rename from src/app/suggestion-notifications/suggestion-targets/publication-claim/publication-claim.component.scss rename to src/app/admin/admin-reports/filters-section/filters-section.component.scss diff --git a/src/app/admin/admin-reports/filters-section/filters-section.component.spec.ts b/src/app/admin/admin-reports/filters-section/filters-section.component.spec.ts new file mode 100644 index 0000000000..94f2753ec0 --- /dev/null +++ b/src/app/admin/admin-reports/filters-section/filters-section.component.spec.ts @@ -0,0 +1,101 @@ +import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { FiltersComponent } from './filters-section.component'; +import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { TranslateLoaderMock } from 'src/app/shared/mocks/translate-loader.mock'; +import { FormBuilder } from '@angular/forms'; + +describe('FiltersComponent', () => { + let component: FiltersComponent; + let fixture: ComponentFixture; + let formBuilder: FormBuilder; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [FiltersComponent], + imports: [ + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateLoaderMock + } + }) + ], + providers: [ + FormBuilder + ], + schemas: [NO_ERRORS_SCHEMA] + }); + })); + + beforeEach(waitForAsync(() => { + formBuilder = TestBed.inject(FormBuilder); + + fixture = TestBed.createComponent(FiltersComponent); + component = fixture.componentInstance; + component.filtersForm = FiltersComponent.formGroup(formBuilder); + fixture.detectChanges(); + })); + + const isOneSelected = (values: {}): boolean => { + let oneSelected = false; + let allFilters = FiltersComponent.FILTERS; + for (let i = 0; !oneSelected && i < allFilters.length; i++) { + let group = allFilters[i]; + for (let j = 0; j < group.filters.length; j++) { + let filter = group.filters[j]; + oneSelected = oneSelected || values[filter.id]; + } + } + return oneSelected; + }; + + const isAllSelected = (values: {}): boolean => { + let allSelected = true; + let allFilters = FiltersComponent.FILTERS; + for (let i = 0; allSelected && i < allFilters.length; i++) { + let group = allFilters[i]; + for (let j = 0; j < group.filters.length; j++) { + let filter = group.filters[j]; + allSelected = allSelected && values[filter.id]; + } + } + return allSelected; + }; + + it('should create the component', () => { + expect(component).toBeTruthy(); + }); + + it('should select all checkboxes', () => { + // By default, nothing is selected, so at least one item is not selected. + let values = component.filtersForm.value; + let allSelected: boolean = isAllSelected(values); + expect(allSelected).toBeFalse(); + + // Now we select everything... + component.selectAll(); + + // We must retrieve the form values again since selectAll() injects a new dictionary. + values = component.filtersForm.value; + allSelected = isAllSelected(values); + expect(allSelected).toBeTrue(); + }); + + it('should deselect all checkboxes', () => { + // Since nothing is selected by default, we select at least an item + // so that deselectAll() actually deselects something. + let values = component.filtersForm.value; + values.is_item = true; + let oneSelected: boolean = isOneSelected(values); + expect(oneSelected).toBeTrue(); + + // Now we deselect everything... + component.deselectAll(); + + // We must retrieve the form values again since deselectAll() injects a new dictionary. + values = component.filtersForm.value; + oneSelected = isOneSelected(values); + expect(oneSelected).toBeFalse(); + }); +}); diff --git a/src/app/admin/admin-reports/filters-section/filters-section.component.ts b/src/app/admin/admin-reports/filters-section/filters-section.component.ts new file mode 100644 index 0000000000..d5dc074f08 --- /dev/null +++ b/src/app/admin/admin-reports/filters-section/filters-section.component.ts @@ -0,0 +1,149 @@ +import { Component, Input } from '@angular/core'; +import { FormBuilder, FormControl, FormGroup } from '@angular/forms'; +import { FilterGroup } from './filter-group.model'; +import { Filter } from './filter.model'; + +/** + * Component representing the Query Filters section used in both + * Filtered Collections and Filtered Items content reports + */ +@Component({ + selector: 'ds-filters', + templateUrl: './filters-section.component.html', + styleUrls: ['./filters-section.component.scss'] +}) +export class FiltersComponent { + + static FILTERS = [ + new FilterGroup('property', [ + new Filter('is_item'), + new Filter('is_withdrawn'), + new Filter('is_not_withdrawn'), + new Filter('is_discoverable'), + new Filter('is_not_discoverable') + ]), + new FilterGroup('bitstream', [ + new Filter('has_multiple_originals'), + new Filter('has_no_originals'), + new Filter('has_one_original') + ]), + new FilterGroup('bitstream_mime', [ + new Filter('has_doc_original'), + new Filter('has_image_original'), + new Filter('has_unsupp_type'), + new Filter('has_mixed_original'), + new Filter('has_pdf_original'), + new Filter('has_jpg_original'), + new Filter('has_small_pdf'), + new Filter('has_large_pdf'), + new Filter('has_doc_without_text') + ]), + new FilterGroup('mime', [ + new Filter('has_only_supp_image_type'), + new Filter('has_unsupp_image_type'), + new Filter('has_only_supp_doc_type'), + new Filter('has_unsupp_doc_type') + ]), + new FilterGroup('bundle', [ + new Filter('has_unsupported_bundle'), + new Filter('has_small_thumbnail'), + new Filter('has_original_without_thumbnail'), + new Filter('has_invalid_thumbnail_name'), + new Filter('has_non_generated_thumb'), + new Filter('no_license'), + new Filter('has_license_documentation') + ]), + new FilterGroup('permission', [ + new Filter('has_restricted_original', true), + new Filter('has_restricted_thumbnail', true), + new Filter('has_restricted_metadata', true) + ]) + ]; + + @Input() filtersForm: FormGroup; + + static formGroup(formBuilder: FormBuilder): FormGroup { + let fields = {}; + let allFilters = FiltersComponent.FILTERS; + for (let i = 0; i < allFilters.length; i++) { + let group = allFilters[i]; + for (let j = 0; j < group.filters.length; j++) { + let filter = group.filters[j]; + fields[filter.id] = new FormControl(false); + } + } + return formBuilder.group(fields); + } + + static getFilter(filterId: string): Filter { + let allFilters = FiltersComponent.FILTERS; + for (let i = 0; i < allFilters.length; i++) { + let group = allFilters[i]; + for (let j = 0; j < group.filters.length; j++) { + let filter = group.filters[j]; + if (filter.id === filterId) { + return filter; + } + } + } + return undefined; + } + + static getGroup(filterId: string): FilterGroup { + let allFilters = FiltersComponent.FILTERS; + for (let i = 0; i < allFilters.length; i++) { + let group = allFilters[i]; + for (let j = 0; j < group.filters.length; j++) { + let filter = group.filters[j]; + if (filter.id === filterId) { + return group; + } + } + } + return undefined; + } + + static toQueryString(filters: Object): string { + let params = ''; + let first = true; + for (const key in filters) { + if (filters[key]) { + if (first) { + first = false; + } else { + params += '&'; + } + params += `filters=${key}`; + } + } + return params; + } + + allFilters(): FilterGroup[] { + return FiltersComponent.FILTERS; + } + + private setAllFilters(value: boolean) { + // I don't know why, but patchValue() with individual controls doesn't work. + // I therefore use setValue() with the whole set, which mercifully works... + let fields = {}; + let allFilters = FiltersComponent.FILTERS; + for (let i = 0; i < allFilters.length; i++) { + let group = allFilters[i]; + for (let j = 0; j < group.filters.length; j++) { + let filter = group.filters[j]; + fields[filter.id] = value; + } + } + this.filtersForm.setValue(fields); + } + + selectAll(): void { + this.setAllFilters(true); + } + + deselectAll(): void { + this.setAllFilters(false); + } + +} diff --git a/src/app/admin/admin-routing-paths.ts b/src/app/admin/admin-routing-paths.ts index 30f801cecb..9c4c6eb15a 100644 --- a/src/app/admin/admin-routing-paths.ts +++ b/src/app/admin/admin-routing-paths.ts @@ -1,13 +1,30 @@ import { URLCombiner } from '../core/url-combiner/url-combiner'; import { getAdminModuleRoute } from '../app-routing-paths'; +import { getQualityAssuranceEditRoute } from './admin-notifications/admin-notifications-routing-paths'; export const REGISTRIES_MODULE_PATH = 'registries'; export const NOTIFICATIONS_MODULE_PATH = 'notifications'; +export const LDN_PATH = 'ldn'; +export const REPORTS_MODULE_PATH = 'reports'; + + export function getRegistriesModuleRoute() { return new URLCombiner(getAdminModuleRoute(), REGISTRIES_MODULE_PATH).toString(); } +export function getLdnServicesModuleRoute() { + return new URLCombiner(getAdminModuleRoute(), LDN_PATH).toString(); +} + export function getNotificationsModuleRoute() { return new URLCombiner(getAdminModuleRoute(), NOTIFICATIONS_MODULE_PATH).toString(); } + +export function getNotificatioQualityAssuranceRoute() { + return new URLCombiner(`/${NOTIFICATIONS_MODULE_PATH}`, getQualityAssuranceEditRoute()).toString(); +} + +export function getReportsModuleRoute() { + return new URLCombiner(getAdminModuleRoute(), REPORTS_MODULE_PATH).toString(); +} diff --git a/src/app/admin/admin-routing.module.ts b/src/app/admin/admin-routing.module.ts index a7d19a6935..ae7d49a915 100644 --- a/src/app/admin/admin-routing.module.ts +++ b/src/app/admin/admin-routing.module.ts @@ -6,8 +6,15 @@ import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.reso import { AdminWorkflowPageComponent } from './admin-workflow-page/admin-workflow-page.component'; import { I18nBreadcrumbsService } from '../core/breadcrumbs/i18n-breadcrumbs.service'; import { AdminCurationTasksComponent } from './admin-curation-tasks/admin-curation-tasks.component'; -import { REGISTRIES_MODULE_PATH, NOTIFICATIONS_MODULE_PATH } from './admin-routing-paths'; +import { + LDN_PATH, + NOTIFICATIONS_MODULE_PATH, + REGISTRIES_MODULE_PATH, REPORTS_MODULE_PATH, +} from './admin-routing-paths'; import { BatchImportPageComponent } from './admin-import-batch-page/batch-import-page.component'; +import { + SiteAdministratorGuard +} from '../core/data/feature-authorization/feature-authorization-guard/site-administrator.guard'; @NgModule({ imports: [ @@ -21,42 +28,65 @@ import { BatchImportPageComponent } from './admin-import-batch-page/batch-import path: REGISTRIES_MODULE_PATH, loadChildren: () => import('./admin-registries/admin-registries.module') .then((m) => m.AdminRegistriesModule), + canActivate: [SiteAdministratorGuard] }, { path: 'search', resolve: { breadcrumb: I18nBreadcrumbResolver }, component: AdminSearchPageComponent, - data: { title: 'admin.search.title', breadcrumbKey: 'admin.search' } + data: { title: 'admin.search.title', breadcrumbKey: 'admin.search' }, + canActivate: [SiteAdministratorGuard] }, { path: 'workflow', resolve: { breadcrumb: I18nBreadcrumbResolver }, component: AdminWorkflowPageComponent, - data: { title: 'admin.workflow.title', breadcrumbKey: 'admin.workflow' } + data: { title: 'admin.workflow.title', breadcrumbKey: 'admin.workflow' }, + canActivate: [SiteAdministratorGuard] }, { path: 'curation-tasks', resolve: { breadcrumb: I18nBreadcrumbResolver }, component: AdminCurationTasksComponent, - data: { title: 'admin.curation-tasks.title', breadcrumbKey: 'admin.curation-tasks' } + data: { title: 'admin.curation-tasks.title', breadcrumbKey: 'admin.curation-tasks' }, + canActivate: [SiteAdministratorGuard] }, { path: 'metadata-import', resolve: { breadcrumb: I18nBreadcrumbResolver }, component: MetadataImportPageComponent, - data: { title: 'admin.metadata-import.title', breadcrumbKey: 'admin.metadata-import' } + data: { title: 'admin.metadata-import.title', breadcrumbKey: 'admin.metadata-import' }, + canActivate: [SiteAdministratorGuard] }, { path: 'batch-import', resolve: { breadcrumb: I18nBreadcrumbResolver }, component: BatchImportPageComponent, - data: { title: 'admin.batch-import.title', breadcrumbKey: 'admin.batch-import' } + data: { title: 'admin.batch-import.title', breadcrumbKey: 'admin.batch-import' }, + canActivate: [SiteAdministratorGuard] }, { path: 'system-wide-alert', resolve: { breadcrumb: I18nBreadcrumbResolver }, loadChildren: () => import('../system-wide-alert/system-wide-alert.module').then((m) => m.SystemWideAlertModule), - data: {title: 'admin.system-wide-alert.title', breadcrumbKey: 'admin.system-wide-alert'} + data: {title: 'admin.system-wide-alert.title', breadcrumbKey: 'admin.system-wide-alert'}, + canActivate: [SiteAdministratorGuard] + }, + { + path: LDN_PATH, + children: [ + { path: '', pathMatch: 'full', redirectTo: 'services' }, + { + path: 'services', + loadChildren: () => import('./admin-ldn-services/admin-ldn-services.module') + .then((m) => m.AdminLdnServicesModule), + } + ], + }, + { + path: REPORTS_MODULE_PATH, + loadChildren: () => import('./admin-reports/admin-reports.module') + .then((m) => m.AdminReportsModule), }, ]) ], diff --git a/src/app/admin/admin.module.ts b/src/app/admin/admin.module.ts index 3dc0036854..e2a2f3194b 100644 --- a/src/app/admin/admin.module.ts +++ b/src/app/admin/admin.module.ts @@ -10,6 +10,7 @@ import { AdminSearchModule } from './admin-search-page/admin-search.module'; import { AdminSidebarSectionComponent } from './admin-sidebar/admin-sidebar-section/admin-sidebar-section.component'; import { ExpandableAdminSidebarSectionComponent } from './admin-sidebar/expandable-admin-sidebar-section/expandable-admin-sidebar-section.component'; import { BatchImportPageComponent } from './admin-import-batch-page/batch-import-page.component'; +import { AdminReportsModule } from './admin-reports/admin-reports.module'; import { UiSwitchModule } from 'ngx-ui-switch'; import { UploadModule } from '../shared/upload/upload.module'; @@ -24,6 +25,7 @@ const ENTRY_COMPONENTS = [ imports: [ AdminRoutingModule, AdminRegistriesModule, + AdminReportsModule, AccessControlModule, AdminSearchModule.withEntryComponents(), AdminWorkflowModuleModule.withEntryComponents(), diff --git a/src/app/app-routing-paths.ts b/src/app/app-routing-paths.ts index fe2837c6e3..63b11ec80e 100644 --- a/src/app/app-routing-paths.ts +++ b/src/app/app-routing-paths.ts @@ -31,6 +31,7 @@ export function getBitstreamRequestACopyRoute(item, bitstream): { routerLink: st } }; } +export const COAR_NOTIFY_SUPPORT = 'coar-notify-support'; export const HOME_PAGE_PATH = 'admin'; @@ -132,3 +133,10 @@ export const SUBSCRIPTIONS_MODULE_PATH = 'subscriptions'; export function getSubscriptionsModuleRoute() { return `/${SUBSCRIPTIONS_MODULE_PATH}`; } + +export const EDIT_ITEM_PATH = 'edit-items'; +export function getEditItemPageRoute() { + return `/${EDIT_ITEM_PATH}`; +} +export const CORRECTION_TYPE_PATH = 'corrections'; + diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index a14000aef4..4766e36ff8 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -1,11 +1,8 @@ import { NgModule } from '@angular/core'; -import { NoPreloading, RouterModule } from '@angular/router'; +import { RouterModule, NoPreloading } from '@angular/router'; import { AuthBlockingGuard } from './core/auth/auth-blocking.guard'; import { AuthenticatedGuard } from './core/auth/authenticated.guard'; -import { - SiteAdministratorGuard -} from './core/data/feature-authorization/feature-authorization-guard/site-administrator.guard'; import { ACCESS_CONTROL_MODULE_PATH, ADMIN_MODULE_PATH, @@ -41,6 +38,7 @@ import { ServerCheckGuard } from './core/server-check/server-check.guard'; import { SUGGESTION_MODULE_PATH } from './suggestions-page/suggestions-page-routing-paths'; import { MenuResolver } from './menu.resolver'; import { ThemedPageErrorComponent } from './page-error/themed-page-error.component'; +import { NOTIFICATIONS_MODULE_PATH } from './admin/admin-routing-paths'; import { ForgotPasswordCheckGuard } from './core/rest-property/forgot-password-check-guard.guard'; @NgModule({ @@ -96,10 +94,7 @@ import { ForgotPasswordCheckGuard } from './core/rest-property/forgot-password-c path: FORGOT_PASSWORD_PATH, loadChildren: () => import('./forgot-password/forgot-password.module') .then((m) => m.ForgotPasswordModule), - canActivate: [ - ForgotPasswordCheckGuard, - EndUserAgreementCurrentUserGuard - ] + canActivate: [EndUserAgreementCurrentUserGuard, ForgotPasswordCheckGuard] }, { path: COMMUNITY_MODULE_PATH, @@ -159,7 +154,19 @@ import { ForgotPasswordCheckGuard } from './core/rest-property/forgot-password-c path: ADMIN_MODULE_PATH, loadChildren: () => import('./admin/admin.module') .then((m) => m.AdminModule), - canActivate: [SiteAdministratorGuard, EndUserAgreementCurrentUserGuard] + canActivate: [EndUserAgreementCurrentUserGuard] + }, + { + path: NOTIFICATIONS_MODULE_PATH, + loadChildren: () => import('./admin/admin-notifications/admin-notifications.module') + .then((m) => m.AdminNotificationsModule), + canActivate: [AuthenticatedGuard, EndUserAgreementCurrentUserGuard] + }, + { + path: NOTIFICATIONS_MODULE_PATH, + loadChildren: () => import('./quality-assurance-notifications-pages/notifications-pages.module') + .then((m) => m.NotificationsPageModule), + canActivate: [AuthenticatedGuard, EndUserAgreementCurrentUserGuard] }, { path: 'login', @@ -247,7 +254,7 @@ import { ForgotPasswordCheckGuard } from './core/rest-property/forgot-password-c .then((m) => m.SubscriptionsPageRoutingModule), canActivate: [AuthenticatedGuard] }, - { path: '**', pathMatch: 'full', component: ThemedPageNotFoundComponent }, + { path: '**', pathMatch: 'full', component: ThemedPageNotFoundComponent } ] } ], { diff --git a/src/app/core/breadcrumbs/navigation-breadcrumb.resolver.spec.ts b/src/app/core/breadcrumbs/navigation-breadcrumb.resolver.spec.ts new file mode 100644 index 0000000000..81b3b8ad2a --- /dev/null +++ b/src/app/core/breadcrumbs/navigation-breadcrumb.resolver.spec.ts @@ -0,0 +1,52 @@ +import { NavigationBreadcrumbResolver } from './navigation-breadcrumb.resolver'; + +describe('NavigationBreadcrumbResolver', () => { + describe('resolve', () => { + let resolver: NavigationBreadcrumbResolver; + let NavigationBreadcrumbService: any; + let i18nKey: string; + let relatedI18nKey: string; + let route: any; + let expectedPath; + let state; + beforeEach(() => { + i18nKey = 'example.key'; + relatedI18nKey = 'related.key'; + route = { + data: { + breadcrumbKey: i18nKey, + relatedRoutes: [ + { + path: '', + data: {breadcrumbKey: relatedI18nKey}, + } + ] + }, + routeConfig: { + path: 'example' + }, + parent: { + routeConfig: { + path: '' + }, + url: [{ + path: 'base' + }] + } as any + }; + + state = { + url: '/base/example' + }; + expectedPath = '/base/example:/base'; + NavigationBreadcrumbService = {}; + resolver = new NavigationBreadcrumbResolver(NavigationBreadcrumbService); + }); + + it('should resolve the breadcrumb config', () => { + const resolvedConfig = resolver.resolve(route, state); + const expectedConfig = { provider: NavigationBreadcrumbService, key: `${i18nKey}:${relatedI18nKey}`, url: expectedPath }; + expect(resolvedConfig).toEqual(expectedConfig); + }); + }); +}); diff --git a/src/app/core/breadcrumbs/navigation-breadcrumb.resolver.ts b/src/app/core/breadcrumbs/navigation-breadcrumb.resolver.ts new file mode 100644 index 0000000000..18ebfc395b --- /dev/null +++ b/src/app/core/breadcrumbs/navigation-breadcrumb.resolver.ts @@ -0,0 +1,52 @@ +import { BreadcrumbConfig } from '../../breadcrumbs/breadcrumb/breadcrumb-config.model'; +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router'; +import { NavigationBreadcrumbsService } from './navigation-breadcrumb.service'; + +/** + * The class that resolves a BreadcrumbConfig object with an i18n key string for a route and related parents + */ +@Injectable({ + providedIn: 'root' +}) +export class NavigationBreadcrumbResolver implements Resolve> { + + private parentRoutes: ActivatedRouteSnapshot[] = []; + constructor(protected breadcrumbService: NavigationBreadcrumbsService) { + } + + /** + * Method to collect all parent routes snapshot from current route snapshot + * @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot + */ + private getParentRoutes(route: ActivatedRouteSnapshot): void { + if (route.parent) { + this.parentRoutes.push(route.parent); + this.getParentRoutes(route.parent); + } + } + /** + * Method for resolving an I18n breadcrumb configuration object + * @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot + * @param {RouterStateSnapshot} state The current RouterStateSnapshot + * @returns BreadcrumbConfig object + */ + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): BreadcrumbConfig { + this.getParentRoutes(route); + const relatedRoutes = route.data.relatedRoutes; + const parentPaths = this.parentRoutes.map(parent => parent.routeConfig?.path); + const relatedParentRoutes = relatedRoutes.filter(relatedRoute => parentPaths.includes(relatedRoute.path)); + const baseUrlSegmentPath = route.parent.url[route.parent.url.length - 1].path; + const baseUrl = state.url.substring(0, state.url.lastIndexOf(baseUrlSegmentPath) + baseUrlSegmentPath.length); + + + const combinedParentBreadcrumbKeys = relatedParentRoutes.reduce((previous, current) => { + return `${previous}:${current.data.breadcrumbKey}`; + }, route.data.breadcrumbKey); + const combinedUrls = relatedParentRoutes.reduce((previous, current) => { + return `${previous}:${baseUrl}${current.path}`; + }, state.url); + + return {provider: this.breadcrumbService, key: combinedParentBreadcrumbKeys, url: combinedUrls}; + } +} diff --git a/src/app/core/breadcrumbs/navigation-breadcrumb.service.ts b/src/app/core/breadcrumbs/navigation-breadcrumb.service.ts new file mode 100644 index 0000000000..beebeed94e --- /dev/null +++ b/src/app/core/breadcrumbs/navigation-breadcrumb.service.ts @@ -0,0 +1,30 @@ +import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model'; +import { BreadcrumbsProviderService } from './breadcrumbsProviderService'; +import { Observable, of as observableOf } from 'rxjs'; +import { Injectable } from '@angular/core'; + +/** + * The postfix for i18n breadcrumbs + */ +export const BREADCRUMB_MESSAGE_POSTFIX = '.breadcrumbs'; + +/** + * Service to calculate i18n breadcrumbs for a single part of the route + */ +@Injectable({ + providedIn: 'root' +}) +export class NavigationBreadcrumbsService implements BreadcrumbsProviderService { + + /** + * Method to calculate the breadcrumbs + * @param key The key used to resolve the breadcrumb + * @param url The url to use as a link for this breadcrumb + */ + getBreadcrumbs(key: string, url: string): Observable { + const keys = key.split(':'); + const urls = url.split(':'); + const breadcrumbs = keys.map((currentKey, index) => new Breadcrumb(currentKey + BREADCRUMB_MESSAGE_POSTFIX, urls[index] )); + return observableOf(breadcrumbs.reverse()); + } +} diff --git a/src/app/core/breadcrumbs/navigation-breadcrumbs.service.spec.ts b/src/app/core/breadcrumbs/navigation-breadcrumbs.service.spec.ts new file mode 100644 index 0000000000..98e20e285d --- /dev/null +++ b/src/app/core/breadcrumbs/navigation-breadcrumbs.service.spec.ts @@ -0,0 +1,43 @@ +import { TestBed, waitForAsync } from '@angular/core/testing'; +import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model'; +import { getTestScheduler } from 'jasmine-marbles'; +import { BREADCRUMB_MESSAGE_POSTFIX } from './i18n-breadcrumbs.service'; +import { NavigationBreadcrumbsService } from './navigation-breadcrumb.service'; + +describe('NavigationBreadcrumbsService', () => { + let service: NavigationBreadcrumbsService; + let exampleString; + let exampleURL; + let childrenString; + let childrenUrl; + let parentString; + let parentUrl; + + function init() { + exampleString = 'example.string:parent.string'; + exampleURL = 'example.com:parent.com'; + childrenString = 'example.string'; + childrenUrl = 'example.com'; + parentString = 'parent.string'; + parentUrl = 'parent.com'; + } + + beforeEach(waitForAsync(() => { + init(); + TestBed.configureTestingModule({}).compileComponents(); + })); + + beforeEach(() => { + service = new NavigationBreadcrumbsService(); + }); + + describe('getBreadcrumbs', () => { + it('should return an array of breadcrumbs based on strings by adding the postfix', () => { + const breadcrumbs = service.getBreadcrumbs(exampleString, exampleURL); + getTestScheduler().expectObservable(breadcrumbs).toBe('(a|)', { a: [ + new Breadcrumb(childrenString + BREADCRUMB_MESSAGE_POSTFIX, childrenUrl), + new Breadcrumb(parentString + BREADCRUMB_MESSAGE_POSTFIX, parentUrl), + ].reverse() }); + }); + }); +}); diff --git a/src/app/core/breadcrumbs/quality-assurance-breadcrumb.service.spec.ts b/src/app/core/breadcrumbs/quality-assurance-breadcrumb.service.spec.ts index 4fef767214..cefa1d2f6f 100644 --- a/src/app/core/breadcrumbs/quality-assurance-breadcrumb.service.spec.ts +++ b/src/app/core/breadcrumbs/quality-assurance-breadcrumb.service.spec.ts @@ -5,7 +5,6 @@ import {QualityAssuranceBreadcrumbService} from './quality-assurance-breadcrumb. describe('QualityAssuranceBreadcrumbService', () => { let service: QualityAssuranceBreadcrumbService; - let dataService: any; let translateService: any = { instant: (str) => str, }; @@ -26,7 +25,7 @@ describe('QualityAssuranceBreadcrumbService', () => { })); beforeEach(() => { - service = new QualityAssuranceBreadcrumbService(dataService,translateService); + service = new QualityAssuranceBreadcrumbService(translateService); }); describe('getBreadcrumbs', () => { diff --git a/src/app/core/breadcrumbs/quality-assurance-breadcrumb.service.ts b/src/app/core/breadcrumbs/quality-assurance-breadcrumb.service.ts index 209ae0722c..a0299705a4 100644 --- a/src/app/core/breadcrumbs/quality-assurance-breadcrumb.service.ts +++ b/src/app/core/breadcrumbs/quality-assurance-breadcrumb.service.ts @@ -2,10 +2,7 @@ import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model'; import { BreadcrumbsProviderService } from './breadcrumbsProviderService'; import { Observable, of as observableOf } from 'rxjs'; import { Injectable } from '@angular/core'; -import { map } from 'rxjs/operators'; -import { getFirstCompletedRemoteData } from '../shared/operators'; import { TranslateService } from '@ngx-translate/core'; -import { QualityAssuranceTopicDataService } from '../notifications/qa/topics/quality-assurance-topic-data.service'; @@ -19,7 +16,6 @@ export class QualityAssuranceBreadcrumbService implements BreadcrumbsProviderSer private QUALITY_ASSURANCE_BREADCRUMB_KEY = 'admin.quality-assurance.breadcrumbs'; constructor( - protected qualityAssuranceService: QualityAssuranceTopicDataService, private translationService: TranslateService, ) { @@ -32,18 +28,14 @@ export class QualityAssuranceBreadcrumbService implements BreadcrumbsProviderSer * @param url The url to use as a link for this breadcrumb */ getBreadcrumbs(key: string, url: string): Observable { - const sourceId = key.split(':')[0]; - const topicId = key.split(':')[1]; + const args = key.split(':'); + const sourceId = args[0]; + const topicId = args.length > 2 ? args[args.length - 1] : args[1]; if (topicId) { - return this.qualityAssuranceService.getTopic(topicId).pipe( - getFirstCompletedRemoteData(), - map((topic) => { - return [new Breadcrumb(this.translationService.instant(this.QUALITY_ASSURANCE_BREADCRUMB_KEY), url), - new Breadcrumb(sourceId, `${url}${sourceId}`), - new Breadcrumb(topicId, undefined)]; - }) - ); + return observableOf( [new Breadcrumb(this.translationService.instant(this.QUALITY_ASSURANCE_BREADCRUMB_KEY), url), + new Breadcrumb(sourceId, `${url}${sourceId}`), + new Breadcrumb(topicId, undefined)]); } else { return observableOf([new Breadcrumb(this.translationService.instant(this.QUALITY_ASSURANCE_BREADCRUMB_KEY), url), new Breadcrumb(sourceId, `${url}${sourceId}`)]); diff --git a/src/app/core/coar-notify/notify-info/notify-info.component.html b/src/app/core/coar-notify/notify-info/notify-info.component.html new file mode 100644 index 0000000000..3370f83d03 --- /dev/null +++ b/src/app/core/coar-notify/notify-info/notify-info.component.html @@ -0,0 +1,18 @@ +
diff --git a/src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.scss b/src/app/core/coar-notify/notify-info/notify-info.component.scss similarity index 100% rename from src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.scss rename to src/app/core/coar-notify/notify-info/notify-info.component.scss diff --git a/src/app/core/coar-notify/notify-info/notify-info.component.spec.ts b/src/app/core/coar-notify/notify-info/notify-info.component.spec.ts new file mode 100644 index 0000000000..881e1b67fb --- /dev/null +++ b/src/app/core/coar-notify/notify-info/notify-info.component.spec.ts @@ -0,0 +1,37 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { NotifyInfoComponent } from './notify-info.component'; +import { NotifyInfoService } from './notify-info.service'; +import { TranslateModule } from '@ngx-translate/core'; +import { of } from 'rxjs'; + +describe('NotifyInfoComponent', () => { + let component: NotifyInfoComponent; + let fixture: ComponentFixture; + let notifyInfoServiceSpy: any; + + beforeEach(async () => { + notifyInfoServiceSpy = jasmine.createSpyObj('NotifyInfoService', ['getCoarLdnLocalInboxUrls']); + + await TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + declarations: [ NotifyInfoComponent ], + providers: [ + { provide: NotifyInfoService, useValue: notifyInfoServiceSpy } + ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(NotifyInfoComponent); + component = fixture.componentInstance; + component.coarRestApiUrl = of([]); + spyOn(component, 'generateCoarRestApiLinksHTML').and.returnValue(of('')); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/core/coar-notify/notify-info/notify-info.component.ts b/src/app/core/coar-notify/notify-info/notify-info.component.ts new file mode 100644 index 0000000000..b124b7baa1 --- /dev/null +++ b/src/app/core/coar-notify/notify-info/notify-info.component.ts @@ -0,0 +1,39 @@ +import { Component, OnInit } from '@angular/core'; +import { NotifyInfoService } from './notify-info.service'; +import { Observable, map, of } from 'rxjs'; + +@Component({ + selector: 'ds-notify-info', + templateUrl: './notify-info.component.html', + styleUrls: ['./notify-info.component.scss'], +}) +/** + * Component for displaying COAR notification information. + */ +export class NotifyInfoComponent implements OnInit { + /** + * Observable containing the COAR REST INBOX API URLs. + */ + coarRestApiUrl: Observable = of([]); + + constructor(private notifyInfoService: NotifyInfoService) {} + + ngOnInit() { + this.coarRestApiUrl = this.notifyInfoService.getCoarLdnLocalInboxUrls(); + } + + /** + * Generates HTML code for COAR REST API links. + * @returns An Observable that emits the generated HTML code. + */ + generateCoarRestApiLinksHTML() { + return this.coarRestApiUrl.pipe( + // transform the data into HTML + map((urls) => { + return urls.map(url => ` + ${url} + `).join(','); + }) + ); + } +} diff --git a/src/app/core/coar-notify/notify-info/notify-info.guard.spec.ts b/src/app/core/coar-notify/notify-info/notify-info.guard.spec.ts new file mode 100644 index 0000000000..81ac0db8d8 --- /dev/null +++ b/src/app/core/coar-notify/notify-info/notify-info.guard.spec.ts @@ -0,0 +1,49 @@ +import { TestBed } from '@angular/core/testing'; + +import { NotifyInfoGuard } from './notify-info.guard'; +import { Router } from '@angular/router'; +import { NotifyInfoService } from './notify-info.service'; +import { of } from 'rxjs'; + +describe('NotifyInfoGuard', () => { + let guard: NotifyInfoGuard; + let notifyInfoServiceSpy: any; + let router: any; + + beforeEach(() => { + notifyInfoServiceSpy = jasmine.createSpyObj('NotifyInfoService', ['isCoarConfigEnabled']); + router = jasmine.createSpyObj('Router', ['parseUrl']); + TestBed.configureTestingModule({ + providers: [ + NotifyInfoGuard, + { provide: NotifyInfoService, useValue: notifyInfoServiceSpy}, + { provide: Router, useValue: router} + ] + }); + guard = TestBed.inject(NotifyInfoGuard); + }); + + it('should be created', () => { + expect(guard).toBeTruthy(); + }); + + it('should return true if COAR config is enabled', (done) => { + notifyInfoServiceSpy.isCoarConfigEnabled.and.returnValue(of(true)); + + guard.canActivate(null, null).subscribe((result) => { + expect(result).toBe(true); + done(); + }); + }); + + it('should call parseUrl method of Router if COAR config is not enabled', (done) => { + notifyInfoServiceSpy.isCoarConfigEnabled.and.returnValue(of(false)); + router.parseUrl.and.returnValue(of('/404')); + + guard.canActivate(null, null).subscribe(() => { + expect(router.parseUrl).toHaveBeenCalledWith('/404'); + done(); + }); + }); + +}); diff --git a/src/app/core/coar-notify/notify-info/notify-info.guard.ts b/src/app/core/coar-notify/notify-info/notify-info.guard.ts new file mode 100644 index 0000000000..7af0821618 --- /dev/null +++ b/src/app/core/coar-notify/notify-info/notify-info.guard.ts @@ -0,0 +1,30 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router'; +import { Observable } from 'rxjs'; +import { NotifyInfoService } from './notify-info.service'; +import { map } from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root' +}) +export class NotifyInfoGuard implements CanActivate { + constructor( + private notifyInfoService: NotifyInfoService, + private router: Router + ) {} + + canActivate( + route: ActivatedRouteSnapshot, + state: RouterStateSnapshot + ): Observable { + return this.notifyInfoService.isCoarConfigEnabled().pipe( + map(coarLdnEnabled => { + if (coarLdnEnabled) { + return true; + } else { + return this.router.parseUrl('/404'); + } + }) + ); + } +} diff --git a/src/app/core/coar-notify/notify-info/notify-info.service.spec.ts b/src/app/core/coar-notify/notify-info/notify-info.service.spec.ts new file mode 100644 index 0000000000..a3cc360a96 --- /dev/null +++ b/src/app/core/coar-notify/notify-info/notify-info.service.spec.ts @@ -0,0 +1,56 @@ +import { TestBed } from '@angular/core/testing'; + +import { NotifyInfoService } from './notify-info.service'; +import { ConfigurationDataService } from '../../data/configuration-data.service'; +import { of } from 'rxjs'; +import { AuthorizationDataService } from '../../data/feature-authorization/authorization-data.service'; + +describe('NotifyInfoService', () => { + let service: NotifyInfoService; + let configurationDataService: any; + let authorizationDataService: any; + beforeEach(() => { + authorizationDataService = { + isAuthorized: jasmine.createSpy('isAuthorized').and.returnValue(of(true)), + }; + configurationDataService = { + findByPropertyName: jasmine.createSpy('findByPropertyName').and.returnValue(of({})), + }; + TestBed.configureTestingModule({ + providers: [ + NotifyInfoService, + { provide: ConfigurationDataService, useValue: configurationDataService }, + { provide: AuthorizationDataService, useValue: authorizationDataService } + ] + }); + service = TestBed.inject(NotifyInfoService); + authorizationDataService = TestBed.inject(AuthorizationDataService); + configurationDataService = TestBed.inject(ConfigurationDataService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); + + it('should retrieve and map coar configuration', () => { + const mockResponse = { payload: { values: ['true'] } }; + (configurationDataService.findByPropertyName as jasmine.Spy).and.returnValue(of(mockResponse)); + + service.isCoarConfigEnabled().subscribe((result) => { + expect(result).toBe(true); + }); + }); + + it('should retrieve and map LDN local inbox URLs', () => { + const mockResponse = { values: ['inbox1', 'inbox2'] }; + (configurationDataService.findByPropertyName as jasmine.Spy).and.returnValue(of(mockResponse)); + + service.getCoarLdnLocalInboxUrls().subscribe((result) => { + expect(result).toEqual(['inbox1', 'inbox2']); + }); + }); + + it('should return the inbox relation link', () => { + expect(service.getInboxRelationLink()).toBe('http://www.w3.org/ns/ldp#inbox'); + }); +}); diff --git a/src/app/core/coar-notify/notify-info/notify-info.service.ts b/src/app/core/coar-notify/notify-info/notify-info.service.ts new file mode 100644 index 0000000000..a15c64237c --- /dev/null +++ b/src/app/core/coar-notify/notify-info/notify-info.service.ts @@ -0,0 +1,52 @@ +import { Injectable } from '@angular/core'; +import { getFirstSucceededRemoteData, getRemoteDataPayload } from '../../shared/operators'; +import { ConfigurationDataService } from '../../data/configuration-data.service'; +import { map, Observable } from 'rxjs'; +import { ConfigurationProperty } from '../../shared/configuration-property.model'; +import { AuthorizationDataService } from '../../data/feature-authorization/authorization-data.service'; +import { FeatureID } from '../../data/feature-authorization/feature-id'; + +/** + * Service to check COAR availability and LDN services information for the COAR Notify functionalities + */ +@Injectable({ + providedIn: 'root' +}) +export class NotifyInfoService { + + /** + * The relation link for the inbox + */ + private _inboxRelationLink = 'http://www.w3.org/ns/ldp#inbox'; + + constructor( + private configService: ConfigurationDataService, + protected authorizationService: AuthorizationDataService, + ) {} + + isCoarConfigEnabled(): Observable { + return this.authorizationService.isAuthorized(FeatureID.CoarNotifyEnabled); + } + + /** + * Get the url of the local inbox from the REST configuration + * @returns the url of the local inbox + */ + getCoarLdnLocalInboxUrls(): Observable { + return this.configService.findByPropertyName('ldn.notify.inbox').pipe( + getFirstSucceededRemoteData(), + getRemoteDataPayload(), + map((response: ConfigurationProperty) => { + return response.values; + }) + ); + } + + /** + * Method to get the relation link for the inbox + * @returns the relation link for the inbox + */ + getInboxRelationLink(): string { + return this._inboxRelationLink; + } +} diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index f151f10f66..7088860674 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -185,8 +185,19 @@ import { FlatBrowseDefinition } from './shared/flat-browse-definition.model'; import { ValueListBrowseDefinition } from './shared/value-list-browse-definition.model'; import { NonHierarchicalBrowseDefinition } from './shared/non-hierarchical-browse-definition'; import { BulkAccessConditionOptions } from './config/models/bulk-access-condition-options.model'; -import { SuggestionTarget } from './suggestion-notifications/models/suggestion-target.model'; -import { SuggestionSource } from './suggestion-notifications/models/suggestion-source.model'; +import { CorrectionTypeDataService } from './submission/correctiontype-data.service'; +import { LdnServicesService } from '../admin/admin-ldn-services/ldn-services-data/ldn-services-data.service'; +import { LdnItemfiltersService } from '../admin/admin-ldn-services/ldn-services-data/ldn-itemfilters-data.service'; +import { + CoarNotifyConfigDataService +} from '../submission/sections/section-coar-notify/coar-notify-config-data.service'; +import { NotifyRequestsStatusDataService } from './data/notify-services-status-data.service'; +import { SuggestionTarget } from './notifications/models/suggestion-target.model'; +import { SuggestionSource } from './notifications/models/suggestion-source.model'; +import { NotifyRequestsStatus } from '../item-page/simple/notify-requests-status/notify-requests-status.model'; +import { LdnService } from '../admin/admin-ldn-services/ldn-services-model/ldn-services.model'; +import { Itemfilter } from '../admin/admin-ldn-services/ldn-services-model/ldn-service-itemfilters'; +import { SubmissionCoarNotifyConfig } from '../submission/sections/section-coar-notify/submission-coar-notify.config'; /** * When not in production, endpoint responses can be mocked for testing purposes @@ -309,7 +320,12 @@ const PROVIDERS = [ OrcidAuthService, OrcidQueueDataService, OrcidHistoryDataService, - SupervisionOrderDataService + SupervisionOrderDataService, + CorrectionTypeDataService, + LdnServicesService, + LdnItemfiltersService, + CoarNotifyConfigDataService, + NotifyRequestsStatusDataService ]; /** @@ -390,7 +406,11 @@ export const models = ItemRequest, BulkAccessConditionOptions, SuggestionTarget, - SuggestionSource + SuggestionSource, + LdnService, + Itemfilter, + SubmissionCoarNotifyConfig, + NotifyRequestsStatus, ]; @NgModule({ diff --git a/src/app/core/data/feature-authorization/feature-id.ts b/src/app/core/data/feature-authorization/feature-id.ts index b5f0c60dc6..3d5803b018 100644 --- a/src/app/core/data/feature-authorization/feature-id.ts +++ b/src/app/core/data/feature-authorization/feature-id.ts @@ -34,6 +34,7 @@ export enum FeatureID { CanEditItem = 'canEditItem', CanRegisterDOI = 'canRegisterDOI', CanSubscribe = 'canSubscribeDso', - EPersonForgotPassword = 'epersonForgotPassword', + CoarNotifyEnabled = 'coarNotifyEnabled', CanSeeQA = 'canSeeQA', + EPersonForgotPassword = 'epersonForgotPassword' } diff --git a/src/app/core/data/notify-services-status-data.service.ts b/src/app/core/data/notify-services-status-data.service.ts new file mode 100644 index 0000000000..9c354d0851 --- /dev/null +++ b/src/app/core/data/notify-services-status-data.service.ts @@ -0,0 +1,46 @@ +import { Injectable } from '@angular/core'; +import { RequestService } from './request.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 { IdentifiableDataService } from './base/identifiable-data.service'; +import { dataService } from './base/data-service.decorator'; +import { NotifyRequestsStatus } from '../../item-page/simple/notify-requests-status/notify-requests-status.model'; +import { NOTIFYREQUEST} from '../../item-page/simple/notify-requests-status/notify-requests-status.resource-type'; +import { Observable, map, take } from 'rxjs'; +import { RemoteData } from './remote-data'; +import { GetRequest } from './request.models'; + + +@Injectable() +@dataService(NOTIFYREQUEST) +export class NotifyRequestsStatusDataService extends IdentifiableDataService { + + constructor( + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected rdb: RemoteDataBuildService, + ) { + super('notifyrequests', requestService, rdbService, objectCache, halService); + } + + /** + * Retrieves the status of notify requests for a specific item. + * @param itemUuid The UUID of the item. + * @returns An Observable that emits the remote data containing the notify requests status. + */ + getNotifyRequestsStatus(itemUuid: string): Observable> { + const href$ = this.getEndpoint().pipe( + map((url: string) => url + '/' + itemUuid ), + ); + + href$.pipe(take(1)).subscribe((url: string) => { + const request = new GetRequest(this.requestService.generateRequestId(), url); + this.requestService.send(request, true); + }); + + return this.rdb.buildFromHref(href$); + } +} diff --git a/src/app/core/data/update-data.service.ts b/src/app/core/data/update-data.service.ts index 715b2ee413..664e2dcabc 100644 --- a/src/app/core/data/update-data.service.ts +++ b/src/app/core/data/update-data.service.ts @@ -201,9 +201,7 @@ export class UpdateDataServiceImpl extends Identifiab create(object: T, ...params: RequestParam[]): Observable> { return this.createData.create(object, ...params); } - /** - <<<<<<< HEAD * Perform a post on an endpoint related item with ID. Ex.: endpoint//related?item= * @param itemId The item id * @param relatedItemId The related item Id 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 f5a584fd3d..0982e3ed53 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,5 +1,6 @@ import { Store } from '@ngrx/store'; import { + FlushPatchOperationAction, NewPatchAddOperationAction, NewPatchMoveOperationAction, NewPatchRemoveOperationAction, @@ -99,6 +100,20 @@ export class JsonPatchOperationsBuilder { path.path)); } + /** + * Dispatches a new FlushPatchOperationAction + * + * @param path + * a JsonPatchOperationPathObject representing path + */ + flushOperation(path: JsonPatchOperationPathObject) { + this.store.dispatch( + new FlushPatchOperationAction( + path.rootElement, + path.subRootElement, + path.path)); + } + protected prepareValue(value: any, plain: boolean, first: boolean) { let operationValue: any = null; if (hasValue(value)) { diff --git a/src/app/core/json-patch/json-patch-operations.actions.ts b/src/app/core/json-patch/json-patch-operations.actions.ts index 6fea7a58fb..81cce174ec 100644 --- a/src/app/core/json-patch/json-patch-operations.actions.ts +++ b/src/app/core/json-patch/json-patch-operations.actions.ts @@ -20,6 +20,7 @@ export const JsonPatchOperationsActionTypes = { COMMIT_JSON_PATCH_OPERATIONS: type('dspace/core/patch/COMMIT_JSON_PATCH_OPERATIONS'), ROLLBACK_JSON_PATCH_OPERATIONS: type('dspace/core/patch/ROLLBACK_JSON_PATCH_OPERATIONS'), FLUSH_JSON_PATCH_OPERATIONS: type('dspace/core/patch/FLUSH_JSON_PATCH_OPERATIONS'), + FLUSH_JSON_PATCH_OPERATION: type('dspace/core/patch/FLUSH_JSON_PATCH_OPERATION'), START_TRANSACTION_JSON_PATCH_OPERATIONS: type('dspace/core/patch/START_TRANSACTION_JSON_PATCH_OPERATIONS'), DELETE_PENDING_JSON_PATCH_OPERATIONS: type('dspace/core/patch/DELETE_PENDING_JSON_PATCH_OPERATIONS'), }; @@ -120,6 +121,32 @@ export class FlushPatchOperationsAction implements Action { } } + +/** + * An ngrx action to flush a single operation of the JSON Patch operations + */ +export class FlushPatchOperationAction implements Action { + type = JsonPatchOperationsActionTypes.FLUSH_JSON_PATCH_OPERATION; + payload: { + resourceType: string; + resourceId: string; + path: string + }; + + /** + * Create a new FlushPatchOperationsAction + * + * @param resourceType + * the resource's type + * @param resourceId + * the resource's ID + * @param path + * the path of the operation + */ + constructor(resourceType: string, resourceId: string, path: string) { + this.payload = { resourceType, resourceId, path }; + } +} /** * An ngrx action to Add new HTTP/PATCH ADD operations to state */ @@ -284,4 +311,5 @@ export type PatchOperationsActions | NewPatchReplaceOperationAction | RollbacktPatchOperationsAction | StartTransactionPatchOperationsAction - | DeletePendingJsonPatchOperationsAction; + | DeletePendingJsonPatchOperationsAction + | FlushPatchOperationAction; diff --git a/src/app/core/json-patch/json-patch-operations.reducer.ts b/src/app/core/json-patch/json-patch-operations.reducer.ts index 86edd339e8..8eefacc518 100644 --- a/src/app/core/json-patch/json-patch-operations.reducer.ts +++ b/src/app/core/json-patch/json-patch-operations.reducer.ts @@ -12,7 +12,7 @@ import { CommitPatchOperationsAction, StartTransactionPatchOperationsAction, RollbacktPatchOperationsAction, - DeletePendingJsonPatchOperationsAction + DeletePendingJsonPatchOperationsAction, FlushPatchOperationAction } from './json-patch-operations.actions'; import { JsonPatchOperationModel, JsonPatchOperationType } from './json-patch.model'; @@ -71,7 +71,7 @@ export function jsonPatchOperationsReducer(state = initialState, action: PatchOp } case JsonPatchOperationsActionTypes.FLUSH_JSON_PATCH_OPERATIONS: { - return flushOperation(state, action as FlushPatchOperationsAction); + return flushOperations(state, action as FlushPatchOperationsAction); } case JsonPatchOperationsActionTypes.NEW_JSON_PATCH_ADD_OPERATION: { @@ -106,6 +106,10 @@ export function jsonPatchOperationsReducer(state = initialState, action: PatchOp return deletePendingOperations(state, action as DeletePendingJsonPatchOperationsAction); } + case JsonPatchOperationsActionTypes.FLUSH_JSON_PATCH_OPERATION: { + return flushOperation(state, action as FlushPatchOperationAction); + } + default: { return state; } @@ -197,6 +201,39 @@ function deletePendingOperations(state: JsonPatchOperationsState, action: Delete return null; } +/** + * Flush one operation from JsonPatchOperationsState. + * + * @param state + * the current state + * @param action + * an FlushPatchOperationsAction + * @return JsonPatchOperationsState + * the new state. + */ +function flushOperation(state: JsonPatchOperationsState, action: FlushPatchOperationAction): JsonPatchOperationsState { + const payload = action.payload; + if (state[payload.resourceType] && state[payload.resourceType].children) { + const body = state[payload.resourceType].children[payload.resourceId].body; + const operation = body.filter(operations => operations.operation.path === payload.path)[0]; + const operationIndex = body.indexOf(operation); + const newBody = [...body]; + newBody.splice(operationIndex, 1); + + return Object.assign({}, state, { + [action.payload.resourceType]: Object.assign({}, { + children: { + [action.payload.resourceId]: { + body: newBody, + } + }, + }) + }); + } else { + return state; + } +} + /** * Add new JSON patch operation list. * @@ -273,7 +310,7 @@ function hasValidBody(state: JsonPatchOperationsState, resourceType: any, resour * @return SubmissionObjectState * the new state, with the section new validity status. */ -function flushOperation(state: JsonPatchOperationsState, action: FlushPatchOperationsAction): JsonPatchOperationsState { +function flushOperations(state: JsonPatchOperationsState, action: FlushPatchOperationsAction): JsonPatchOperationsState { if (hasValue(state[ action.payload.resourceType ])) { let newChildren; if (isNotUndefined(action.payload.resourceId)) { diff --git a/src/app/core/suggestion-notifications/models/suggestion-objects.resource-type.ts b/src/app/core/notifications/models/suggestion-objects.resource-type.ts similarity index 100% rename from src/app/core/suggestion-notifications/models/suggestion-objects.resource-type.ts rename to src/app/core/notifications/models/suggestion-objects.resource-type.ts diff --git a/src/app/core/suggestion-notifications/models/suggestion-source-object.resource-type.ts b/src/app/core/notifications/models/suggestion-source-object.resource-type.ts similarity index 100% rename from src/app/core/suggestion-notifications/models/suggestion-source-object.resource-type.ts rename to src/app/core/notifications/models/suggestion-source-object.resource-type.ts diff --git a/src/app/core/suggestion-notifications/models/suggestion-source.model.ts b/src/app/core/notifications/models/suggestion-source.model.ts similarity index 100% rename from src/app/core/suggestion-notifications/models/suggestion-source.model.ts rename to src/app/core/notifications/models/suggestion-source.model.ts diff --git a/src/app/core/suggestion-notifications/models/suggestion-target-object.resource-type.ts b/src/app/core/notifications/models/suggestion-target-object.resource-type.ts similarity index 100% rename from src/app/core/suggestion-notifications/models/suggestion-target-object.resource-type.ts rename to src/app/core/notifications/models/suggestion-target-object.resource-type.ts diff --git a/src/app/core/suggestion-notifications/models/suggestion-target.model.ts b/src/app/core/notifications/models/suggestion-target.model.ts similarity index 100% rename from src/app/core/suggestion-notifications/models/suggestion-target.model.ts rename to src/app/core/notifications/models/suggestion-target.model.ts diff --git a/src/app/core/suggestion-notifications/models/suggestion.model.ts b/src/app/core/notifications/models/suggestion.model.ts similarity index 100% rename from src/app/core/suggestion-notifications/models/suggestion.model.ts rename to src/app/core/notifications/models/suggestion.model.ts diff --git a/src/app/core/notifications/qa/events/quality-assurance-event-data.service.ts b/src/app/core/notifications/qa/events/quality-assurance-event-data.service.ts index 7f7e68afaa..e266ace080 100644 --- a/src/app/core/notifications/qa/events/quality-assurance-event-data.service.ts +++ b/src/app/core/notifications/qa/events/quality-assurance-event-data.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; -import { find, take } from 'rxjs/operators'; +import { find, switchMap, take } from 'rxjs/operators'; import { ReplaceOperation } from 'fast-json-patch'; import { HALEndpointService } from '../../../shared/hal-endpoint.service'; @@ -25,6 +25,11 @@ import { SearchData, SearchDataImpl } from '../../../data/base/search-data'; import { DefaultChangeAnalyzer } from '../../../data/default-change-analyzer.service'; import { hasValue } from '../../../../shared/empty.util'; import { DeleteByIDRequest, PostRequest } from '../../../data/request.models'; +import { HttpHeaders, HttpParams } from '@angular/common/http'; +import { HttpOptions } from '../../../dspace-rest/dspace-rest.service'; +import { + QualityAssuranceEventData +} from '../../../../notifications/qa/project-entry-import-modal/project-entry-import-modal.component'; /** * The service handling all Quality Assurance topic REST requests. @@ -84,6 +89,16 @@ export class QualityAssuranceEventDataService extends IdentifiableDataService[]): Observable>> { + return this.searchData.searchBy('findByTopic', options, true, true, ...linksToFollow); + } + /** * Clear findByTopic requests from cache */ @@ -200,4 +215,38 @@ export class QualityAssuranceEventDataService extends IdentifiableDataService(requestId); } + + /** + * Perform a post on an endpoint related to correction type + * @param data the data to post + * @returns the RestResponse as an Observable + */ + postData(target: string, correctionType: string, related: string, reason: string): Observable> { + const requestId = this.requestService.generateRequestId(); + const href$ = this.getBrowseEndpoint(); + + return href$.pipe( + switchMap((href: string) => { + const options: HttpOptions = Object.create({}); + let headers = new HttpHeaders(); + headers = headers.append('Content-Type', 'application/json'); + options.headers = headers; + let params = new HttpParams(); + params = params.append('target', target) + .append('correctionType', correctionType); + options.params = params; + const request = new PostRequest(requestId, href, {'reason': reason} , options); + if (hasValue(this.responseMsToLive)) { + request.responseMsToLive = this.responseMsToLive; + } + this.requestService.send(request); + return this.rdbService.buildFromRequestUUID(requestId); + }) + ); + } + + public deleteQAEvent(qaEvent: QualityAssuranceEventData): Observable> { + return this.deleteData.delete(qaEvent.id); + } + } diff --git a/src/app/core/notifications/qa/models/quality-assurance-event.model.ts b/src/app/core/notifications/qa/models/quality-assurance-event.model.ts index 0cdb4a5745..1d66e5bb28 100644 --- a/src/app/core/notifications/qa/models/quality-assurance-event.model.ts +++ b/src/app/core/notifications/qa/models/quality-assurance-event.model.ts @@ -28,6 +28,8 @@ export interface SourceQualityAssuranceEventMessageObject { */ type: string; + reason: string; + /** * The value suggested by Notifications */ diff --git a/src/app/core/notifications/qa/source/quality-assurance-source-data.service.ts b/src/app/core/notifications/qa/source/quality-assurance-source-data.service.ts index 03a5da2e8c..f6a58fdd45 100644 --- a/src/app/core/notifications/qa/source/quality-assurance-source-data.service.ts +++ b/src/app/core/notifications/qa/source/quality-assurance-source-data.service.ts @@ -16,6 +16,7 @@ import { PaginatedList } from '../../../data/paginated-list.model'; import { FindListOptions } from '../../../data/find-list-options.model'; import { IdentifiableDataService } from '../../../data/base/identifiable-data.service'; import { FindAllData, FindAllDataImpl } from '../../../data/base/find-all-data'; +import { SearchData, SearchDataImpl } from '../../../data/base/search-data'; /** * The service handling all Quality Assurance source REST requests. @@ -25,6 +26,9 @@ import { FindAllData, FindAllDataImpl } from '../../../data/base/find-all-data'; export class QualityAssuranceSourceDataService extends IdentifiableDataService { private findAllData: FindAllData; + private searchAllData: SearchData; + + private searchByTargetMethod = 'byTarget'; /** * Initialize service variables @@ -43,6 +47,7 @@ export class QualityAssuranceSourceDataService extends IdentifiableDataService[]): Observable> { return this.findById(id, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); } + + /** + * Retrieves a paginated list of QualityAssuranceSourceObject objects that are associated with a given target object. + * @param options The options for the search query. + * @param useCachedVersionIfAvailable Whether to use a cached version of the data if available. + * @param reRequestOnStale Whether to re-request the data if the cached version is stale. + * @param linksToFollow The links to follow to retrieve the data. + * @returns An observable that emits a RemoteData object containing the paginated list of QualityAssuranceSourceObject objects. + */ + public getSourcesByTarget(options: FindListOptions = {}, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable>> { + return this.searchAllData.searchBy(this.searchByTargetMethod, options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + } } diff --git a/src/app/core/notifications/qa/topics/quality-assurance-topic-data.service.spec.ts b/src/app/core/notifications/qa/topics/quality-assurance-topic-data.service.spec.ts index 360e6b1ccd..bade6cace5 100644 --- a/src/app/core/notifications/qa/topics/quality-assurance-topic-data.service.spec.ts +++ b/src/app/core/notifications/qa/topics/quality-assurance-topic-data.service.spec.ts @@ -83,20 +83,27 @@ describe('QualityAssuranceTopicDataService', () => { spyOn((service as any).findAllData, 'findAll').and.callThrough(); spyOn((service as any), 'findById').and.callThrough(); + spyOn((service as any).searchData, 'searchBy').and.callThrough(); }); - describe('getTopics', () => { - it('should call findListByHref', (done) => { - service.getTopics().subscribe( - (res) => { - expect((service as any).findAllData.findAll).toHaveBeenCalledWith({}, true, true); - } + describe('searchTopicsByTarget', () => { + it('should call searchData.searchBy with the correct parameters', () => { + const options = { elementsPerPage: 10 }; + const useCachedVersionIfAvailable = true; + const reRequestOnStale = true; + + service.searchTopicsByTarget(options, useCachedVersionIfAvailable, reRequestOnStale); + + expect((service as any).searchData.searchBy).toHaveBeenCalledWith( + 'byTarget', + options, + useCachedVersionIfAvailable, + reRequestOnStale ); - done(); }); it('should return a RemoteData> for the object with the given URL', () => { - const result = service.getTopics(); + const result = service.searchTopicsByTarget(); const expected = cold('(a)', { a: paginatedListRD }); diff --git a/src/app/core/notifications/qa/topics/quality-assurance-topic-data.service.ts b/src/app/core/notifications/qa/topics/quality-assurance-topic-data.service.ts index 2bf5195bf1..919aaac71a 100644 --- a/src/app/core/notifications/qa/topics/quality-assurance-topic-data.service.ts +++ b/src/app/core/notifications/qa/topics/quality-assurance-topic-data.service.ts @@ -15,6 +15,7 @@ import { FindListOptions } from '../../../data/find-list-options.model'; import { IdentifiableDataService } from '../../../data/base/identifiable-data.service'; import { dataService } from '../../../data/base/data-service.decorator'; import { QUALITY_ASSURANCE_TOPIC_OBJECT } from '../models/quality-assurance-topic-object.resource-type'; +import { SearchData, SearchDataImpl } from '../../../data/base/search-data'; import { FindAllData, FindAllDataImpl } from '../../../data/base/find-all-data'; /** @@ -25,6 +26,10 @@ import { FindAllData, FindAllDataImpl } from '../../../data/base/find-all-data'; export class QualityAssuranceTopicDataService extends IdentifiableDataService { private findAllData: FindAllData; + private searchData: SearchData; + + private searchByTargetMethod = 'byTarget'; + private searchBySourceMethod = 'bySource'; /** * Initialize service variables @@ -43,23 +48,31 @@ export class QualityAssuranceTopicDataService extends IdentifiableDataService>> - * The list of Quality Assurance topics. + * Search for Quality Assurance topics. + * @param options The search options. + * @param useCachedVersionIfAvailable Whether to use cached version if available. + * @param reRequestOnStale Whether to re-request on stale. + * @param linksToFollow The links to follow. + * @returns An observable of remote data containing a paginated list of Quality Assurance topics. */ - public getTopics(options: FindListOptions = {}, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable>> { - return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + public searchTopicsByTarget(options: FindListOptions = {}, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable>> { + return this.searchData.searchBy(this.searchByTargetMethod, options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + } + + /** + * Searches for quality assurance topics by source. + * @param options The search options. + * @param useCachedVersionIfAvailable Whether to use a cached version if available. + * @param reRequestOnStale Whether to re-request the data if it's stale. + * @param linksToFollow The links to follow. + * @returns An observable of the remote data containing the paginated list of quality assurance topics. + */ + public searchTopicsBySource(options: FindListOptions = {}, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable>> { + return this.searchData.searchBy(this.searchBySourceMethod, options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); } /** diff --git a/src/app/core/suggestion-notifications/source/suggestion-source-data.service.ts b/src/app/core/notifications/source/suggestion-source-data.service.ts similarity index 100% rename from src/app/core/suggestion-notifications/source/suggestion-source-data.service.ts rename to src/app/core/notifications/source/suggestion-source-data.service.ts diff --git a/src/app/core/suggestion-notifications/source/suggestions-source-data.service.spec.ts b/src/app/core/notifications/source/suggestions-source-data.service.spec.ts similarity index 100% rename from src/app/core/suggestion-notifications/source/suggestions-source-data.service.spec.ts rename to src/app/core/notifications/source/suggestions-source-data.service.spec.ts diff --git a/src/app/core/suggestion-notifications/suggestion-data.service.spec.ts b/src/app/core/notifications/suggestion-data.service.spec.ts similarity index 100% rename from src/app/core/suggestion-notifications/suggestion-data.service.spec.ts rename to src/app/core/notifications/suggestion-data.service.spec.ts diff --git a/src/app/core/suggestion-notifications/suggestions-data.service.ts b/src/app/core/notifications/suggestions-data.service.ts similarity index 100% rename from src/app/core/suggestion-notifications/suggestions-data.service.ts rename to src/app/core/notifications/suggestions-data.service.ts diff --git a/src/app/core/suggestion-notifications/target/suggestion-target-data.service.ts b/src/app/core/notifications/target/suggestion-target-data.service.ts similarity index 100% rename from src/app/core/suggestion-notifications/target/suggestion-target-data.service.ts rename to src/app/core/notifications/target/suggestion-target-data.service.ts diff --git a/src/app/core/suggestion-notifications/target/suggestions-target-data.service.spec.ts b/src/app/core/notifications/target/suggestions-target-data.service.spec.ts similarity index 100% rename from src/app/core/suggestion-notifications/target/suggestions-target-data.service.spec.ts rename to src/app/core/notifications/target/suggestions-target-data.service.spec.ts diff --git a/src/app/core/submission/correctiontype-data.service.ts b/src/app/core/submission/correctiontype-data.service.ts new file mode 100644 index 0000000000..8a5bbb1fb8 --- /dev/null +++ b/src/app/core/submission/correctiontype-data.service.ts @@ -0,0 +1,89 @@ +import { Injectable } from '@angular/core'; + +import { dataService } from '../data/base/data-service.decorator'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { RequestService } from '../data/request.service'; +import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../cache/object-cache.service'; +import { IdentifiableDataService } from '../data/base/identifiable-data.service'; +import { SearchDataImpl } from '../data/base/search-data'; +import { CorrectionType } from './models/correctiontype.model'; +import { Observable, map } from 'rxjs'; +import { RemoteData } from '../data/remote-data'; +import { PaginatedList } from '../data/paginated-list.model'; +import { FindListOptions } from '../data/find-list-options.model'; +import { RequestParam } from '../cache/models/request-param.model'; +import { getAllSucceededRemoteDataPayload, getPaginatedListPayload } from '../shared/operators'; + +/** + * A service that provides methods to make REST requests with correctiontypes endpoint. + */ +@Injectable() +@dataService(CorrectionType.type) +export class CorrectionTypeDataService extends IdentifiableDataService { + protected linkPath = 'correctiontypes'; + protected searchByTopic = 'findByTopic'; + protected searchFindByItem = 'findByItem'; + private searchData: SearchDataImpl; + + constructor( + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected notificationsService: NotificationsService, + ) { + super('correctiontypes', requestService, rdbService, objectCache, halService); + + this.searchData = new SearchDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive); + } + + /** + * Get the correction type by id + * @param id the id of the correction type + * @param useCachedVersionIfAvailable use the cached version if available + * @param reRequestOnStale re-request on stale + * @returns {Observable>} the correction type + */ + getCorrectionTypeById(id: string, useCachedVersionIfAvailable = true, reRequestOnStale = true): Observable> { + return this.findById(id, useCachedVersionIfAvailable, reRequestOnStale); + } + + /** + * Search for the correction types for the item + * @param itemUuid the uuid of the item + * @param useCachedVersionIfAvailable use the cached version if available + * @returns the list of correction types for the item + */ + findByItem(itemUuid: string, useCachedVersionIfAvailable): Observable>> { + const options = new FindListOptions(); + options.searchParams = [new RequestParam('uuid', itemUuid)]; + return this.searchData.searchBy(this.searchFindByItem, options, useCachedVersionIfAvailable); + } + + /** + * Find the correction type for the topic + * @param topic the topic of the correction type to search for + * @param useCachedVersionIfAvailable use the cached version if available + * @param reRequestOnStale re-request on stale + * @returns the correction type for the topic + */ + findByTopic(topic: string, useCachedVersionIfAvailable = true, reRequestOnStale = true): Observable { + const options = new FindListOptions(); + options.searchParams = [ + { + fieldName: 'topic', + fieldValue: topic, + }, + ]; + + return this.searchData.searchBy(this.searchByTopic, options, useCachedVersionIfAvailable, reRequestOnStale).pipe( + getAllSucceededRemoteDataPayload(), + getPaginatedListPayload(), + map((list: CorrectionType[]) => { + return list[0]; + }) + ); + } +} diff --git a/src/app/core/submission/models/correctiontype.model.ts b/src/app/core/submission/models/correctiontype.model.ts new file mode 100644 index 0000000000..9329fa88d8 --- /dev/null +++ b/src/app/core/submission/models/correctiontype.model.ts @@ -0,0 +1,49 @@ +import { autoserialize, deserialize } from 'cerialize'; +import { typedObject } from '../../cache/builders/build-decorators'; +import { CacheableObject } from '../../cache/cacheable-object.model'; +import { ResourceType } from '../../shared/resource-type'; +import { excludeFromEquals } from '../../utilities/equals.decorators'; +import { HALLink } from '../../shared/hal-link.model'; + +@typedObject +/** + * Represents a correction type. It extends the CacheableObject. + * The correction type represents a type of correction that can be applied to a submission. + */ +export class CorrectionType extends CacheableObject { + static type = new ResourceType('correctiontype'); + + /** + * The object type + */ + @excludeFromEquals + @autoserialize + type: ResourceType; + @autoserialize + /** + * The unique identifier for the correction type mode. + */ + id: string; + @autoserialize + /** + * The topic of the correction type mode. + */ + topic: string; + @autoserialize + /** + * The discovery configuration for the correction type mode. + */ + discoveryConfiguration: string; + @autoserialize + /** + * The form used for creating a correction type. + */ + creationForm: string; + @deserialize + /** + * Represents the links associated with the correction type mode. + */ + _links: { + self: HALLink; + }; +} diff --git a/src/app/core/submission/models/workspaceitem-sections.model.ts b/src/app/core/submission/models/workspaceitem-sections.model.ts index a3ccd49dac..dd19c3fb8b 100644 --- a/src/app/core/submission/models/workspaceitem-sections.model.ts +++ b/src/app/core/submission/models/workspaceitem-sections.model.ts @@ -26,3 +26,5 @@ export type WorkspaceitemSectionDataType | WorkspaceitemSectionSherpaPoliciesObject | WorkspaceitemSectionIdentifiersObject | string; + + diff --git a/src/app/core/submission/workspaceitem-data.service.ts b/src/app/core/submission/workspaceitem-data.service.ts index 181530a29b..38810d8fd6 100644 --- a/src/app/core/submission/workspaceitem-data.service.ts +++ b/src/app/core/submission/workspaceitem-data.service.ts @@ -53,6 +53,20 @@ export class WorkspaceitemDataService extends IdentifiableDataService> { return this.deleteData.delete(objectId, copyVirtualMetadata); } + + /** + * Delete an existing object on the server + * @param href The self link of the object to be removed + * @param copyVirtualMetadata (optional parameter) the identifiers of the relationship types for which the virtual + * metadata should be saved as real metadata + * @return A RemoteData observable with an empty payload, but still representing the state of the request: statusCode, + * errorMessage, timeCompleted, etc + * Only emits once all request related to the DSO has been invalidated. + */ + public deleteByHref(href: string, copyVirtualMetadata?: string[]): Observable> { + return this.deleteData.deleteByHref(href, copyVirtualMetadata); + } + /** * Return the WorkspaceItem object found through the UUID of an item * @@ -96,19 +110,6 @@ export class WorkspaceitemDataService extends IdentifiableDataService> { - return this.deleteData.deleteByHref(href, copyVirtualMetadata); - } - /** * Make a new FindListRequest with given search method * diff --git a/src/app/footer/footer.component.html b/src/app/footer/footer.component.html index ac903929f6..b937b2ce60 100644 --- a/src/app/footer/footer.component.html +++ b/src/app/footer/footer.component.html @@ -82,6 +82,12 @@ + diff --git a/src/app/footer/footer.component.scss b/src/app/footer/footer.component.scss index f1a872c099..5f86137b44 100644 --- a/src/app/footer/footer.component.scss +++ b/src/app/footer/footer.component.scss @@ -22,6 +22,23 @@ } .bottom-footer { + .notify-enabled { + position: absolute; + bottom: 4px; + right: 0; + + .coar-notify-support-route { + padding: 0 calc(var(--bs-spacer) / 2); + color: inherit; + } + + .n-coar { + height: var(--ds-footer-n-coar-height); + margin-bottom: 8.5px; + } + + margin-top: 20px; + } ul { li { display: inline-flex; @@ -55,3 +72,4 @@ } + diff --git a/src/app/footer/footer.component.spec.ts b/src/app/footer/footer.component.spec.ts index 9f0250edc4..010d4e22c2 100644 --- a/src/app/footer/footer.component.spec.ts +++ b/src/app/footer/footer.component.spec.ts @@ -1,5 +1,5 @@ // ... test imports -import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, fakeAsync, inject, TestBed,waitForAsync } from '@angular/core/testing'; import { CUSTOM_ELEMENTS_SCHEMA, DebugElement } from '@angular/core'; @@ -9,6 +9,7 @@ import { By } from '@angular/platform-browser'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { StoreModule } from '@ngrx/store'; +import { of } from 'rxjs'; // Load the implementations that should be tested import { FooterComponent } from './footer.component'; @@ -17,15 +18,21 @@ import { TranslateLoaderMock } from '../shared/mocks/translate-loader.mock'; import { storeModuleConfig } from '../app.reducer'; import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service'; import { AuthorizationDataServiceStub } from '../shared/testing/authorization-service.stub'; +import { NotifyInfoService } from '../core/coar-notify/notify-info/notify-info.service'; +import { environment } from 'src/environments/environment'; + let comp: FooterComponent; +let compAny: any; let fixture: ComponentFixture; let de: DebugElement; let el: HTMLElement; -describe('Footer component', () => { +let notifyInfoService = { + isCoarConfigEnabled: () => of(true) +}; - // waitForAsync beforeEach +describe('Footer component', () => { beforeEach(waitForAsync(() => { return TestBed.configureTestingModule({ imports: [CommonModule, StoreModule.forRoot({}, storeModuleConfig), TranslateModule.forRoot({ @@ -38,6 +45,7 @@ describe('Footer component', () => { providers: [ FooterComponent, { provide: AuthorizationDataService, useClass: AuthorizationDataServiceStub }, + { provide: NotifyInfoService, useValue: notifyInfoService } ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }); @@ -46,9 +54,8 @@ describe('Footer component', () => { // synchronous beforeEach beforeEach(() => { fixture = TestBed.createComponent(FooterComponent); - - comp = fixture.componentInstance; // component test instance - + comp = fixture.componentInstance; + compAny = comp as any; // query for the title

by CSS element selector de = fixture.debugElement.query(By.css('p')); el = de.nativeElement; @@ -59,4 +66,56 @@ describe('Footer component', () => { expect(app).toBeTruthy(); })); + + it('should set showPrivacyPolicy to the value of environment.info.enablePrivacyStatement', () => { + expect(comp.showPrivacyPolicy).toBe(environment.info.enablePrivacyStatement); + }); + + it('should set showEndUserAgreement to the value of environment.info.enableEndUserAgreement', () => { + expect(comp.showEndUserAgreement).toBe(environment.info.enableEndUserAgreement); + }); + + describe('showCookieSettings', () => { + it('should call cookies.showSettings() if cookies is defined', () => { + const cookies = jasmine.createSpyObj('cookies', ['showSettings']); + compAny.cookies = cookies; + comp.showCookieSettings(); + expect(cookies.showSettings).toHaveBeenCalled(); + }); + + it('should not call cookies.showSettings() if cookies is undefined', () => { + compAny.cookies = undefined; + expect(() => comp.showCookieSettings()).not.toThrow(); + }); + + it('should return false', () => { + expect(comp.showCookieSettings()).toBeFalse(); + }); + }); + + describe('when coarLdnEnabled is true', () => { + beforeEach(() => { + spyOn(notifyInfoService, 'isCoarConfigEnabled').and.returnValue(of(true)); + fixture.detectChanges(); + }); + + it('should set coarLdnEnabled based on notifyInfoService', () => { + expect(comp.coarLdnEnabled).toBeTruthy(); + // Check if COAR Notify section is rendered + const notifySection = fixture.debugElement.query(By.css('.notify-enabled')); + expect(notifySection).toBeTruthy(); + }); + + it('should redirect to info/coar-notify-support', () => { + // Check if the link to the COAR Notify support page is present + const routerLink = fixture.debugElement.query(By.css('a[routerLink="info/coar-notify-support"].coar-notify-support-route')); + expect(routerLink).toBeTruthy(); + }); + + it('should have an img tag with the class "n-coar" when coarLdnEnabled is true', fakeAsync(() => { + // Check if the img tag with the class "n-coar" is present + const imgTag = fixture.debugElement.query(By.css('.notify-enabled img.n-coar')); + expect(imgTag).toBeTruthy(); + })); + }); }); diff --git a/src/app/footer/footer.component.ts b/src/app/footer/footer.component.ts index f5e4c3799a..86186c6b12 100644 --- a/src/app/footer/footer.component.ts +++ b/src/app/footer/footer.component.ts @@ -2,6 +2,7 @@ import { Component, Optional } from '@angular/core'; import { hasValue } from '../shared/empty.util'; import { KlaroService } from '../shared/cookies/klaro.service'; import { environment } from '../../environments/environment'; +import { NotifyInfoService } from '../core/coar-notify/notify-info/notify-info.service'; import { Observable } from 'rxjs'; import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service'; import { FeatureID } from '../core/data/feature-authorization/feature-id'; @@ -21,12 +22,17 @@ export class FooterComponent { showPrivacyPolicy = environment.info.enablePrivacyStatement; showEndUserAgreement = environment.info.enableEndUserAgreement; showSendFeedback$: Observable; + coarLdnEnabled: boolean; constructor( @Optional() private cookies: KlaroService, private authorizationService: AuthorizationDataService, + private notifyInfoService: NotifyInfoService ) { this.showSendFeedback$ = this.authorizationService.isAuthorized(FeatureID.CanSendFeedback); + this.notifyInfoService.isCoarConfigEnabled().subscribe(coarLdnEnabled => { + this.coarLdnEnabled = coarLdnEnabled; + }); } showCookieSettings() { diff --git a/src/app/home-page/home-page.component.ts b/src/app/home-page/home-page.component.ts index 9adc478b90..b4dfd06c33 100644 --- a/src/app/home-page/home-page.component.ts +++ b/src/app/home-page/home-page.component.ts @@ -1,24 +1,52 @@ -import { Component, Inject, OnInit } from '@angular/core'; -import { map } from 'rxjs/operators'; +import { Component, Inject, OnDestroy, OnInit, PLATFORM_ID } from '@angular/core'; +import { map, switchMap } from 'rxjs/operators'; import { ActivatedRoute } from '@angular/router'; import { Observable } from 'rxjs'; import { Site } from '../core/shared/site.model'; import { environment } from '../../environments/environment'; +import { isPlatformServer } from '@angular/common'; +import { ServerResponseService } from '../core/services/server-response.service'; +import { NotifyInfoService } from '../core/coar-notify/notify-info/notify-info.service'; +import { LinkDefinition, LinkHeadService } from '../core/services/link-head.service'; +import { isNotEmpty } from '../shared/empty.util'; + import { APP_CONFIG, AppConfig } from 'src/config/app-config.interface'; @Component({ selector: 'ds-home-page', styleUrls: ['./home-page.component.scss'], templateUrl: './home-page.component.html' }) -export class HomePageComponent implements OnInit { +export class HomePageComponent implements OnInit, OnDestroy { site$: Observable; recentSubmissionspageSize: number; + /** + * An array of LinkDefinition objects representing inbox links for the home page. + */ + inboxLinks: LinkDefinition[] = []; + constructor( @Inject(APP_CONFIG) protected appConfig: AppConfig, private route: ActivatedRoute, + private responseService: ServerResponseService, + private notifyInfoService: NotifyInfoService, + protected linkHeadService: LinkHeadService, + @Inject(PLATFORM_ID) private platformId: string ) { this.recentSubmissionspageSize = environment.homePage.recentSubmissions.pageSize; + // Get COAR REST API URLs from REST configuration + // only if COAR configuration is enabled + this.notifyInfoService.isCoarConfigEnabled().pipe( + switchMap((coarLdnEnabled: boolean) => { + if (coarLdnEnabled) { + return this.notifyInfoService.getCoarLdnLocalInboxUrls(); + } + }) + ).subscribe((coarRestApiUrls: string[]) => { + if (coarRestApiUrls.length > 0) { + this.initPageLinks(coarRestApiUrls); + } + }); } ngOnInit(): void { @@ -26,4 +54,38 @@ export class HomePageComponent implements OnInit { map((data) => data.site as Site), ); } + + /** + * Initializes page links for COAR REST API URLs. + * @param coarRestApiUrls An array of COAR REST API URLs. + */ + private initPageLinks(coarRestApiUrls: string[]): void { + const rel = this.notifyInfoService.getInboxRelationLink(); + let links = ''; + coarRestApiUrls.forEach((coarRestApiUrl: string) => { + // Add link to head + let tag: LinkDefinition = { + href: coarRestApiUrl, + rel: rel + }; + this.inboxLinks.push(tag); + this.linkHeadService.addTag(tag); + + links = links + (isNotEmpty(links) ? ', ' : '') + `<${coarRestApiUrl}> ; rel="${rel}"`; + }); + + if (isPlatformServer(this.platformId)) { + // Add link to response header + this.responseService.setHeader('Link', links); + } + } + + /** + * It removes the inbox links from the head of the html. + */ + ngOnDestroy(): void { + this.inboxLinks.forEach((link: LinkDefinition) => { + this.linkHeadService.removeTag(`href='${link.href}'`); + }); + } } diff --git a/src/app/info/info-routing.module.ts b/src/app/info/info-routing.module.ts index 4c497461e7..c91c534fe4 100644 --- a/src/app/info/info-routing.module.ts +++ b/src/app/info/info-routing.module.ts @@ -7,6 +7,9 @@ import { ThemedPrivacyComponent } from './privacy/themed-privacy.component'; import { ThemedFeedbackComponent } from './feedback/themed-feedback.component'; import { FeedbackGuard } from '../core/feedback/feedback.guard'; import { environment } from '../../environments/environment'; +import { COAR_NOTIFY_SUPPORT } from '../app-routing-paths'; +import { NotifyInfoComponent } from '../core/coar-notify/notify-info/notify-info.component'; +import { NotifyInfoGuard } from '../core/coar-notify/notify-info/notify-info.guard'; const imports = [ @@ -18,11 +21,20 @@ const imports = [ data: { title: 'info.feedback.title', breadcrumbKey: 'info.feedback' }, canActivate: [FeedbackGuard] } + ]), + RouterModule.forChild([ + { + path: COAR_NOTIFY_SUPPORT, + component: NotifyInfoComponent, + resolve: { breadcrumb: I18nBreadcrumbResolver }, + data: { title: 'info.coar-notify-support.title', breadcrumbKey: 'info.coar-notify' }, + canActivate: [NotifyInfoGuard] + } ]) ]; - if (environment.info.enableEndUserAgreement) { - imports.push( +if (environment.info.enableEndUserAgreement) { + imports.push( RouterModule.forChild([ { path: END_USER_AGREEMENT_PATH, @@ -31,9 +43,9 @@ const imports = [ data: { title: 'info.end-user-agreement.title', breadcrumbKey: 'info.end-user-agreement' } } ])); - } - if (environment.info.enablePrivacyStatement) { - imports.push( +} +if (environment.info.enablePrivacyStatement) { + imports.push( RouterModule.forChild([ { path: PRIVACY_PATH, @@ -42,7 +54,7 @@ const imports = [ data: { title: 'info.privacy.title', breadcrumbKey: 'info.privacy' } } ])); - } +} @NgModule({ imports: [ diff --git a/src/app/info/info.module.ts b/src/app/info/info.module.ts index ccc4af0a7d..0cadbf4bfa 100644 --- a/src/app/info/info.module.ts +++ b/src/app/info/info.module.ts @@ -13,6 +13,7 @@ import { FeedbackFormComponent } from './feedback/feedback-form/feedback-form.co import { ThemedFeedbackFormComponent } from './feedback/feedback-form/themed-feedback-form.component'; import { ThemedFeedbackComponent } from './feedback/themed-feedback.component'; import { FeedbackGuard } from '../core/feedback/feedback.guard'; +import { NotifyInfoComponent } from '../core/coar-notify/notify-info/notify-info.component'; const DECLARATIONS = [ @@ -25,7 +26,8 @@ const DECLARATIONS = [ FeedbackComponent, FeedbackFormComponent, ThemedFeedbackFormComponent, - ThemedFeedbackComponent + ThemedFeedbackComponent, + NotifyInfoComponent ]; @NgModule({ diff --git a/src/app/item-page/alerts/item-alerts.component.html b/src/app/item-page/alerts/item-alerts.component.html index cd71d23a91..f6304340f3 100644 --- a/src/app/item-page/alerts/item-alerts.component.html +++ b/src/app/item-page/alerts/item-alerts.component.html @@ -6,7 +6,10 @@

diff --git a/src/app/item-page/alerts/item-alerts.component.spec.ts b/src/app/item-page/alerts/item-alerts.component.spec.ts index a933eb6a58..47a4852cf1 100644 --- a/src/app/item-page/alerts/item-alerts.component.spec.ts +++ b/src/app/item-page/alerts/item-alerts.component.spec.ts @@ -4,16 +4,41 @@ import { TranslateModule } from '@ngx-translate/core'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { Item } from '../../core/shared/item.model'; import { By } from '@angular/platform-browser'; +import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; +import { DsoWithdrawnReinstateModalService, REQUEST_REINSTATE } from '../../shared/dso-page/dso-withdrawn-reinstate-service/dso-withdrawn-reinstate-modal.service'; +import { CorrectionTypeDataService } from '../../core/submission/correctiontype-data.service'; +import { TestScheduler } from 'rxjs/testing'; +import { CorrectionType } from '../../core/submission/models/correctiontype.model'; +import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; +import { createPaginatedList } from '../../shared/testing/utils.test'; +import { of } from 'rxjs'; describe('ItemAlertsComponent', () => { let component: ItemAlertsComponent; let fixture: ComponentFixture; let item: Item; + let authorizationService; + let dsoWithdrawnReinstateModalService; + let correctionTypeDataService; + let testScheduler: TestScheduler; + + const itemMock = Object.assign(new Item(), { + uuid: 'item-uuid', + id: 'item-uuid', + }); beforeEach(waitForAsync(() => { + authorizationService = jasmine.createSpyObj('authorizationService', ['isAuthorized']); + dsoWithdrawnReinstateModalService = jasmine.createSpyObj('dsoWithdrawnReinstateModalService', ['openCreateWithdrawnReinstateModal']); + correctionTypeDataService = jasmine.createSpyObj('correctionTypeDataService', ['findByItem']); TestBed.configureTestingModule({ declarations: [ItemAlertsComponent], imports: [TranslateModule.forRoot()], + providers: [ + { provide: AuthorizationDataService, useValue: authorizationService }, + { provide: DsoWithdrawnReinstateModalService, useValue: dsoWithdrawnReinstateModalService }, + { provide: CorrectionTypeDataService, useValue: correctionTypeDataService } + ], schemas: [NO_ERRORS_SCHEMA] }) .compileComponents(); @@ -21,7 +46,9 @@ describe('ItemAlertsComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(ItemAlertsComponent); + component = fixture.componentInstance; + component.item = itemMock; fixture.detectChanges(); }); @@ -61,6 +88,7 @@ describe('ItemAlertsComponent', () => { isWithdrawn: true }); component.item = item; + (correctionTypeDataService.findByItem).and.returnValue(createSuccessfulRemoteDataObject$([])); fixture.detectChanges(); }); @@ -76,6 +104,7 @@ describe('ItemAlertsComponent', () => { isWithdrawn: false }); component.item = item; + (correctionTypeDataService.findByItem).and.returnValue(createSuccessfulRemoteDataObject$([])); fixture.detectChanges(); }); @@ -84,4 +113,43 @@ describe('ItemAlertsComponent', () => { expect(privateWarning).toBeNull(); }); }); + + describe('when the item is reinstated', () => { + const correctionType = Object.assign(new CorrectionType(), { + topic: REQUEST_REINSTATE + }); + const correctionRD = createSuccessfulRemoteDataObject(createPaginatedList([correctionType])); + + beforeEach(() => { + item = itemMock; + component.item = item; + (correctionTypeDataService.findByItem).and.returnValue(of(correctionRD)); + + testScheduler = new TestScheduler((actual, expected) => { + expect(actual).toEqual(expected); + }); + fixture.detectChanges(); + }); + + it('should return true when user is not an admin and there is at least one correction with topic REQUEST_REINSTATE', () => { + testScheduler.run(({ cold, expectObservable }) => { + const isAdminMarble = 'a'; + const correctionMarble = 'b'; + const expectedMarble = 'c'; + + const isAdminValues = { a: false }; + const correctionValues = { b: correctionRD }; + const expectedValues = { c: true }; + + const isAdmin$ = cold(isAdminMarble, isAdminValues); + const correction$ = cold(correctionMarble, correctionValues); + + (authorizationService.isAuthorized).and.returnValue(isAdmin$); + (correctionTypeDataService.findByItem).and.returnValue(correction$); + + expectObservable(component.showReinstateButton$()).toBe(expectedMarble, expectedValues); + }); + }); + + }); }); diff --git a/src/app/item-page/alerts/item-alerts.component.ts b/src/app/item-page/alerts/item-alerts.component.ts index 2b1df58c9f..025dafb425 100644 --- a/src/app/item-page/alerts/item-alerts.component.ts +++ b/src/app/item-page/alerts/item-alerts.component.ts @@ -1,6 +1,12 @@ import { Component, Input } from '@angular/core'; import { Item } from '../../core/shared/item.model'; import { AlertType } from '../../shared/alert/alert-type'; +import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; +import { FeatureID } from '../../core/data/feature-authorization/feature-id'; +import { Observable, combineLatest, map } from 'rxjs'; +import { DsoWithdrawnReinstateModalService, REQUEST_REINSTATE } from '../../shared/dso-page/dso-withdrawn-reinstate-service/dso-withdrawn-reinstate-modal.service'; +import { CorrectionTypeDataService } from '../../core/submission/correctiontype-data.service'; +import { getFirstCompletedRemoteData, getPaginatedListPayload, getRemoteDataPayload } from 'src/app/core/shared/operators'; @Component({ selector: 'ds-item-alerts', @@ -21,4 +27,37 @@ export class ItemAlertsComponent { * @type {AlertType} */ public AlertTypeEnum = AlertType; + + constructor( + private authService: AuthorizationDataService, + private dsoWithdrawnReinstateModalService: DsoWithdrawnReinstateModalService, + private correctionTypeDataService: CorrectionTypeDataService + ) { + } + + /** + * Determines whether to show the reinstate button. + * The button is shown if the user is not an admin and the item has a reinstate request. + * @returns An Observable that emits a boolean value indicating whether to show the reinstate button. + */ + showReinstateButton$(): Observable { + const correction$ = this.correctionTypeDataService.findByItem(this.item.uuid, true).pipe( + getFirstCompletedRemoteData(), + getRemoteDataPayload(), + getPaginatedListPayload() + ); + const isAdmin$ = this.authService.isAuthorized(FeatureID.AdministratorOf); + return combineLatest([isAdmin$, correction$]).pipe( + map(([isAdmin, correction]) => { + return !isAdmin && correction.some((correctionType) => correctionType.topic === REQUEST_REINSTATE); + } + )); + } + + /** + * Opens the reinstate modal for the item. + */ + openReinstateModal() { + this.dsoWithdrawnReinstateModalService.openCreateWithdrawnReinstateModal(this.item, 'request-reinstate', this.item.isArchived); + } } diff --git a/src/app/item-page/field-components/metadata-uri-values/metadata-uri-values.component.html b/src/app/item-page/field-components/metadata-uri-values/metadata-uri-values.component.html index 9091beb6c7..4cef0a1592 100644 --- a/src/app/item-page/field-components/metadata-uri-values/metadata-uri-values.component.html +++ b/src/app/item-page/field-components/metadata-uri-values/metadata-uri-values.component.html @@ -1,5 +1,5 @@ - + {{ linktext || mdValue.value }} diff --git a/src/app/item-page/field-components/metadata-values/metadata-values.component.ts b/src/app/item-page/field-components/metadata-values/metadata-values.component.ts index 29c20c6e2a..34dd8cf351 100644 --- a/src/app/item-page/field-components/metadata-values/metadata-values.component.ts +++ b/src/app/item-page/field-components/metadata-values/metadata-values.component.ts @@ -5,6 +5,7 @@ import { BrowseDefinition } from '../../../core/shared/browse-definition.model'; import { hasValue } from '../../../shared/empty.util'; import { VALUE_LIST_BROWSE_DEFINITION } from '../../../core/shared/value-list-browse-definition.resource-type'; import { ImageField } from '../../simple/field-components/specific-field/item-page-field.component'; +import { environment } from '../../../../environments/environment'; /** * This component renders the configured 'values' into the ds-metadata-field-wrapper component. @@ -96,4 +97,14 @@ export class MetadataValuesComponent implements OnChanges { } return queryParams; } + + + /** + * Checks if the given link value is an internal link. + * @param linkValue - The link value to check. + * @returns True if the link value starts with the base URL defined in the environment configuration, false otherwise. + */ + hasInternalLink(linkValue: string): boolean { + return linkValue.startsWith(environment.ui.baseUrl); + } } diff --git a/src/app/item-page/full/full-item-page.component.spec.ts b/src/app/item-page/full/full-item-page.component.spec.ts index 9fc078c2cd..c09c3177e3 100644 --- a/src/app/item-page/full/full-item-page.component.spec.ts +++ b/src/app/item-page/full/full-item-page.component.spec.ts @@ -23,6 +23,7 @@ import { RemoteData } from '../../core/data/remote-data'; import { ServerResponseService } from '../../core/services/server-response.service'; import { SignpostingDataService } from '../../core/data/signposting-data.service'; import { LinkHeadService } from '../../core/services/link-head.service'; +import { NotifyInfoService } from '../../core/coar-notify/notify-info/notify-info.service'; const mockItem: Item = Object.assign(new Item(), { bundles: createSuccessfulRemoteDataObject$(createPaginatedList([])), @@ -61,6 +62,7 @@ describe('FullItemPageComponent', () => { let serverResponseService: jasmine.SpyObj; let signpostingDataService: jasmine.SpyObj; let linkHeadService: jasmine.SpyObj; + let notifyInfoService: jasmine.SpyObj; const mocklink = { href: 'http://test.org', @@ -105,6 +107,12 @@ describe('FullItemPageComponent', () => { removeTag: jasmine.createSpy('removeTag'), }); + notifyInfoService = jasmine.createSpyObj('NotifyInfoService', { + isCoarConfigEnabled: observableOf(true), + getCoarLdnLocalInboxUrls: observableOf(['http://test.org']), + getInboxRelationLink: observableOf('http://test.org'), + }); + TestBed.configureTestingModule({ imports: [TranslateModule.forRoot({ loader: { @@ -122,6 +130,7 @@ describe('FullItemPageComponent', () => { { provide: ServerResponseService, useValue: serverResponseService }, { provide: SignpostingDataService, useValue: signpostingDataService }, { provide: LinkHeadService, useValue: linkHeadService }, + { provide: NotifyInfoService, useValue: notifyInfoService }, { provide: PLATFORM_ID, useValue: 'server' } ], schemas: [NO_ERRORS_SCHEMA] @@ -178,7 +187,7 @@ describe('FullItemPageComponent', () => { it('should add the signposting links', () => { expect(serverResponseService.setHeader).toHaveBeenCalled(); - expect(linkHeadService.addTag).toHaveBeenCalledTimes(2); + expect(linkHeadService.addTag).toHaveBeenCalledTimes(3); }); }); describe('when the item is withdrawn and the user is not an admin', () => { @@ -207,7 +216,7 @@ describe('FullItemPageComponent', () => { it('should add the signposting links', () => { expect(serverResponseService.setHeader).toHaveBeenCalled(); - expect(linkHeadService.addTag).toHaveBeenCalledTimes(2); + expect(linkHeadService.addTag).toHaveBeenCalledTimes(3); }); }); @@ -224,7 +233,7 @@ describe('FullItemPageComponent', () => { it('should add the signposting links', () => { expect(serverResponseService.setHeader).toHaveBeenCalled(); - expect(linkHeadService.addTag).toHaveBeenCalledTimes(2); + expect(linkHeadService.addTag).toHaveBeenCalledTimes(3); }); }); }); diff --git a/src/app/item-page/full/full-item-page.component.ts b/src/app/item-page/full/full-item-page.component.ts index 31dd2c5fc2..09238c30ab 100644 --- a/src/app/item-page/full/full-item-page.component.ts +++ b/src/app/item-page/full/full-item-page.component.ts @@ -19,6 +19,7 @@ import { AuthorizationDataService } from '../../core/data/feature-authorization/ import { ServerResponseService } from '../../core/services/server-response.service'; import { SignpostingDataService } from '../../core/data/signposting-data.service'; import { LinkHeadService } from '../../core/services/link-head.service'; +import { NotifyInfoService } from '../../core/coar-notify/notify-info/notify-info.service'; /** * This component renders a full item page. @@ -55,9 +56,10 @@ export class FullItemPageComponent extends ItemPageComponent implements OnInit, protected responseService: ServerResponseService, protected signpostingDataService: SignpostingDataService, protected linkHeadService: LinkHeadService, + protected notifyInfoService: NotifyInfoService, @Inject(PLATFORM_ID) protected platformId: string, ) { - super(route, router, items, authService, authorizationService, responseService, signpostingDataService, linkHeadService, platformId); + super(route, router, items, authService, authorizationService, responseService, signpostingDataService, linkHeadService, notifyInfoService, platformId); } /*** AoT inheritance fix, will hopefully be resolved in the near future **/ diff --git a/src/app/item-page/item-page.module.ts b/src/app/item-page/item-page.module.ts index a8d41d1535..7fd7b3b623 100644 --- a/src/app/item-page/item-page.module.ts +++ b/src/app/item-page/item-page.module.ts @@ -60,6 +60,9 @@ import { ThemedItemAlertsComponent } from './alerts/themed-item-alerts.component import { ThemedFullFileSectionComponent } from './full/field-components/file-section/themed-full-file-section.component'; +import { QaEventNotificationComponent } from './simple/qa-event-notification/qa-event-notification.component'; +import { NotifyRequestsStatusComponent } from './simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component'; +import { RequestStatusAlertBoxComponent } from './simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component'; const ENTRY_COMPONENTS = [ // put only entry components that use custom decorator @@ -103,6 +106,9 @@ const DECLARATIONS = [ ItemAlertsComponent, ThemedItemAlertsComponent, BitstreamRequestACopyPageComponent, + QaEventNotificationComponent, + NotifyRequestsStatusComponent, + RequestStatusAlertBoxComponent ]; @NgModule({ diff --git a/src/app/item-page/item-shared.module.ts b/src/app/item-page/item-shared.module.ts index 8b7243acde..49f575cbb3 100644 --- a/src/app/item-page/item-shared.module.ts +++ b/src/app/item-page/item-shared.module.ts @@ -30,11 +30,15 @@ import { RelatedItemsComponent } from './simple/related-items/related-items-comp import { ThemedMetadataRepresentationListComponent } from './simple/metadata-representation-list/themed-metadata-representation-list.component'; +import { + ItemWithdrawnReinstateModalComponent +} from '../shared/correction-suggestion/withdrawn-reinstate-modal.component'; import { ItemPageImgFieldComponent } from './simple/field-components/specific-field/img/item-page-img-field.component'; const ENTRY_COMPONENTS = [ ItemVersionsDeleteModalComponent, ItemVersionsSummaryModalComponent, + ItemWithdrawnReinstateModalComponent ]; diff --git a/src/app/item-page/simple/item-page.component.html b/src/app/item-page/simple/item-page.component.html index cc9983bb35..dc8ed87a86 100644 --- a/src/app/item-page/simple/item-page.component.html +++ b/src/app/item-page/simple/item-page.component.html @@ -2,6 +2,8 @@
+ + diff --git a/src/app/item-page/simple/item-page.component.spec.ts b/src/app/item-page/simple/item-page.component.spec.ts index b3202108f4..d4a83fbf85 100644 --- a/src/app/item-page/simple/item-page.component.spec.ts +++ b/src/app/item-page/simple/item-page.component.spec.ts @@ -26,6 +26,7 @@ import { ServerResponseService } from '../../core/services/server-response.servi import { SignpostingDataService } from '../../core/data/signposting-data.service'; import { LinkDefinition, LinkHeadService } from '../../core/services/link-head.service'; import { SignpostingLink } from '../../core/data/signposting-links.model'; +import { NotifyInfoService } from '../../core/coar-notify/notify-info/notify-info.service'; const mockItem: Item = Object.assign(new Item(), { bundles: createSuccessfulRemoteDataObject$(createPaginatedList([])), @@ -62,6 +63,7 @@ describe('ItemPageComponent', () => { let serverResponseService: jasmine.SpyObj; let signpostingDataService: jasmine.SpyObj; let linkHeadService: jasmine.SpyObj; + let notifyInfoService: jasmine.SpyObj; const mockMetadataService = { /* eslint-disable no-empty,@typescript-eslint/no-empty-function */ @@ -73,6 +75,8 @@ describe('ItemPageComponent', () => { data: observableOf({ dso: createSuccessfulRemoteDataObject(mockItem) }) }); + const getCoarLdnLocalInboxUrls = ['http://InboxUrls.org', 'http://InboxUrls2.org']; + beforeEach(waitForAsync(() => { authService = jasmine.createSpyObj('authService', { isAuthenticated: observableOf(true), @@ -94,6 +98,12 @@ describe('ItemPageComponent', () => { removeTag: jasmine.createSpy('removeTag'), }); + notifyInfoService = jasmine.createSpyObj('NotifyInfoService', { + getInboxRelationLink: 'http://www.w3.org/ns/ldp#inbox', + isCoarConfigEnabled: observableOf(true), + getCoarLdnLocalInboxUrls: observableOf(getCoarLdnLocalInboxUrls), + }); + TestBed.configureTestingModule({ imports: [TranslateModule.forRoot({ loader: { @@ -112,6 +122,7 @@ describe('ItemPageComponent', () => { { provide: ServerResponseService, useValue: serverResponseService }, { provide: SignpostingDataService, useValue: signpostingDataService }, { provide: LinkHeadService, useValue: linkHeadService }, + { provide: NotifyInfoService, useValue: notifyInfoService}, { provide: PLATFORM_ID, useValue: 'server' }, ], @@ -166,7 +177,7 @@ describe('ItemPageComponent', () => { it('should add the signposting links', () => { expect(serverResponseService.setHeader).toHaveBeenCalled(); - expect(linkHeadService.addTag).toHaveBeenCalledTimes(2); + expect(linkHeadService.addTag).toHaveBeenCalledTimes(4); }); @@ -175,7 +186,7 @@ describe('ItemPageComponent', () => { expect(comp.signpostingLinks).toEqual([mocklink, mocklink2]); // Check if linkHeadService.addTag() was called with the correct arguments - expect(linkHeadService.addTag).toHaveBeenCalledTimes(mockSignpostingLinks.length); + expect(linkHeadService.addTag).toHaveBeenCalledTimes(mockSignpostingLinks.length + getCoarLdnLocalInboxUrls.length); let expected: LinkDefinition = mockSignpostingLinks[0] as LinkDefinition; expect(linkHeadService.addTag).toHaveBeenCalledWith(expected); expected = { @@ -186,8 +197,7 @@ describe('ItemPageComponent', () => { }); it('should set Link header on the server', () => { - - expect(serverResponseService.setHeader).toHaveBeenCalledWith('Link', ' ; rel="rel1" ; type="type1" , ; rel="rel2" '); + expect(serverResponseService.setHeader).toHaveBeenCalledWith('Link', ' ; rel="rel1" ; type="type1" , ; rel="rel2" , ; rel="http://www.w3.org/ns/ldp#inbox", ; rel="http://www.w3.org/ns/ldp#inbox"'); }); }); @@ -217,7 +227,7 @@ describe('ItemPageComponent', () => { it('should add the signposting links', () => { expect(serverResponseService.setHeader).toHaveBeenCalled(); - expect(linkHeadService.addTag).toHaveBeenCalledTimes(2); + expect(linkHeadService.addTag).toHaveBeenCalledTimes(4); }); }); @@ -234,7 +244,7 @@ describe('ItemPageComponent', () => { it('should add the signposting links', () => { expect(serverResponseService.setHeader).toHaveBeenCalled(); - expect(linkHeadService.addTag).toHaveBeenCalledTimes(2); + expect(linkHeadService.addTag).toHaveBeenCalledTimes(4); }); }); diff --git a/src/app/item-page/simple/item-page.component.ts b/src/app/item-page/simple/item-page.component.ts index b9be6bebfb..a057e99715 100644 --- a/src/app/item-page/simple/item-page.component.ts +++ b/src/app/item-page/simple/item-page.component.ts @@ -2,8 +2,8 @@ import { ChangeDetectionStrategy, Component, Inject, OnDestroy, OnInit, PLATFORM import { ActivatedRoute, Router } from '@angular/router'; import { isPlatformServer } from '@angular/common'; -import { Observable } from 'rxjs'; -import { map, take } from 'rxjs/operators'; +import { Observable, combineLatest } from 'rxjs'; +import { map, switchMap, take } from 'rxjs/operators'; import { ItemDataService } from '../../core/data/item-data.service'; import { RemoteData } from '../../core/data/remote-data'; @@ -21,6 +21,7 @@ import { SignpostingDataService } from '../../core/data/signposting-data.service import { SignpostingLink } from '../../core/data/signposting-links.model'; import { isNotEmpty } from '../../shared/empty.util'; import { LinkDefinition, LinkHeadService } from '../../core/services/link-head.service'; +import { NotifyInfoService } from 'src/app/core/coar-notify/notify-info/notify-info.service'; /** * This component renders a simple item page. @@ -32,7 +33,7 @@ import { LinkDefinition, LinkHeadService } from '../../core/services/link-head.s styleUrls: ['./item-page.component.scss'], templateUrl: './item-page.component.html', changeDetection: ChangeDetectionStrategy.OnPush, - animations: [fadeInOut] + animations: [fadeInOut], }) export class ItemPageComponent implements OnInit, OnDestroy { @@ -68,6 +69,13 @@ export class ItemPageComponent implements OnInit, OnDestroy { */ signpostingLinks: SignpostingLink[] = []; + /** + * An array of LinkDefinition objects representing inbox links for the item page. + */ + inboxTags: LinkDefinition[] = []; + + coarRestApiUrls: string[] = []; + constructor( protected route: ActivatedRoute, protected router: Router, @@ -77,6 +85,7 @@ export class ItemPageComponent implements OnInit, OnDestroy { protected responseService: ServerResponseService, protected signpostingDataService: SignpostingDataService, protected linkHeadService: LinkHeadService, + protected notifyInfoService: NotifyInfoService, @Inject(PLATFORM_ID) protected platformId: string ) { this.initPageLinks(); @@ -106,7 +115,8 @@ export class ItemPageComponent implements OnInit, OnDestroy { */ private initPageLinks(): void { this.route.params.subscribe(params => { - this.signpostingDataService.getLinks(params.id).pipe(take(1)).subscribe((signpostingLinks: SignpostingLink[]) => { + combineLatest([this.signpostingDataService.getLinks(params.id).pipe(take(1)), this.getCoarLdnLocalInboxUrls()]) + .subscribe(([signpostingLinks, coarRestApiUrls]) => { let links = ''; this.signpostingLinks = signpostingLinks; @@ -124,6 +134,11 @@ export class ItemPageComponent implements OnInit, OnDestroy { this.linkHeadService.addTag(tag); }); + if (coarRestApiUrls.length > 0) { + let inboxLinks = this.initPageInboxLinks(coarRestApiUrls); + links = links + (isNotEmpty(links) ? ', ' : '') + inboxLinks; + } + if (isPlatformServer(this.platformId)) { this.responseService.setHeader('Link', links); } @@ -131,9 +146,49 @@ export class ItemPageComponent implements OnInit, OnDestroy { }); } + /** + * Sets the COAR LDN local inbox URL if COAR configuration is enabled. + * If the COAR LDN local inbox URL is retrieved successfully, initializes the page inbox links. + */ + private getCoarLdnLocalInboxUrls(): Observable { + return this.notifyInfoService.isCoarConfigEnabled().pipe( + switchMap((coarLdnEnabled: boolean) => { + if (coarLdnEnabled) { + return this.notifyInfoService.getCoarLdnLocalInboxUrls(); + } + }) + ); + } + + /** + * Initializes the page inbox links. + * @param coarRestApiUrls - An array of COAR REST API URLs. + */ + private initPageInboxLinks(coarRestApiUrls: string[]): string { + const rel = this.notifyInfoService.getInboxRelationLink(); + let links = ''; + + coarRestApiUrls.forEach((coarRestApiUrl: string) => { + // Add link to head + let tag: LinkDefinition = { + href: coarRestApiUrl, + rel: rel + }; + this.inboxTags.push(tag); + this.linkHeadService.addTag(tag); + + links = links + (isNotEmpty(links) ? ', ' : '') + `<${coarRestApiUrl}> ; rel="${rel}"`; + }); + + return links; + } + ngOnDestroy(): void { this.signpostingLinks.forEach((link: SignpostingLink) => { this.linkHeadService.removeTag(`href='${link.href}'`); }); + this.inboxTags.forEach((link: LinkDefinition) => { + this.linkHeadService.removeTag(`href='${link.href}'`); + }); } } diff --git a/src/app/item-page/simple/item-types/publication/publication.component.html b/src/app/item-page/simple/item-types/publication/publication.component.html index 3749f63964..771ea84af0 100644 --- a/src/app/item-page/simple/item-types/publication/publication.component.html +++ b/src/app/item-page/simple/item-types/publication/publication.component.html @@ -84,6 +84,22 @@ [label]="'item.page.uri'"> + + + + + + + +
{{"item.page.link.full" | translate}} diff --git a/src/app/item-page/simple/item-types/untyped-item/untyped-item.component.html b/src/app/item-page/simple/item-types/untyped-item/untyped-item.component.html index 904b7e039c..d30250f956 100644 --- a/src/app/item-page/simple/item-types/untyped-item/untyped-item.component.html +++ b/src/app/item-page/simple/item-types/untyped-item/untyped-item.component.html @@ -70,6 +70,22 @@ [label]="'item.page.uri'"> + + + + + + + +
{{"item.page.link.full" | translate}} diff --git a/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.html b/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.html new file mode 100644 index 0000000000..c68255f2ed --- /dev/null +++ b/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.html @@ -0,0 +1,5 @@ + + + + + diff --git a/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.scss b/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.scss similarity index 100% rename from src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.scss rename to src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.scss diff --git a/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.spec.ts b/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.spec.ts new file mode 100644 index 0000000000..0ec4febc0b --- /dev/null +++ b/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.spec.ts @@ -0,0 +1,88 @@ +import { ComponentFixture, TestBed, tick, fakeAsync } from '@angular/core/testing'; +import { NotifyRequestsStatusComponent } from './notify-requests-status.component'; +import { NotifyRequestsStatusDataService } from 'src/app/core/data/notify-services-status-data.service'; +import { NotifyRequestsStatus } from '../notify-requests-status.model'; +import { RequestStatusEnum } from '../notify-status.enum'; +import { createSuccessfulRemoteDataObject$ } from '../../../../shared/remote-data.utils'; +import { TranslateModule } from '@ngx-translate/core'; + +describe('NotifyRequestsStatusComponent', () => { + let component: NotifyRequestsStatusComponent; + let fixture: ComponentFixture; + let notifyInfoServiceSpy; + + const mock: NotifyRequestsStatus = Object.assign(new NotifyRequestsStatus(), { + notifyStatus: [], + itemuuid: 'testUuid' + }); + + beforeEach(() => { + notifyInfoServiceSpy = { + getNotifyRequestsStatus:() => createSuccessfulRemoteDataObject$(mock) + }; + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + declarations: [NotifyRequestsStatusComponent], + providers: [ + { provide: NotifyRequestsStatusDataService, useValue: notifyInfoServiceSpy } + ] + }); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(NotifyRequestsStatusComponent); + component = fixture.componentInstance; + }); + + it('should create the component', () => { + expect(component).toBeTruthy(); + }); + + it('should fetch data from the service on initialization', fakeAsync(() => { + const mockData: NotifyRequestsStatus = Object.assign(new NotifyRequestsStatus(), { + notifyStatus: [], + itemuuid: 'testUuid' + }); + component.itemUuid = mockData.itemuuid; + spyOn(notifyInfoServiceSpy, 'getNotifyRequestsStatus').and.callThrough(); + component.ngOnInit(); + fixture.detectChanges(); + tick(); + + expect(notifyInfoServiceSpy.getNotifyRequestsStatus).toHaveBeenCalledWith('testUuid'); + component.requestMap$.subscribe((map) => { + expect(map.size).toBe(0); + }); + })); + + it('should group data by status', () => { + const mockData: NotifyRequestsStatus = Object.assign(new NotifyRequestsStatus(), { + notifyStatus: [ + { + serviceName: 'test1', + serviceUrl: 'test', + status: RequestStatusEnum.ACCEPTED, + }, + { + serviceName: 'test2', + serviceUrl: 'test', + status: RequestStatusEnum.REJECTED, + }, + { + serviceName: 'test3', + serviceUrl: 'test', + status: RequestStatusEnum.ACCEPTED, + }, + ], + itemUuid: 'testUuid' + }); + spyOn(notifyInfoServiceSpy, 'getNotifyRequestsStatus').and.returnValue(createSuccessfulRemoteDataObject$(mockData)); + fixture.detectChanges(); + (component as any).groupDataByStatus(mockData); + component.requestMap$.subscribe((map) => { + expect(map.size).toBe(2); + expect(map.get(RequestStatusEnum.ACCEPTED)?.length).toBe(2); + expect(map.get(RequestStatusEnum.REJECTED)?.length).toBe(1); + }); + }); +}); diff --git a/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.ts b/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.ts new file mode 100644 index 0000000000..381a3751a9 --- /dev/null +++ b/src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.ts @@ -0,0 +1,78 @@ +import { + ChangeDetectionStrategy, + Component, + Input, + OnInit, +} from '@angular/core'; +import { Observable, filter, map } from 'rxjs'; +import { + NotifyRequestsStatus, + NotifyStatuses, +} from '../notify-requests-status.model'; +import { NotifyRequestsStatusDataService } from '../../../../core/data/notify-services-status-data.service'; +import { RequestStatusEnum } from '../notify-status.enum'; +import { + getFirstCompletedRemoteData, + getRemoteDataPayload, +} from '../../../../core/shared/operators'; +import { hasValue } from '../../../../shared/empty.util'; +@Component({ + selector: 'ds-notify-requests-status', + templateUrl: './notify-requests-status.component.html', + styleUrls: ['./notify-requests-status.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) + +/** + * Component to show an alert box for each update in th Notify feature (e.g. COAR updates) + */ + +export class NotifyRequestsStatusComponent implements OnInit { + /** + * The UUID of the item. + */ + @Input() itemUuid: string; + + /** + * Observable representing the request map. + * The map contains request status enums as keys and arrays of notify statuses as values. + */ + requestMap$: Observable>; + + constructor(private notifyInfoService: NotifyRequestsStatusDataService) { } + + ngOnInit(): void { + this.requestMap$ = this.notifyInfoService + .getNotifyRequestsStatus(this.itemUuid) + .pipe( + getFirstCompletedRemoteData(), + filter((data) => hasValue(data)), + getRemoteDataPayload(), + filter((data: NotifyRequestsStatus) => hasValue(data)), + map((data: NotifyRequestsStatus) => { + return this.groupDataByStatus(data); + }) + ); + } + + /** + * Groups the notify requests status data by status. + * @param notifyRequestsStatus The notify requests status data. + */ + private groupDataByStatus(notifyRequestsStatus: NotifyRequestsStatus) { + const statusMap: Map = new Map(); + notifyRequestsStatus.notifyStatus?.forEach( + (notifyStatus: NotifyStatuses) => { + const status = notifyStatus.status; + + if (!statusMap.has(status)) { + statusMap.set(status, []); + } + + statusMap.get(status)?.push(notifyStatus); + } + ); + + return statusMap; + } +} diff --git a/src/app/item-page/simple/notify-requests-status/notify-requests-status.model.ts b/src/app/item-page/simple/notify-requests-status/notify-requests-status.model.ts new file mode 100644 index 0000000000..95d8b0ba05 --- /dev/null +++ b/src/app/item-page/simple/notify-requests-status/notify-requests-status.model.ts @@ -0,0 +1,72 @@ +// eslint-disable-next-line max-classes-per-file +import { autoserialize, deserialize, inheritSerialization } from 'cerialize'; +import { typedObject } from '../../../core/cache/builders/build-decorators'; +import { CacheableObject } from '../../../core/cache/cacheable-object.model'; +import { ResourceType } from '../../../core/shared/resource-type'; +import { excludeFromEquals } from '../../../core/utilities/equals.decorators'; +import { NOTIFYREQUEST } from './notify-requests-status.resource-type'; +import { HALLink } from '../../../core/shared/hal-link.model'; +import { RequestStatusEnum } from './notify-status.enum'; + +/** + * Represents the status of notify requests for an item. + */ +@typedObject +@inheritSerialization(CacheableObject) +export class NotifyRequestsStatus implements CacheableObject { + static type = NOTIFYREQUEST; + + /** + * The object type. + */ + @excludeFromEquals + @autoserialize + type: ResourceType; + + /** + * The notify statuses. + */ + @autoserialize + notifyStatus: NotifyStatuses[]; + + /** + * The UUID of the item. + */ + @autoserialize + itemuuid: string; + + /** + * The links associated with the notify requests status. + */ + @deserialize + _links: { + self: HALLink; + [k: string]: HALLink | HALLink[]; + }; +} + +/** + * Represents the status of a notification request. + */ +export class NotifyStatuses { + /** + * The name of the service. + */ + serviceName: string; + + /** + * The URL of the service. + */ + serviceUrl: string; + + /** + * The status of the notification request. + */ + status: RequestStatusEnum; + /** + * Type of request. + */ + offerType: string; +} + + diff --git a/src/app/item-page/simple/notify-requests-status/notify-requests-status.resource-type.ts b/src/app/item-page/simple/notify-requests-status/notify-requests-status.resource-type.ts new file mode 100644 index 0000000000..53b5545fd4 --- /dev/null +++ b/src/app/item-page/simple/notify-requests-status/notify-requests-status.resource-type.ts @@ -0,0 +1,8 @@ +import {ResourceType} from '../../../core/shared/resource-type'; +/** + * The resource type for the root endpoint + * + * Needs to be in a separate file to prevent circular + * dependencies in webpack. + */ +export const NOTIFYREQUEST = new ResourceType('notifyrequests'); diff --git a/src/app/item-page/simple/notify-requests-status/notify-status.enum.ts b/src/app/item-page/simple/notify-requests-status/notify-status.enum.ts new file mode 100644 index 0000000000..e44c614130 --- /dev/null +++ b/src/app/item-page/simple/notify-requests-status/notify-status.enum.ts @@ -0,0 +1,5 @@ +export enum RequestStatusEnum { + ACCEPTED = 'ACCEPTED', + REJECTED = 'REJECTED', + REQUESTED = 'REQUESTED', +} diff --git a/src/app/item-page/simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component.html b/src/app/item-page/simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component.html new file mode 100644 index 0000000000..28022f4837 --- /dev/null +++ b/src/app/item-page/simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component.html @@ -0,0 +1,33 @@ + +
+ + + +
+ +
+
+
+
+
+
+
diff --git a/src/app/item-page/simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component.scss b/src/app/item-page/simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component.scss new file mode 100644 index 0000000000..f852bb8454 --- /dev/null +++ b/src/app/item-page/simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component.scss @@ -0,0 +1,7 @@ +.source-logo { + max-height: var(--ds-header-logo-height); +} + +.sections-gap { + gap: 1rem; +} diff --git a/src/app/item-page/simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component.spec.ts b/src/app/item-page/simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component.spec.ts new file mode 100644 index 0000000000..b379af657f --- /dev/null +++ b/src/app/item-page/simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component.spec.ts @@ -0,0 +1,53 @@ +import { ComponentFixture, TestBed, fakeAsync } from '@angular/core/testing'; +import { RequestStatusAlertBoxComponent } from './request-status-alert-box.component'; +import { TranslateModule } from '@ngx-translate/core'; +import { RequestStatusEnum } from '../notify-status.enum'; + +describe('RequestStatusAlertBoxComponent', () => { + let component: RequestStatusAlertBoxComponent; + let componentAsAny: any; + let fixture: ComponentFixture; + + const mockData = [ + { + serviceName: 'test', + serviceUrl: 'test', + status: RequestStatusEnum.ACCEPTED, + offerType: 'test' + }, + { + serviceName: 'test1', + serviceUrl: 'test', + status: RequestStatusEnum.REJECTED, + offerType: 'test' + }, + ]; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + declarations: [RequestStatusAlertBoxComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(RequestStatusAlertBoxComponent); + component = fixture.componentInstance; + component.data = mockData; + component.displayOptions = { + alertType: 'alert-danger', + text: 'request-status-alert-box.rejected', + }; + componentAsAny = component; + fixture.detectChanges(); + }); + + it('should create the component', () => { + expect(component).toBeTruthy(); + }); + + it('should display the alert box when data is available', fakeAsync(() => { + const alertBoxElement = fixture.nativeElement.querySelector('.alert'); + expect(alertBoxElement).toBeTruthy(); + })); +}); diff --git a/src/app/item-page/simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component.ts b/src/app/item-page/simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component.ts new file mode 100644 index 0000000000..355980836a --- /dev/null +++ b/src/app/item-page/simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component.ts @@ -0,0 +1,82 @@ +import { + ChangeDetectionStrategy, + Component, + Input, + type OnInit, +} from '@angular/core'; +import { NotifyStatuses } from '../notify-requests-status.model'; +import { RequestStatusEnum } from '../notify-status.enum'; + +@Component({ + selector: 'ds-request-status-alert-box', + templateUrl: './request-status-alert-box.component.html', + styleUrls: ['./request-status-alert-box.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +/** + * Represents a component that displays the status of a request. + */ +export class RequestStatusAlertBoxComponent implements OnInit { + /** + * The status of the request. + */ + @Input() status: RequestStatusEnum; + + /** + * The input data for the request status alert box component. + * @type {NotifyStatuses[]} + */ + @Input() data: NotifyStatuses[] = []; + + /** + * The display options for the request status alert box. + */ + displayOptions: NotifyRequestDisplayOptions; + + ngOnInit(): void { + this.prepareDataToDisplay(); + } + + /** + * Prepares the data to be displayed based on the current status. + */ + private prepareDataToDisplay() { + switch (this.status) { + case RequestStatusEnum.ACCEPTED: + this.displayOptions = { + alertType: 'alert-info', + text: 'request-status-alert-box.accepted', + }; + break; + + case RequestStatusEnum.REJECTED: + this.displayOptions = { + alertType: 'alert-danger', + text: 'request-status-alert-box.rejected', + }; + break; + + case RequestStatusEnum.REQUESTED: + this.displayOptions = { + alertType: 'alert-warning', + text: 'request-status-alert-box.requested', + }; + break; + } + } +} + +/** + * Represents the display options for a notification request. + */ +export interface NotifyRequestDisplayOptions { + /** + * The type of alert to display. + * Possible values are 'alert-danger', 'alert-warning', or 'alert-info'. + */ + alertType: 'alert-danger' | 'alert-warning' | 'alert-info'; + /** + * The text to display in the notification. + */ + text: string; +} diff --git a/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.html b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.html new file mode 100644 index 0000000000..77370f462d --- /dev/null +++ b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.html @@ -0,0 +1,22 @@ + + +
+
+ +
+
+
+ {{'item.qa-event-notification.check.notification-info' | translate : {num: source.totalEvents } }} +
+ +
+
+
+
diff --git a/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.scss b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.scss new file mode 100644 index 0000000000..2a62342b7c --- /dev/null +++ b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.scss @@ -0,0 +1,13 @@ +.source-logo { + max-height: var(--ds-header-logo-height); +} + +.source-logo-container { + width: var(--ds-qa-logo-width); + display: flex; + justify-content: center; +} + +.sections-gap { + gap: 1rem; +} diff --git a/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.spec.ts b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.spec.ts new file mode 100644 index 0000000000..ce231affee --- /dev/null +++ b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.spec.ts @@ -0,0 +1,73 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { QaEventNotificationComponent } from './qa-event-notification.component'; +import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; +import { createPaginatedList } from '../../../shared/testing/utils.test'; +import { QualityAssuranceSourceObject } from '../../../core/notifications/qa/models/quality-assurance-source.model'; +import { CommonModule } from '@angular/common'; +import { TranslateModule } from '@ngx-translate/core'; +import { QualityAssuranceSourceDataService } from '../../../core/notifications/qa/source/quality-assurance-source-data.service'; +import { RequestService } from '../../../core/data/request.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { ObjectCacheService } from '../../../core/cache/object-cache.service'; +import { RemoteDataBuildService } from '../../../core/cache/builders/remote-data-build.service'; +import { provideMockStore } from '@ngrx/store/testing'; +import { HALEndpointService } from '../../../core/shared/hal-endpoint.service'; +import { HALEndpointServiceStub } from '../../../shared/testing/hal-endpoint-service.stub'; +import { of } from 'rxjs'; +import { By } from '@angular/platform-browser'; +import { SplitPipe } from 'src/app/shared/utils/split.pipe'; + +describe('QaEventNotificationComponent', () => { + let component: QaEventNotificationComponent; + let fixture: ComponentFixture; + let qualityAssuranceSourceDataServiceStub: any; + + const obj = Object.assign(new QualityAssuranceSourceObject(), { + id: 'sourceName:target', + source: 'sourceName', + target: 'target', + totalEvents: 1 + }); + + const objPL = createSuccessfulRemoteDataObject$(createPaginatedList([obj])); + const item = Object.assign({ uuid: '1234' }); + beforeEach(async () => { + + qualityAssuranceSourceDataServiceStub = { + getSourcesByTarget: () => objPL + }; + await TestBed.configureTestingModule({ + imports: [CommonModule, TranslateModule.forRoot()], + declarations: [QaEventNotificationComponent, SplitPipe], + providers: [ + { provide: QualityAssuranceSourceDataService, useValue: qualityAssuranceSourceDataServiceStub }, + { provide: RequestService, useValue: {} }, + { provide: NotificationsService, useValue: {} }, + { provide: HALEndpointService, useValue: new HALEndpointServiceStub('test') }, + ObjectCacheService, + RemoteDataBuildService, + provideMockStore({}) + ], + }) + .compileComponents(); + fixture = TestBed.createComponent(QaEventNotificationComponent); + component = fixture.componentInstance; + component.item = item; + component.sources$ = of([obj]); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should display sources if present', () => { + const alertElements = fixture.debugElement.queryAll(By.css('.alert')); + expect(alertElements.length).toBe(1); + }); + + it('should return the quality assurance route when getQualityAssuranceRoute is called', () => { + const route = component.getQualityAssuranceRoute(); + expect(route).toBe('/notifications/quality-assurance'); + }); +}); diff --git a/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.ts b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.ts new file mode 100644 index 0000000000..1557a65a0e --- /dev/null +++ b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.ts @@ -0,0 +1,76 @@ +import { ChangeDetectionStrategy, Component, Input, OnChanges, SimpleChanges } from '@angular/core'; +import { Item } from '../../../core/shared/item.model'; +import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; +import { Observable } from 'rxjs'; +import { FindListOptions } from '../../../core/data/find-list-options.model'; +import { RequestParam } from '../../../core/cache/models/request-param.model'; +import { QualityAssuranceSourceDataService } from '../../../core/notifications/qa/source/quality-assurance-source-data.service'; +import { QualityAssuranceSourceObject } from '../../../core/notifications/qa/models/quality-assurance-source.model'; +import { catchError, map } from 'rxjs/operators'; +import { RemoteData } from '../../../core/data/remote-data'; +import { getNotificatioQualityAssuranceRoute } from '../../../admin/admin-routing-paths'; +import { PaginatedList } from '../../../core/data/paginated-list.model'; + +@Component({ + selector: 'ds-qa-event-notification', + templateUrl: './qa-event-notification.component.html', + styleUrls: ['./qa-event-notification.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, + providers: [QualityAssuranceSourceDataService] +}) +/** + * Component for displaying quality assurance event notifications for an item. + */ +export class QaEventNotificationComponent implements OnChanges { + /** + * The item to display quality assurance event notifications for. + */ + @Input() item: Item; + + /** + * An observable that emits an array of QualityAssuranceSourceObject. + */ + sources$: Observable; + + constructor( + private qualityAssuranceSourceDataService: QualityAssuranceSourceDataService, + ) {} + + /** + * Detect changes to the item input and update the sources$ observable. + */ + ngOnChanges(changes: SimpleChanges): void { + if (changes.item && changes.item.currentValue.uuid !== changes.item.previousValue?.uuid) { + this.sources$ = this.getQualityAssuranceSources$(); + } + } + /** + * Returns an Observable of QualityAssuranceSourceObject[] for the current item. + * @returns An Observable of QualityAssuranceSourceObject[] for the current item. + * Note: sourceId is composed as: id: "sourceName:" + */ + getQualityAssuranceSources$(): Observable { + const findListTopicOptions: FindListOptions = { + searchParams: [new RequestParam('target', this.item.uuid)] + }; + return this.qualityAssuranceSourceDataService.getSourcesByTarget(findListTopicOptions, false) + .pipe( + getFirstCompletedRemoteData(), + map((data: RemoteData>) => { + if (data.hasSucceeded) { + return data.payload.page; + } + return []; + }), + catchError(() => []) + ); + } + + /** + * Returns the quality assurance route. + * @returns The quality assurance route. + */ + getQualityAssuranceRoute(): string { + return getNotificatioQualityAssuranceRoute(); + } +} diff --git a/src/app/menu.resolver.spec.ts b/src/app/menu.resolver.spec.ts index 838d5a53c5..9f812477b5 100644 --- a/src/app/menu.resolver.spec.ts +++ b/src/app/menu.resolver.spec.ts @@ -19,6 +19,8 @@ import { cold } from 'jasmine-marbles'; import createSpy = jasmine.createSpy; import { createSuccessfulRemoteDataObject$ } from './shared/remote-data.utils'; import { createPaginatedList } from './shared/testing/utils.test'; +import { ConfigurationDataService } from './core/data/configuration-data.service'; +import { ConfigurationDataServiceStub } from './shared/testing/configuration-data.service.stub'; const BOOLEAN = { t: true, f: false }; const MENU_STATE = { @@ -37,6 +39,7 @@ describe('MenuResolver', () => { let browseService; let authorizationService; let scriptService; + let configurationDataService; beforeEach(waitForAsync(() => { menuService = new MenuServiceStub(); @@ -53,6 +56,9 @@ describe('MenuResolver', () => { scriptWithNameExistsAndCanExecute: observableOf(true) }); + configurationDataService = new ConfigurationDataServiceStub(); + spyOn(configurationDataService, 'findByPropertyName').and.returnValue(observableOf(true)); + TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), NoopAnimationsModule, RouterTestingModule], declarations: [AdminSidebarComponent], @@ -61,6 +67,7 @@ describe('MenuResolver', () => { { provide: BrowseService, useValue: browseService }, { provide: AuthorizationDataService, useValue: authorizationService }, { provide: ScriptDataService, useValue: scriptService }, + { provide: ConfigurationDataService, useValue: configurationDataService }, { provide: NgbModal, useValue: { open: () => {/*comment*/ diff --git a/src/app/menu.resolver.ts b/src/app/menu.resolver.ts index fc6eb00195..6793a70856 100644 --- a/src/app/menu.resolver.ts +++ b/src/app/menu.resolver.ts @@ -48,6 +48,8 @@ import { ExportBatchSelectorComponent } from './shared/dso-selector/modal-wrappers/export-batch-selector/export-batch-selector.component'; import { PUBLICATION_CLAIMS_PATH } from './admin/admin-notifications/admin-notifications-routing-paths'; +import { ConfigurationDataService } from './core/data/configuration-data.service'; +import { ConfigurationProperty } from './core/shared/configuration-property.model'; /** * Creates all of the app's menus @@ -62,6 +64,7 @@ export class MenuResolver implements Resolve { protected authorizationService: AuthorizationDataService, protected modalService: NgbModal, protected scriptDataService: ScriptDataService, + protected configurationDataService: ConfigurationDataService ) { } @@ -156,6 +159,7 @@ export class MenuResolver implements Resolve { this.createExportMenuSections(); this.createImportMenuSections(); this.createAccessControlMenuSections(); + this.createReportMenuSections(); return this.waitForMenu$(MenuID.ADMIN); } @@ -171,7 +175,9 @@ export class MenuResolver implements Resolve { this.authorizationService.isAuthorized(FeatureID.AdministratorOf), this.authorizationService.isAuthorized(FeatureID.CanSubmit), this.authorizationService.isAuthorized(FeatureID.CanEditItem), - ]).subscribe(([isCollectionAdmin, isCommunityAdmin, isSiteAdmin, canSubmit, canEditItem]) => { + this.authorizationService.isAuthorized(FeatureID.CanSeeQA), + this.authorizationService.isAuthorized(FeatureID.CoarNotifyEnabled), + ]).subscribe(([isCollectionAdmin, isCommunityAdmin, isSiteAdmin, canSubmit, canEditItem, canSeeQa, isCoarNotifyEnabled]) => { const newSubMenuList = [ { id: 'new_community', @@ -222,6 +228,18 @@ export class MenuResolver implements Resolve { text: 'menu.section.new_process', link: '/processes/new' } as LinkMenuItemModel, + },/* ldn_services */ + { + id: 'ldn_services_new', + parentID: 'new', + active: false, + visible: isSiteAdmin && isCoarNotifyEnabled, + model: { + type: MenuItemType.LINK, + text: 'menu.section.services_new', + link: '/admin/ldn/services/new' + } as LinkMenuItemModel, + icon: '', }, ]; const editSubMenuList = [ @@ -350,6 +368,19 @@ export class MenuResolver implements Resolve { icon: 'terminal', index: 10 }, + /* LDN Services */ + { + id: 'ldn_services', + active: false, + visible: isSiteAdmin && isCoarNotifyEnabled, + model: { + type: MenuItemType.LINK, + text: 'menu.section.services', + link: '/admin/ldn/services' + } as LinkMenuItemModel, + icon: 'inbox', + index: 14 + }, { id: 'health', active: false, @@ -362,6 +393,41 @@ export class MenuResolver implements Resolve { icon: 'heartbeat', index: 11 }, + /* Notifications */ + { + id: 'notifications', + active: false, + visible: canSeeQa || isSiteAdmin, + model: { + type: MenuItemType.TEXT, + text: 'menu.section.notifications' + } as TextMenuItemModel, + icon: 'bell', + index: 4 + }, + { + id: 'notifications_quality-assurance', + parentID: 'notifications', + active: false, + visible: canSeeQa, + model: { + type: MenuItemType.LINK, + text: 'menu.section.quality-assurance', + link: '/notifications/quality-assurance' + } as LinkMenuItemModel, + }, + { + id: 'notifications_publication-claim', + parentID: 'notifications', + active: false, + visible: isSiteAdmin, + model: { + type: MenuItemType.LINK, + text: 'menu.section.notifications_publication-claim', + link: '/admin/notifications/' + PUBLICATION_CLAIMS_PATH + } as LinkMenuItemModel, + }, + /* Admin Search */ ]; menuList.forEach((menuSection) => this.menuService.addSection(MenuID.ADMIN, Object.assign(menuSection, { shouldPersistOnRouteChange: true @@ -531,47 +597,9 @@ export class MenuResolver implements Resolve { * Create menu sections dependent on whether or not the current user is a site administrator */ createSiteAdministratorMenuSections() { - combineLatest([ - this.authorizationService.isAuthorized(FeatureID.AdministratorOf), - this.authorizationService.isAuthorized(FeatureID.CanSeeQA) - ]) - .subscribe(([authorized, canSeeQA]) => { + this.authorizationService.isAuthorized(FeatureID.AdministratorOf) + .subscribe((authorized) => { const menuList = [ - /* Notifications */ - { - id: 'notifications', - active: false, - visible: authorized && canSeeQA, - model: { - type: MenuItemType.TEXT, - text: 'menu.section.notifications' - } as TextMenuItemModel, - icon: 'bell', - index: 4 - }, - { - id: 'notifications_quality-assurance', - parentID: 'notifications', - active: false, - visible: authorized, - model: { - type: MenuItemType.LINK, - text: 'menu.section.quality-assurance', - link: '/admin/notifications/quality-assurance' - } as LinkMenuItemModel, - }, - { - id: 'notifications_publication-claim', - parentID: 'notifications', - active: false, - visible: authorized, - model: { - type: MenuItemType.LINK, - text: 'menu.section.notifications_publication-claim', - link: '/admin/notifications/' + PUBLICATION_CLAIMS_PATH - } as LinkMenuItemModel, - }, - /* Admin Search */ { id: 'admin_search', active: false, @@ -739,4 +767,60 @@ export class MenuResolver implements Resolve { }))); }); } + + /** + * Create menu sections dependent on whether or not the current user is a site administrator + */ + createReportMenuSections() { + observableCombineLatest([ + this.configurationDataService.findByPropertyName('contentreport.enable').pipe( + map((res: RemoteData) => res.hasSucceeded && res.payload && res.payload.values[0] === 'true') + ), + this.authorizationService.isAuthorized(FeatureID.AdministratorOf) + ]).subscribe(([isSiteAdmin]) => { + const menuList = [ + { + id: 'reports', + active: false, + visible: isSiteAdmin, + model: { + type: MenuItemType.TEXT, + text: 'menu.section.reports' + } as TextMenuItemModel, + icon: 'file-alt', + index: 5 + }, + /* Collections Report */ + { + id: 'reports_collections', + parentID: 'reports', + active: false, + visible: isSiteAdmin, + model: { + type: MenuItemType.LINK, + text: 'menu.section.reports.collections', + link: '/admin/reports/collections' + } as LinkMenuItemModel, + icon: 'user-check' + }, + /* Queries Report */ + { + id: 'reports_queries', + parentID: 'reports', + active: false, + visible: isSiteAdmin, + model: { + type: MenuItemType.LINK, + text: 'menu.section.reports.queries', + link: '/admin/reports/queries' + } as LinkMenuItemModel, + icon: 'user-check' + }, + ]; + + menuList.forEach((menuSection) => this.menuService.addSection(MenuID.ADMIN, Object.assign(menuSection, { + shouldPersistOnRouteChange: true + }))); + }); + } } diff --git a/src/app/my-dspace-page/my-dspace-page.component.html b/src/app/my-dspace-page/my-dspace-page.component.html index c5e49b0cec..cfae8e07a8 100644 --- a/src/app/my-dspace-page/my-dspace-page.component.html +++ b/src/app/my-dspace-page/my-dspace-page.component.html @@ -1,6 +1,7 @@
- + +
+ +
+
+ +
+
+
+ {{ "mydspace.qa-event-notification.check.notification-info" | translate : { num: source.totalEvents } }} +
+ +
+
+
+ diff --git a/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.scss b/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.scss new file mode 100644 index 0000000000..2a62342b7c --- /dev/null +++ b/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.scss @@ -0,0 +1,13 @@ +.source-logo { + max-height: var(--ds-header-logo-height); +} + +.source-logo-container { + width: var(--ds-qa-logo-width); + display: flex; + justify-content: center; +} + +.sections-gap { + gap: 1rem; +} diff --git a/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.spec.ts b/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.spec.ts new file mode 100644 index 0000000000..99d2b601a2 --- /dev/null +++ b/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.spec.ts @@ -0,0 +1,36 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MyDspaceQaEventsNotificationsComponent } from './my-dspace-qa-events-notifications.component'; +import { QualityAssuranceSourceDataService } from '../../core/notifications/qa/source/quality-assurance-source-data.service'; +import { createSuccessfulRemoteDataObject$ } from 'src/app/shared/remote-data.utils'; +import { createPaginatedList } from 'src/app/shared/testing/utils.test'; +import { QualityAssuranceSourceObject } from 'src/app/core/notifications/qa/models/quality-assurance-source.model'; + +describe('MyDspaceQaEventsNotificationsComponent', () => { + let component: MyDspaceQaEventsNotificationsComponent; + let fixture: ComponentFixture; + + let qualityAssuranceSourceDataServiceStub: any; + const obj = createSuccessfulRemoteDataObject$(createPaginatedList([new QualityAssuranceSourceObject()])); + + beforeEach(async () => { + qualityAssuranceSourceDataServiceStub = { + getSources: () => obj + }; + await TestBed.configureTestingModule({ + declarations: [ MyDspaceQaEventsNotificationsComponent ], + providers: [ + { provide: QualityAssuranceSourceDataService, useValue: qualityAssuranceSourceDataServiceStub } + ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(MyDspaceQaEventsNotificationsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.ts b/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.ts new file mode 100644 index 0000000000..2c5f34cbd7 --- /dev/null +++ b/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.ts @@ -0,0 +1,53 @@ +import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; +import { QualityAssuranceSourceDataService } from '../../core/notifications/qa/source/quality-assurance-source-data.service'; +import { getFirstCompletedRemoteData, getPaginatedListPayload, getRemoteDataPayload } from '../../core/shared/operators'; +import { Observable, of, tap } from 'rxjs'; +import { getNotificatioQualityAssuranceRoute } from '../../admin/admin-routing-paths'; +import { QualityAssuranceSourceObject } from 'src/app/core/notifications/qa/models/quality-assurance-source.model'; + +@Component({ + selector: 'ds-my-dspace-qa-events-notifications', + templateUrl: './my-dspace-qa-events-notifications.component.html', + styleUrls: ['./my-dspace-qa-events-notifications.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class MyDspaceQaEventsNotificationsComponent implements OnInit { + + /** + * An Observable that emits an array of QualityAssuranceSourceObject. + */ + sources$: Observable = of([]); + + constructor(private qualityAssuranceSourceDataService: QualityAssuranceSourceDataService) { } + + ngOnInit(): void { + this.getSources(); + } + + /** + * Retrieves the sources for Quality Assurance. + * @returns An Observable of the sources for Quality Assurance. + * @throws An error if the retrieval of Quality Assurance sources fails. + */ + getSources() { + this.sources$ = this.qualityAssuranceSourceDataService.getSources() + .pipe( + getFirstCompletedRemoteData(), + tap((rd) => { + if (rd.hasFailed) { + throw new Error('Can\'t retrieve Quality Assurance sources'); + } + }), + getRemoteDataPayload(), + getPaginatedListPayload(), + ); + } + + /** + * Retrieves the quality assurance route. + * @returns The quality assurance route. + */ + getQualityAssuranceRoute(): string { + return getNotificatioQualityAssuranceRoute(); + } +} diff --git a/src/app/notifications/notifications-effects.ts b/src/app/notifications/notifications-effects.ts index a73fd04fc0..9c446cb66a 100644 --- a/src/app/notifications/notifications-effects.ts +++ b/src/app/notifications/notifications-effects.ts @@ -1,6 +1,6 @@ import { QualityAssuranceSourceEffects } from './qa/source/quality-assurance-source.effects'; import { QualityAssuranceTopicsEffects } from './qa/topics/quality-assurance-topics.effects'; -import { SuggestionTargetsEffects } from '../suggestion-notifications/suggestion-targets/suggestion-targets.effects'; +import { SuggestionTargetsEffects } from './suggestion-targets/suggestion-targets.effects'; export const notificationsEffects = [ QualityAssuranceTopicsEffects, diff --git a/src/app/notifications/notifications-state.service.spec.ts b/src/app/notifications/notifications-state.service.spec.ts index f07b4f5697..324710ad09 100644 --- a/src/app/notifications/notifications-state.service.spec.ts +++ b/src/app/notifications/notifications-state.service.spec.ts @@ -271,8 +271,8 @@ describe('NotificationsStateService', () => { it('Should call store.dispatch', () => { const elementsPerPage = 3; const currentPage = 1; - const action = new RetrieveAllTopicsAction(elementsPerPage, currentPage); - service.dispatchRetrieveQualityAssuranceTopics(elementsPerPage, currentPage); + const action = new RetrieveAllTopicsAction(elementsPerPage, currentPage, 'source', 'target'); + service.dispatchRetrieveQualityAssuranceTopics(elementsPerPage, currentPage, 'source', 'target'); expect(serviceAsAny.store.dispatch).toHaveBeenCalledWith(action); }); }); diff --git a/src/app/notifications/notifications-state.service.ts b/src/app/notifications/notifications-state.service.ts index c123cfa304..3cdaa589d6 100644 --- a/src/app/notifications/notifications-state.service.ts +++ b/src/app/notifications/notifications-state.service.ts @@ -118,8 +118,8 @@ export class NotificationsStateService { * @param currentPage * The number of the current page. */ - public dispatchRetrieveQualityAssuranceTopics(elementsPerPage: number, currentPage: number): void { - this.store.dispatch(new RetrieveAllTopicsAction(elementsPerPage, currentPage)); + public dispatchRetrieveQualityAssuranceTopics(elementsPerPage: number, currentPage: number, sourceId: string, targteId?: string): void { + this.store.dispatch(new RetrieveAllTopicsAction(elementsPerPage, currentPage, sourceId, targteId)); } // Quality Assurance source diff --git a/src/app/notifications/notifications.module.ts b/src/app/notifications/notifications.module.ts index 00c7582b2f..11bf675f72 100644 --- a/src/app/notifications/notifications.module.ts +++ b/src/app/notifications/notifications.module.ts @@ -26,29 +26,21 @@ import { QualityAssuranceSourceService } from './qa/source/quality-assurance-sou import { QualityAssuranceSourceDataService } from '../core/notifications/qa/source/quality-assurance-source-data.service'; -import { PublicationClaimComponent } from '../suggestion-notifications/suggestion-targets/publication-claim/publication-claim.component'; -import { SuggestionActionsComponent } from '../suggestion-notifications/suggestion-actions/suggestion-actions.component'; -import { - SuggestionListElementComponent -} from '../suggestion-notifications/suggestion-list-element/suggestion-list-element.component'; +import { EPersonDataComponent } from './qa/events/ePerson-data/ePerson-data.component'; +import { SuggestionActionsComponent } from './suggestion-actions/suggestion-actions.component'; +import { PublicationClaimComponent } from './suggestion-targets/publication-claim/publication-claim.component'; +import { SuggestionListElementComponent } from './suggestion-list-element/suggestion-list-element.component'; import { SuggestionEvidencesComponent -} from '../suggestion-notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component'; -import { SuggestionsPopupComponent } from '../suggestion-notifications/suggestions-popup/suggestions-popup.component'; -import { - SuggestionsNotificationComponent -} from '../suggestion-notifications/suggestions-notification/suggestions-notification.component'; -import { SuggestionsService } from '../suggestion-notifications/suggestions.service'; -import { SuggestionsDataService } from '../core/suggestion-notifications/suggestions-data.service'; -import { - SuggestionSourceDataService -} from '../core/suggestion-notifications/source/suggestion-source-data.service'; -import { - SuggestionTargetDataService -} from '../core/suggestion-notifications/target/suggestion-target-data.service'; -import { - SuggestionTargetsStateService -} from '../suggestion-notifications/suggestion-targets/suggestion-targets.state.service'; +} from './suggestion-list-element/suggestion-evidences/suggestion-evidences.component'; +import { SuggestionsPopupComponent } from './suggestions-popup/suggestions-popup.component'; +import { SuggestionsNotificationComponent } from './suggestions-notification/suggestions-notification.component'; +import { SuggestionsService } from './suggestions.service'; +import { SuggestionSourceDataService } from '../core/notifications/source/suggestion-source-data.service'; +import { SuggestionTargetDataService } from '../core/notifications/target/suggestion-target-data.service'; +import { SuggestionTargetsStateService } from './suggestion-targets/suggestion-targets.state.service'; +import { SuggestionsDataService } from '../core/notifications/suggestions-data.service'; + const MODULES = [ @@ -65,6 +57,7 @@ const COMPONENTS = [ QualityAssuranceTopicsComponent, QualityAssuranceEventsComponent, QualityAssuranceSourceComponent, + EPersonDataComponent, PublicationClaimComponent, SuggestionActionsComponent, SuggestionListElementComponent, @@ -100,7 +93,7 @@ const PROVIDERS = [ declarations: [ ...COMPONENTS, ...DIRECTIVES, - ...ENTRY_COMPONENTS + ...ENTRY_COMPONENTS, ], providers: [ ...PROVIDERS @@ -110,7 +103,7 @@ const PROVIDERS = [ ], exports: [ ...COMPONENTS, - ...DIRECTIVES + ...DIRECTIVES, ] }) diff --git a/src/app/notifications/notifications.reducer.ts b/src/app/notifications/notifications.reducer.ts index cced6755fa..665c5d7392 100644 --- a/src/app/notifications/notifications.reducer.ts +++ b/src/app/notifications/notifications.reducer.ts @@ -1,7 +1,7 @@ import { ActionReducerMap, createFeatureSelector } from '@ngrx/store'; import { qualityAssuranceSourceReducer, QualityAssuranceSourceState } from './qa/source/quality-assurance-source.reducer'; import { qualityAssuranceTopicsReducer, QualityAssuranceTopicState, } from './qa/topics/quality-assurance-topics.reducer'; -import { SuggestionTargetsReducer, SuggestionTargetState } from '../suggestion-notifications/suggestion-targets/suggestion-targets.reducer'; +import { SuggestionTargetsReducer, SuggestionTargetState } from './suggestion-targets/suggestion-targets.reducer'; /** * The OpenAIRE State diff --git a/src/app/notifications/qa/events/ePerson-data/ePerson-data.component.html b/src/app/notifications/qa/events/ePerson-data/ePerson-data.component.html new file mode 100644 index 0000000000..058457fd40 --- /dev/null +++ b/src/app/notifications/qa/events/ePerson-data/ePerson-data.component.html @@ -0,0 +1,10 @@ + + + + + {{ ePersonData[property] }} + +
+
+
+
diff --git a/src/app/notifications/qa/events/ePerson-data/ePerson-data.component.scss b/src/app/notifications/qa/events/ePerson-data/ePerson-data.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/notifications/qa/events/ePerson-data/ePerson-data.component.spec.ts b/src/app/notifications/qa/events/ePerson-data/ePerson-data.component.spec.ts new file mode 100644 index 0000000000..6fad8dbc92 --- /dev/null +++ b/src/app/notifications/qa/events/ePerson-data/ePerson-data.component.spec.ts @@ -0,0 +1,58 @@ +/* tslint:disable:no-unused-variable */ +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; + +import { EPersonDataComponent } from './ePerson-data.component'; +import { EPersonDataService } from './../../../../core/eperson/eperson-data.service'; +import { EPerson } from 'src/app/core/eperson/models/eperson.model'; +import { createSuccessfulRemoteDataObject$ } from 'src/app/shared/remote-data.utils'; + +describe('EPersonDataComponent', () => { + let component: EPersonDataComponent; + let fixture: ComponentFixture; + let ePersonDataService = jasmine.createSpyObj('EPersonDataService', ['findById']); + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [ EPersonDataComponent ], + providers: [ { + provide: EPersonDataService, + useValue: ePersonDataService + } ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(EPersonDataComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should retrieve EPerson data when ePersonId is provided', () => { + const ePersonId = '123'; + const ePersonData = Object.assign(new EPerson(), { + id: ePersonId, + email: 'john.doe@domain.com', + metadata: [ + { + key: 'eperson.firstname', + value: 'John' + }, + { + key: 'eperson.lastname', + value: 'Doe' + } + ] + }); + const ePersonDataRD$ = createSuccessfulRemoteDataObject$(ePersonData); + ePersonDataService.findById.and.returnValue(ePersonDataRD$); + component.ePersonId = ePersonId; + component.getEPersonData$(); + fixture.detectChanges(); + expect(ePersonDataService.findById).toHaveBeenCalledWith(ePersonId, true); + }); +}); diff --git a/src/app/notifications/qa/events/ePerson-data/ePerson-data.component.ts b/src/app/notifications/qa/events/ePerson-data/ePerson-data.component.ts new file mode 100644 index 0000000000..f1a9c8c592 --- /dev/null +++ b/src/app/notifications/qa/events/ePerson-data/ePerson-data.component.ts @@ -0,0 +1,45 @@ +import { Component, Input } from '@angular/core'; +import { EPersonDataService } from '../../../../core/eperson/eperson-data.service'; +import { getFirstCompletedRemoteData, getRemoteDataPayload } from '../../../../core/shared/operators'; +import { Observable } from 'rxjs'; +import { EPerson } from '../../../../core/eperson/models/eperson.model'; + +@Component({ + selector: 'ds-eperson-data', + templateUrl: './ePerson-data.component.html', + styleUrls: ['./ePerson-data.component.scss'] +}) +/** + * Represents the component for displaying ePerson data. + */ +export class EPersonDataComponent { + + /** + * The ID of the ePerson. + */ + @Input() ePersonId: string; + + /** + * The properties of the ePerson to display. + */ + @Input() properties: string[]; + + /** + * Creates an instance of the EPersonDataComponent. + * @param ePersonDataService The service for retrieving ePerson data. + */ + constructor(private ePersonDataService: EPersonDataService) { } + + /** + * Retrieves the EPerson data based on the provided ePersonId. + * @returns An Observable that emits the EPerson data. + */ + getEPersonData$(): Observable { + if (this.ePersonId) { + return this.ePersonDataService.findById(this.ePersonId, true).pipe( + getFirstCompletedRemoteData(), + getRemoteDataPayload() + ); + } + } +} diff --git a/src/app/notifications/qa/events/quality-assurance-events.component.html b/src/app/notifications/qa/events/quality-assurance-events.component.html index d87ff1b353..8f0bd4323f 100644 --- a/src/app/notifications/qa/events/quality-assurance-events.component.html +++ b/src/app/notifications/qa/events/quality-assurance-events.component.html @@ -6,7 +6,13 @@ {{'notifications.events.title'| translate}}
- + + + + + + {{(getTargetItemTitle() | async)}} +
@@ -33,12 +39,17 @@ {{'quality-assurance.event.table.trust' | translate}} {{'quality-assurance.event.table.publication' | translate}} - - {{'quality-assurance.event.table.details' | translate}} - {{'quality-assurance.event.table.project-details' | translate}} + + + {{'quality-assurance.event.table.reasons' | translate}} + + + {{'quality-assurance.event.table.person-who-requested' | translate}} + + {{'quality-assurance.event.table.actions' | translate}} @@ -51,6 +62,18 @@ rel="noopener noreferrer" [routerLink]="['/items', eventElement?.target?.id]">{{eventElement.title}} {{eventElement.title}} +
+ {{'quality-assurance.event.table.event.message.serviceUrl' | translate}} + + {{eventElement.event.message.serviceId}} + +
+
+ {{'quality-assurance.event.table.event.message.link' | translate}} + + {{eventElement.event.message.href}} + +

{{'quality-assurance.event.table.pidtype' | translate}} {{eventElement.event.message.type}}

@@ -62,7 +85,8 @@

-

{{'quality-assurance.event.table.subjectValue' | translate}}
{{eventElement.event.message.value}}

+

{{'quality-assurance.event.table.subjectValue' | translate}} +
{{eventElement.event.message.value}}

@@ -75,6 +99,23 @@ {{ (showMore ? 'quality-assurance.event.table.less': 'quality-assurance.event.table.more') | translate }} + + +

+ + {{eventElement.event.message.reason}}
+
+

+ + +

+ + + +

+ + +

{{'quality-assurance.event.table.suggestedProject' | translate}} @@ -115,7 +156,7 @@

-
+
+
+ +
@@ -164,14 +215,6 @@
- @@ -225,3 +268,20 @@ + + + + + diff --git a/src/app/notifications/qa/events/quality-assurance-events.component.spec.ts b/src/app/notifications/qa/events/quality-assurance-events.component.spec.ts index 3349dd3154..c69a9108f9 100644 --- a/src/app/notifications/qa/events/quality-assurance-events.component.spec.ts +++ b/src/app/notifications/qa/events/quality-assurance-events.component.spec.ts @@ -42,6 +42,8 @@ import { SortDirection, SortOptions } from '../../../core/cache/models/sort-opti import { PaginationService } from '../../../core/pagination/pagination.service'; import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; import { FindListOptions } from '../../../core/data/find-list-options.model'; +import { ItemDataService } from 'src/app/core/data/item-data.service'; +import { AuthorizationDataService } from 'src/app/core/data/feature-authorization/authorization-data.service'; describe('QualityAssuranceEventsComponent test suite', () => { let fixture: ComponentFixture; @@ -118,6 +120,8 @@ describe('QualityAssuranceEventsComponent test suite', () => { { provide: NotificationsService, useValue: new NotificationsServiceStub() }, { provide: TranslateService, useValue: getMockTranslateService() }, { provide: PaginationService, useValue: paginationService }, + { provide: ItemDataService, useValue: {} }, + { provide: AuthorizationDataService, useValue: {} }, QualityAssuranceEventsComponent ], schemas: [NO_ERRORS_SCHEMA] diff --git a/src/app/notifications/qa/events/quality-assurance-events.component.ts b/src/app/notifications/qa/events/quality-assurance-events.component.ts index c22c28f41e..953fc9c405 100644 --- a/src/app/notifications/qa/events/quality-assurance-events.component.ts +++ b/src/app/notifications/qa/events/quality-assurance-events.component.ts @@ -26,11 +26,16 @@ import { ProjectEntryImportModalComponent, QualityAssuranceEventData } from '../project-entry-import-modal/project-entry-import-modal.component'; -import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; +import { getFirstCompletedRemoteData, getRemoteDataPayload } from '../../../core/shared/operators'; import { PaginationService } from '../../../core/pagination/pagination.service'; import { Item } from '../../../core/shared/item.model'; import { FindListOptions } from '../../../core/data/find-list-options.model'; -import {environment} from '../../../../environments/environment'; +import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; +import { FeatureID } from '../../../core/data/feature-authorization/feature-id'; +import { NoContent } from '../../../core/shared/NoContent.model'; +import { environment } from '../../../../environments/environment'; +import { getItemPageRoute } from '../../../item-page/item-page-routing-paths'; +import { ItemDataService } from '../../../core/data/item-data.service'; /** * Component to display the Quality Assurance event list. @@ -76,6 +81,11 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { * @type {string} */ public topic: string; + /** + * The sourceId of the Quality Assurance events. + * @type {string} + */ + sourceId: string; /** * The rejected/ignore reason. * @type {string} @@ -86,6 +96,7 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { * @type {Observable} */ public isEventPageLoading: BehaviorSubject = new BehaviorSubject(false); + /** * The modal reference. * @type {any} @@ -110,6 +121,27 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { */ protected subs: Subscription[] = []; + /** + * The target item id, retrieved from the topic-id composition. + */ + public targetId: string; + + /** + * The URL of the item page/target. + */ + public itemPageUrl: string; + + /** + * Plain topic name (without the source id) + */ + public selectedTopicName: string; + + + /** + * Observable that emits a boolean value indicating whether the user is an admin. + */ + isAdmin$: Observable; + /** * Initialize the component variables. * @param {ActivatedRoute} activatedRoute @@ -118,6 +150,8 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { * @param {QualityAssuranceEventDataService} qualityAssuranceEventRestService * @param {PaginationService} paginationService * @param {TranslateService} translateService + * @param authorizationService + * @param itemService */ constructor( private activatedRoute: ActivatedRoute, @@ -125,7 +159,9 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { private notificationsService: NotificationsService, private qualityAssuranceEventRestService: QualityAssuranceEventDataService, private paginationService: PaginationService, - private translateService: TranslateService + private translateService: TranslateService, + private authorizationService: AuthorizationDataService, + private itemService: ItemDataService, ) { } @@ -134,23 +170,35 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { */ ngOnInit(): void { this.isEventPageLoading.next(true); - + this.isAdmin$ = this.authorizationService.isAuthorized(FeatureID.AdministratorOf); this.activatedRoute.paramMap.pipe( - tap((params) => { - this.sourceUrlForProjectSearch = environment.qualityAssuranceConfig.sourceUrlMapForProjectSearch[params.get('sourceId')]; - }), - map((params) => params.get('topicId')), + tap((params) => { + this.sourceUrlForProjectSearch = environment.qualityAssuranceConfig.sourceUrlMapForProjectSearch[params.get('sourceId')]; + this.sourceId = params.get('sourceId'); + }), + map((params) => params.get('topicId')), take(1), switchMap((id: string) => { const regEx = /!/g; this.showTopic = id.replace(regEx, '/'); this.topic = id; + const splitList = this.showTopic?.split(':'); + this.targetId = splitList.length > 2 ? splitList.pop() : null; + this.selectedTopicName = splitList[1]; + this.sourceId = splitList[0]; return this.getQualityAssuranceEvents(); }) - ).subscribe((events: QualityAssuranceEventData[]) => { - this.eventsUpdated$.next(events); - this.isEventPageLoading.next(false); - }); + ).subscribe( + { + next: (events: QualityAssuranceEventData[]) => { + this.eventsUpdated$.next(events); + this.isEventPageLoading.next(false); + }, + error: (error) => { + this.isEventPageLoading.next(false); + } + } + ); } /** @@ -160,6 +208,8 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { return (this.showTopic.indexOf('/PROJECT') !== -1 || this.showTopic.indexOf('/PID') !== -1 || this.showTopic.indexOf('/SUBJECT') !== -1 || + this.showTopic.indexOf('/WITHDRAWN') !== -1 || + this.showTopic.indexOf('/REINSTATE') !== -1 || this.showTopic.indexOf('/ABSTRACT') !== -1 ); } @@ -244,8 +294,14 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { */ public executeAction(action: string, eventData: QualityAssuranceEventData): void { eventData.isRunning = true; + let operation; + if (action === 'UNDO') { + operation = this.delete(eventData); + } else { + operation = this.qualityAssuranceEventRestService.patchEvent(action, eventData.event, eventData.reason); + } this.subs.push( - this.qualityAssuranceEventRestService.patchEvent(action, eventData.event, eventData.reason).pipe( + operation.pipe( getFirstCompletedRemoteData(), switchMap((rd: RemoteData) => { if (rd.hasSucceeded) { @@ -362,7 +418,7 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { switchMap((rd: RemoteData>) => { if (rd.hasSucceeded) { this.totalElements$.next(rd.payload.totalElements); - if (rd.payload.totalElements > 0) { + if (rd.payload?.page?.length > 0) { return this.fetchEvents(rd.payload.page); } else { return of([]); @@ -431,4 +487,30 @@ export class QualityAssuranceEventsComponent implements OnInit, OnDestroy { last() ); } + + /** + * Deletes a quality assurance event. + * @param qaEvent The quality assurance event to delete. + * @returns An Observable of RemoteData containing NoContent. + */ + delete(qaEvent: QualityAssuranceEventData): Observable> { + return this.qualityAssuranceEventRestService.deleteQAEvent(qaEvent); + } + + /** + * Returns an Observable that emits the title of the target item. + * The target item is retrieved by its ID using the itemService. + * The title is extracted from the first metadata value of the item. + * The item page URL is also set in the component. + * @returns An Observable that emits the title of the target item. + */ + public getTargetItemTitle(): Observable { + return this.itemService.findById(this.targetId).pipe( + take(1), + getFirstCompletedRemoteData(), + getRemoteDataPayload(), + tap((item: Item) => this.itemPageUrl = getItemPageRoute(item)), + map((item: Item) => item.firstMetadataValue('dc.title')) + ); + } } diff --git a/src/app/notifications/qa/source/quality-assurance-source.component.html b/src/app/notifications/qa/source/quality-assurance-source.component.html index 0f6cf18402..543304aacc 100644 --- a/src/app/notifications/qa/source/quality-assurance-source.component.html +++ b/src/app/notifications/qa/source/quality-assurance-source.component.html @@ -34,12 +34,12 @@ {{sourceElement.id}} - {{sourceElement.lastEvent}} + {{sourceElement.lastEvent | date: 'dd/MM/yyyy hh:mm' }}
diff --git a/src/app/notifications/qa/topics/quality-assurance-topics.component.spec.ts b/src/app/notifications/qa/topics/quality-assurance-topics.component.spec.ts index fd64b82ce7..228dbffd5e 100644 --- a/src/app/notifications/qa/topics/quality-assurance-topics.component.spec.ts +++ b/src/app/notifications/qa/topics/quality-assurance-topics.component.spec.ts @@ -16,7 +16,7 @@ import { NotificationsStateService } from '../../notifications-state.service'; import { cold } from 'jasmine-marbles'; import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; import { PaginationService } from '../../../core/pagination/pagination.service'; -import { QualityAssuranceTopicsService } from './quality-assurance-topics.service'; +import { ItemDataService } from 'src/app/core/data/item-data.service'; describe('QualityAssuranceTopicsComponent test suite', () => { let fixture: ComponentFixture; @@ -44,14 +44,14 @@ describe('QualityAssuranceTopicsComponent test suite', () => { providers: [ { provide: NotificationsStateService, useValue: mockNotificationsStateService }, { provide: ActivatedRoute, useValue: { data: observableOf(activatedRouteParams), snapshot: { - paramMap: { - get: () => 'openaire', + params: { + sourceId: 'openaire', + targetId: null }, }}}, { provide: PaginationService, useValue: paginationService }, + { provide: ItemDataService, useValue: {} }, QualityAssuranceTopicsComponent, - // tslint:disable-next-line: no-empty - { provide: QualityAssuranceTopicsService, useValue: { setSourceId: (sourceId: string) => { } }} ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents().then(() => { diff --git a/src/app/notifications/qa/topics/quality-assurance-topics.component.ts b/src/app/notifications/qa/topics/quality-assurance-topics.component.ts index 542d36a9ed..5a077de1fe 100644 --- a/src/app/notifications/qa/topics/quality-assurance-topics.component.ts +++ b/src/app/notifications/qa/topics/quality-assurance-topics.component.ts @@ -1,7 +1,7 @@ -import { Component, OnInit } from '@angular/core'; +import { AfterViewInit, Component, OnDestroy, OnInit } from '@angular/core'; import { Observable, Subscription } from 'rxjs'; -import { distinctUntilChanged, take } from 'rxjs/operators'; +import { distinctUntilChanged, map, take, tap } from 'rxjs/operators'; import { SortOptions } from '../../../core/cache/models/sort-options.model'; import { @@ -10,12 +10,17 @@ import { import { hasValue } from '../../../shared/empty.util'; import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; import { NotificationsStateService } from '../../notifications-state.service'; -import { - AdminQualityAssuranceTopicsPageParams -} from '../../../admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page-resolver.service'; + import { PaginationService } from '../../../core/pagination/pagination.service'; -import { ActivatedRoute } from '@angular/router'; -import { QualityAssuranceTopicsService } from './quality-assurance-topics.service'; +import { ActivatedRoute, Router } from '@angular/router'; +import { ItemDataService } from '../../../core/data/item-data.service'; +import { getFirstCompletedRemoteData, getRemoteDataPayload } from '../../../core/shared/operators'; +import { Item } from '../../../core/shared/item.model'; +import { getItemPageRoute } from '../../../item-page/item-page-routing-paths'; +import { getNotificatioQualityAssuranceRoute } from '../../../admin/admin-routing-paths'; +import { + QualityAssuranceTopicsPageParams +} from '../../../quality-assurance-notifications-pages/quality-assurance-topics-page/quality-assurance-topics-page-resolver.service'; /** * Component to display the Quality Assurance topic list. @@ -25,7 +30,7 @@ import { QualityAssuranceTopicsService } from './quality-assurance-topics.servic templateUrl: './quality-assurance-topics.component.html', styleUrls: ['./quality-assurance-topics.component.scss'], }) -export class QualityAssuranceTopicsComponent implements OnInit { +export class QualityAssuranceTopicsComponent implements OnInit, OnDestroy, AfterViewInit { /** * The pagination system configuration for HTML listing. * @type {PaginationComponentOptions} @@ -60,28 +65,49 @@ export class QualityAssuranceTopicsComponent implements OnInit { */ public sourceId: string; + /** + * This property represents a targetId (item-id) which is used to retrive a topic + * @type {string} + */ + public targetId: string; + + /** + * The URL of the item page. + */ + public itemPageUrl: string; + /** * Initialize the component variables. * @param {PaginationService} paginationService * @param {ActivatedRoute} activatedRoute + * @param itemService * @param {NotificationsStateService} notificationsStateService - * @param {QualityAssuranceTopicsService} qualityAssuranceTopicsService + * @param router */ constructor( private paginationService: PaginationService, private activatedRoute: ActivatedRoute, + private itemService: ItemDataService, private notificationsStateService: NotificationsStateService, - private qualityAssuranceTopicsService: QualityAssuranceTopicsService + private router: Router, ) { + this.sourceId = this.activatedRoute.snapshot.params.sourceId; + this.targetId = this.activatedRoute.snapshot.params.targetId; } /** * Component initialization. */ ngOnInit(): void { - this.sourceId = this.activatedRoute.snapshot.paramMap.get('sourceId'); - this.qualityAssuranceTopicsService.setSourceId(this.sourceId); - this.topics$ = this.notificationsStateService.getQualityAssuranceTopics(); + this.topics$ = this.notificationsStateService.getQualityAssuranceTopics().pipe( + tap((topics: QualityAssuranceTopicObject[]) => { + const forward = this.activatedRoute.snapshot.queryParams?.forward === 'true'; + if (topics.length === 1 && forward) { + // If there is only one topic, navigate to the first topic automatically + this.router.navigate([this.getQualityAssuranceRoute(), this.sourceId, topics[0].id]); + } + }) + ); this.totalElements$ = this.notificationsStateService.getQualityAssuranceTopicsTotals(); } @@ -93,7 +119,7 @@ export class QualityAssuranceTopicsComponent implements OnInit { this.notificationsStateService.isQualityAssuranceTopicsLoaded().pipe( take(1) ).subscribe(() => { - this.getQualityAssuranceTopics(); + this.getQualityAssuranceTopics(this.sourceId, this.targetId); }) ); } @@ -121,15 +147,17 @@ export class QualityAssuranceTopicsComponent implements OnInit { /** * Dispatch the Quality Assurance topics retrival. */ - public getQualityAssuranceTopics(): void { - this.paginationService.getCurrentPagination(this.paginationConfig.id, this.paginationConfig).pipe( + public getQualityAssuranceTopics(source: string, target?: string): void { + this.subs.push(this.paginationService.getCurrentPagination(this.paginationConfig.id, this.paginationConfig).pipe( distinctUntilChanged(), ).subscribe((options: PaginationComponentOptions) => { this.notificationsStateService.dispatchRetrieveQualityAssuranceTopics( options.pageSize, - options.currentPage + options.currentPage, + source, + target ); - }); + })); } /** @@ -137,7 +165,7 @@ export class QualityAssuranceTopicsComponent implements OnInit { * * @param eventsRouteParams */ - protected updatePaginationFromRouteParams(eventsRouteParams: AdminQualityAssuranceTopicsPageParams) { + protected updatePaginationFromRouteParams(eventsRouteParams: QualityAssuranceTopicsPageParams) { if (eventsRouteParams.currentPage) { this.paginationConfig.currentPage = eventsRouteParams.currentPage; } @@ -150,6 +178,40 @@ export class QualityAssuranceTopicsComponent implements OnInit { } } + /** + * Returns an Observable that emits the title of the target item. + * The target item is retrieved by its ID using the itemService. + * The title is extracted from the first metadata value of the item. + * The item page URL is also set in the component. + * @returns An Observable that emits the title of the target item. + */ + getTargetItemTitle(): Observable { + return this.itemService.findById(this.targetId).pipe( + take(1), + getFirstCompletedRemoteData(), + getRemoteDataPayload(), + tap((item: Item) => this.itemPageUrl = getItemPageRoute(item)), + map((item: Item) => item.firstMetadataValue('dc.title')) + ); + } + + /** + * Returns the page route for the given item. + * @param item The item to get the page route for. + * @returns The page route for the given item. + */ + getItemPageRoute(item: Item): string { + return getItemPageRoute(item); + } + + /** + * Returns the quality assurance route. + * @returns The quality assurance route. + */ + getQualityAssuranceRoute(): string { + return getNotificatioQualityAssuranceRoute(); + } + /** * Unsubscribe from all subscriptions. */ diff --git a/src/app/notifications/qa/topics/quality-assurance-topics.effects.ts b/src/app/notifications/qa/topics/quality-assurance-topics.effects.ts index a7b4dddd62..830f10c323 100644 --- a/src/app/notifications/qa/topics/quality-assurance-topics.effects.ts +++ b/src/app/notifications/qa/topics/quality-assurance-topics.effects.ts @@ -37,7 +37,9 @@ export class QualityAssuranceTopicsEffects { switchMap(([action, currentState]: [RetrieveAllTopicsAction, any]) => { return this.qualityAssuranceTopicService.getTopics( action.payload.elementsPerPage, - action.payload.currentPage + action.payload.currentPage, + action.payload.source, + action.payload.target ).pipe( map((topics: PaginatedList) => new AddTopicsAction(topics.page, topics.totalPages, topics.currentPage, topics.totalElements) diff --git a/src/app/notifications/qa/topics/quality-assurance-topics.reducer.spec.ts b/src/app/notifications/qa/topics/quality-assurance-topics.reducer.spec.ts index a1c002d3f2..37d83f6e4f 100644 --- a/src/app/notifications/qa/topics/quality-assurance-topics.reducer.spec.ts +++ b/src/app/notifications/qa/topics/quality-assurance-topics.reducer.spec.ts @@ -29,7 +29,7 @@ describe('qualityAssuranceTopicsReducer test suite', () => { const expectedState = qualityAssuranceTopicInitialState; expectedState.processing = true; - const action = new RetrieveAllTopicsAction(elementPerPage, currentPage); + const action = new RetrieveAllTopicsAction(elementPerPage, currentPage, 'ENRICH!MORE!ABSTRACT'); const newState = qualityAssuranceTopicsReducer(qualityAssuranceTopicInitialState, action); expect(newState).toEqual(expectedState); diff --git a/src/app/notifications/qa/topics/quality-assurance-topics.service.spec.ts b/src/app/notifications/qa/topics/quality-assurance-topics.service.spec.ts index c6aae27a88..78cedb2e2a 100644 --- a/src/app/notifications/qa/topics/quality-assurance-topics.service.spec.ts +++ b/src/app/notifications/qa/topics/quality-assurance-topics.service.spec.ts @@ -42,30 +42,30 @@ describe('QualityAssuranceTopicsService', () => { beforeEach(() => { restService = TestBed.inject(QualityAssuranceTopicDataService); restServiceAsAny = restService; - restServiceAsAny.getTopics.and.returnValue(observableOf(paginatedListRD)); + restServiceAsAny.searchTopicsBySource.and.returnValue(observableOf(paginatedListRD)); + restServiceAsAny.searchTopicsByTarget.and.returnValue(observableOf(paginatedListRD)); service = new QualityAssuranceTopicsService(restService); serviceAsAny = service; }); describe('getTopics', () => { - it('Should proxy the call to qualityAssuranceTopicRestService.getTopics', () => { + it('should proxy the call to qualityAssuranceTopicRestService.searchTopicsBySource', () => { const sortOptions = new SortOptions('name', SortDirection.ASC); const findListOptions: FindListOptions = { elementsPerPage: elementsPerPage, currentPage: currentPage, sort: sortOptions, - searchParams: [new RequestParam('source', 'ENRICH!MORE!ABSTRACT')] + searchParams: [new RequestParam('source', 'openaire')] }; - service.setSourceId('ENRICH!MORE!ABSTRACT'); - const result = service.getTopics(elementsPerPage, currentPage); - expect((service as any).qualityAssuranceTopicRestService.getTopics).toHaveBeenCalledWith(findListOptions); + service.getTopics(elementsPerPage, currentPage, 'openaire'); + expect((service as any).qualityAssuranceTopicRestService.searchTopicsBySource).toHaveBeenCalledWith(findListOptions); }); - it('Should return a paginated list of Quality Assurance topics', () => { + it('should return a paginated list of Quality Assurance topics', () => { const expected = cold('(a|)', { a: paginatedList }); - const result = service.getTopics(elementsPerPage, currentPage); + const result = service.getTopics(elementsPerPage, currentPage, 'openaire'); expect(result).toBeObservable(expected); }); }); diff --git a/src/app/notifications/qa/topics/quality-assurance-topics.service.ts b/src/app/notifications/qa/topics/quality-assurance-topics.service.ts index 9dd581ebed..131be400ca 100644 --- a/src/app/notifications/qa/topics/quality-assurance-topics.service.ts +++ b/src/app/notifications/qa/topics/quality-assurance-topics.service.ts @@ -13,6 +13,7 @@ import { import { RequestParam } from '../../../core/cache/models/request-param.model'; import { FindListOptions } from '../../../core/data/find-list-options.model'; import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; +import { hasValue } from '../../../shared/empty.util'; /** * The service handling all Quality Assurance topic requests to the REST service. @@ -28,10 +29,6 @@ export class QualityAssuranceTopicsService { private qualityAssuranceTopicRestService: QualityAssuranceTopicDataService ) { } - /** - * sourceId used to get topics - */ - sourceId: string; /** * Return the list of Quality Assurance topics managing pagination and errors. @@ -43,17 +40,25 @@ export class QualityAssuranceTopicsService { * @return Observable> * The list of Quality Assurance topics. */ - public getTopics(elementsPerPage, currentPage): Observable> { + public getTopics(elementsPerPage, currentPage, source: string, target?: string): Observable> { const sortOptions = new SortOptions('name', SortDirection.ASC); - const findListOptions: FindListOptions = { elementsPerPage: elementsPerPage, currentPage: currentPage, sort: sortOptions, - searchParams: [new RequestParam('source', this.sourceId)] + searchParams: [new RequestParam('source', source)] }; - return this.qualityAssuranceTopicRestService.getTopics(findListOptions).pipe( + let request$: Observable>>; + + if (hasValue(target)) { + findListOptions.searchParams.push(new RequestParam('target', target)); + request$ = this.qualityAssuranceTopicRestService.searchTopicsByTarget(findListOptions); + } else { + request$ = this.qualityAssuranceTopicRestService.searchTopicsBySource(findListOptions); + } + + return request$.pipe( getFirstCompletedRemoteData(), map((rd: RemoteData>) => { if (rd.hasSucceeded) { @@ -64,12 +69,4 @@ export class QualityAssuranceTopicsService { }) ); } - - /** - * set sourceId which is used to get topics - * @param sourceId string - */ - setSourceId(sourceId: string) { - this.sourceId = sourceId; - } } diff --git a/src/app/notifications/reciter-suggestions/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.scss b/src/app/notifications/reciter-suggestions/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/notifications/reciter-suggestions/suggestion-targets/suggestion-targets.component.scss b/src/app/notifications/reciter-suggestions/suggestion-targets/suggestion-targets.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/notifications/reciter-suggestions/suggestions-notification/suggestions-notification.component.scss b/src/app/notifications/reciter-suggestions/suggestions-notification/suggestions-notification.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.scss b/src/app/notifications/reciter-suggestions/suggestions-popup/suggestions-popup.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/suggestion-notifications/suggestion-actions/suggestion-actions.component.html b/src/app/notifications/suggestion-actions/suggestion-actions.component.html similarity index 100% rename from src/app/suggestion-notifications/suggestion-actions/suggestion-actions.component.html rename to src/app/notifications/suggestion-actions/suggestion-actions.component.html diff --git a/src/app/suggestion-notifications/suggestion-actions/suggestion-actions.component.scss b/src/app/notifications/suggestion-actions/suggestion-actions.component.scss similarity index 100% rename from src/app/suggestion-notifications/suggestion-actions/suggestion-actions.component.scss rename to src/app/notifications/suggestion-actions/suggestion-actions.component.scss diff --git a/src/app/suggestion-notifications/suggestion-actions/suggestion-actions.component.ts b/src/app/notifications/suggestion-actions/suggestion-actions.component.ts similarity index 96% rename from src/app/suggestion-notifications/suggestion-actions/suggestion-actions.component.ts rename to src/app/notifications/suggestion-actions/suggestion-actions.component.ts index f6e2452738..5f1443794c 100644 --- a/src/app/suggestion-notifications/suggestion-actions/suggestion-actions.component.ts +++ b/src/app/notifications/suggestion-actions/suggestion-actions.component.ts @@ -1,11 +1,12 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; import { ItemType } from '../../core/shared/item-relationships/item-type.model'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; -import { Suggestion } from '../../core/suggestion-notifications/models/suggestion.model'; -import { SuggestionApproveAndImport } from '../suggestion-list-element/suggestion-list-element.component'; + import { Collection } from '../../core/shared/collection.model'; import { take } from 'rxjs/operators'; import { CreateItemParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component'; +import { Suggestion } from '../../core/notifications/models/suggestion.model'; +import { SuggestionApproveAndImport } from '../suggestion-list-element/suggestion-list-element.component'; /** * Show and trigger the actions to submit for a suggestion diff --git a/src/app/suggestion-notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.html b/src/app/notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.html similarity index 100% rename from src/app/suggestion-notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.html rename to src/app/notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.html diff --git a/src/app/notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.scss b/src/app/notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/suggestion-notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.ts b/src/app/notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.ts similarity index 82% rename from src/app/suggestion-notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.ts rename to src/app/notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.ts index 60c36603f1..d58f8d39c1 100644 --- a/src/app/suggestion-notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.ts +++ b/src/app/notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.ts @@ -1,6 +1,7 @@ import { Component, Input } from '@angular/core'; import { fadeIn } from '../../../shared/animations/fade'; -import { SuggestionEvidences } from '../../../core/suggestion-notifications/models/suggestion.model'; +import { SuggestionEvidences } from '../../../core/notifications/models/suggestion.model'; + /** * Show suggestion evidences such as score (authorScore, dateScore) diff --git a/src/app/suggestion-notifications/suggestion-list-element/suggestion-list-element.component.html b/src/app/notifications/suggestion-list-element/suggestion-list-element.component.html similarity index 100% rename from src/app/suggestion-notifications/suggestion-list-element/suggestion-list-element.component.html rename to src/app/notifications/suggestion-list-element/suggestion-list-element.component.html diff --git a/src/app/suggestion-notifications/suggestion-list-element/suggestion-list-element.component.scss b/src/app/notifications/suggestion-list-element/suggestion-list-element.component.scss similarity index 100% rename from src/app/suggestion-notifications/suggestion-list-element/suggestion-list-element.component.scss rename to src/app/notifications/suggestion-list-element/suggestion-list-element.component.scss diff --git a/src/app/suggestion-notifications/suggestion-list-element/suggestion-list-element.component.spec.ts b/src/app/notifications/suggestion-list-element/suggestion-list-element.component.spec.ts similarity index 100% rename from src/app/suggestion-notifications/suggestion-list-element/suggestion-list-element.component.spec.ts rename to src/app/notifications/suggestion-list-element/suggestion-list-element.component.spec.ts diff --git a/src/app/suggestion-notifications/suggestion-list-element/suggestion-list-element.component.ts b/src/app/notifications/suggestion-list-element/suggestion-list-element.component.ts similarity index 96% rename from src/app/suggestion-notifications/suggestion-list-element/suggestion-list-element.component.ts rename to src/app/notifications/suggestion-list-element/suggestion-list-element.component.ts index f569054bb0..bc5db3d1bf 100644 --- a/src/app/suggestion-notifications/suggestion-list-element/suggestion-list-element.component.ts +++ b/src/app/notifications/suggestion-list-element/suggestion-list-element.component.ts @@ -1,12 +1,13 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; - +import { Suggestion } from 'src/app/core/notifications/models/suggestion.model'; import { fadeIn } from '../../shared/animations/fade'; -import { Suggestion } from '../../core/suggestion-notifications/models/suggestion.model'; import { Item } from '../../core/shared/item.model'; import { isNotEmpty } from '../../shared/empty.util'; + + /** * A simple interface to unite a specific suggestion and the id of the chosen collection */ diff --git a/src/app/suggestion-notifications/suggestion-targets/publication-claim/publication-claim.component.html b/src/app/notifications/suggestion-targets/publication-claim/publication-claim.component.html similarity index 100% rename from src/app/suggestion-notifications/suggestion-targets/publication-claim/publication-claim.component.html rename to src/app/notifications/suggestion-targets/publication-claim/publication-claim.component.html diff --git a/src/app/notifications/suggestion-targets/publication-claim/publication-claim.component.scss b/src/app/notifications/suggestion-targets/publication-claim/publication-claim.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/suggestion-notifications/suggestion-targets/publication-claim/publication-claim.component.ts b/src/app/notifications/suggestion-targets/publication-claim/publication-claim.component.ts similarity index 97% rename from src/app/suggestion-notifications/suggestion-targets/publication-claim/publication-claim.component.ts rename to src/app/notifications/suggestion-targets/publication-claim/publication-claim.component.ts index 1c3f751ea7..1b6d70cba4 100644 --- a/src/app/suggestion-notifications/suggestion-targets/publication-claim/publication-claim.component.ts +++ b/src/app/notifications/suggestion-targets/publication-claim/publication-claim.component.ts @@ -4,13 +4,14 @@ import { Router } from '@angular/router'; import { Observable, Subscription } from 'rxjs'; import { distinctUntilChanged, take } from 'rxjs/operators'; -import { SuggestionTarget } from '../../../core/suggestion-notifications/models/suggestion-target.model'; + import { hasValue } from '../../../shared/empty.util'; import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; -import { SuggestionTargetsStateService } from '../suggestion-targets.state.service'; import { getSuggestionPageRoute } from '../../../suggestions-page/suggestions-page-routing-paths'; -import { SuggestionsService } from '../../suggestions.service'; import { PaginationService } from '../../../core/pagination/pagination.service'; +import { SuggestionTarget } from '../../../core/notifications/models/suggestion-target.model'; +import { SuggestionTargetsStateService } from '../suggestion-targets.state.service'; +import { SuggestionsService } from '../../suggestions.service'; /** * Component to display the Suggestion Target list. diff --git a/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.actions.ts b/src/app/notifications/suggestion-targets/suggestion-targets.actions.ts similarity index 97% rename from src/app/suggestion-notifications/suggestion-targets/suggestion-targets.actions.ts rename to src/app/notifications/suggestion-targets/suggestion-targets.actions.ts index 058fa36751..281e07d99e 100644 --- a/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.actions.ts +++ b/src/app/notifications/suggestion-targets/suggestion-targets.actions.ts @@ -1,7 +1,8 @@ /* eslint-disable max-classes-per-file */ import { Action } from '@ngrx/store'; import { type } from '../../shared/ngrx/type'; -import { SuggestionTarget } from '../../core/suggestion-notifications/models/suggestion-target.model'; +import { SuggestionTarget } from '../../core/notifications/models/suggestion-target.model'; + /** * For each action type in an action group, make a simple diff --git a/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.effects.ts b/src/app/notifications/suggestion-targets/suggestion-targets.effects.ts similarity index 96% rename from src/app/suggestion-notifications/suggestion-targets/suggestion-targets.effects.ts rename to src/app/notifications/suggestion-targets/suggestion-targets.effects.ts index 23eedcedc5..f8be925d8b 100644 --- a/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.effects.ts +++ b/src/app/notifications/suggestion-targets/suggestion-targets.effects.ts @@ -15,8 +15,9 @@ import { } from './suggestion-targets.actions'; import { PaginatedList } from '../../core/data/paginated-list.model'; import { SuggestionsService } from '../suggestions.service'; +import { SuggestionTarget } from '../../core/notifications/models/suggestion-target.model'; import { NotificationsService } from '../../shared/notifications/notifications.service'; -import { SuggestionTarget } from '../../core/suggestion-notifications/models/suggestion-target.model'; + /** * Provides effect methods for the Suggestion Targets actions. @@ -71,7 +72,7 @@ export class SuggestionTargetsEffects { .pipe( map((suggestionTargets: SuggestionTarget[]) => new AddUserSuggestionsAction(suggestionTargets)), catchError((errors) => of(errors)) - ); + ); }), catchError((errors) => of(errors)) ); diff --git a/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.reducer.ts b/src/app/notifications/suggestion-targets/suggestion-targets.reducer.ts similarity index 96% rename from src/app/suggestion-notifications/suggestion-targets/suggestion-targets.reducer.ts rename to src/app/notifications/suggestion-targets/suggestion-targets.reducer.ts index 09ead019d1..6ba29303b3 100644 --- a/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.reducer.ts +++ b/src/app/notifications/suggestion-targets/suggestion-targets.reducer.ts @@ -1,5 +1,6 @@ +import { SuggestionTarget } from '../../core/notifications/models/suggestion-target.model'; import { SuggestionTargetActionTypes, SuggestionTargetsActions } from './suggestion-targets.actions'; -import { SuggestionTarget } from '../../core/suggestion-notifications/models/suggestion-target.model'; + /** * The interface representing the OpenAIRE suggestion targets state. diff --git a/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.state.service.ts b/src/app/notifications/suggestion-targets/suggestion-targets.state.service.ts similarity index 95% rename from src/app/suggestion-notifications/suggestion-targets/suggestion-targets.state.service.ts rename to src/app/notifications/suggestion-targets/suggestion-targets.state.service.ts index 7e0e6ad836..1ca01b10f2 100644 --- a/src/app/suggestion-notifications/suggestion-targets/suggestion-targets.state.service.ts +++ b/src/app/notifications/suggestion-targets/suggestion-targets.state.service.ts @@ -4,16 +4,7 @@ import { select, Store } from '@ngrx/store'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; -import { - getCurrentUserSuggestionTargetsSelector, - getCurrentUserSuggestionTargetsVisitedSelector, - getSuggestionTargetCurrentPageSelector, - getSuggestionTargetTotalsSelector, - isSuggestionTargetLoadedSelector, - isReciterSuggestionTargetProcessingSelector, - suggestionTargetObjectSelector -} from '../selectors'; -import { SuggestionTarget } from '../../core/suggestion-notifications/models/suggestion-target.model'; + import { ClearSuggestionTargetsAction, MarkUserSuggestionsAsVisitedAction, @@ -21,6 +12,15 @@ import { RetrieveTargetsBySourceAction } from './suggestion-targets.actions'; import { SuggestionNotificationsState } from '../../notifications/notifications.reducer'; +import { SuggestionTarget } from '../../core/notifications/models/suggestion-target.model'; +import { + getCurrentUserSuggestionTargetsSelector, getCurrentUserSuggestionTargetsVisitedSelector, + getSuggestionTargetCurrentPageSelector, + getSuggestionTargetTotalsSelector, + isReciterSuggestionTargetProcessingSelector, + isSuggestionTargetLoadedSelector, + suggestionTargetObjectSelector +} from '../../suggestion-notifications/selectors'; /** * The service handling the Suggestion targets State. diff --git a/src/app/suggestion-notifications/suggestion.service.spec.ts b/src/app/notifications/suggestion.service.spec.ts similarity index 95% rename from src/app/suggestion-notifications/suggestion.service.spec.ts rename to src/app/notifications/suggestion.service.spec.ts index 268eb59ddd..082c7c3f04 100644 --- a/src/app/suggestion-notifications/suggestion.service.spec.ts +++ b/src/app/notifications/suggestion.service.spec.ts @@ -1,13 +1,6 @@ import { SuggestionsService } from './suggestions.service'; import { ResearcherProfileDataService } from '../core/profile/researcher-profile-data.service'; -import { - SuggestionsDataService -} from '../core/suggestion-notifications/suggestions-data.service'; - -import { - SuggestionTargetDataService -} from '../core/suggestion-notifications/target/suggestion-target-data.service'; import { TestScheduler } from 'rxjs/testing'; import { getTestScheduler } from 'jasmine-marbles'; import { of as observableOf } from 'rxjs'; @@ -18,11 +11,11 @@ import { createSuccessfulRemoteDataObject$ } from '../shared/remote-data.utils'; import { WorkspaceitemDataService } from '../core/submission/workspaceitem-data.service'; import { mockSuggestionPublicationOne } from '../shared/mocks/publication-claim.mock'; import { ResourceType } from '../core/shared/resource-type'; +import { SuggestionsDataService } from '../core/notifications/suggestions-data.service'; +import { SuggestionTargetDataService } from '../core/notifications/target/suggestion-target-data.service'; +import { SuggestionTarget } from '../core/notifications/models/suggestion-target.model'; -import { - SuggestionTarget -} from '../core/suggestion-notifications/models/suggestion-target.model'; describe('SuggestionsService test', () => { let scheduler: TestScheduler; diff --git a/src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.html b/src/app/notifications/suggestions-notification/suggestions-notification.component.html similarity index 100% rename from src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.html rename to src/app/notifications/suggestions-notification/suggestions-notification.component.html diff --git a/src/app/notifications/suggestions-notification/suggestions-notification.component.scss b/src/app/notifications/suggestions-notification/suggestions-notification.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.ts b/src/app/notifications/suggestions-notification/suggestions-notification.component.ts similarity index 92% rename from src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.ts rename to src/app/notifications/suggestions-notification/suggestions-notification.component.ts index 357a6ca34e..107da67fce 100644 --- a/src/app/suggestion-notifications/suggestions-notification/suggestions-notification.component.ts +++ b/src/app/notifications/suggestions-notification/suggestions-notification.component.ts @@ -1,8 +1,9 @@ import { Component, OnInit } from '@angular/core'; -import { SuggestionTarget } from '../../core/suggestion-notifications/models/suggestion-target.model'; + import { SuggestionTargetsStateService } from '../suggestion-targets/suggestion-targets.state.service'; import { SuggestionsService } from '../suggestions.service'; import { Observable } from 'rxjs'; +import { SuggestionTarget } from '../../core/notifications/models/suggestion-target.model'; /** * Show suggestions notification, used on myDSpace and Profile pages diff --git a/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.html b/src/app/notifications/suggestions-popup/suggestions-popup.component.html similarity index 100% rename from src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.html rename to src/app/notifications/suggestions-popup/suggestions-popup.component.html diff --git a/src/app/notifications/suggestions-popup/suggestions-popup.component.scss b/src/app/notifications/suggestions-popup/suggestions-popup.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.spec.ts b/src/app/notifications/suggestions-popup/suggestions-popup.component.spec.ts similarity index 100% rename from src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.spec.ts rename to src/app/notifications/suggestions-popup/suggestions-popup.component.spec.ts diff --git a/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.ts b/src/app/notifications/suggestions-popup/suggestions-popup.component.ts similarity index 95% rename from src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.ts rename to src/app/notifications/suggestions-popup/suggestions-popup.component.ts index 2cf3db128e..1921c4fe93 100644 --- a/src/app/suggestion-notifications/suggestions-popup/suggestions-popup.component.ts +++ b/src/app/notifications/suggestions-popup/suggestions-popup.component.ts @@ -2,13 +2,13 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; import { SuggestionTargetsStateService } from '../suggestion-targets/suggestion-targets.state.service'; import { SuggestionsService } from '../suggestions.service'; import { take, takeUntil } from 'rxjs/operators'; -import { SuggestionTarget } from '../../core/suggestion-notifications/models/suggestion-target.model'; import { isNotEmpty } from '../../shared/empty.util'; import { combineLatest, Observable, of, Subject } from 'rxjs'; import { trigger } from '@angular/animations'; import { fromTopEnter } from '../../shared/animations/fromTop'; +import { SuggestionTarget } from '../../core/notifications/models/suggestion-target.model'; /** * Show suggestions on a popover window, used on the homepage diff --git a/src/app/suggestion-notifications/suggestions.service.ts b/src/app/notifications/suggestions.service.ts similarity index 95% rename from src/app/suggestion-notifications/suggestions.service.ts rename to src/app/notifications/suggestions.service.ts index 3b2ce081f1..2fa85a5671 100644 --- a/src/app/suggestion-notifications/suggestions.service.ts +++ b/src/app/notifications/suggestions.service.ts @@ -6,16 +6,15 @@ import { catchError, map, mergeMap, take } from 'rxjs/operators'; import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model'; import { RemoteData } from '../core/data/remote-data'; import { PaginatedList } from '../core/data/paginated-list.model'; -import { SuggestionTarget } from '../core/suggestion-notifications/models/suggestion-target.model'; import { hasValue, isNotEmpty } from '../shared/empty.util'; import { ResearcherProfile } from '../core/profile/model/researcher-profile.model'; import { getAllSucceededRemoteDataPayload, - getFinishedRemoteData, getFirstCompletedRemoteData, + getFinishedRemoteData, + getFirstCompletedRemoteData, getFirstSucceededRemoteDataPayload, - getFirstSucceededRemoteListPayload + getFirstSucceededRemoteListPayload, } from '../core/shared/operators'; -import { Suggestion } from '../core/suggestion-notifications/models/suggestion.model'; import { WorkspaceitemDataService } from '../core/submission/workspaceitem-data.service'; import { TranslateService } from '@ngx-translate/core'; import { NoContent } from '../core/shared/NoContent.model'; @@ -24,13 +23,11 @@ import { WorkspaceItem } from '../core/submission/models/workspaceitem.model'; import {FindListOptions} from '../core/data/find-list-options.model'; import {SuggestionConfig} from '../../config/suggestion-config.interfaces'; import { ResearcherProfileDataService } from '../core/profile/researcher-profile-data.service'; -import { - SuggestionTargetDataService -} from '../core/suggestion-notifications/target/suggestion-target-data.service'; -import { - SuggestionsDataService -} from '../core/suggestion-notifications/suggestions-data.service'; import { getSuggestionPageRoute } from '../suggestions-page/suggestions-page-routing-paths'; +import { SuggestionsDataService } from '../core/notifications/suggestions-data.service'; +import { SuggestionTargetDataService } from '../core/notifications/target/suggestion-target-data.service'; +import { SuggestionTarget } from '../core/notifications/models/suggestion-target.model'; +import { Suggestion } from '../core/notifications/models/suggestion.model'; /** * useful for multiple approvals and ignores operation diff --git a/src/app/quality-assurance-notifications-pages/notifications-pages-routing-paths.ts b/src/app/quality-assurance-notifications-pages/notifications-pages-routing-paths.ts new file mode 100644 index 0000000000..c517ddafd4 --- /dev/null +++ b/src/app/quality-assurance-notifications-pages/notifications-pages-routing-paths.ts @@ -0,0 +1,7 @@ + +export const QUALITY_ASSURANCE_EDIT_PATH = 'quality-assurance'; +export const NOTIFICATIONS_RECITER_SUGGESTION_PATH = 'suggestion-targets'; + +export function getQualityAssuranceEditRoute() { + return `/${QUALITY_ASSURANCE_EDIT_PATH}`; +} diff --git a/src/app/quality-assurance-notifications-pages/notifications-pages-routing.module.ts b/src/app/quality-assurance-notifications-pages/notifications-pages-routing.module.ts new file mode 100644 index 0000000000..c57b22a028 --- /dev/null +++ b/src/app/quality-assurance-notifications-pages/notifications-pages-routing.module.ts @@ -0,0 +1,122 @@ +import { NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; + +import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; +import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver'; +import { I18nBreadcrumbsService } from '../core/breadcrumbs/i18n-breadcrumbs.service'; +import { NOTIFICATIONS_RECITER_SUGGESTION_PATH } from './notifications-pages-routing-paths'; +import { NotificationsSuggestionTargetsPageComponent } from './notifications-suggestion-targets-page/notifications-suggestion-targets-page.component'; +import { AdminNotificationsPublicationClaimPageResolver } from './notifications-suggestion-targets-page/notifications-suggestion-targets-page-resolver.service'; +import { QUALITY_ASSURANCE_EDIT_PATH } from './notifications-pages-routing-paths'; +import { QualityAssuranceTopicsPageComponent } from './quality-assurance-topics-page/quality-assurance-topics-page.component'; +import { QualityAssuranceEventsPageComponent } from './quality-assurance-events-page/quality-assurance-events-page.component'; +import { QualityAssuranceTopicsPageResolver } from './quality-assurance-topics-page/quality-assurance-topics-page-resolver.service'; +import { QualityAssuranceEventsPageResolver } from './quality-assurance-events-page/quality-assurance-events-page.resolver'; +import { QualityAssuranceSourcePageComponent } from './quality-assurance-source-page-component/quality-assurance-source-page.component'; +import { QualityAssuranceSourcePageResolver } from './quality-assurance-source-page-component/quality-assurance-source-page-resolver.service'; +import { QualityAssuranceBreadcrumbResolver } from '../core/breadcrumbs/quality-assurance-breadcrumb.resolver'; +import { QualityAssuranceBreadcrumbService } from '../core/breadcrumbs/quality-assurance-breadcrumb.service'; +import { + SourceDataResolver +} from './quality-assurance-source-page-component/quality-assurance-source-data.resolver'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + { + canActivate: [ AuthenticatedGuard ], + path: `${NOTIFICATIONS_RECITER_SUGGESTION_PATH}`, + component: NotificationsSuggestionTargetsPageComponent, + pathMatch: 'full', + resolve: { + breadcrumb: I18nBreadcrumbResolver, + reciterSuggestionTargetParams: AdminNotificationsPublicationClaimPageResolver + }, + data: { + title: 'admin.notifications.recitersuggestion.page.title', + breadcrumbKey: 'admin.notifications.recitersuggestion', + showBreadcrumbsFluid: false + } + }, + { + canActivate: [ AuthenticatedGuard ], + path: `${QUALITY_ASSURANCE_EDIT_PATH}/:sourceId`, + component: QualityAssuranceTopicsPageComponent, + pathMatch: 'full', + resolve: { + breadcrumb: QualityAssuranceBreadcrumbResolver, + openaireQualityAssuranceTopicsParams: QualityAssuranceTopicsPageResolver + }, + data: { + title: 'admin.quality-assurance.page.title', + breadcrumbKey: 'admin.quality-assurance', + showBreadcrumbsFluid: false + } + }, + { + canActivate: [ AuthenticatedGuard ], + path: `${QUALITY_ASSURANCE_EDIT_PATH}/:sourceId/target/:targetId`, + component: QualityAssuranceTopicsPageComponent, + pathMatch: 'full', + resolve: { + breadcrumb: I18nBreadcrumbResolver, + openaireQualityAssuranceTopicsParams: QualityAssuranceTopicsPageResolver + }, + data: { + title: 'admin.quality-assurance.page.title', + breadcrumbKey: 'admin.quality-assurance', + showBreadcrumbsFluid: false + } + }, + { + canActivate: [ AuthenticatedGuard ], + path: `${QUALITY_ASSURANCE_EDIT_PATH}`, + component: QualityAssuranceSourcePageComponent, + pathMatch: 'full', + resolve: { + breadcrumb: I18nBreadcrumbResolver, + openaireQualityAssuranceSourceParams: QualityAssuranceSourcePageResolver, + sourceData: SourceDataResolver + }, + data: { + title: 'admin.notifications.source.breadcrumbs', + breadcrumbKey: 'admin.notifications.source', + showBreadcrumbsFluid: false + } + }, + { + canActivate: [ AuthenticatedGuard ], + path: `${QUALITY_ASSURANCE_EDIT_PATH}/:sourceId/:topicId`, + component: QualityAssuranceEventsPageComponent, + pathMatch: 'full', + resolve: { + breadcrumb: QualityAssuranceBreadcrumbResolver, + openaireQualityAssuranceEventsParams: QualityAssuranceEventsPageResolver + }, + data: { + title: 'admin.notifications.event.page.title', + breadcrumbKey: 'admin.notifications.event', + showBreadcrumbsFluid: false + } + } + ]) + ], + providers: [ + I18nBreadcrumbResolver, + I18nBreadcrumbsService, + AdminNotificationsPublicationClaimPageResolver, + SourceDataResolver, + QualityAssuranceSourcePageResolver, + QualityAssuranceTopicsPageResolver, + QualityAssuranceEventsPageResolver, + QualityAssuranceSourcePageResolver, + QualityAssuranceBreadcrumbResolver, + QualityAssuranceBreadcrumbService + ] +}) +/** + * Routing module for the Notifications section of the admin sidebar + */ +export class NotificationsPageRoutingModule { + +} diff --git a/src/app/quality-assurance-notifications-pages/notifications-pages.module.ts b/src/app/quality-assurance-notifications-pages/notifications-pages.module.ts new file mode 100644 index 0000000000..bf5c608bf7 --- /dev/null +++ b/src/app/quality-assurance-notifications-pages/notifications-pages.module.ts @@ -0,0 +1,34 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { NotificationsPageRoutingModule } from './notifications-pages-routing.module'; +import { NotificationsSuggestionTargetsPageComponent } from './notifications-suggestion-targets-page/notifications-suggestion-targets-page.component'; +import { QualityAssuranceTopicsPageComponent } from './quality-assurance-topics-page/quality-assurance-topics-page.component'; +import { QualityAssuranceEventsPageComponent } from './quality-assurance-events-page/quality-assurance-events-page.component'; +import { QualityAssuranceSourcePageComponent } from './quality-assurance-source-page-component/quality-assurance-source-page.component'; +import { NotificationsModule } from '../notifications/notifications.module'; +import { SharedModule } from '../shared/shared.module'; +import { CoreModule } from '../core/core.module'; + + +@NgModule({ + imports: [ + CommonModule, + SharedModule, + CoreModule.forRoot(), + NotificationsPageRoutingModule, + NotificationsModule + ], + declarations: [ + NotificationsSuggestionTargetsPageComponent, + QualityAssuranceTopicsPageComponent, + QualityAssuranceEventsPageComponent, + QualityAssuranceSourcePageComponent + ], + entryComponents: [] +}) +/** + * This module handles all components related to the notifications pages + */ +export class NotificationsPageModule { + +} diff --git a/src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page-resolver.service.ts b/src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page-resolver.service.ts new file mode 100644 index 0000000000..783387281e --- /dev/null +++ b/src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page-resolver.service.ts @@ -0,0 +1,35 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router'; + +/** + * Interface for the route parameters. + */ + +export interface AdminNotificationsPublicationClaimPageParams { + pageId?: string; + pageSize?: number; + currentPage?: number; +} + +/** + * This class represents a resolver that retrieve the route data before the route is activated. + */ +@Injectable() + +export class AdminNotificationsPublicationClaimPageResolver implements Resolve { + + /** + * Method for resolving the parameters in the current route. + * @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot + * @param {RouterStateSnapshot} state The current RouterStateSnapshot + * @returns AdminNotificationsSuggestionTargetsPageParams Emits the route parameters + */ + + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): AdminNotificationsPublicationClaimPageParams { + return { + pageId: route.queryParams.pageId, + pageSize: parseInt(route.queryParams.pageSize, 10), + currentPage: parseInt(route.queryParams.page, 10) + }; + } +} diff --git a/src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.html b/src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.html new file mode 100644 index 0000000000..11db25fa7b --- /dev/null +++ b/src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.html @@ -0,0 +1 @@ + diff --git a/src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.scss b/src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.spec.ts b/src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.spec.ts new file mode 100644 index 0000000000..bbca7f8d39 --- /dev/null +++ b/src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.spec.ts @@ -0,0 +1,41 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { NotificationsSuggestionTargetsPageComponent } from './notifications-suggestion-targets-page.component'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { TranslateModule } from '@ngx-translate/core'; +import { + AdminNotificationsPublicationClaimPageComponent +} from '../../admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component'; + +describe('NotificationsSuggestionTargetsPageComponent', () => { + let component: NotificationsSuggestionTargetsPageComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + CommonModule, + TranslateModule.forRoot() + ], + declarations: [ + NotificationsSuggestionTargetsPageComponent + ], + providers: [ + AdminNotificationsPublicationClaimPageComponent + ], + schemas: [NO_ERRORS_SCHEMA] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(NotificationsSuggestionTargetsPageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.ts b/src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.ts new file mode 100644 index 0000000000..65b7f7667e --- /dev/null +++ b/src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'ds-notifications-reciter-page', + templateUrl: './notifications-suggestion-targets-page.component.html', + styleUrls: ['./notifications-suggestion-targets-page.component.scss'] +}) +export class NotificationsSuggestionTargetsPageComponent { + +} diff --git a/src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.component.html b/src/app/quality-assurance-notifications-pages/quality-assurance-events-page/quality-assurance-events-page.component.html similarity index 100% rename from src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.component.html rename to src/app/quality-assurance-notifications-pages/quality-assurance-events-page/quality-assurance-events-page.component.html diff --git a/src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.component.spec.ts b/src/app/quality-assurance-notifications-pages/quality-assurance-events-page/quality-assurance-events-page.component.spec.ts similarity index 51% rename from src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.component.spec.ts rename to src/app/quality-assurance-notifications-pages/quality-assurance-events-page/quality-assurance-events-page.component.spec.ts index b952078215..bc1fb21453 100644 --- a/src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.component.spec.ts +++ b/src/app/quality-assurance-notifications-pages/quality-assurance-events-page/quality-assurance-events-page.component.spec.ts @@ -1,21 +1,21 @@ import { NO_ERRORS_SCHEMA } from '@angular/core'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { AdminQualityAssuranceEventsPageComponent } from './admin-quality-assurance-events-page.component'; +import { QualityAssuranceEventsPageComponent } from './quality-assurance-events-page.component'; -describe('AdminQualityAssuranceEventsPageComponent', () => { - let component: AdminQualityAssuranceEventsPageComponent; - let fixture: ComponentFixture; +describe('QualityAssuranceEventsPageComponent', () => { + let component: QualityAssuranceEventsPageComponent; + let fixture: ComponentFixture; beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [ AdminQualityAssuranceEventsPageComponent ], + declarations: [ QualityAssuranceEventsPageComponent ], schemas: [NO_ERRORS_SCHEMA] }) .compileComponents(); })); beforeEach(() => { - fixture = TestBed.createComponent(AdminQualityAssuranceEventsPageComponent); + fixture = TestBed.createComponent(QualityAssuranceEventsPageComponent); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.component.ts b/src/app/quality-assurance-notifications-pages/quality-assurance-events-page/quality-assurance-events-page.component.ts similarity index 61% rename from src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.component.ts rename to src/app/quality-assurance-notifications-pages/quality-assurance-events-page/quality-assurance-events-page.component.ts index bd3470f301..0f9ddd509f 100644 --- a/src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.component.ts +++ b/src/app/quality-assurance-notifications-pages/quality-assurance-events-page/quality-assurance-events-page.component.ts @@ -5,8 +5,8 @@ import { Component } from '@angular/core'; */ @Component({ selector: 'ds-quality-assurance-events-page', - templateUrl: './admin-quality-assurance-events-page.component.html' + templateUrl: './quality-assurance-events-page.component.html' }) -export class AdminQualityAssuranceEventsPageComponent { +export class QualityAssuranceEventsPageComponent { } diff --git a/src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.resolver.ts b/src/app/quality-assurance-notifications-pages/quality-assurance-events-page/quality-assurance-events-page.resolver.ts similarity index 80% rename from src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.resolver.ts rename to src/app/quality-assurance-notifications-pages/quality-assurance-events-page/quality-assurance-events-page.resolver.ts index 3139355629..30b838dd13 100644 --- a/src/app/admin/admin-notifications/admin-quality-assurance-events-page/admin-quality-assurance-events-page.resolver.ts +++ b/src/app/quality-assurance-notifications-pages/quality-assurance-events-page/quality-assurance-events-page.resolver.ts @@ -4,7 +4,7 @@ import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/r /** * Interface for the route parameters. */ -export interface AdminQualityAssuranceEventsPageParams { +export interface AssuranceEventsPageParams { pageId?: string; pageSize?: number; currentPage?: number; @@ -14,7 +14,7 @@ export interface AdminQualityAssuranceEventsPageParams { * This class represents a resolver that retrieve the route data before the route is activated. */ @Injectable() -export class AdminQualityAssuranceEventsPageResolver implements Resolve { +export class QualityAssuranceEventsPageResolver implements Resolve { /** * Method for resolving the parameters in the current route. @@ -22,7 +22,7 @@ export class AdminQualityAssuranceEventsPageResolver implements Resolve { +export class QualityAssuranceSourcePageResolver implements Resolve { /** * Method for resolving the parameters in the current route. @@ -22,7 +22,7 @@ export class AdminQualityAssuranceSourcePageResolver implements Resolve { + let component: QualityAssuranceSourcePageComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ QualityAssuranceSourcePageComponent ], + schemas: [NO_ERRORS_SCHEMA] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(QualityAssuranceSourcePageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create QualityAssuranceSourcePageComponent', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/quality-assurance-notifications-pages/quality-assurance-source-page-component/quality-assurance-source-page.component.ts b/src/app/quality-assurance-notifications-pages/quality-assurance-source-page-component/quality-assurance-source-page.component.ts new file mode 100644 index 0000000000..f066364708 --- /dev/null +++ b/src/app/quality-assurance-notifications-pages/quality-assurance-source-page-component/quality-assurance-source-page.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +/** + * Component for the page that show the QA sources. + */ +@Component({ + selector: 'ds-quality-assurance-source-page-component', + templateUrl: './quality-assurance-source-page.component.html', +}) +export class QualityAssuranceSourcePageComponent {} diff --git a/src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page-resolver.service.ts b/src/app/quality-assurance-notifications-pages/quality-assurance-topics-page/quality-assurance-topics-page-resolver.service.ts similarity index 80% rename from src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page-resolver.service.ts rename to src/app/quality-assurance-notifications-pages/quality-assurance-topics-page/quality-assurance-topics-page-resolver.service.ts index 47500d1878..b0e43e549f 100644 --- a/src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page-resolver.service.ts +++ b/src/app/quality-assurance-notifications-pages/quality-assurance-topics-page/quality-assurance-topics-page-resolver.service.ts @@ -4,7 +4,7 @@ import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/r /** * Interface for the route parameters. */ -export interface AdminQualityAssuranceTopicsPageParams { +export interface QualityAssuranceTopicsPageParams { pageId?: string; pageSize?: number; currentPage?: number; @@ -14,7 +14,7 @@ export interface AdminQualityAssuranceTopicsPageParams { * This class represents a resolver that retrieve the route data before the route is activated. */ @Injectable() -export class AdminQualityAssuranceTopicsPageResolver implements Resolve { +export class QualityAssuranceTopicsPageResolver implements Resolve { /** * Method for resolving the parameters in the current route. @@ -22,7 +22,7 @@ export class AdminQualityAssuranceTopicsPageResolver implements Resolve { + let component: QualityAssuranceTopicsPageComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ QualityAssuranceTopicsPageComponent ], + schemas: [NO_ERRORS_SCHEMA] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(QualityAssuranceTopicsPageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create QualityAssuranceTopicsPageComponent', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component.ts b/src/app/quality-assurance-notifications-pages/quality-assurance-topics-page/quality-assurance-topics-page.component.ts similarity index 60% rename from src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component.ts rename to src/app/quality-assurance-notifications-pages/quality-assurance-topics-page/quality-assurance-topics-page.component.ts index f17d3448d5..af0c8085af 100644 --- a/src/app/admin/admin-notifications/admin-quality-assurance-topics-page/admin-quality-assurance-topics-page.component.ts +++ b/src/app/quality-assurance-notifications-pages/quality-assurance-topics-page/quality-assurance-topics-page.component.ts @@ -5,8 +5,8 @@ import { Component } from '@angular/core'; */ @Component({ selector: 'ds-notification-qa-page', - templateUrl: './admin-quality-assurance-topics-page.component.html' + templateUrl: './quality-assurance-topics-page.component.html' }) -export class AdminQualityAssuranceTopicsPageComponent { +export class QualityAssuranceTopicsPageComponent { } diff --git a/src/app/shared/correction-suggestion/item-withdrawn-reinstate-modal.component.html b/src/app/shared/correction-suggestion/item-withdrawn-reinstate-modal.component.html new file mode 100644 index 0000000000..1463235bee --- /dev/null +++ b/src/app/shared/correction-suggestion/item-withdrawn-reinstate-modal.component.html @@ -0,0 +1,55 @@ +
+ + + +
+ + + + + + + + + diff --git a/src/app/shared/correction-suggestion/item-withdrawn-reinstate-modal.component.scss b/src/app/shared/correction-suggestion/item-withdrawn-reinstate-modal.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/shared/correction-suggestion/withdrawn-reinstate-modal.component.ts b/src/app/shared/correction-suggestion/withdrawn-reinstate-modal.component.ts new file mode 100644 index 0000000000..de842eb1e5 --- /dev/null +++ b/src/app/shared/correction-suggestion/withdrawn-reinstate-modal.component.ts @@ -0,0 +1,74 @@ +import { Component, EventEmitter, Output } from '@angular/core'; +import { ModalBeforeDismiss } from '../interfaces/modal-before-dismiss.interface'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { BehaviorSubject } from 'rxjs'; +import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; + +@Component({ + selector: 'ds-item-withdrawn-reinstate-modal', + templateUrl: './item-withdrawn-reinstate-modal.component.html', + styleUrls: ['./item-withdrawn-reinstate-modal.component.scss'] +}) +/** + * Represents a modal component for withdrawing or reinstating an item. + * Implements the ModalBeforeDismiss interface. + */ +export class ItemWithdrawnReinstateModalComponent implements ModalBeforeDismiss { + + /** + * The reason for withdrawing or reinstating a suggestion. + */ + reason: string; + /** + * Indicates whether the item can be withdrawn. + */ + canWithdraw: boolean; + /** + * BehaviorSubject that represents the submitted state. + * Emits a boolean value indicating whether the form has been submitted or not. + */ + submitted$: BehaviorSubject = new BehaviorSubject(false); + /** + * Event emitter for creating a QA event. + * @event createQAEvent + */ + @Output() createQAEvent: EventEmitter = new EventEmitter(); + + constructor( + protected activeModal: NgbActiveModal, + protected authorizationService: AuthorizationDataService, + ) {} + + /** + * Closes the modal. + */ + onModalClose() { + this.activeModal.close(); + } + + /** + * Determines whether the modal can be dismissed. + * @returns {boolean} True if the modal can be dismissed, false otherwise. + */ + beforeDismiss(): boolean { + // prevent the modal from being dismissed after version creation is initiated + return !this.submitted$.getValue(); + } + + /** + * Handles the submission of the modal form. + * Emits the reason for withdrawal or reinstatement through the createQAEvent output. + */ + onModalSubmit() { + this.submitted$.next(true); + this.createQAEvent.emit(this.reason); + } + + /** + * Sets the withdrawal state of the component. + * @param state The new withdrawal state. + */ + public setWithdraw(state: boolean) { + this.canWithdraw = state; + } +} diff --git a/src/app/shared/dso-page/dso-edit-menu.resolver.spec.ts b/src/app/shared/dso-page/dso-edit-menu.resolver.spec.ts index e28a416f23..14b4313ac2 100644 --- a/src/app/shared/dso-page/dso-edit-menu.resolver.spec.ts +++ b/src/app/shared/dso-page/dso-edit-menu.resolver.spec.ts @@ -23,6 +23,10 @@ import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { Community } from '../../core/shared/community.model'; import { Collection } from '../../core/shared/collection.model'; import flatten from 'lodash/flatten'; +import { DsoWithdrawnReinstateModalService } from './dso-withdrawn-reinstate-service/dso-withdrawn-reinstate-modal.service'; +import { AuthService } from 'src/app/core/auth/auth.service'; +import { AuthServiceMock } from '../mocks/auth.service.mock'; +import { CorrectionTypeDataService } from 'src/app/core/submission/correctiontype-data.service'; describe('DSOEditMenuResolver', () => { @@ -39,6 +43,8 @@ describe('DSOEditMenuResolver', () => { let researcherProfileService; let notificationsService; let translate; + let dsoWithdrawnReinstateModalService; + let correctionsDataService; const dsoRoute = (dso: DSpaceObject) => { return { @@ -141,6 +147,14 @@ describe('DSOEditMenuResolver', () => { error: {}, }); + dsoWithdrawnReinstateModalService = jasmine.createSpyObj('dsoWithdrawnReinstateModalService', { + openCreateWithdrawnReinstateModal: {}, + }); + + correctionsDataService = jasmine.createSpyObj('correctionsDataService', { + findByItem: observableOf([]) + }); + TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), NoopAnimationsModule, RouterTestingModule], declarations: [AdminSidebarComponent], @@ -152,6 +166,9 @@ describe('DSOEditMenuResolver', () => { {provide: ResearcherProfileDataService, useValue: researcherProfileService}, {provide: TranslateService, useValue: translate}, {provide: NotificationsService, useValue: notificationsService}, + {provide: DsoWithdrawnReinstateModalService, useValue: dsoWithdrawnReinstateModalService}, + {provide: AuthService, useValue: new AuthServiceMock()}, + {provide: CorrectionTypeDataService, useValue: correctionsDataService}, { provide: NgbModal, useValue: { open: () => {/*comment*/ @@ -350,7 +367,7 @@ describe('DSOEditMenuResolver', () => { route = dsoRoute(testItem); }); - it('should return Item-specific entries', (done) => { + it('should return Item-specific entries', () => { const result = resolver.getDsoMenus(testObject, route, state); combineLatest(result).pipe(map(flatten)).subscribe((menu) => { const orcidEntry = menu.find(entry => entry.id === 'orcid-dso'); @@ -371,20 +388,18 @@ describe('DSOEditMenuResolver', () => { expect(claimEntry.active).toBeFalse(); expect(claimEntry.visible).toBeFalse(); expect(claimEntry.model.type).toEqual(MenuItemType.ONCLICK); - done(); }); }); - it('should not return Community/Collection-specific entries', (done) => { + it('should not return Community/Collection-specific entries', () => { const result = resolver.getDsoMenus(testObject, route, state); combineLatest(result).pipe(map(flatten)).subscribe((menu) => { const subscribeEntry = menu.find(entry => entry.id === 'subscribe'); expect(subscribeEntry).toBeFalsy(); - done(); }); }); - it('should return as third part the common list ', (done) => { + it('should return as third part the common list ', () => { const result = resolver.getDsoMenus(testObject, route, state); combineLatest(result).pipe(map(flatten)).subscribe((menu) => { const editEntry = menu.find(entry => entry.id === 'edit-dso'); @@ -395,7 +410,6 @@ describe('DSOEditMenuResolver', () => { expect((editEntry.model as LinkMenuItemModel).link).toEqual( '/items/test-item-uuid/edit/metadata' ); - done(); }); }); }); diff --git a/src/app/shared/dso-page/dso-edit-menu.resolver.ts b/src/app/shared/dso-page/dso-edit-menu.resolver.ts index 1ade457840..bcded3acd5 100644 --- a/src/app/shared/dso-page/dso-edit-menu.resolver.ts +++ b/src/app/shared/dso-page/dso-edit-menu.resolver.ts @@ -8,7 +8,9 @@ import { LinkMenuItemModel } from '../menu/menu-item/models/link.model'; import { Item } from '../../core/shared/item.model'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { OnClickMenuItemModel } from '../menu/menu-item/models/onclick.model'; -import { getFirstCompletedRemoteData } from '../../core/shared/operators'; +import { + getFirstCompletedRemoteData, getRemoteDataPayload, +} from '../../core/shared/operators'; import { map, switchMap } from 'rxjs/operators'; import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service'; import { URLCombiner } from '../../core/url-combiner/url-combiner'; @@ -21,6 +23,11 @@ import { getDSORoute } from '../../app-routing-paths'; import { ResearcherProfileDataService } from '../../core/profile/researcher-profile-data.service'; import { NotificationsService } from '../notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; +import { DsoWithdrawnReinstateModalService, REQUEST_REINSTATE, REQUEST_WITHDRAWN } from './dso-withdrawn-reinstate-service/dso-withdrawn-reinstate-modal.service'; +import { AuthService } from '../../core/auth/auth.service'; +import { FindListOptions } from '../../core/data/find-list-options.model'; +import { RequestParam } from '../../core/cache/models/request-param.model'; +import { CorrectionTypeDataService } from '../../core/submission/correctiontype-data.service'; import { SubscriptionModalComponent } from '../subscriptions/subscription-modal/subscription-modal.component'; import { Community } from '../../core/shared/community.model'; import { Collection } from '../../core/shared/collection.model'; @@ -42,6 +49,9 @@ export class DSOEditMenuResolver implements Resolve<{ [key: string]: MenuSection protected researcherProfileService: ResearcherProfileDataService, protected notificationsService: NotificationsService, protected translate: TranslateService, + protected dsoWithdrawnReinstateModalService: DsoWithdrawnReinstateModalService, + private auth: AuthService, + private correctionTypeDataService: CorrectionTypeDataService ) { } @@ -123,14 +133,20 @@ export class DSOEditMenuResolver implements Resolve<{ [key: string]: MenuSection */ protected getItemMenu(dso): Observable { if (dso instanceof Item) { + const findListTopicOptions: FindListOptions = { + searchParams: [new RequestParam('target', dso.uuid)] + }; return combineLatest([ this.authorizationService.isAuthorized(FeatureID.CanCreateVersion, dso.self), this.dsoVersioningModalService.isNewVersionButtonDisabled(dso), this.dsoVersioningModalService.getVersioningTooltipMessage(dso, 'item.page.version.hasDraft', 'item.page.version.create'), this.authorizationService.isAuthorized(FeatureID.CanSynchronizeWithORCID, dso.self), this.authorizationService.isAuthorized(FeatureID.CanClaimItem, dso.self), + this.correctionTypeDataService.findByItem(dso.uuid, false).pipe( + getFirstCompletedRemoteData(), + getRemoteDataPayload()) ]).pipe( - map(([canCreateVersion, disableVersioning, versionTooltip, canSynchronizeWithOrcid, canClaimItem]) => { + map(([canCreateVersion, disableVersioning, versionTooltip, canSynchronizeWithOrcid, canClaimItem, correction]) => { const isPerson = this.getDsoType(dso) === 'person'; return [ { @@ -174,6 +190,34 @@ export class DSOEditMenuResolver implements Resolve<{ [key: string]: MenuSection icon: 'hand-paper', index: 3 }, + { + id: 'withdrawn-item', + active: false, + visible: dso.isArchived && correction?.page.some((c) => c.topic === REQUEST_WITHDRAWN), + model: { + type: MenuItemType.ONCLICK, + text:'item.page.withdrawn', + function: () => { + this.dsoWithdrawnReinstateModalService.openCreateWithdrawnReinstateModal(dso, 'request-withdrawn', dso.isArchived); + } + } as OnClickMenuItemModel, + icon: 'eye-slash', + index: 4 + }, + { + id: 'reinstate-item', + active: false, + visible: dso.isWithdrawn && correction?.page.some((c) => c.topic === REQUEST_REINSTATE), + model: { + type: MenuItemType.ONCLICK, + text:'item.page.reinstate', + function: () => { + this.dsoWithdrawnReinstateModalService.openCreateWithdrawnReinstateModal(dso, 'request-reinstate', dso.isArchived); + } + } as OnClickMenuItemModel, + icon: 'eye', + index: 5 + } ]; }), ); @@ -263,4 +307,5 @@ export class DSOEditMenuResolver implements Resolve<{ [key: string]: MenuSection return menu; }); } + } diff --git a/src/app/shared/dso-page/dso-withdrawn-reinstate-service/dso-withdrawn-reinstate-modal.service.ts b/src/app/shared/dso-page/dso-withdrawn-reinstate-service/dso-withdrawn-reinstate-modal.service.ts new file mode 100644 index 0000000000..d5f47ed57b --- /dev/null +++ b/src/app/shared/dso-page/dso-withdrawn-reinstate-service/dso-withdrawn-reinstate-modal.service.ts @@ -0,0 +1,102 @@ +import { Injectable } from '@angular/core'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { Router } from '@angular/router'; +import { ItemDataService } from '../../../core/data/item-data.service'; +import { ItemWithdrawnReinstateModalComponent } from '../../correction-suggestion/withdrawn-reinstate-modal.component'; +import { + QualityAssuranceEventDataService +} from '../../../core/notifications/qa/events/quality-assurance-event-data.service'; +import { + QualityAssuranceEventObject +} from '../../../core/notifications/qa/models/quality-assurance-event.model'; +import { RemoteData } from '../../../core/data/remote-data'; +import { TranslateService } from '@ngx-translate/core'; +import { NotificationsService } from '../../notifications/notifications.service'; +import { take } from 'rxjs/operators'; +import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; +import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; +import { Item } from 'src/app/core/shared/item.model'; + +export const REQUEST_WITHDRAWN = 'REQUEST/WITHDRAWN'; +export const REQUEST_REINSTATE = 'REQUEST/REINSTATE'; + +@Injectable({ + providedIn: 'root' +}) +/** + * Service for managing the withdrawn/reinstate modal for a DSO. + */ +export class DsoWithdrawnReinstateModalService { + + constructor( + protected router: Router, + protected modalService: NgbModal, + protected itemService: ItemDataService, + private notificationsService: NotificationsService, + protected authorizationService: AuthorizationDataService, + private translateService: TranslateService, + protected qaEventDataService: QualityAssuranceEventDataService, + ) {} + + /** + * Open the create withdrawn modal for the provided dso + */ + openCreateWithdrawnReinstateModal(dso: Item, correctionType: 'request-reinstate' | 'request-withdrawn', state: boolean): void { + const target = dso.id; + // Open modal + const activeModal = this.modalService.open(ItemWithdrawnReinstateModalComponent); + (activeModal.componentInstance as ItemWithdrawnReinstateModalComponent).setWithdraw(state); + (activeModal.componentInstance as ItemWithdrawnReinstateModalComponent).createQAEvent + .pipe( + take(1) + ).subscribe( + (reasone) => { + this.sendQARequest(target, correctionType, reasone); + activeModal.close(); + } + ); + } + + /** + * Sends a quality assurance request. + * + * @param target - The target - the item's UUID. + * @param correctionType - The type of correction. + * @param reason - The reason for the request. + * Reloads the current page in order to update the withdrawn/reinstate button. + * and desplay a notification box. + */ + sendQARequest(target: string, correctionType: 'request-reinstate' | 'request-withdrawn', reason: string): void { + this.qaEventDataService.postData(target, correctionType, '', reason) + .pipe ( + getFirstCompletedRemoteData() + ) + .subscribe((res: RemoteData) => { + if (res.hasSucceeded) { + const message = (correctionType === 'request-withdrawn') + ? 'correction-type.manage-relation.action.notification.withdrawn' + : 'correction-type.manage-relation.action.notification.reinstate'; + + this.notificationsService.success(this.translateService.get(message)); + this.authorizationService.invalidateAuthorizationsRequestCache(); + this.reloadPage(true); + } else { + this.notificationsService.error(this.translateService.get('correction-type.manage-relation.action.notification.error')); + } + }); + } + + /** + * Reloads the current page or navigates to a specified URL. + * @param self - A boolean indicating whether to reload the current page (true) or navigate to a specified URL (false). + * @param urlToNavigateTo - The URL to navigate to if `self` is false. + * skipLocationChange:true means dont update the url to / when navigating + */ + reloadPage(self: boolean, urlToNavigateTo?: string) { + const url = self ? this.router.url : urlToNavigateTo; + this.router.navigateByUrl('/', { skipLocationChange: true }).then(() => { + this.router.navigate([`/${url}`]); + }); + } +} + diff --git a/src/app/shared/mocks/active-router.mock.ts b/src/app/shared/mocks/active-router.mock.ts index 672cdcd8f6..00bfced12c 100644 --- a/src/app/shared/mocks/active-router.mock.ts +++ b/src/app/shared/mocks/active-router.mock.ts @@ -5,19 +5,29 @@ import { BehaviorSubject } from 'rxjs'; export class MockActivatedRoute { private _testParams?: any; + private _testUrl?: any; // ActivatedRoute.params is Observable private subject?: BehaviorSubject = new BehaviorSubject(this.testParams); + // ActivatedRoute.url is Observable + private urlSubject?: BehaviorSubject = new BehaviorSubject(this.testUrl); params = this.subject.asObservable(); queryParams = this.subject.asObservable(); + url = this.urlSubject.asObservable(); - constructor(params?: Params) { + constructor(params?: Params, url?: any) { if (params) { this.testParams = params; } else { this.testParams = {}; } + + if (url) { + this.testUrl = url; + } else { + this.testUrl = {}; + } } // Test parameters @@ -31,4 +41,11 @@ export class MockActivatedRoute { get snapshot() { return { params: this.testParams, queryParams: this.testParams }; } + + //ActivatedRoute.url + get testUrl() { return this._testUrl; } + set testUrl(url: any) { + this._testUrl = url; + this.urlSubject.next(url); + } } diff --git a/src/app/shared/mocks/notifications.mock.ts b/src/app/shared/mocks/notifications.mock.ts index 707b9a9e6a..86f7b74a80 100644 --- a/src/app/shared/mocks/notifications.mock.ts +++ b/src/app/shared/mocks/notifications.mock.ts @@ -1482,7 +1482,8 @@ export const qualityAssuranceEventObjectMissingPid: QualityAssuranceEventObject funder: null, fundingProgram: null, jurisdiction: null, - title: null + title: null, + reason: 'Missing PID' }, _links: { self: { @@ -1519,7 +1520,8 @@ export const qualityAssuranceEventObjectMissingPid2: QualityAssuranceEventObject funder: null, fundingProgram: null, jurisdiction: null, - title: null + title: null, + reason: 'Missing PID' }, _links: { self: { @@ -1556,7 +1558,8 @@ export const qualityAssuranceEventObjectMissingPid3: QualityAssuranceEventObject funder: null, fundingProgram: null, jurisdiction: null, - title: null + title: null, + reason: 'Missing PID' }, _links: { self: { @@ -1593,7 +1596,8 @@ export const qualityAssuranceEventObjectMissingPid4: QualityAssuranceEventObject funder: null, fundingProgram: null, jurisdiction: null, - title: null + title: null, + reason: 'Missing DOI' }, _links: { self: { @@ -1630,7 +1634,8 @@ export const qualityAssuranceEventObjectMissingPid5: QualityAssuranceEventObject funder: null, fundingProgram: null, jurisdiction: null, - title: null + title: null, + reason: 'Missing PID' }, _links: { self: { @@ -1667,7 +1672,8 @@ export const qualityAssuranceEventObjectMissingPid6: QualityAssuranceEventObject funder: null, fundingProgram: null, jurisdiction: null, - title: null + title: null, + reason: 'Missing PID' }, _links: { self: { @@ -1704,7 +1710,8 @@ export const qualityAssuranceEventObjectMissingAbstract: QualityAssuranceEventOb funder: null, fundingProgram: null, jurisdiction: null, - title: null + title: null, + reason: 'Missing abstract' }, _links: { self: { @@ -1741,6 +1748,7 @@ export const qualityAssuranceEventObjectMissingProjectFound: QualityAssuranceEve funder: 'EC', fundingProgram: 'H2020', jurisdiction: 'EU', + reason: 'Project found', title: 'Tracking Papyrus and Parchment Paths: An Archaeological Atlas of Coptic Literature.\nLiterary Texts in their Geographical Context: Production, Copying, Usage, Dissemination and Storage' }, _links: { @@ -1778,7 +1786,8 @@ export const qualityAssuranceEventObjectMissingProjectNotFound: QualityAssurance funder: 'EC', fundingProgram: 'H2021', jurisdiction: 'EU', - title: 'Tracking Unknown Papyrus and Parchment Paths: An Archaeological Atlas of Coptic Literature.\nLiterary Texts in their Geographical Context: Production, Copying, Usage, Dissemination and Storage' + title: 'Tracking Unknown Papyrus and Parchment Paths: An Archaeological Atlas of Coptic Literature.\nLiterary Texts in their Geographical Context: Production, Copying, Usage, Dissemination and Storage', + reason: 'Project not found' }, _links: { self: { @@ -1838,8 +1847,10 @@ export function getMockNotificationsStateService(): any { */ export function getMockQualityAssuranceTopicRestService(): QualityAssuranceTopicDataService { return jasmine.createSpyObj('QualityAssuranceTopicDataService', { - getTopics: jasmine.createSpy('getTopics'), getTopic: jasmine.createSpy('getTopic'), + searchTopicsByTarget: jasmine.createSpy('searchTopicsByTarget'), + searchTopicsBySource: jasmine.createSpy('searchTopicsBySource'), + clearFindAllTopicsRequests: jasmine.createSpy('clearFindAllTopicsRequests'), }); } diff --git a/src/app/shared/mocks/publication-claim-targets.mock.ts b/src/app/shared/mocks/publication-claim-targets.mock.ts index 1d7688c1e3..932a98bee5 100644 --- a/src/app/shared/mocks/publication-claim-targets.mock.ts +++ b/src/app/shared/mocks/publication-claim-targets.mock.ts @@ -1,5 +1,5 @@ import { ResourceType } from '../../core/shared/resource-type'; -import { SuggestionTarget } from '../../core/suggestion-notifications/models/suggestion-target.model'; +import { SuggestionTarget } from '../../core/notifications/models/suggestion-target.model'; // REST Mock --------------------------------------------------------------------- // ------------------------------------------------------------------------------- diff --git a/src/app/shared/mocks/publication-claim.mock.ts b/src/app/shared/mocks/publication-claim.mock.ts index 143b54d8dd..02364347f4 100644 --- a/src/app/shared/mocks/publication-claim.mock.ts +++ b/src/app/shared/mocks/publication-claim.mock.ts @@ -2,8 +2,9 @@ // REST Mock --------------------------------------------------------------------- // ------------------------------------------------------------------------------- -import { Suggestion } from '../../core/suggestion-notifications/models/suggestion.model'; -import { SUGGESTION } from '../../core/suggestion-notifications/models/suggestion-objects.resource-type'; + +import { Suggestion } from '../../core/notifications/models/suggestion.model'; +import { SUGGESTION } from '../../core/notifications/models/suggestion-objects.resource-type'; export const mockSuggestionPublicationOne: Suggestion = { id: '24694773', diff --git a/src/app/shared/search/advanced-search/advanced-search.component.html b/src/app/shared/search/advanced-search/advanced-search.component.html new file mode 100644 index 0000000000..e03fb40532 --- /dev/null +++ b/src/app/shared/search/advanced-search/advanced-search.component.html @@ -0,0 +1,51 @@ +
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
\ No newline at end of file diff --git a/src/app/shared/search/advanced-search/advanced-search.component.scss b/src/app/shared/search/advanced-search/advanced-search.component.scss new file mode 100644 index 0000000000..13ca767b2b --- /dev/null +++ b/src/app/shared/search/advanced-search/advanced-search.component.scss @@ -0,0 +1 @@ +@import '../search-filters/search-filter/search-filter.component.scss'; \ No newline at end of file diff --git a/src/app/shared/search/advanced-search/advanced-search.component.spec.ts b/src/app/shared/search/advanced-search/advanced-search.component.spec.ts new file mode 100644 index 0000000000..a6a7f46491 --- /dev/null +++ b/src/app/shared/search/advanced-search/advanced-search.component.spec.ts @@ -0,0 +1,74 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { FormBuilderService } from '../../../shared/form/builder/form-builder.service'; +import { AdvancedSearchComponent } from './advanced-search.component'; +import { getMockFormBuilderService } from '../../../shared/mocks/form-builder-service.mock'; +import { SearchService } from '../../../core/shared/search/search.service'; +import { SEARCH_CONFIG_SERVICE } from '../../../my-dspace-page/my-dspace-page.component'; +import { SearchConfigurationServiceStub } from '../../testing/search-configuration-service.stub'; +import { RemoteDataBuildService } from '../../../core/cache/builders/remote-data-build.service'; +import { FormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { APP_CONFIG } from '../../../../config/app-config.interface'; +import { environment } from '../../../../environments/environment'; +import { RouterStub } from '../../testing/router.stub'; +import { Router } from '@angular/router'; +import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; +import { BrowserOnlyMockPipe } from '../../testing/browser-only-mock.pipe'; +import { RouterTestingModule } from '@angular/router/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +describe('AdvancedSearchComponent', () => { + let component: AdvancedSearchComponent; + let fixture: ComponentFixture; + let builderService: FormBuilderService = getMockFormBuilderService(); + let searchService: SearchService; + let router; + const searchServiceStub = { + /* eslint-disable no-empty,@typescript-eslint/no-empty-function */ + getClearFiltersQueryParams: () => { + }, + getSearchLink: () => { + }, + getConfigurationSearchConfig: () => { }, + /* eslint-enable no-empty, @typescript-eslint/no-empty-function */ + }; + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [AdvancedSearchComponent, BrowserOnlyMockPipe], + imports: [FormsModule, RouterTestingModule, TranslateModule.forRoot(), BrowserAnimationsModule, ReactiveFormsModule], + providers: [ + FormBuilder, + { provide: APP_CONFIG, useValue: environment }, + { provide: FormBuilderService, useValue: builderService }, + { provide: Router, useValue: new RouterStub() }, + { provide: SEARCH_CONFIG_SERVICE, useValue: new SearchConfigurationServiceStub() }, + { provide: RemoteDataBuildService, useValue: {} }, + { provide: SearchService, useValue: searchServiceStub }, + ], + schemas: [NO_ERRORS_SCHEMA] + }).overrideComponent(AdvancedSearchComponent, { + set: { changeDetection: ChangeDetectionStrategy.Default } + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AdvancedSearchComponent); + component = fixture.componentInstance; + router = TestBed.inject(Router); + fixture.detectChanges(); + }); + describe('when the getSearchLink method is called', () => { + const data = { filter: 'title', textsearch: 'demo', operator: 'equals' }; + it('should call navigate on the router with the right searchlink and parameters when the filter is provided with a valid operator', () => { + component.advSearchForm.get('textsearch').patchValue('1'); + component.advSearchForm.get('filter').patchValue('1'); + component.advSearchForm.get('operator').patchValue('1'); + + component.onSubmit(data); + expect(router.navigate).toHaveBeenCalledWith([undefined], { + queryParams: { ['f.' + data.filter]: data.textsearch + ',' + data.operator }, + queryParamsHandling: 'merge' + }); + + }); + }); +}); diff --git a/src/app/shared/search/advanced-search/advanced-search.component.ts b/src/app/shared/search/advanced-search/advanced-search.component.ts new file mode 100644 index 0000000000..ca6a7c9e28 --- /dev/null +++ b/src/app/shared/search/advanced-search/advanced-search.component.ts @@ -0,0 +1,115 @@ +import { Component, Inject, Input, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; +import { slide } from '../../animations/slide'; +import { FormBuilder } from '@angular/forms'; +import { FormControl, FormGroup, Validators } from '@angular/forms'; +import { SearchService } from '../../../core/shared/search/search.service'; +import { SearchConfigurationService } from '../../../core/shared/search/search-configuration.service'; +import { SEARCH_CONFIG_SERVICE } from '../../../my-dspace-page/my-dspace-page.component'; +import { AppConfig, APP_CONFIG } from 'src/config/app-config.interface'; +@Component({ + selector: 'ds-advanced-search', + templateUrl: './advanced-search.component.html', + styleUrls: ['./advanced-search.component.scss'], + animations: [slide], +}) + /** + * This component represents the part of the search sidebar that contains advanced filters. + */ +export class AdvancedSearchComponent implements OnInit { + /** + * True when the search component should show results on the current page + */ + @Input() inPlaceSearch; + + + /** + * Link to the search page + */ + notab: boolean; + + closed: boolean; + collapsedSearch = false; + focusBox = false; + + advSearchForm: FormGroup; + constructor( + @Inject(APP_CONFIG) protected appConfig: AppConfig, + private formBuilder: FormBuilder, + protected searchService: SearchService, + protected router: Router, + @Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: SearchConfigurationService) { + } + + ngOnInit(): void { + + this.advSearchForm = this.formBuilder.group({ + textsearch: new FormControl('', { + validators: [Validators.required], + }), + filter: new FormControl('title', { + validators: [Validators.required], + }), + operator: new FormControl('equals', + { validators: [Validators.required], }), + + }); + this.collapsedSearch = this.isCollapsed(); + + } + + get textsearch() { + return this.advSearchForm.get('textsearch'); + } + + get filter() { + return this.advSearchForm.get('filter'); + } + + get operator() { + return this.advSearchForm.get('operator'); + } + paramName(filter) { + return 'f.' + filter; + } + onSubmit(data) { + if (this.advSearchForm.valid) { + let queryParams = { [this.paramName(data.filter)]: data.textsearch + ',' + data.operator }; + if (!this.inPlaceSearch) { + this.router.navigate([this.searchService.getSearchLink()], { queryParams: queryParams, queryParamsHandling: 'merge' }); + } else { + if (!this.router.url.includes('?')) { + this.router.navigateByUrl(this.router.url + '?f.' + data.filter + '=' + data.textsearch + ',' + data.operator); + } else { + this.router.navigateByUrl(this.router.url + '&f.' + data.filter + '=' + data.textsearch + ',' + data.operator); + } + } + + this.advSearchForm.reset({ operator: data.operator, filter: data.filter, textsearch: '' }); + } + } + startSlide(event: any): void { + if (event.toState === 'collapsed') { + this.closed = true; + } + if (event.fromState === 'collapsed') { + this.notab = false; + } + } + finishSlide(event: any): void { + if (event.fromState === 'collapsed') { + this.closed = false; + } + if (event.toState === 'collapsed') { + this.notab = true; + } + } + toggle() { + this.collapsedSearch = !this.collapsedSearch; + } + private isCollapsed(): boolean { + return !this.collapsedSearch; + } + +} + diff --git a/src/app/shared/search/search-filters/search-filters.component.html b/src/app/shared/search/search-filters/search-filters.component.html index b5377f502b..3f70a759bc 100644 --- a/src/app/shared/search/search-filters/search-filters.component.html +++ b/src/app/shared/search/search-filters/search-filters.component.html @@ -5,4 +5,6 @@
+ {{"search.filters.reset" | translate}} diff --git a/src/app/shared/search/search-filters/search-filters.component.spec.ts b/src/app/shared/search/search-filters/search-filters.component.spec.ts index 85fd8e09a1..246b9fb8b7 100644 --- a/src/app/shared/search/search-filters/search-filters.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filters.component.spec.ts @@ -9,6 +9,8 @@ import { SearchFiltersComponent } from './search-filters.component'; import { SearchService } from '../../../core/shared/search/search.service'; import { SEARCH_CONFIG_SERVICE } from '../../../my-dspace-page/my-dspace-page.component'; import { SearchConfigurationServiceStub } from '../../testing/search-configuration-service.stub'; +import { APP_CONFIG } from 'src/config/app-config.interface'; +import { environment } from 'src/environments/environment'; describe('SearchFiltersComponent', () => { let comp: SearchFiltersComponent; @@ -38,6 +40,7 @@ describe('SearchFiltersComponent', () => { { provide: SearchService, useValue: searchServiceStub }, { provide: SEARCH_CONFIG_SERVICE, useValue: new SearchConfigurationServiceStub() }, { provide: SearchFilterService, useValue: searchFiltersStub }, + { provide: APP_CONFIG, useValue: environment }, ], schemas: [NO_ERRORS_SCHEMA] diff --git a/src/app/shared/search/search-filters/search-filters.component.ts b/src/app/shared/search/search-filters/search-filters.component.ts index 57cce61788..51065f827f 100644 --- a/src/app/shared/search/search-filters/search-filters.component.ts +++ b/src/app/shared/search/search-filters/search-filters.component.ts @@ -3,7 +3,7 @@ import { Router } from '@angular/router'; import { BehaviorSubject, Observable } from 'rxjs'; import { map } from 'rxjs/operators'; - +import { AppConfig, APP_CONFIG } from 'src/config/app-config.interface'; import { SearchService } from '../../../core/shared/search/search.service'; import { RemoteData } from '../../../core/data/remote-data'; import { SearchFilterConfig } from '../models/search-filter-config.model'; @@ -12,6 +12,7 @@ import { SearchFilterService } from '../../../core/shared/search/search-filter.s import { SEARCH_CONFIG_SERVICE } from '../../../my-dspace-page/my-dspace-page.component'; import { currentPath } from '../../utils/route.utils'; import { hasValue } from '../../empty.util'; +import { PaginatedSearchOptions } from '../models/paginated-search-options.model'; @Component({ selector: 'ds-search-filters', @@ -28,7 +29,7 @@ export class SearchFiltersComponent implements OnInit, OnDestroy { * An observable containing configuration about which filters are shown and how they are shown */ @Input() filters: Observable>; - + @Input() searchOptions: PaginatedSearchOptions; /** * List of all filters that are currently active with their value set to null. * Used to reset all filters at once @@ -71,6 +72,7 @@ export class SearchFiltersComponent implements OnInit, OnDestroy { * @param {SearchConfigurationService} searchConfigService */ constructor( + @Inject(APP_CONFIG) protected appConfig: AppConfig, private searchService: SearchService, private filterService: SearchFilterService, private router: Router, diff --git a/src/app/shared/search/search.module.ts b/src/app/shared/search/search.module.ts index d8474a5ea3..efb1a12581 100644 --- a/src/app/shared/search/search.module.ts +++ b/src/app/shared/search/search.module.ts @@ -32,6 +32,7 @@ import { ThemedSearchComponent } from './themed-search.component'; import { ThemedSearchResultsComponent } from './search-results/themed-search-results.component'; import { ThemedSearchSettingsComponent } from './search-settings/themed-search-settings.component'; import { NouisliderModule } from 'ng2-nouislider'; +import { AdvancedSearchComponent } from './advanced-search/advanced-search.component'; import { ThemedSearchFiltersComponent } from './search-filters/themed-search-filters.component'; import { ThemedSearchSidebarComponent } from './search-sidebar/themed-search-sidebar.component'; const COMPONENTS = [ @@ -59,6 +60,7 @@ const COMPONENTS = [ ThemedConfigurationSearchPageComponent, ThemedSearchResultsComponent, ThemedSearchSettingsComponent, + AdvancedSearchComponent, ThemedSearchFiltersComponent, ThemedSearchSidebarComponent, ]; diff --git a/src/app/shared/search/search.utils.ts b/src/app/shared/search/search.utils.ts index cfb96a5285..d5891f2b4e 100644 --- a/src/app/shared/search/search.utils.ts +++ b/src/app/shared/search/search.utils.ts @@ -49,7 +49,7 @@ export function stripOperatorFromFilterValue(value: string) { * @param operator */ export function addOperatorToFilterValue(value: string, operator: string) { - if (!value.match(new RegExp(`^.+,(equals|query|authority)$`))) { + if (!value.match(new RegExp(`^.+,(equals|query|authority|contains|notcontains|notequals)$`))) { return `${value},${operator}`; } return value; diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index f8fb2fbb32..9fd09789cf 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -279,10 +279,14 @@ import { } from '../item-page/simple/field-components/specific-field/title/themed-item-page-field.component'; import { BitstreamListItemComponent } from './object-list/bitstream-list-item/bitstream-list-item.component'; import { NgxPaginationModule } from 'ngx-pagination'; +import { SplitPipe } from './utils/split.pipe'; import { ThemedUserMenuComponent } from './auth-nav-menu/user-menu/themed-user-menu.component'; import { ThemedLangSwitchComponent } from './lang-switch/themed-lang-switch.component'; +import { QualityAssuranceEventDataService } from '../core/notifications/qa/events/quality-assurance-event-data.service'; +import { QualityAssuranceSourceDataService } from '../core/notifications/qa/source/quality-assurance-source-data.service'; import { DynamicComponentLoaderDirective } from './abstract-component-loader/dynamic-component-loader.directive'; import { StartsWithLoaderComponent } from './starts-with/starts-with-loader.component'; +import { IpV4Validator } from './utils/ipV4.validator'; const MODULES = [ CommonModule, @@ -322,7 +326,8 @@ const PIPES = [ ObjNgFor, BrowserOnlyPipe, MarkdownPipe, - ShortNumberPipe + ShortNumberPipe, + SplitPipe ]; const COMPONENTS = [ @@ -472,7 +477,9 @@ const ENTRY_COMPONENTS = [ const PROVIDERS = [ TruncatableService, MockAdminGuard, - AbstractTrackableComponent + AbstractTrackableComponent, + QualityAssuranceEventDataService, + QualityAssuranceSourceDataService ]; const DIRECTIVES = [ @@ -490,6 +497,7 @@ const DIRECTIVES = [ HoverClassDirective, ContextHelpDirective, DynamicComponentLoaderDirective, + IpV4Validator, ]; @NgModule({ diff --git a/src/app/shared/utils/ipV4.validator.spec.ts b/src/app/shared/utils/ipV4.validator.spec.ts new file mode 100644 index 0000000000..93f5ee86e9 --- /dev/null +++ b/src/app/shared/utils/ipV4.validator.spec.ts @@ -0,0 +1,36 @@ +import { IpV4Validator } from './ipV4.validator'; +import { TestBed } from '@angular/core/testing'; +import { UntypedFormControl, UntypedFormGroup } from '@angular/forms'; + + +describe('IpV4 validator', () => { + + let ipV4Validator: IpV4Validator; + const validIp = '192.168.0.1'; + const formGroup = new UntypedFormGroup({ + ip: new UntypedFormControl(''), + }); + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ + IpV4Validator, + ], + }).compileComponents(); + + ipV4Validator = TestBed.inject(IpV4Validator); + }); + + it('should return null for valid ipV4', () => { + formGroup.controls.ip.setValue(validIp); + expect(ipV4Validator.validate(formGroup.controls.ip as UntypedFormControl)).toBeNull(); + }); + + it('should return {isValidIp: false} for invalid Ip', () => { + formGroup.controls.ip.setValue('100.260.45.1'); + expect(ipV4Validator.validate(formGroup.controls.ip as UntypedFormControl)).toEqual({isValidIp: false}); + formGroup.controls.ip.setValue('100'); + expect(ipV4Validator.validate(formGroup.controls.ip as UntypedFormControl)).toEqual({isValidIp: false}); + formGroup.controls.ip.setValue('testString'); + expect(ipV4Validator.validate(formGroup.controls.ip as UntypedFormControl)).toEqual({isValidIp: false}); + }); +}); diff --git a/src/app/shared/utils/ipV4.validator.ts b/src/app/shared/utils/ipV4.validator.ts new file mode 100644 index 0000000000..170dbeb547 --- /dev/null +++ b/src/app/shared/utils/ipV4.validator.ts @@ -0,0 +1,26 @@ +import {Directive} from '@angular/core'; +import {NG_VALIDATORS, Validator, UntypedFormControl} from '@angular/forms'; + +@Directive({ + // eslint-disable-next-line @angular-eslint/directive-selector + selector: '[ipV4format]', + providers: [ + { provide: NG_VALIDATORS, useExisting: IpV4Validator, multi: true }, + ] +}) +/** + * Validator to validate if an Ip is in the right format + */ +export class IpV4Validator implements Validator { + validate(formControl: UntypedFormControl): {[key: string]: boolean} | null { + const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/; + const ipValue = formControl.value; + const ipParts = ipValue?.split('.'); + + if (ipv4Regex.test(ipValue) && ipParts.every(part => parseInt(part, 10) <= 255)) { + return null; + } + + return {isValidIp: false}; + } +} diff --git a/src/app/shared/utils/split.pipe.ts b/src/app/shared/utils/split.pipe.ts new file mode 100644 index 0000000000..e4d0f2cc49 --- /dev/null +++ b/src/app/shared/utils/split.pipe.ts @@ -0,0 +1,16 @@ +import { Pipe, PipeTransform } from '@angular/core'; +/** + * Custom pipe to split a string into an array of substrings based on a specified separator. + * @param value - The string to be split. + * @param separator - The separator used to split the string. + * @returns An array of substrings. + */ +@Pipe({ + name: 'dsSplit' +}) +export class SplitPipe implements PipeTransform { + transform(value: string, separator: string): string[] { + return value.split(separator); + } + +} diff --git a/src/app/submission/form/submission-form.component.html b/src/app/submission/form/submission-form.component.html index 4a916cfe23..b3536a6fbf 100644 --- a/src/app/submission/form/submission-form.component.html +++ b/src/app/submission/form/submission-form.component.html @@ -9,7 +9,8 @@
- + [sectionData]="object"> +
+ diff --git a/src/app/submission/sections/container/section-container.component.html b/src/app/submission/sections/container/section-container.component.html index e6ae9d1b9c..99bcec168f 100644 --- a/src/app/submission/sections/container/section-container.component.html +++ b/src/app/submission/sections/container/section-container.component.html @@ -48,4 +48,4 @@ - \ No newline at end of file + diff --git a/src/app/submission/sections/section-coar-notify/coar-notify-config-data.service.ts b/src/app/submission/sections/section-coar-notify/coar-notify-config-data.service.ts new file mode 100644 index 0000000000..7b8d309667 --- /dev/null +++ b/src/app/submission/sections/section-coar-notify/coar-notify-config-data.service.ts @@ -0,0 +1,122 @@ +import { Injectable } from '@angular/core'; +import { dataService } from '../../../core/data/base/data-service.decorator'; +import { IdentifiableDataService } from '../../../core/data/base/identifiable-data.service'; +import { FindAllData, FindAllDataImpl } from '../../../core/data/base/find-all-data'; +import { DeleteData, DeleteDataImpl } from '../../../core/data/base/delete-data'; +import { RequestService } from '../../../core/data/request.service'; +import { RemoteDataBuildService } from '../../../core/cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../../../core/cache/object-cache.service'; +import { HALEndpointService } from '../../../core/shared/hal-endpoint.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { FindListOptions } from '../../../core/data/find-list-options.model'; +import { FollowLinkConfig } from '../../../shared/utils/follow-link-config.model'; +import { Observable } from 'rxjs'; +import { RemoteData } from '../../../core/data/remote-data'; +import { PaginatedList } from '../../../core/data/paginated-list.model'; +import { NoContent } from '../../../core/shared/NoContent.model'; +import { map, take } from 'rxjs/operators'; +import { URLCombiner } from '../../../core/url-combiner/url-combiner'; +import { MultipartPostRequest } from '../../../core/data/request.models'; +import { RestRequest } from '../../../core/data/rest-request.model'; +import { SUBMISSION_COAR_NOTIFY_CONFIG } from './section-coar-notify-service.resource-type'; +import { SubmissionCoarNotifyConfig } from './submission-coar-notify.config'; +import { CreateData, CreateDataImpl } from '../../../core/data/base/create-data'; +import { PatchData, PatchDataImpl } from '../../../core/data/base/patch-data'; +import { ChangeAnalyzer } from '../../../core/data/change-analyzer'; +import { Operation } from 'fast-json-patch'; +import { RestRequestMethod } from '../../../core/data/rest-request-method'; +import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; +import { hasValue } from '../../../shared/empty.util'; + + +/** + * A service responsible for fetching/sending data from/to the REST API on the CoarNotifyConfig endpoint + */ +@Injectable() +@dataService(SUBMISSION_COAR_NOTIFY_CONFIG) +export class CoarNotifyConfigDataService extends IdentifiableDataService implements FindAllData, DeleteData, PatchData, CreateData { + createData: CreateDataImpl; + private findAllData: FindAllDataImpl; + private deleteData: DeleteDataImpl; + private patchData: PatchDataImpl; + private comparator: ChangeAnalyzer; + + constructor( + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected notificationsService: NotificationsService, + ) { + super('submissioncoarnotifyconfigs', requestService, rdbService, objectCache, halService); + + this.findAllData = new FindAllDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive); + this.deleteData = new DeleteDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, notificationsService, this.responseMsToLive, this.constructIdEndpoint); + this.patchData = new PatchDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.comparator, this.responseMsToLive, this.constructIdEndpoint); + this.createData = new CreateDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, notificationsService, this.responseMsToLive); + } + + + create(object: SubmissionCoarNotifyConfig): Observable> { + return this.createData.create(object); + } + + patch(object: SubmissionCoarNotifyConfig, operations: Operation[]): Observable> { + return this.patchData.patch(object, operations); + } + + update(object: SubmissionCoarNotifyConfig): Observable> { + return this.patchData.update(object); + } + + commitUpdates(method?: RestRequestMethod): void { + return this.patchData.commitUpdates(method); + } + + createPatchFromCache(object: SubmissionCoarNotifyConfig): Observable { + return this.patchData.createPatchFromCache(object); + } + + findAll(options?: FindListOptions, useCachedVersionIfAvailable?: boolean, reRequestOnStale?: boolean, ...linksToFollow: FollowLinkConfig[]): Observable>> { + return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + } + + public delete(objectId: string, copyVirtualMetadata?: string[]): Observable> { + return this.deleteData.delete(objectId, copyVirtualMetadata); + } + + public deleteByHref(href: string, copyVirtualMetadata?: string[]): Observable> { + return this.deleteData.deleteByHref(href, copyVirtualMetadata); + } + + public invoke(serviceName: string, serviceId: string, files: File[]): Observable> { + const requestId = this.requestService.generateRequestId(); + this.getBrowseEndpoint().pipe( + take(1), + map((endpoint: string) => new URLCombiner(endpoint, serviceName, 'submissioncoarnotifyconfigmodel', serviceId).toString()), + map((endpoint: string) => { + const body = this.getInvocationFormData(files); + return new MultipartPostRequest(requestId, endpoint, body); + }) + ).subscribe((request: RestRequest) => this.requestService.send(request)); + + return this.rdbService.buildFromRequestUUID(requestId); + } + + public SubmissionCoarNotifyConfigModelWithNameExistsAndCanExecute(scriptName: string): Observable { + return this.findById(scriptName).pipe( + getFirstCompletedRemoteData(), + map((rd: RemoteData) => { + return hasValue(rd.payload); + }), + ); + } + + private getInvocationFormData(files: File[]): FormData { + const form: FormData = new FormData(); + files.forEach((file: File) => { + form.append('file', file); + }); + return form; + } +} diff --git a/src/app/submission/sections/section-coar-notify/section-coar-notify-service.resource-type.ts b/src/app/submission/sections/section-coar-notify/section-coar-notify-service.resource-type.ts new file mode 100644 index 0000000000..53e41783ce --- /dev/null +++ b/src/app/submission/sections/section-coar-notify/section-coar-notify-service.resource-type.ts @@ -0,0 +1,13 @@ +/** + * The resource type for Ldn-Services + * + * Needs to be in a separate file to prevent circular + * dependencies in webpack. + */ +import { ResourceType } from '../../../core/shared/resource-type'; + + +export const SUBMISSION_COAR_NOTIFY_CONFIG = new ResourceType('submissioncoarnotifyconfig'); + +export const COAR_NOTIFY_WORKSPACEITEM = new ResourceType('workspaceitem'); + diff --git a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.html b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.html new file mode 100644 index 0000000000..a10a710109 --- /dev/null +++ b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.html @@ -0,0 +1,149 @@ +
+ +
+
+ +
+
+
+
+
+ + +
+ +
+ +
+ + + {{'submission.section.section-coar-notify.small.notification' | translate : {pattern : ldnPattern.pattern} }} + + + + {{ error.message | translate}} + + +
+
+ +
+
{{ 'submission.section.section-coar-notify.selection.description' | translate }}
+
+ {{ ldnServiceByPattern[ldnPattern.pattern].services[serviceIndex].description }} +
+ + + {{ 'submission.section.section-coar-notify.selection.no-description' | translate }} + + +
+
+
+
+
+
+ + {{ 'submission.section.section-coar-notify.notification.error' | translate }} + +
+
+
+
+ +
+
+
+
+
+
+ +

+ {{ 'submission.section.section-coar-notify.info.no-pattern' | translate }} +

+
+
diff --git a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.scss b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.scss new file mode 100644 index 0000000000..4a3e7072a3 --- /dev/null +++ b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.scss @@ -0,0 +1,5 @@ +// Getting styles for NgbDropdown +@import '../../../shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.scss'; +@import '../../../shared/form/form.component.scss'; + + diff --git a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.spec.ts b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.spec.ts new file mode 100644 index 0000000000..74e82722a6 --- /dev/null +++ b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.spec.ts @@ -0,0 +1,443 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SubmissionSectionCoarNotifyComponent } from './section-coar-notify.component'; +import { LdnServicesService } from '../../../admin/admin-ldn-services/ldn-services-data/ldn-services-data.service'; +import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap'; +import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder'; +import { SectionsService } from '../sections.service'; +import { CoarNotifyConfigDataService } from './coar-notify-config-data.service'; +import { ChangeDetectorRef } from '@angular/core'; +import { SubmissionCoarNotifyConfig } from './submission-coar-notify.config'; +import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; +import { createPaginatedList } from '../../../shared/testing/utils.test'; +import { of } from 'rxjs'; +import { + LdnService, + LdnServiceByPattern +} from '../../../admin/admin-ldn-services/ldn-services-model/ldn-services.model'; +import { NotifyServicePattern } from '../../../admin/admin-ldn-services/ldn-services-model/ldn-service-patterns.model'; +import { TranslateModule } from '@ngx-translate/core'; + +describe('SubmissionSectionCoarNotifyComponent', () => { + let component: SubmissionSectionCoarNotifyComponent; + let componentAsAny: any; + let fixture: ComponentFixture; + + let ldnServicesService: jasmine.SpyObj; + let coarNotifyConfigDataService: jasmine.SpyObj; + let operationsBuilder: jasmine.SpyObj; + let sectionService: jasmine.SpyObj; + let cdRefStub: any; + + + const patterns: SubmissionCoarNotifyConfig[] = Object.assign( + [new SubmissionCoarNotifyConfig()], + { + patterns: [{pattern: 'review', multipleRequest: false}, {pattern: 'endorsment', multipleRequest: false}], + } + ); + const patternsPL = createPaginatedList(patterns); + const coarNotifyConfig = createSuccessfulRemoteDataObject$(patternsPL); + + beforeEach(async () => { + ldnServicesService = jasmine.createSpyObj('LdnServicesService', [ + 'findByInboundPattern', + ]); + coarNotifyConfigDataService = jasmine.createSpyObj( + 'CoarNotifyConfigDataService', + ['findAll'] + ); + operationsBuilder = jasmine.createSpyObj('JsonPatchOperationsBuilder', [ + 'remove', + 'replace', + 'add', + 'flushOperation', + ]); + sectionService = jasmine.createSpyObj('SectionsService', [ + 'dispatchRemoveSectionErrors', + 'getSectionServerErrors', + 'setSectionError', + ]); + cdRefStub = Object.assign({ + detectChanges: () => fixture.detectChanges(), + }); + + await TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + declarations: [SubmissionSectionCoarNotifyComponent], + providers: [ + { provide: LdnServicesService, useValue: ldnServicesService }, + { provide: CoarNotifyConfigDataService, useValue: coarNotifyConfigDataService}, + { provide: JsonPatchOperationsBuilder, useValue: operationsBuilder }, + { provide: SectionsService, useValue: sectionService }, + { provide: ChangeDetectorRef, useValue: cdRefStub }, + { provide: 'collectionIdProvider', useValue: 'collectionId' }, + { provide: 'sectionDataProvider', useValue: { id: 'sectionId', data: {} }}, + { provide: 'submissionIdProvider', useValue: 'submissionId' }, + NgbDropdown, + ], + }).compileComponents(); + + fixture = TestBed.createComponent(SubmissionSectionCoarNotifyComponent); + component = fixture.componentInstance; + componentAsAny = component; + + component.patterns = patterns[0].patterns; + coarNotifyConfigDataService.findAll.and.returnValue(coarNotifyConfig); + sectionService.getSectionServerErrors.and.returnValue( + of( + Object.assign([], { + path: 'sections/sectionId/data/notifyCoar', + message: 'error', + }) + ) + ); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('onSectionInit', () => { + it('should call setCoarNotifyConfig and getSectionServerErrorsAndSetErrorsToDisplay', () => { + spyOn(component, 'setCoarNotifyConfig'); + spyOn(componentAsAny, 'getSectionServerErrorsAndSetErrorsToDisplay'); + + component.onSectionInit(); + + expect(component.setCoarNotifyConfig).toHaveBeenCalled(); + expect(componentAsAny.getSectionServerErrorsAndSetErrorsToDisplay).toHaveBeenCalled(); + }); + }); + + describe('onChange', () => { + const ldnPattern = {pattern: 'review', multipleRequest: false}; + const index = 0; + const selectedService: LdnService = Object.assign(new LdnService(), { + id: 1, + name: 'service1', + notifyServiceInboundPatterns: [ + { + pattern: 'review', + }, + ], + description: '', + }); + + beforeEach(() => { + component.ldnServiceByPattern[ldnPattern.pattern] = { + allowsMultipleRequests: false, + services: [] + } as LdnServiceByPattern; + + component.patterns = []; + }); + + it('should do nothing if the selected value is the same as the previous one', () => { + + component.ldnServiceByPattern[ldnPattern.pattern].services[index] = selectedService; + component.onChange(ldnPattern.pattern, index, selectedService); + + expect(componentAsAny.operationsBuilder.remove).not.toHaveBeenCalled(); + expect(componentAsAny.operationsBuilder.replace).not.toHaveBeenCalled(); + expect(componentAsAny.operationsBuilder.add).not.toHaveBeenCalled(); + }); + + it('should remove the path when the selected value is null', () => { + component.ldnServiceByPattern[ldnPattern.pattern].services[index] = selectedService; + component.onChange(ldnPattern.pattern, index, null); + + expect(componentAsAny.operationsBuilder.flushOperation).toHaveBeenCalledWith( + componentAsAny.pathCombiner.getPath([ldnPattern.pattern, '-']) + ); + expect(component.ldnServiceByPattern[ldnPattern.pattern].services[index]).toBeNull(); + expect(component.previousServices[ldnPattern.pattern].services[index]).toBeNull(); + }); + + it('should replace the path when there is a previous value stored and it is different from the new one', () => { + const previousService: LdnService = Object.assign(new LdnService(), { + id: 2, + name: 'service2', + notifyServiceInboundPatterns: [ + { + pattern: 'endorsement', + }, + ], + description: 'test', + }); + component.ldnServiceByPattern[ldnPattern.pattern].services[index] = previousService; + component.previousServices[ldnPattern.pattern] = { + allowsMultipleRequests: false, + services: [previousService] + } as LdnServiceByPattern; + + component.onChange(ldnPattern.pattern, index, selectedService); + + expect(componentAsAny.operationsBuilder.add).toHaveBeenCalledWith( + componentAsAny.pathCombiner.getPath([ldnPattern.pattern, '-']), + [selectedService.id], + false, + true + ); + expect(component.ldnServiceByPattern[ldnPattern.pattern].services[index]).toEqual( + selectedService + ); + expect(component.previousServices[ldnPattern.pattern].services[index].id).toEqual( + selectedService.id + ); + }); + + it('should add the path when there is no previous value stored', () => { + component.onChange(ldnPattern.pattern, index, selectedService); + + expect(componentAsAny.operationsBuilder.add).toHaveBeenCalledWith( + componentAsAny.pathCombiner.getPath([ldnPattern.pattern, '-']), + [selectedService.id], + false, + true + ); + expect(component.ldnServiceByPattern[ldnPattern.pattern].services[index]).toEqual( + selectedService + ); + expect(component.previousServices[ldnPattern.pattern].services[index].id).toEqual( + selectedService.id + ); + }); + }); + + describe('initSelectedServicesByPattern', () => { + const pattern1 = {pattern: 'review', multipleRequest: false}; + const pattern2 = {pattern: 'endorsement', multipleRequest: false}; + const service1: LdnService = Object.assign(new LdnService(), { + id: 1, + uuid: 1, + name: 'service1', + notifyServiceInboundPatterns: [ + Object.assign(new NotifyServicePattern(), { + pattern: pattern1, + }), + ], + }); + const service2: LdnService = Object.assign(new LdnService(), { + id: 2, + uuid: 2, + name: 'service2', + notifyServiceInboundPatterns: [ + Object.assign(new NotifyServicePattern(), { + pattern: pattern2, + }), + ], + }); + const service3: LdnService = Object.assign(new LdnService(), { + id: 3, + uuid: 3, + name: 'service3', + notifyServiceInboundPatterns: [ + Object.assign(new NotifyServicePattern(), { + pattern: pattern1, + }), + Object.assign(new NotifyServicePattern(), { + pattern: pattern2, + }), + ], + }); + + const services = [service1, service2, service3]; + + beforeEach(() => { + ldnServicesService.findByInboundPattern.and.returnValue( + createSuccessfulRemoteDataObject$(createPaginatedList(services)) + ); + component.ldnServiceByPattern[pattern1.pattern] = { + allowsMultipleRequests: false, + services: [] + } as LdnServiceByPattern; + + component.ldnServiceByPattern[pattern2.pattern] = { + allowsMultipleRequests: false, + services: [] + } as LdnServiceByPattern; + + component.patterns = [pattern1, pattern2]; + + spyOn(component, 'filterServices').and.callFake((pattern) => { + return of(services); + }); + }); + + it('should initialize the selected services by pattern', () => { + component.initSelectedServicesByPattern(); + + expect(component.ldnServiceByPattern[pattern1.pattern].services).toEqual([null]); + expect(component.ldnServiceByPattern[pattern2.pattern].services).toEqual([null]); + }); + + it('should add the service to the selected services by pattern if the section data has a value for the pattern', () => { + component.sectionData.data[pattern1.pattern] = [service1.uuid, service3.uuid]; + component.sectionData.data[pattern2.pattern] = [service2.uuid, service3.uuid]; + component.initSelectedServicesByPattern(); + + expect(component.ldnServiceByPattern[pattern1.pattern].services).toEqual([ + service1, + service3, + ]); + expect(component.ldnServiceByPattern[pattern2.pattern].services).toEqual([ + service2, + service3, + ]); + }); + }); + + describe('addService', () => { + const ldnPattern = {pattern: 'review', multipleRequest: false}; + const service: any = { + id: 1, + name: 'service1', + notifyServiceInboundPatterns: [{ pattern: ldnPattern.pattern }], + }; + + beforeEach(() => { + component.ldnServiceByPattern[ldnPattern.pattern] = { + allowsMultipleRequests: false, + services: [] + } as LdnServiceByPattern; + }); + + it('should push the new service to the array corresponding to the pattern', () => { + component.addService(ldnPattern, service); + + expect(component.ldnServiceByPattern[ldnPattern.pattern].services).toEqual([service]); + }); + }); + + describe('removeService', () => { + const ldnPattern = {pattern: 'review', multipleRequest: false}; + const service1: LdnService = Object.assign(new LdnService(), { + id: 1, + name: 'service1', + notifyServiceInboundPatterns: [ + Object.assign(new NotifyServicePattern(), { + pattern: ldnPattern.pattern, + }), + ], + }); + const service2: LdnService = Object.assign(new LdnService(), { + id: 2, + name: 'service2', + notifyServiceInboundPatterns: [ + Object.assign(new NotifyServicePattern(), { + pattern: ldnPattern.pattern, + }), + ], + }); + const service3: LdnService = Object.assign(new LdnService(), { + id: 3, + name: 'service3', + notifyServiceInboundPatterns: [ + Object.assign(new NotifyServicePattern(), { + pattern: ldnPattern.pattern, + }), + ], + }); + + beforeEach(() => { + component.ldnServiceByPattern[ldnPattern.pattern] = { + allowsMultipleRequests: false, + services: [] + } as LdnServiceByPattern; + }); + + + it('should remove the service at the specified index from the array corresponding to the pattern', () => { + component.ldnServiceByPattern[ldnPattern.pattern].services = [service1, service2, service3]; + component.removeService(ldnPattern, 1); + + expect(component.ldnServiceByPattern[ldnPattern.pattern].services).toEqual([ + service1, + service3, + ]); + }); + }); + + describe('filterServices', () => { + const pattern = 'review'; + const service1: any = { + id: 1, + name: 'service1', + notifyServiceInboundPatterns: [{ pattern: pattern }], + }; + const service2: any = { + id: 2, + name: 'service2', + notifyServiceInboundPatterns: [{ pattern: pattern }], + }; + const service3: any = { + id: 3, + name: 'service3', + notifyServiceInboundPatterns: [{ pattern: pattern }], + }; + const services = [service1, service2, service3]; + + beforeEach(() => { + ldnServicesService.findByInboundPattern.and.returnValue( + createSuccessfulRemoteDataObject$(createPaginatedList(services)) + ); + }); + + it('should return an observable of the services that match the given pattern', () => { + component.filterServices(pattern).subscribe((result) => { + expect(result).toEqual(services); + }); + }); + }); + + describe('hasInboundPattern', () => { + const pattern = 'review'; + const service: any = { + id: 1, + name: 'service1', + notifyServiceInboundPatterns: [{ pattern: pattern }], + }; + + it('should return true if the service has the specified inbound pattern type', () => { + expect(component.hasInboundPattern(service, pattern)).toBeTrue(); + }); + + it('should return false if the service does not have the specified inbound pattern type', () => { + expect(component.hasInboundPattern(service, 'endorsement')).toBeFalse(); + }); + }); + + describe('getSectionServerErrorsAndSetErrorsToDisplay', () => { + it('should set the validation errors for the current section to display', () => { + const validationErrors = [ + { path: 'sections/sectionId/data/notifyCoar', message: 'error' }, + ]; + sectionService.getSectionServerErrors.and.returnValue( + of(validationErrors) + ); + + componentAsAny.getSectionServerErrorsAndSetErrorsToDisplay(); + + expect(sectionService.setSectionError).toHaveBeenCalledWith( + component.submissionId, + component.sectionData.id, + validationErrors[0] + ); + }); + }); + + describe('onSectionDestroy', () => { + it('should unsubscribe from all subscriptions', () => { + const sub1 = of(null).subscribe(); + const sub2 = of(null).subscribe(); + componentAsAny.subs = [sub1, sub2]; + spyOn(sub1, 'unsubscribe'); + spyOn(sub2, 'unsubscribe'); + component.onSectionDestroy(); + expect(sub1.unsubscribe).toHaveBeenCalled(); + expect(sub2.unsubscribe).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/app/submission/sections/section-coar-notify/section-coar-notify.component.ts b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.ts new file mode 100644 index 0000000000..2fe7391106 --- /dev/null +++ b/src/app/submission/sections/section-coar-notify/section-coar-notify.component.ts @@ -0,0 +1,327 @@ +import { ChangeDetectorRef, Component, Inject } from '@angular/core'; +import { Observable, Subscription } from 'rxjs'; +import { SectionModelComponent } from '../models/section.model'; +import { renderSectionFor } from '../sections-decorator'; +import { SectionsType } from '../sections-type'; +import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner'; +import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder'; +import { SectionsService } from '../sections.service'; +import { SectionDataObject } from '../models/section-data.model'; + +import { hasValue, isEmpty, isNotEmpty } from '../../../shared/empty.util'; + +import { getFirstCompletedRemoteData, getPaginatedListPayload, getRemoteDataPayload } from '../../../core/shared/operators'; +import { LdnServicesService } from '../../../admin/admin-ldn-services/ldn-services-data/ldn-services-data.service'; +import { + LdnService, + LdnServiceByPattern +} from '../../../admin/admin-ldn-services/ldn-services-model/ldn-services.model'; +import { CoarNotifyConfigDataService } from './coar-notify-config-data.service'; +import { filter, map, take, tap } from 'rxjs/operators'; +import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap'; +import { SubmissionSectionError } from '../../objects/submission-section-error.model'; +import { LdnPattern } from './submission-coar-notify.config'; + +/** + * This component represents a section that contains the submission section-coar-notify form. + */ +@Component({ + selector: 'ds-submission-section-coar-notify', + templateUrl: './section-coar-notify.component.html', + styleUrls: ['./section-coar-notify.component.scss'], + providers: [NgbDropdown] +}) +@renderSectionFor(SectionsType.CoarNotify) +export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent { + + hasSectionData = false; + /** + * Contains an array of string patterns. + */ + patterns: LdnPattern[] = []; + /** + * An object that maps string keys to arrays of LdnService objects. + * Used to store LdnService objects by pattern. + */ + ldnServiceByPattern: { [key: string]: LdnServiceByPattern } = {}; + /** + * A map representing all services for each pattern + * { + * 'pattern': { + * 'index': 'service.id' + * } + * } + * + * @type {{ [key: string]: {[key: number]: number} }} + * @memberof SubmissionSectionCoarNotifyComponent + */ + previousServices: { [key: string]: LdnServiceByPattern } = {}; + + /** + * The [[JsonPatchOperationPathCombiner]] object + * @type {JsonPatchOperationPathCombiner} + */ + protected pathCombiner: JsonPatchOperationPathCombiner; + /** + * A map representing all field on their way to be removed + * @type {Map} + */ + protected fieldsOnTheirWayToBeRemoved: Map = new Map(); + /** + * Array to track all subscriptions and unsubscribe them onDestroy + * @type {Array} + */ + protected subs: Subscription[] = []; + + constructor(protected ldnServicesService: LdnServicesService, + // protected formOperationsService: SectionFormOperationsService, + protected operationsBuilder: JsonPatchOperationsBuilder, + protected sectionService: SectionsService, + protected coarNotifyConfigDataService: CoarNotifyConfigDataService, + protected chd: ChangeDetectorRef, + @Inject('collectionIdProvider') public injectedCollectionId: string, + @Inject('sectionDataProvider') public injectedSectionData: SectionDataObject, + @Inject('submissionIdProvider') public injectedSubmissionId: string) { + super(injectedCollectionId, injectedSectionData, injectedSubmissionId); + } + + /** + * Initialize all instance variables + */ + onSectionInit() { + this.setCoarNotifyConfig(); + this.getSectionServerErrorsAndSetErrorsToDisplay(); + this.pathCombiner = new JsonPatchOperationPathCombiner('sections', this.sectionData.id); + } + + /** + * Method called when section is initialized + * Retriev available NotifyConfigs + */ + setCoarNotifyConfig() { + this.subs.push( + this.coarNotifyConfigDataService.findAll().pipe( + getFirstCompletedRemoteData() + ).subscribe((data) => { + if (data.hasSucceeded) { + this.patterns = data.payload.page[0].patterns; + this.initSelectedServicesByPattern(); + } + })); + } + + /** + * Handles the change event of a select element. + * @param pattern - The pattern of the select element. + * @param index - The index of the select element. + * @param selectedService - The selected LDN service. + */ + onChange(pattern: string, index: number, selectedService: LdnService | null) { + // do nothing if the selected value is the same as the previous one + if (this.ldnServiceByPattern[pattern].services[index]?.id === selectedService?.id) { + return; + } + + // initialize the previousServices object for the pattern if it does not exist + if (!this.previousServices[pattern]) { + this.previousServices[pattern] = { + services: [], + allowsMultipleRequests: this.patterns.find(ldnPattern => ldnPattern.pattern === pattern)?.multipleRequest + }; + } + + // store the previous value + this.previousServices[pattern].services[index] = this.ldnServiceByPattern[pattern].services[index]; + // set the new value + this.ldnServiceByPattern[pattern].services[index] = selectedService; + + const hasPrevValueStored = hasValue(this.previousServices[pattern].services[index]) && this.previousServices[pattern].services[index].id !== selectedService?.id; + if (hasPrevValueStored) { + // when there is a previous value stored and it is different from the new one + this.operationsBuilder.flushOperation(this.pathCombiner.getPath([pattern, '-'])); + } + + if (!hasPrevValueStored || (selectedService?.id && hasPrevValueStored) || (!hasValue(selectedService) && hasPrevValueStored)) { + // add the path when there is no previous value stored + this.operationsBuilder.add(this.pathCombiner.getPath([pattern, '-']), hasValue(selectedService) ? [selectedService.id] : [], false, true); + } + // set the previous value to the new value + this.previousServices[pattern].services[index] = this.ldnServiceByPattern[pattern].services[index]; + this.sectionService.dispatchRemoveSectionErrors(this.submissionId, this.sectionData.id); + this.chd.detectChanges(); + } + + /** + * Initializes the selected services by pattern. + * Loops through each pattern and filters the services based on the pattern. + * If the section data has a value for the pattern, it adds the service to the selected services by pattern. + * If the section data does not have a value for the pattern, it adds a null service to the selected services by pattern, + * so that the select element is initialized with a null value and to display the default select input. + */ + initSelectedServicesByPattern(): void { + this.patterns.forEach((ldnPattern) => { + if (hasValue(this.sectionData.data[ldnPattern.pattern])) { + this.subs.push( + this.filterServices(ldnPattern.pattern) + .subscribe((services: LdnService[]) => { + + if (!this.ldnServiceByPattern[ldnPattern.pattern]) { + this.ldnServiceByPattern[ldnPattern.pattern] = { + services: [], + allowsMultipleRequests: ldnPattern.multipleRequest + }; + } + + this.ldnServiceByPattern[ldnPattern.pattern].services = services.filter((service) => { + const selection = (this.sectionData.data[ldnPattern.pattern] as LdnService[]).find((s: LdnService) => s.id === service.id); + this.addService(ldnPattern, selection); + return this.sectionData.data[ldnPattern.pattern].includes(service.uuid); + }); + }) + ); + } else { + this.ldnServiceByPattern[ldnPattern.pattern] = { + services: [], + allowsMultipleRequests: ldnPattern.multipleRequest + }; + this.addService(ldnPattern, null); + } + }); + } + + /** + * Adds a new service to the selected services for the given pattern. + * @param ldnPattern - The pattern to add the new service to. + * @param newService - The new service to add. + */ + addService(ldnPattern: LdnPattern, newService: LdnService) { + // Your logic to add a new service to the selected services for the pattern + // Example: Push the newService to the array corresponding to the pattern + if (!this.ldnServiceByPattern[ldnPattern.pattern]) { + this.ldnServiceByPattern[ldnPattern.pattern] = { + services: [], + allowsMultipleRequests: ldnPattern.multipleRequest + }; + } + this.ldnServiceByPattern[ldnPattern.pattern].services.push(newService); + } + + /** + * Removes the service at the specified index from the array corresponding to the pattern. + * @param ldnPattern - The LDN pattern from which to remove the service + * @param serviceIndex - the service index to remove + */ + removeService(ldnPattern: LdnPattern, serviceIndex: number) { + if (this.ldnServiceByPattern[ldnPattern.pattern]) { + // Remove the service at the specified index from the array + this.ldnServiceByPattern[ldnPattern.pattern].services.splice(serviceIndex, 1); + this.previousServices[ldnPattern.pattern]?.services.splice(serviceIndex, 1); + this.operationsBuilder.flushOperation(this.pathCombiner.getPath([ldnPattern.pattern, '-'])); + this.sectionService.dispatchRemoveSectionErrors(this.submissionId, this.sectionData.id); + } + if (!this.ldnServiceByPattern[ldnPattern.pattern].services.length) { + this.addNewService(ldnPattern); + } + } + + /** + * Method called when dropdowns for the section are initialized + * Retrieve services with corresponding patterns to the dropdowns. + */ + filterServices(pattern: string): Observable { + return this.ldnServicesService.findByInboundPattern(pattern).pipe( + getFirstCompletedRemoteData(), + tap((rd) => { + if (rd.hasFailed) { + throw new Error(`Failed to retrieve services for pattern ${pattern}`); + } + }), + filter((rd) => rd.hasSucceeded), + getRemoteDataPayload(), + getPaginatedListPayload(), + map((res: LdnService[]) => res.filter((service) => { + if (!this.hasSectionData){ + this.hasSectionData = this.hasInboundPattern(service, pattern); + } + return this.hasInboundPattern(service, pattern); + })) + ); + } + + /** + * Checks if the given service has the specified inbound pattern type. + * @param service - The service to check. + * @param patternType - The inbound pattern type to look for. + * @returns True if the service has the specified inbound pattern type, false otherwise. + */ + hasInboundPattern(service: any, patternType: string): boolean { + return service.notifyServiceInboundPatterns.some((pattern: { pattern: string }) => { + return pattern.pattern === patternType; + }); + } + + /** + * Retrieves server errors for the current section and sets them to display. + * @returns An Observable that emits the validation errors for the current section. + */ + private getSectionServerErrorsAndSetErrorsToDisplay() { + this.subs.push( + this.sectionService.getSectionServerErrors(this.submissionId, this.sectionData.id).pipe( + take(1), + filter((validationErrors) => isNotEmpty(validationErrors)), + ).subscribe((validationErrors: SubmissionSectionError[]) => { + if (isNotEmpty(validationErrors)) { + validationErrors.forEach((error) => { + this.sectionService.setSectionError(this.submissionId, this.sectionData.id, error); + }); + } + })); + } + + /** + * Returns an observable of the errors for the current section that match the given pattern and index. + * @param pattern - The pattern to match against the error paths. + * @param index - The index to match against the error paths. + * @returns An observable of the errors for the current section that match the given pattern and index. + */ + public getShownSectionErrors$(pattern: string, index: number): Observable { + return this.sectionService.getShownSectionErrors(this.submissionId, this.sectionData.id, this.sectionData.sectionType) + .pipe( + take(1), + filter((validationErrors) => isNotEmpty(validationErrors)), + map((validationErrors: SubmissionSectionError[]) => { + return validationErrors.filter((error) => { + const path = `${pattern}/${index}`; + return error.path.includes(path); + }); + }) + ); + } + + /** + * @returns An observable that emits a boolean indicating whether the section has any server errors or not. + */ + protected getSectionStatus(): Observable { + return this.sectionService.getSectionServerErrors(this.submissionId, this.sectionData.id).pipe( + map((validationErrors) => isEmpty(validationErrors) + )); + } + + /** + * Unsubscribe from all subscriptions + */ + onSectionDestroy() { + this.subs + .filter((subscription) => hasValue(subscription)) + .forEach((subscription) => subscription.unsubscribe()); + } + + /** + * Add new row to dropdown for multiple service selection + * @param ldnPattern - the related LDN pattern where the service is added + */ + addNewService(ldnPattern: LdnPattern): void { + //idle new service for new selection + this.ldnServiceByPattern[ldnPattern.pattern].services.push(null); + } +} diff --git a/src/app/submission/sections/section-coar-notify/submission-coar-notify-workspaceitem.model.ts b/src/app/submission/sections/section-coar-notify/submission-coar-notify-workspaceitem.model.ts new file mode 100644 index 0000000000..41ef69cd7a --- /dev/null +++ b/src/app/submission/sections/section-coar-notify/submission-coar-notify-workspaceitem.model.ts @@ -0,0 +1,35 @@ +import { CacheableObject } from '../../../core/cache/cacheable-object.model'; +import { autoserialize, deserialize, deserializeAs, inheritSerialization } from 'cerialize'; + +import { excludeFromEquals } from '../../../core/utilities/equals.decorators'; +import { typedObject } from '../../../core/cache/builders/build-decorators'; +import { COAR_NOTIFY_WORKSPACEITEM } from './section-coar-notify-service.resource-type'; + + +/** An CoarNotify and its properties. */ +@typedObject +@inheritSerialization(CacheableObject) +export class SubmissionCoarNotifyWorkspaceitemModel extends CacheableObject { + static type = COAR_NOTIFY_WORKSPACEITEM; + + @excludeFromEquals + @autoserialize + endorsement?: number[]; + + @deserializeAs('id') + review?: number[]; + + @autoserialize + ingest?: number[]; + + @deserialize + _links: { + self: { + href: string; + }; + }; + + get self(): string { + return this._links.self.href; + } +} diff --git a/src/app/submission/sections/section-coar-notify/submission-coar-notify.config.ts b/src/app/submission/sections/section-coar-notify/submission-coar-notify.config.ts new file mode 100644 index 0000000000..4a8116cdde --- /dev/null +++ b/src/app/submission/sections/section-coar-notify/submission-coar-notify.config.ts @@ -0,0 +1,42 @@ +import { ResourceType } from '../../../core/shared/resource-type'; +import { CacheableObject } from '../../../core/cache/cacheable-object.model'; +import { autoserialize, deserialize, deserializeAs, inheritSerialization } from 'cerialize'; + +import { excludeFromEquals } from '../../../core/utilities/equals.decorators'; +import { typedObject } from '../../../core/cache/builders/build-decorators'; +import { SUBMISSION_COAR_NOTIFY_CONFIG } from './section-coar-notify-service.resource-type'; + +export interface LdnPattern { + pattern: string, + multipleRequest: boolean +} +/** A SubmissionCoarNotifyConfig and its properties. */ +@typedObject +@inheritSerialization(CacheableObject) +export class SubmissionCoarNotifyConfig extends CacheableObject { + static type = SUBMISSION_COAR_NOTIFY_CONFIG; + + @excludeFromEquals + @autoserialize + type: ResourceType; + + @autoserialize + id: string; + + @deserializeAs('id') + uuid: string; + + @autoserialize + patterns: LdnPattern[]; + + @deserialize + _links: { + self: { + href: string; + }; + }; + + get self(): string { + return this._links.self.href; + } +} diff --git a/src/app/submission/sections/sections-type.ts b/src/app/submission/sections/sections-type.ts index 6bca8a7252..5f71d1731d 100644 --- a/src/app/submission/sections/sections-type.ts +++ b/src/app/submission/sections/sections-type.ts @@ -9,4 +9,5 @@ export enum SectionsType { SherpaPolicies = 'sherpaPolicy', Identifiers = 'identifiers', Collection = 'collection', + CoarNotify = 'coarnotify' } diff --git a/src/app/submission/submission.module.ts b/src/app/submission/submission.module.ts index cf0ab2b369..d839565f8d 100644 --- a/src/app/submission/submission.module.ts +++ b/src/app/submission/submission.module.ts @@ -10,7 +10,7 @@ import { SubmissionFormFooterComponent } from './form/footer/submission-form-foo import { SubmissionFormComponent } from './form/submission-form.component'; import { SubmissionFormSectionAddComponent } from './form/section-add/submission-form-section-add.component'; import { SubmissionSectionContainerComponent } from './sections/container/section-container.component'; -import { CommonModule } from '@angular/common'; +import { CommonModule, NgOptimizedImage } from '@angular/common'; import { Action, StoreConfig, StoreModule } from '@ngrx/store'; import { EffectsModule } from '@ngrx/effects'; import { submissionReducers, SubmissionState } from './submission.reducers'; @@ -67,6 +67,11 @@ import { } from './sections/sherpa-policies/metadata-information/metadata-information.component'; import { SectionFormOperationsService } from './sections/form/section-form-operations.service'; import {SubmissionSectionIdentifiersComponent} from './sections/identifiers/section-identifiers.component'; +import { SubmissionSectionCoarNotifyComponent } from './sections/section-coar-notify/section-coar-notify.component'; +import { + CoarNotifyConfigDataService +} from './sections/section-coar-notify/coar-notify-config-data.service'; +import { LdnServicesService } from '../admin/admin-ldn-services/ldn-services-data/ldn-services-data.service'; const ENTRY_COMPONENTS = [ // put only entry components that use custom decorator @@ -76,6 +81,7 @@ const ENTRY_COMPONENTS = [ SubmissionSectionCcLicensesComponent, SubmissionSectionAccessesComponent, SubmissionSectionSherpaPoliciesComponent, + SubmissionSectionCoarNotifyComponent ]; const DECLARATIONS = [ @@ -109,20 +115,22 @@ const DECLARATIONS = [ ]; @NgModule({ - imports: [ - CommonModule, - CoreModule.forRoot(), - SharedModule, - StoreModule.forFeature('submission', submissionReducers, storeModuleConfig as StoreConfig), - EffectsModule.forFeature(submissionEffects), - JournalEntitiesModule.withEntryComponents(), - ResearchEntitiesModule.withEntryComponents(), - FormModule, - NgbModalModule, - NgbCollapseModule, - NgbAccordionModule, - UploadModule, - ], + imports: [ + CommonModule, + CoreModule.forRoot(), + SharedModule, + StoreModule.forFeature('submission', submissionReducers, storeModuleConfig as StoreConfig), + EffectsModule.forFeature(), + EffectsModule.forFeature(submissionEffects), + JournalEntitiesModule.withEntryComponents(), + ResearchEntitiesModule.withEntryComponents(), + FormModule, + NgbModalModule, + NgbCollapseModule, + NgbAccordionModule, + UploadModule, + NgOptimizedImage, + ], declarations: DECLARATIONS, exports: [ ...DECLARATIONS, @@ -135,6 +143,8 @@ const DECLARATIONS = [ SubmissionAccessesConfigDataService, SectionAccessesService, SectionFormOperationsService, + CoarNotifyConfigDataService, + LdnServicesService ] }) diff --git a/src/app/suggestion-notifications/selectors.ts b/src/app/suggestion-notifications/selectors.ts index 97ed3a8360..1dd0df11a7 100644 --- a/src/app/suggestion-notifications/selectors.ts +++ b/src/app/suggestion-notifications/selectors.ts @@ -1,8 +1,9 @@ import {createFeatureSelector, createSelector, MemoizedSelector} from '@ngrx/store'; import { suggestionNotificationsSelector, SuggestionNotificationsState } from '../notifications/notifications.reducer'; -import { SuggestionTarget } from '../core/suggestion-notifications/models/suggestion-target.model'; -import { SuggestionTargetState } from './suggestion-targets/suggestion-targets.reducer'; + import {subStateSelector} from '../submission/selectors'; +import { SuggestionTargetState } from '../notifications/suggestion-targets/suggestion-targets.reducer'; +import { SuggestionTarget } from '../core/notifications/models/suggestion-target.model'; /** * Returns the Reciter Suggestion Target state. diff --git a/src/app/suggestions-page/suggestions-page.component.spec.ts b/src/app/suggestions-page/suggestions-page.component.spec.ts index 98535297a2..7cdeaddc78 100644 --- a/src/app/suggestions-page/suggestions-page.component.spec.ts +++ b/src/app/suggestions-page/suggestions-page.component.spec.ts @@ -7,14 +7,9 @@ import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { of as observableOf } from 'rxjs'; import { SuggestionsPageComponent } from './suggestions-page.component'; -import { - SuggestionApproveAndImport, - SuggestionListElementComponent -} from '../suggestion-notifications/suggestion-list-element/suggestion-list-element.component'; -import { SuggestionsService } from '../suggestion-notifications/suggestions.service'; + import { getMockSuggestionNotificationsStateService, getMockSuggestionsService } from '../shared/mocks/suggestion.mock'; import { mockSuggestionPublicationOne, mockSuggestionPublicationTwo } from '../shared/mocks/publication-claim.mock'; -import { SuggestionEvidencesComponent } from '../suggestion-notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component'; import { ObjectKeysPipe } from '../shared/utils/object-keys-pipe'; import { VarDirective } from '../shared/utils/var.directive'; import { ActivatedRoute, Router } from '@angular/router'; @@ -24,13 +19,21 @@ import { AuthService } from '../core/auth/auth.service'; import { NotificationsService } from '../shared/notifications/notifications.service'; import { NotificationsServiceStub } from '../shared/testing/notifications-service.stub'; import { getMockTranslateService } from '../shared/mocks/translate.service.mock'; -import { SuggestionTargetsStateService } from '../suggestion-notifications/suggestion-targets/suggestion-targets.state.service'; import { WorkspaceitemDataService } from '../core/submission/workspaceitem-data.service'; import { createSuccessfulRemoteDataObject } from '../shared/remote-data.utils'; import { TestScheduler } from 'rxjs/testing'; import { getTestScheduler } from 'jasmine-marbles'; import { PaginationServiceStub } from '../shared/testing/pagination-service.stub'; import { PaginationService } from '../core/pagination/pagination.service'; +import { + SuggestionEvidencesComponent +} from '../notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component'; +import { + SuggestionApproveAndImport, + SuggestionListElementComponent +} from '../notifications/suggestion-list-element/suggestion-list-element.component'; +import { SuggestionsService } from '../notifications/suggestions.service'; +import { SuggestionTargetsStateService } from '../notifications/suggestion-targets/suggestion-targets.state.service'; describe('SuggestionPageComponent', () => { let component: SuggestionsPageComponent; diff --git a/src/app/suggestions-page/suggestions-page.component.ts b/src/app/suggestions-page/suggestions-page.component.ts index fdbf131e59..e4305cc226 100644 --- a/src/app/suggestions-page/suggestions-page.component.ts +++ b/src/app/suggestions-page/suggestions-page.component.ts @@ -9,14 +9,9 @@ import { SortDirection, SortOptions, } from '../core/cache/models/sort-options.m import { PaginatedList } from '../core/data/paginated-list.model'; import { RemoteData } from '../core/data/remote-data'; import { getFirstSucceededRemoteDataPayload } from '../core/shared/operators'; -import { SuggestionBulkResult, SuggestionsService } from '../suggestion-notifications/suggestions.service'; import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model'; -import { Suggestion } from '../core/suggestion-notifications/models/suggestion.model'; -import { SuggestionTarget } from '../core/suggestion-notifications/models/suggestion-target.model'; import { AuthService } from '../core/auth/auth.service'; -import { SuggestionApproveAndImport } from '../suggestion-notifications/suggestion-list-element/suggestion-list-element.component'; import { NotificationsService } from '../shared/notifications/notifications.service'; -import { SuggestionTargetsStateService } from '../suggestion-notifications/suggestion-targets/suggestion-targets.state.service'; import { WorkspaceitemDataService } from '../core/submission/workspaceitem-data.service'; import { PaginationService } from '../core/pagination/pagination.service'; import { WorkspaceItem } from '../core/submission/models/workspaceitem.model'; @@ -25,6 +20,11 @@ import {redirectOn4xx} from '../core/shared/authorized.operators'; import { getWorkspaceItemEditRoute } from '../workflowitems-edit-page/workflowitems-edit-page-routing-paths'; +import { Suggestion } from '../core/notifications/models/suggestion.model'; +import { SuggestionTarget } from '../core/notifications/models/suggestion-target.model'; +import { SuggestionBulkResult, SuggestionsService } from '../notifications/suggestions.service'; +import { SuggestionTargetsStateService } from '../notifications/suggestion-targets/suggestion-targets.state.service'; +import { SuggestionApproveAndImport } from '../notifications/suggestion-list-element/suggestion-list-element.component'; @Component({ selector: 'ds-suggestion-page', diff --git a/src/app/suggestions-page/suggestions-page.module.ts b/src/app/suggestions-page/suggestions-page.module.ts index e25e483e39..90fbdbcf70 100644 --- a/src/app/suggestions-page/suggestions-page.module.ts +++ b/src/app/suggestions-page/suggestions-page.module.ts @@ -4,9 +4,9 @@ import { CommonModule } from '@angular/common'; import { SuggestionsPageComponent } from './suggestions-page.component'; import { SharedModule } from '../shared/shared.module'; import { SuggestionsPageRoutingModule } from './suggestions-page-routing.module'; -import { SuggestionsService } from '../suggestion-notifications/suggestions.service'; -import { SuggestionsDataService } from '../core/suggestion-notifications/suggestions-data.service'; import { NotificationsModule } from '../notifications/notifications.module'; +import { SuggestionsDataService } from '../core/notifications/suggestions-data.service'; +import { SuggestionsService } from '../notifications/suggestions.service'; @NgModule({ declarations: [SuggestionsPageComponent], diff --git a/src/app/suggestions-page/suggestions-page.resolver.ts b/src/app/suggestions-page/suggestions-page.resolver.ts index dde5b847f5..a2074d38bf 100644 --- a/src/app/suggestions-page/suggestions-page.resolver.ts +++ b/src/app/suggestions-page/suggestions-page.resolver.ts @@ -6,10 +6,9 @@ import { find } from 'rxjs/operators'; import { RemoteData } from '../core/data/remote-data'; import { hasValue } from '../shared/empty.util'; -import { SuggestionTarget } from '../core/suggestion-notifications/models/suggestion-target.model'; -import { - SuggestionTargetDataService -} from '../core/suggestion-notifications/target/suggestion-target-data.service'; +import { SuggestionTarget } from '../core/notifications/models/suggestion-target.model'; +import { SuggestionTargetDataService } from '../core/notifications/target/suggestion-target-data.service'; + /** * This class represents a resolver that requests a specific collection before the route is activated diff --git a/src/assets/i18n/ar.json5 b/src/assets/i18n/ar.json5 index 617d2a93de..0b69b46b55 100644 --- a/src/assets/i18n/ar.json5 +++ b/src/assets/i18n/ar.json5 @@ -878,7 +878,408 @@ // TODO New key - Add a translation "admin.access-control.groups.form.return": "Return to groups", + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", // "admin.search.breadcrumbs": "Administrative Search", // TODO New key - Add a translation @@ -3878,6 +4279,20 @@ + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + + + // "menu.section.admin_search": "Admin Search", // TODO New key - Add a translation "menu.section.admin_search": "Admin Search", @@ -3980,6 +4395,10 @@ // TODO New key - Add a translation "menu.section.icon.access_control": "Access Control menu section", + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", // TODO New key - Add a translation "menu.section.icon.admin_search": "Admin search menu section", @@ -4113,6 +4532,9 @@ "menu.section.statistics_task": "Statistics Task", + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", // "menu.section.toggle.access_control": "Toggle Access Control section", // TODO New key - Add a translation diff --git a/src/assets/i18n/bn.json5 b/src/assets/i18n/bn.json5 index c9c5ba2640..8c99662d4b 100644 --- a/src/assets/i18n/bn.json5 +++ b/src/assets/i18n/bn.json5 @@ -717,7 +717,408 @@ // "admin.access-control.groups.form.return": "Back", "admin.access-control.groups.form.return": "পেছনে", + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", // "admin.search.breadcrumbs": "Administrative Search", "admin.search.breadcrumbs": "প্রশাসনিক অনুসন্ধান", @@ -3565,6 +3966,17 @@ "menu.section.access_control_people": "ব্যাক্তি", + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", // "menu.section.admin_search": "Admin Search", "menu.section.admin_search": "অ্যাডমিন অনুসন্ধান", @@ -3645,6 +4057,10 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "অ্যাক্সেস কন্ট্রোল মেনু বিভাগ", + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "অ্যাডমিন অনুসন্ধান মেনু বিভাগ", @@ -3751,6 +4167,9 @@ "menu.section.statistics_task": "পরিসংখ্যান টাস্ক", + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "অ্যাক্সেস কন্ট্রোল বিভাগ টগল করুন", diff --git a/src/assets/i18n/ca.json5 b/src/assets/i18n/ca.json5 index db624f2c3f..6fefff87dc 100644 --- a/src/assets/i18n/ca.json5 +++ b/src/assets/i18n/ca.json5 @@ -748,6 +748,409 @@ + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // "admin.search.breadcrumbs": "Administrative Search", "admin.search.breadcrumbs": "Cerca administrativa", @@ -3863,6 +4266,20 @@ + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + + + // "menu.section.admin_search": "Admin Search", "menu.section.admin_search": "Cerca d'administrador", @@ -3944,6 +4361,10 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "Secció del menú de control d'accés", + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "Secció del menú de cerca d'administrador", @@ -4057,6 +4478,10 @@ + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", + // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Alternar secció de Control d'accés", diff --git a/src/assets/i18n/cs.json5 b/src/assets/i18n/cs.json5 index 9816571e05..651a3fd6b3 100644 --- a/src/assets/i18n/cs.json5 +++ b/src/assets/i18n/cs.json5 @@ -858,7 +858,408 @@ // TODO New key - Add a translation "admin.access-control.groups.form.return": "Return to groups", + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", // "admin.search.breadcrumbs": "Administrative Search", // TODO New key - Add a translation @@ -3789,6 +4190,18 @@ + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + // "menu.section.admin_search": "Admin Search", // TODO New key - Add a translation "menu.section.admin_search": "Admin Search", @@ -3891,6 +4304,10 @@ // TODO New key - Add a translation "menu.section.icon.access_control": "Access Control menu section", + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", // TODO New key - Add a translation "menu.section.icon.admin_search": "Admin search menu section", @@ -4024,6 +4441,9 @@ "menu.section.statistics_task": "Statistics Task", + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", // "menu.section.toggle.access_control": "Toggle Access Control section", // TODO New key - Add a translation diff --git a/src/assets/i18n/de.json5 b/src/assets/i18n/de.json5 index 4f9988acb6..b726f62b71 100644 --- a/src/assets/i18n/de.json5 +++ b/src/assets/i18n/de.json5 @@ -684,7 +684,408 @@ // "admin.access-control.groups.form.return": "Return to groups", "admin.access-control.groups.form.return": "Zurück zu den Gruppen", + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", // "admin.search.breadcrumbs": "Administrative Search", "admin.search.breadcrumbs": "Admin-Suche", @@ -3215,6 +3616,15 @@ + // "menu.section.reports": "Reports", + "menu.section.reports": "Berichte", + + // "menu.section.reports.collections": "Filtered Collections", + "menu.section.reports.collections": "Filtrierte Sammlungen", + + // "menu.section.reports.queries": "Metadata Query", + "menu.section.reports.queries": "Metadatenabfrage", + // "menu.section.admin_search": "Admin Search", "menu.section.admin_search": "Admin-Suche", @@ -3294,6 +3704,10 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "Menübereich Zugriffskontrolle", + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "Menüabschnitt (Admin-Suche)", @@ -3397,6 +3811,9 @@ "menu.section.statistics_task": "Statistikaufgaben", + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Bereich Zugriffskontrolle umschalten", diff --git a/src/assets/i18n/el.json5 b/src/assets/i18n/el.json5 index 176eadff62..018181c43f 100644 --- a/src/assets/i18n/el.json5 +++ b/src/assets/i18n/el.json5 @@ -151,6 +151,410 @@ "admin.access-control.groups.title": "Ομάδες", "admin.access-control.groups.title.addGroup": "Νέα ομάδα", "admin.access-control.groups.title.singleGroup": "Επεξεργασία ομάδας", + + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + "admin.curation-tasks.breadcrumbs": "Εργασίες επιμέλειας συστήματος", "admin.curation-tasks.header": "Εργασίες επιμέλειας συστήματος", "admin.curation-tasks.title": "Εργασίες επιμέλειας συστήματος", @@ -1214,6 +1618,19 @@ "menu.section.access_control_authorizations": "Εξουσιοδοτήσεις", "menu.section.access_control_groups": "Ομάδες", "menu.section.access_control_people": "Ανθρωποι", + + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + "menu.section.admin_search": "Αναζήτηση διαχειριστή", "menu.section.browse_community": "Αυτή η Κοινότητα", "menu.section.browse_community_by_author": "Από Συγγραφέα", @@ -1238,6 +1655,11 @@ "menu.section.export_metadata": "Μεταδεδομένα", "menu.section.health": "Υγεία", "menu.section.icon.access_control": "Ενότητα μενού ελέγχου πρόσβασης", + + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + "menu.section.icon.admin_search": "Ενότητα μενού αναζήτησης διαχειριστή", "menu.section.icon.control_panel": "Ενότητα μενού Πίνακας Ελέγχου", "menu.section.icon.curation_tasks": "Ενότητα μενού Εργασίας Επιμέλειας", @@ -1270,6 +1692,11 @@ "menu.section.statistics": "Στατιστικά", "menu.section.statistics_task": "Εργασία Στατιστικών", "menu.section.toggle.access_control": "Εναλλαγή ενότητας Ελέγχου πρόσβασης", + + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", + "menu.section.toggle.control_panel": "Εναλλαγή ενότητας Πίνακας Ελέγχου", "menu.section.toggle.curation_task": "Εναλλαγή ενότητας Εργασία Επιμέλειας", "menu.section.toggle.edit": "Εναλλαγή ενότητας Επεξεργασία", diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 98a84a0250..58adaf9663 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -534,7 +534,7 @@ "admin.quality-assurance.page.title": "Quality Assurance", - "admin.notifications.source.breadcrumbs": "Quality Assurance Source", + "admin.notifications.source.breadcrumbs": "Quality Assurance", "admin.access-control.groups.form.tooltip.editGroupPage": "On this page, you can modify the properties and members of a group. In the top section, you can edit the group name and description, unless this is an admin group for a collection or community, in which case the group name and description are auto-generated and cannot be edited. In the following sections, you can edit group membership. See [the wiki](https://wiki.lyrasis.org/display/DSDOC7x/Create+or+manage+a+user+group) for more details.", @@ -542,6 +542,209 @@ "admin.access-control.groups.form.tooltip.editGroup.addSubgroups": "To add or remove a Subgroup to/from this group, either click the 'Browse All' button or use the search bar below to search for groups. Then click the plus icon for each group you wish to add in the list below, or the trash can icon for each group you wish to remove. The list below may have several pages: use the page controls below the list to navigate to the next pages.", + "admin.reports.collections.title": "Collection Filter Report", + + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + "admin.reports.collections.head": "Collection Filter Report", + + "admin.reports.button.show-collections": "Show Collections", + + "admin.reports.collections.collections-report": "Collection Report", + + "admin.reports.collections.item-results": "Item Results", + + "admin.reports.collections.community": "Community", + + "admin.reports.collections.collection": "Collection", + + "admin.reports.collections.nb_items": "Nb. Items", + + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + "admin.reports.items.title": "Metadata Query Report", + + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + "admin.reports.items.head": "Metadata Query Report", + + "admin.reports.items.run": "Run Item Query", + + "admin.reports.items.section.collectionSelector": "Collection Selector", + + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + "admin.reports.items.predefinedQueries": "Predefined Queries", + + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + "admin.reports.items.limit": "Limit/", + + "admin.reports.items.offset": "Offset", + + "admin.reports.items.wholeRepo": "Whole Repository", + + "admin.reports.items.anyField": "Any field", + + "admin.reports.items.predicate.exists": "exists", + + "admin.reports.items.predicate.doesNotExist": "does not exist", + + "admin.reports.items.predicate.equals": "equals", + + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + "admin.reports.items.predicate.like": "like", + + "admin.reports.items.predicate.notLike": "not like", + + "admin.reports.items.predicate.contains": "contains", + + "admin.reports.items.predicate.doesNotContain": "does not contain", + + "admin.reports.items.predicate.matches": "matches", + + "admin.reports.items.predicate.doesNotMatch": "does not match", + + "admin.reports.items.preset.new": "New Query", + + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + "admin.reports.items.number": "No.", + + "admin.reports.items.id": "UUID", + + "admin.reports.items.collection": "Collection", + + "admin.reports.items.handle": "URI", + + "admin.reports.items.title": "Title", + + + "admin.reports.commons.filters": "Filters", + + "admin.reports.commons.additional-data": "Additional data to return", + + "admin.reports.commons.previous-page": "Prev Page", + + "admin.reports.commons.next-page": "Next Page", + + "admin.reports.commons.page": "Page", + + "admin.reports.commons.of": "of", + + "admin.reports.commons.export": "Export for Metadata Update", + + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + "admin.reports.commons.filters.select_all": "Select all filters", + + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + "admin.reports.commons.filters.property": "Item Property Filters", + + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + "admin.reports.commons.filters.permission": "Permission Filters", + + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + "admin.search.breadcrumbs": "Administrative Search", "admin.search.collection.edit": "Edit", @@ -1954,6 +2157,10 @@ "item.alerts.withdrawn": "This item has been withdrawn", + "item.alerts.reinstate-request": "Request reinstate", + + "quality-assurance.event.table.person-who-requested": "Requested by", + "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", @@ -2432,6 +2639,14 @@ "item.truncatable-part.show-less": "Collapse", + "item.qa-event-notification.check.notification-info": "There are {{num}} pending suggestions related to your account", + + "item.qa-event-notification-info.check.button": "View", + + "mydspace.qa-event-notification.check.notification-info": "There are {{num}} pending suggestions related to your account", + + "mydspace.qa-event-notification-info.check.button": "View", + "workflow-item.search.result.delete-supervision.modal.header": "Delete Supervision Order", "workflow-item.search.result.delete-supervision.modal.info": "Are you sure you want to delete Supervision Order", @@ -2536,6 +2751,10 @@ "item.page.version.create": "Create new version", + "item.page.withdrawn": "Request a withdrawal for this item", + + "item.page.reinstate": "Request reinstatement", + "item.page.version.hasDraft": "A new version cannot be created because there is an inprogress submission in the version history", "item.page.claim.button": "Claim", @@ -2670,6 +2889,12 @@ "item.version.create.modal.header": "New version", + "item.qa.withdrawn.modal.header": "Request withdrawal", + + "item.qa.reinstate.modal.header": "Request reinstate", + + "item.qa.reinstate.create.modal.header": "New version", + "item.version.create.modal.text": "Create a new version for this item", "item.version.create.modal.text.startingFrom": "starting from version {{version}}", @@ -2678,16 +2903,44 @@ "item.version.create.modal.button.confirm.tooltip": "Create new version", + "item.qa.withdrawn-reinstate.modal.button.confirm.tooltip": "Send request", + + "qa-withdrown.create.modal.button.confirm": "Withdraw", + + "qa-reinstate.create.modal.button.confirm": "Reinstate", + "item.version.create.modal.button.cancel": "Cancel", + "item.qa.withdrawn-reinstate.create.modal.button.cancel": "Cancel", + "item.version.create.modal.button.cancel.tooltip": "Do not create new version", + "item.qa.withdrawn-reinstate.create.modal.button.cancel.tooltip": "Do not send request", + "item.version.create.modal.form.summary.label": "Summary", + "qa-withdrawn.create.modal.form.summary.label": "You are requesting to withdraw this item", + + "qa-withdrawn.create.modal.form.summary2.label": "Please enter the reason for the withdrawal", + + "qa-reinstate.create.modal.form.summary.label": "You are requesting to reinstate this item", + + "qa-reinstate.create.modal.form.summary2.label": "Please enter the reason for the reinstatment", + "item.version.create.modal.form.summary.placeholder": "Insert the summary for the new version", + "qa-withdrown.modal.form.summary.placeholder": "Enter the reason for the withdrawal", + + "qa-reinstate.modal.form.summary.placeholder": "Enter the reason for the reinstatement", + "item.version.create.modal.submitted.header": "Creating new version...", + "item.qa.withdrawn.modal.submitted.header": "Sending withdrawn request...", + + "correction-type.manage-relation.action.notification.reinstate": "Reinstate request sent.", + + "correction-type.manage-relation.action.notification.withdrawn": "Withdraw request sent.", + "item.version.create.modal.submitted.text": "The new version is being created. This may take some time if the item has a lot of relationships.", "item.version.create.notification.success": "New version has been created with version number {{version}}", @@ -2934,6 +3187,12 @@ "menu.section.access_control_people": "People", + "menu.section.reports": "Reports", + + "menu.section.reports.collections": "Filtered Collections", + + "menu.section.reports.queries": "Metadata Query", + "menu.section.admin_search": "Admin Search", "menu.section.browse_community": "This Community", @@ -2986,6 +3245,8 @@ "menu.section.icon.access_control": "Access Control menu section", + "menu.section.icon.reports": "Reports menu section", + "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.control_panel": "Control Panel menu section", @@ -3062,6 +3323,8 @@ "menu.section.toggle.access_control": "Toggle Access Control section", + "menu.section.toggle.reports": "Toggle Reports section", + "menu.section.toggle.control_panel": "Toggle Control Panel section", "menu.section.toggle.curation_task": "Toggle Curation Task section", @@ -3174,8 +3437,6 @@ "nav.expandable-navbar-section-suffix": "(submenu)", - "mydspace.import": "Import", - "notification.suggestion": "We found {{count}} publications in the {{source}} that seems to be related to your profile.
", "notification.suggestion.review": "review the suggestions", @@ -3222,6 +3483,8 @@ "quality-assurance.topics.description": "Below you can see all the topics received from the subscriptions to {{source}}.", + "quality-assurance.topics.description-with-target": "Below you can see all the topics received from the subscriptions to {{source}} in regards to the", + "quality-assurance.source.description": "Below you can see all the notification's sources.", "quality-assurance.topics": "Current Topics", @@ -3236,7 +3499,9 @@ "quality-assurance.table.actions": "Actions", - "quality-assurance.button.detail": "Show details", + "quality-assurance.source-list.button.detail": "Show topics for {{param}}", + + "quality-assurance.topics-list.button.detail": "Show suggestions for {{param}}", "quality-assurance.noTopics": "No topics found.", @@ -3248,8 +3513,6 @@ "quality-assurance.source.error.service.retrieve": "An error occurred while loading the Quality Assurance source", - "quality-assurance.events.description": "Below the list of all the suggestions for the selected topic.", - "quality-assurance.loading": "Loading ...", "quality-assurance.events.topic": "Topic:", @@ -3264,12 +3527,16 @@ "quality-assurance.event.table.project-details": "Project details", + "quality-assurance.event.table.reasons": "Reasons", + "quality-assurance.event.table.actions": "Actions", "quality-assurance.event.action.accept": "Accept suggestion", "quality-assurance.event.action.ignore": "Ignore suggestion", + "quality-assurance.event.action.undo": "DELETE", + "quality-assurance.event.action.reject": "Reject suggestion", "quality-assurance.event.action.import": "Import project and accept suggestion", @@ -3298,6 +3565,8 @@ "quality-assurance.events.back": "Back to topics", + "quality-assurance.events.back-to-sources": "Back to sources", + "quality-assurance.event.table.less": "Show less", "quality-assurance.event.table.more": "Show more", @@ -3310,6 +3579,8 @@ "quality-assurance.event.ignore.description": "This operation can't be undone. Ignore this suggestion?", + "quality-assurance.event.undo.description": "This operation can't be undone!", + "quality-assurance.event.reject.description": "This operation can't be undone. Reject this suggestion?", "quality-assurance.event.accept.description": "No DSpace project selected. A new project will be created based on the suggestion data.", @@ -4356,6 +4627,8 @@ "submission.general.discard.submit": "Discard", + "submission.general.back.submit": "Back", + "submission.general.info.saved": "Saved", "submission.general.info.pending-changes": "Unsaved changes", @@ -5703,5 +5976,344 @@ "admin.notifications.publicationclaim.breadcrumbs": "Publication Claim", "admin.notifications.publicationclaim.page.title": "Publication Claim", -} + "filter.search.operator.placeholder": "Operator", + + "search.filters.filter.entityType.text": "Item Type", + + "search.filters.operator.equals.text": "Equals", + + "search.filters.operator.notequals.text": "Not Equals", + + "search.filters.operator.notcontains.text": "Not Contains", + + "search.filters.operator.contains.text": "Contains", + + "search.filters.filter.title.text": "Title", + + "search.filters.applied.f.title": "Title", + + "search.filters.filter.author.text": "Author", + + "coar-notify-support.title": "COAR Notify Protocol", + + "coar-notify-support-title.content": "Here, we fully support the COAR Notify protocol, which is designed to enhance the communication between repositories. To learn more about the COAR Notify protocol, visit the COAR Notify website.", + + "coar-notify-support.ldn-inbox.title": "LDN InBox", + + "coar-notify-support.ldn-inbox.content": "For your convenience, our LDN (Linked Data Notifications) InBox is easily accessible at {ldnInboxUrl}. The LDN InBox enables seamless communication and data exchange, ensuring efficient and effective collaboration.", + + "coar-notify-support.message-moderation.title": "Message Moderation", + + "coar-notify-support.message-moderation.content": "To ensure a secure and productive environment, all incoming LDN messages are moderated. If you are planning to exchange information with us, kindly reach out via our dedicated", + + "coar-notify-support.message-moderation.feedback-form": " Feedback form.", + + "service.overview.delete.header": "Delete Service", + + "ldn-registered-services.title": "Registered Services", + "ldn-registered-services.table.name": "Name", + "ldn-registered-services.table.description": "Description", + "ldn-registered-services.table.status": "Status", + "ldn-registered-services.table.action": "Action", + "ldn-registered-services.new": "NEW", + "ldn-registered-services.new.breadcrumbs": "Registered Services", + + "ldn-service.overview.table.enabled": "Enabled", + "ldn-service.overview.table.disabled": "Disabled", + "ldn-service.overview.table.clickToEnable": "Click to enable", + "ldn-service.overview.table.clickToDisable": "Click to disable", + + "ldn-edit-registered-service.title": "Edit Service", + "ldn-create-service.title": "Create service", + "service.overview.create.modal": "Create Service", + "service.overview.create.body": "Please confirm the creation of this service.", + "ldn-service-status": "Status", + "service.confirm.create": "Create", + "service.refuse.create": "Cancel", + "ldn-register-new-service.title": "Register a new service", + "ldn-new-service.form.label.submit": "Save", + "ldn-new-service.form.label.name": "Name", + "ldn-new-service.form.label.description": "Description", + "ldn-new-service.form.label.url": "Service URL", + "ldn-new-service.form.label.ip-range": "Service IP range", + "ldn-new-service.form.label.score": "Level of trust", + "ldn-new-service.form.label.ldnUrl": "LDN Inbox URL", + "ldn-new-service.form.placeholder.name": "Please provide service name", + "ldn-new-service.form.placeholder.description": "Please provide a description regarding your service", + "ldn-new-service.form.placeholder.url": "Please input the URL for users to check out more information about the service", + "ldn-new-service.form.placeholder.lowerIp": "IPv4 range lower bound", + "ldn-new-service.form.placeholder.upperIp": "IPv4 range upper bound", + "ldn-new-service.form.placeholder.ldnUrl": "Please specify the URL of the LDN Inbox", + "ldn-new-service.form.placeholder.score": "Please enter a value between 0 and 1. Use the “.” as decimal separator", + "ldn-service.form.label.placeholder.default-select": "Select a pattern", + + "ldn-service.form.pattern.ack-accept.label": "Acknowledge and Accept", + "ldn-service.form.pattern.ack-accept.description": "This pattern is used to acknowledge and accept a request (offer). It implies an intention to act on the request.", + "ldn-service.form.pattern.ack-accept.category": "Acknowledgements", + + "ldn-service.form.pattern.ack-reject.label": "Acknowledge and Reject", + "ldn-service.form.pattern.ack-reject.description": "This pattern is used to acknowledge and reject a request (offer). It signifies no further action regarding the request.", + "ldn-service.form.pattern.ack-reject.category": "Acknowledgements", + + "ldn-service.form.pattern.ack-tentative-accept.label": "Acknowledge and Tentatively Accept", + "ldn-service.form.pattern.ack-tentative-accept.description": "This pattern is used to acknowledge and tentatively accept a request (offer). It implies an intention to act, which may change.", + "ldn-service.form.pattern.ack-tentative-accept.category": "Acknowledgements", + + "ldn-service.form.pattern.ack-tentative-reject.label": "Acknowledge and Tentatively Reject", + "ldn-service.form.pattern.ack-tentative-reject.description": "This pattern is used to acknowledge and tentatively reject a request (offer). It signifies no further action, subject to change.", + "ldn-service.form.pattern.ack-tentative-reject.category": "Acknowledgements", + + "ldn-service.form.pattern.announce-endorsement.label": "Announce Endorsement", + "ldn-service.form.pattern.announce-endorsement.description": "This pattern is used to announce the existence of an endorsement, referencing the endorsed resource.", + "ldn-service.form.pattern.announce-endorsement.category": "Announcements", + + "ldn-service.form.pattern.announce-ingest.label": "Announce Ingest", + "ldn-service.form.pattern.announce-ingest.description": "This pattern is used to announce that a resource has been ingested.", + "ldn-service.form.pattern.announce-ingest.category": "Announcements", + + "ldn-service.form.pattern.announce-relationship.label": "Announce Relationship", + "ldn-service.form.pattern.announce-relationship.description": "This pattern is used to announce a relationship between two resources.", + "ldn-service.form.pattern.announce-relationship.category": "Announcements", + + "ldn-service.form.pattern.announce-review.label": "Announce Review", + "ldn-service.form.pattern.announce-review.description": "This pattern is used to announce the existence of a review, referencing the reviewed resource.", + "ldn-service.form.pattern.announce-review.category": "Announcements", + + "ldn-service.form.pattern.announce-service-result.label": "Announce Service Result", + "ldn-service.form.pattern.announce-service-result.description": "This pattern is used to announce the existence of a 'service result', referencing the relevant resource.", + "ldn-service.form.pattern.announce-service-result.category": "Announcements", + + "ldn-service.form.pattern.request-endorsement.label": "Request Endorsement", + "ldn-service.form.pattern.request-endorsement.description": "This pattern is used to request endorsement of a resource owned by the origin system.", + "ldn-service.form.pattern.request-endorsement.category": "Requests", + + "ldn-service.form.pattern.request-ingest.label": "Request Ingest", + "ldn-service.form.pattern.request-ingest.description": "This pattern is used to request that the target system ingest a resource.", + "ldn-service.form.pattern.request-ingest.category": "Requests", + + "ldn-service.form.pattern.request-review.label": "Request Review", + "ldn-service.form.pattern.request-review.description": "This pattern is used to request a review of a resource owned by the origin system.", + "ldn-service.form.pattern.request-review.category": "Requests", + + "ldn-service.form.pattern.undo-offer.label": "Undo Offer", + "ldn-service.form.pattern.undo-offer.description": "This pattern is used to undo (retract) an offer previously made.", + "ldn-service.form.pattern.undo-offer.category": "Undo", + + "ldn-new-service.form.label.placeholder.selectedItemFilter": "No Item Filter Selected", + "ldn-new-service.form.label.ItemFilter": "Item Filter", + "ldn-new-service.form.label.automatic": "Automatic", + "ldn-new-service.form.error.name": "Name is required", + "ldn-new-service.form.error.url": "URL is required", + "ldn-new-service.form.error.ipRange": "Please enter a valid IP range", + "ldn-new-service.form.hint.ipRange": "Please enter a valid IpV4 in both range bounds (note: for single IP, please enter the same value in both fields)", + "ldn-new-service.form.error.ldnurl": "LDN URL is required", + "ldn-new-service.form.error.patterns": "At least a pattern is required", + "ldn-new-service.form.error.score": "Please enter a valid score (between 0 and 1). Use the “.” as decimal separator", + + "ldn-new-service.form.label.inboundPattern": "Inbound Pattern", + "ldn-new-service.form.label.addPattern": "+ Add more", + "ldn-new-service.form.label.removeItemFilter": "Remove", + "ldn-register-new-service.breadcrumbs": "New Service", + "service.overview.delete.body": "Are you sure you want to delete this service?", + "service.overview.edit.body": "Do you confirm the changes?", + "service.overview.edit.modal": "Edit Service", + "service.detail.update": "Confirm", + "service.detail.return": "Cancel", + "service.overview.reset-form.body": "Are you sure you want to discard the changes and leave?", + "service.overview.reset-form.modal": "Discard Changes", + "service.overview.reset-form.reset-confirm": "Discard", + "admin.registries.services-formats.modify.success.head": "Successful Edit", + "admin.registries.services-formats.modify.success.content": "The service has been edited", + "admin.registries.services-formats.modify.failure.head": "Failed Edit", + "admin.registries.services-formats.modify.failure.content": "The service has not been edited", + "ldn-service-notification.created.success.title": "Successful Create", + "ldn-service-notification.created.success.body": "The service has been created", + "ldn-service-notification.created.failure.title": "Failed Create", + "ldn-service-notification.created.failure.body": "The service has not been created", + "ldn-service-notification.created.warning.title": "Please select at least one Inbound Pattern", + "ldn-enable-service.notification.success.title": "Successful status updated", + "ldn-enable-service.notification.success.content": "The service status has been updated", + "ldn-service-delete.notification.success.title": "Successful Deletion", + "ldn-service-delete.notification.success.content": "The service has been deleted", + "ldn-service-delete.notification.error.title": "Failed Deletion", + "ldn-service-delete.notification.error.content": "The service has not been deleted", + "service.overview.reset-form.reset-return": "Cancel", + "service.overview.delete": "Delete service", + "ldn-edit-service.title": "Edit service", + "ldn-edit-service.form.label.name": "Name", + "ldn-edit-service.form.label.description": "Description", + "ldn-edit-service.form.label.url": "Service URL", + "ldn-edit-service.form.label.ldnUrl": "LDN Inbox URL", + "ldn-edit-service.form.label.inboundPattern": "Inbound Pattern", + "ldn-edit-service.form.label.noInboundPatternSelected": "No Inbound Pattern", + "ldn-edit-service.form.label.selectedItemFilter": "Selected Item Filter", + "ldn-edit-service.form.label.selectItemFilter": "No Item Filter", + "ldn-edit-service.form.label.automatic": "Automatic", + "ldn-edit-service.form.label.addInboundPattern": "+ Add more", + "ldn-edit-service.form.label.submit": "Save", + "ldn-edit-service.breadcrumbs": "Edit Service", + "ldn-service.control-constaint-select-none": "Select none", + + "ldn-register-new-service.notification.error.title": "Error", + "ldn-register-new-service.notification.error.content": "An error occurred while creating this process", + "ldn-register-new-service.notification.success.title": "Success", + "ldn-register-new-service.notification.success.content": "The process was successfully created", + + "info.coar-notify-support.title": "Notify Support", + + "info.coar-notify.breadcrumbs": "Notify Support", + + "submission.sections.notify.info": "The selected service is compatible with the item according to its current status. {{ service.name }}: {{ service.description }}", + + "item.qa-event-notification.check.notification-info": "There are {{num}} pending review to check", + + "item.qa-event-notification-info.check.button": "Check", + + "mydspace.qa-event-notification.check.notification-info": "There are {{num}} pending review to check", + + "mydspace.qa-event-notification-info.check.button": "Check", + + "item.page.endorsed-by": "Endorsement", + + "item.page.is-reviewed-by": "Review", + + "item.page.is-supplemented-by": "Dataset", + + "item.page.endorsment": "Endorsment", + + "item.page.review": "Review", + + "item.page.dataset": "Dataset", + "menu.section.icon.ldn_services": "LDN Services overview", + "menu.section.services": "LDN Services", + + "menu.section.services_new": "LDN Service", + + "quality-assurance.topics.description-with-target": "Below you can see all the topics received from the subscriptions to {{source}} in regards to the", + "quality-assurance.events.description": "Below the list of all the suggestions for the selected topic {{topic}}, related to {{source}}.", + + "quality-assurance.events.description-with-topic-and-target": "Below the list of all the suggestions for the selected topic {{topic}}, related to {{source}} and ", + + "quality-assurance.event.table.event.message.serviceUrl": "Service URL:", + + "quality-assurance.event.table.event.message.link": "Link:", + + "service.detail.delete.cancel": "Cancel", + + "service.detail.delete.button": "Delete service", + + "service.detail.delete.header": "Delete service", + + "service.detail.delete.body": "Are you sure you want to delete the current service?", + + "service.detail.delete.confirm": "Delete service", + + "service.detail.delete.success": "The service was successfully deleted.", + + "service.detail.delete.error": "Something went wrong when deleting the service", + + "service.overview.table.id": "Services ID", + + "service.overview.table.name": "Name", + + "service.overview.table.start": "Start time (UTC)", + + "service.overview.table.status": "Status", + + "service.overview.table.user": "User", + + "service.overview.title": "Services Overview", + + "service.overview.breadcrumbs": "Services Overview", + + "service.overview.table.actions": "Actions", + + "service.overview.table.description": "Description", + + "submission.sections.submit.progressbar.coarnotify": "COAR Notify", + + "submission.section.section-coar-notify.control.request-review.label": "You can request a review to one of the following services", + + "submission.section.section-coar-notify.control.request-endorsement.label": "You can request an Endorsement to one of the following overlay journals", + + "submission.section.section-coar-notify.control.request-ingest.label": "You can request to ingest a copy of your submission to one of the following services", + + "submission.section.section-coar-notify.dropdown.no-data": "No data available", + + "submission.section.section-coar-notify.dropdown.select-none": "Select none", + + "submission.section.section-coar-notify.small.notification": "Select a service for {{ pattern }} of this item", + + "submission.section.section-coar-notify.selection.description": "Selected service's description:", + + "submission.section.section-coar-notify.selection.no-description": "No further information is available", + + "submission.section.section-coar-notify.notification.error": "The selected service is not suitable for the current item. Please check the description for details about which record can be managed by this service.", + + "submission.section.section-coar-notify.info.no-pattern": "No configurable patterns found.", + + "error.validation.coarnotify.invalidfilter": "Invalid filter, try to select another service or none.", + + "request-status-alert-box.accepted": "The requested {{ offerType }} for {{ serviceName }} has been taken in charge.", + + "request-status-alert-box.rejected": "The requested {{ offerType }} for {{ serviceName }} has been rejected.", + + "request-status-alert-box.requested": "The requested {{ offerType }} for {{ serviceName }} is pending.", + + "ldn-service-button-mark-inbound-deletion": "Mark inbound pattern for deletion", + + "ldn-service-button-unmark-inbound-deletion": "Unmark inbound pattern for deletion", + + "ldn-service-input-inbound-item-filter-dropdown": "Select Item filter for inbound pattern", + + "ldn-service-input-inbound-pattern-dropdown": "Select inbound pattern for service", + + "ldn-service-overview-select-delete": "Select service for deletion", + + "ldn-service-overview-select-edit": "Edit LDN service", + + "ldn-service-overview-close-modal": "Close modal", + + "a-common-or_statement.label": "Item type is Journal Article or Dataset", + + "always_true_filter.label": "Always true", + + "automatic_processing_collection_filter_16.label": "Automatic processing", + + "dc-identifier-uri-contains-doi_condition.label": "URI contains DOI", + + "doi-filter.label": "DOI filter", + + "driver-document-type_condition.label": "Document type equals driver", + + "has-at-least-one-bitstream_condition.label": "Has at least one Bitstream", + + "has-bitstream_filter.label": "Has Bitstream", + + "has-one-bitstream_condition.label": "Has one Bitstream", + + "is-archived_condition.label": "Is archived", + + "is-withdrawn_condition.label": "Is withdrawn", + + "item-is-public_condition.label": "Item is public", + + "journals_ingest_suggestion_collection_filter_18.label": "Journals ingest", + + "title-starts-with-pattern_condition.label": "Title starts with pattern", + + "type-equals-dataset_condition.label": "Type equals Dataset", + + "type-equals-journal-article_condition.label": "Type equals Journal Article", + + "search.filters.filter.subject.text": "Subject", + + "search.advanced.filters.head": "Advanced Search", + + "filter.search.text.placeholder": "Search text", + + "advancesearch.form.submit": "Add", + + "ldn.no-filter.label": "None", +} diff --git a/src/assets/i18n/es.json5 b/src/assets/i18n/es.json5 index dc4e3afcc7..298c0ff21f 100644 --- a/src/assets/i18n/es.json5 +++ b/src/assets/i18n/es.json5 @@ -732,6 +732,412 @@ // "admin.access-control.groups.form.subgroups-list.table.edit.currentGroup": "Current group", "admin.access-control.groups.form.subgroups-list.table.edit.currentGroup": "Grupo actual", + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + + // "admin.search.breadcrumbs": "Administrative Search", + "admin.search.breadcrumbs": "Búsqueda administrativa", + // "admin.access-control.groups.form.subgroups-list.notification.success.addSubgroup": "Successfully added subgroup: \"{{name}}\"", "admin.access-control.groups.form.subgroups-list.notification.success.addSubgroup": "Subgrupo agregado exitosamente: \"{{ name }}\"", @@ -3600,6 +4006,18 @@ // "item.page.filesection.size": "Size:", "item.page.filesection.size": "Tamaño:", + // "menu.section.reports": "Reports", + "menu.section.reports": "Informes", + + // "menu.section.reports.collections": "Filtered Collections", + "menu.section.reports.collections": "Colecciones filtradas", + + // "menu.section.reports.queries": "Metadata Query", + "menu.section.reports.queries": "Consulta de metadatos", + + // "menu.section.admin_search": "Admin Search", + "menu.section.admin_search": "Búsqueda de administrador", + // "item.page.journal.search.title": "Articles in this journal", "item.page.journal.search.title": "Ítems de esta revista", @@ -4284,6 +4702,10 @@ // "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.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "Sección del menú de búsqueda de administrador", @@ -4383,6 +4805,10 @@ // "menu.section.statistics_task": "Statistics Task", "menu.section.statistics_task": "Tarea de estadísticas", + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", + // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Alternar sección de control de acceso", diff --git a/src/assets/i18n/fi.json5 b/src/assets/i18n/fi.json5 index 5fec62d2b9..122d95704a 100644 --- a/src/assets/i18n/fi.json5 +++ b/src/assets/i18n/fi.json5 @@ -744,6 +744,409 @@ // "admin.access-control.groups.form.tooltip.editGroup.addSubgroups": "To add or remove a Subgroup to/from this group, either click the 'Browse All' button or use the search bar below to search for users. Then click the plus icon for each user you wish to add in the list below, or the trash can icon for each user you wish to remove. The list below may have several pages: use the page controls below the list to navigate to the next pages. Once you are ready, save your changes by clicking the 'Save' button in the top section.", "admin.access-control.groups.form.tooltip.editGroup.addSubgroups": "Jos haluat lisätä tai poistaa alaryhmän tähän ryhmään tai tästä ryhmästä, napsauta joko 'Selaa kaikkia' -painiketta tai käytä alla olevaa hakupalkkia ryhmien etsimiseen. Napsauta sitten luettelossa plus-kuvaketta jokaisen ryhmän kohdalla, jonka haluat lisätä, tai roskakorikuvaketta jokaisen ryhmän kohdalla, jonka haluat poistaa. Luettelossa voi olla useita sivuja: voit siirtyä seuraaville sivuille luettelon alapuolella olevilla sivunohjaimilla. Kun olet valmis, tallenna muutokset napsauttamalla yläosassa olevaa Tallenna-painiketta.", + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // "admin.search.breadcrumbs": "Administrative Search", "admin.search.breadcrumbs": "Ylläpitäjän haku", @@ -4164,6 +4567,18 @@ // "menu.section.access_control_people": "People", "menu.section.access_control_people": "Käyttäjät", + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + // "menu.section.admin_search": "Admin Search", "menu.section.admin_search": "Ylläpitäjän haku", @@ -4239,6 +4654,10 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "Pääsyoikeudet", + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "Ylläpitäjän haku", @@ -4338,6 +4757,10 @@ // "menu.section.statistics_task": "Statistics Task", "menu.section.statistics_task": "Tilastointitehtävä", + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", + // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Näytä/piilota Pääsyoikeudet-osio", diff --git a/src/assets/i18n/fr.json5 b/src/assets/i18n/fr.json5 index 80566e589e..ba427292bc 100644 --- a/src/assets/i18n/fr.json5 +++ b/src/assets/i18n/fr.json5 @@ -718,6 +718,303 @@ // "admin.access-control.groups.form.return": "Back", "admin.access-control.groups.form.return": "Retour", + //"admin.reports.collections.title": "Collection Filter Report", + "admin.reports.collections.title": "Rapport de collections filtrées", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + "admin.reports.collections.breadcrumbs": "Collections filtrées", + + //"admin.reports.collections.head": "Collection Filter Report", + "admin.reports.collections.head": "Rapport de collections filtrées", + + //"admin.reports.button.show-collections": "Show Collections", + "admin.reports.button.show-collections": "Afficher les collections", + + //"admin.reports.collections.collections-report": "Collection Report", + "admin.reports.collections.collections-report": "Rapport des collections", + + //"admin.reports.collections.item-results": "Item Results", + "admin.reports.collections.item-results": "Éléments résultants", + + //"admin.reports.collections.community": "Community", + "admin.reports.collections.community": "Communauté", + + //"admin.reports.collections.collection": "Collection", + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + "admin.reports.collections.nb_items": "Nb. d'éléments", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + "admin.reports.collections.match_all_selected_filters": "Correspondant à tous les filtres sélectionnés", + + + //"admin.reports.items.title": "Metadata Query Report", + "admin.reports.items.title": "Rapport de requête de métadonnées", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + "admin.reports.items.breadcrumbs": "Requête de métadonnées", + + //"admin.reports.items.head": "Metadata Query Report", + "admin.reports.items.head": "Rapport de requête de métadonnées", + + //"admin.reports.items.run": "Run Item Query", + "admin.reports.items.run": "Exécuter la requête", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + "admin.reports.items.section.collectionSelector": "Sélecteur de collections", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + "admin.reports.items.section.metadataFieldQueries": "Requêtes sur les champs de métadonnées", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + "admin.reports.items.predefinedQueries": "Requêtes prédéfinies", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + "admin.reports.items.section.limitPaginateQueries": "Limiter/paginer les résultats", + + //"admin.reports.items.limit": "Limit/", + "admin.reports.items.limit": "Limite", + + //"admin.reports.items.limit": "Offset/", + "admin.reports.items.offset": "À partir de", + + //"admin.reports.items.wholeRepo": "Whole Repository", + "admin.reports.items.wholeRepo": "Tout le dépôt", + + //"admin.reports.items.anyField": "Any field", + "admin.reports.items.anyField": "Tous les champs", + + //"admin.reports.items.predicate.exists": "exists", + "admin.reports.items.predicate.exists": "existe", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + "admin.reports.items.predicate.doesNotExist": "n'existe pas", + + //"admin.reports.items.predicate.equals": "equals", + "admin.reports.items.predicate.equals": "est égal à", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + "admin.reports.items.predicate.doesNotEqual": "n'est pas égal à", + + //"admin.reports.items.predicate.like": "like", + "admin.reports.items.predicate.like": "est de forme (like)", + + //"admin.reports.items.predicate.notLike": "not like", + "admin.reports.items.predicate.notLike": "n'est pas de forme (not like)", + + //"admin.reports.items.predicate.contains": "contains", + "admin.reports.items.predicate.contains": "contient", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + "admin.reports.items.predicate.doesNotContain": "ne contient pas", + + //"admin.reports.items.predicate.matches": "matches", + "admin.reports.items.predicate.matches": "correspond à (matches)", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + "admin.reports.items.predicate.doesNotMatch": "ne correspond pas à (does not match)", + + //"admin.reports.items.preset.new": "New Query", + "admin.reports.items.preset.new": "Nouvelle requête", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + "admin.reports.items.preset.hasNoTitle": "Sans titre", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + "admin.reports.items.preset.hasNoIdentifierUri": "Sans dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + "admin.reports.items.preset.hasCompoundSubject": "A un sujet composite", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + "admin.reports.items.preset.hasCompoundAuthor": "A un dc.contributor.author composite", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + "admin.reports.items.preset.hasCompoundCreator": "A un dc.creator composite", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + "admin.reports.items.preset.hasUrlInDescription": "A un URL dans dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + "admin.reports.items.preset.hasFullTextInProvenance": "A des documents texte dans dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + "admin.reports.items.preset.hasNonFullTextInProvenance": "N'a pas de document texte dans dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + "admin.reports.items.preset.hasEmptyMetadata": "A des métadonnées vides", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + "admin.reports.items.preset.hasUnbreakingDataInDescription": "A du contenu insécable dans la description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + "admin.reports.items.preset.hasXmlEntityInMetadata": "A des entités XML dans les métadonnées", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ASCII character in metadata", + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "A des caractères non ASCII dans les métadonnées", + + //"admin.reports.items.number": "No.", + "admin.reports.items.number": "Nº", + + //"admin.reports.items.id": "UUID", + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + "admin.reports.items.title": "Titre", + + + //"admin.reports.commons.filters": "Filters", + "admin.reports.commons.filters": "Filtres", + + //"admin.reports.commons.additional-data": "Additional data to return", + "admin.reports.commons.additional-data": "Données additionnelles", + + //"admin.reports.commons.previous-page": "Prev Page", + "admin.reports.commons.previous-page": "Page précédente", + + //"admin.reports.commons.next-page": "Next Page", + "admin.reports.commons.next-page": "Page suivante", + + //"admin.reports.commons.page": "Page", + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + "admin.reports.commons.of": "de", + + //"admin.reports.commons.export": "Export for Metadata Update", + "admin.reports.commons.export": "Exporter les métadonnées", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + "admin.reports.commons.filters.deselect_all": "Désélectionner tous les filtres", + + //"admin.reports.commons.filters.select_all": "Select all filters", + "admin.reports.commons.filters.select_all": "Sélectionner tous les filtres", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + "admin.reports.commons.filters.matches_all": "Tous les filtres spécifiés", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + "admin.reports.commons.filters.property": "Filtres de propriétés d'éléments", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + "admin.reports.commons.filters.property.is_item": "Est un élément - toujours vrai", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + "admin.reports.commons.filters.property.is_withdrawn": "Éléments retirés", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + "admin.reports.commons.filters.property.is_not_withdrawn": "Éléments disponibles - Non retirés", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + "admin.reports.commons.filters.property.is_discoverable": "Éléments découvrables - Non privés", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + "admin.reports.commons.filters.property.is_not_discoverable": "Éléments non découvrables - Privés", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + "admin.reports.commons.filters.bitstream": "Filtres Bitstream de base", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + "admin.reports.commons.filters.bitstream.has_multiple_originals": "L'élément a plusieurs Bitstreams originaux", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + "admin.reports.commons.filters.bitstream.has_no_originals": "L'élément n'a pas de Bitstreams originaux", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + "admin.reports.commons.filters.bitstream.has_one_original": "L'élément a un seul Bitstream original", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + "admin.reports.commons.filters.bitstream_mime": "Filtres Bitstream par type MIME", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "L'élément a un Bitstream original de type document (PDF, Office, Text, HTML, XML, etc.)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + "admin.reports.commons.filters.bitstream_mime.has_image_original": "L'élément a un Bitstream original de type image", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "L'élément a d'autres types de Bitstream (ni document ni image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "L'élément a des Bitstreams originaux de types multiples (document, image, autres)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "L'élément a un Bitstream original PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "L'élément a un Bitstream original JPG", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "L'élément a un PDF anormalement petit", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "L'élément a un PDF anormalement grand", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "L'élément a un Bitstream sans élément TEXT", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + "admin.reports.commons.filters.mime": "Filtres de types MIME pris en charge", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + "admin.reports.commons.filters.mime.has_only_supp_image_type": "L'élément a des Bitstreams image pris en charge", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + "admin.reports.commons.filters.mime.has_unsupp_image_type": "L'élément a des Bitstreams image non pris en charge", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Les Bitstreams document de l'élément sont pris en charge", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "L'élément a des Bitstreams document non pris en charge", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + "admin.reports.commons.filters.bundle": "Filtres de Bitstreams de type Bundle", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "L'élément a un Bitstream dans un Bundle non pris en charge", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + "admin.reports.commons.filters.bundle.has_small_thumbnail": "L'élément a une vignette anormalement petite", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "L'élément a un Bitstream original sans vignette", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "L'élément a une vignette ayant un nom invalide (une vignette par original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "L'élément a une vignette non générée", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + "admin.reports.commons.filters.bundle.no_license": "L'élément n'a pas de licence", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + "admin.reports.commons.filters.bundle.has_license_documentation": "L'élément a de la documentation dans le Bundle de licence", + + //"admin.reports.commons.filters.permission": "Permission Filters", + "admin.reports.commons.filters.permission": "Filtres de permissions", + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + "admin.reports.commons.filters.permission.has_restricted_original": "L'élément a un Bitstream original à accès restreint", + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "L'élément a au moins un Bitstream original non accessible aux utilisateurs anonymes", + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "L'élément a une vignette à accès restreint", + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "L'élément a au moins une vignette non accessible aux utilisateurs anonymes", + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + "admin.reports.commons.filters.permission.has_restricted_metadata": "L'élément a des métadonnées à accès restreint", + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "L'élément a des métadonnées non accessibles aux utilisateurs anonymes", + // "admin.search.breadcrumbs": "Administrative Search", "admin.search.breadcrumbs": "Recherche Administrateur", @@ -3528,6 +3825,15 @@ // "menu.section.access_control_people": "People", "menu.section.access_control_people": "Utilisateurs", + //"menu.section.reports": "Reports", + "menu.section.reports": "Rapports", + + //"menu.section.reports.collections": "Filtered Collections", + "menu.section.reports.collections": "Collections filtrées", + + //"menu.section.reports.queries": "Metadata Query", + "menu.section.reports.queries": "Requête de métadonnées", + // "menu.section.admin_search": "Admin Search", "menu.section.admin_search": "Recherche Administrateur", @@ -3600,6 +3906,9 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "Section du menu relative au contrôle d'accès", + //"menu.section.icon.reports": "Reports menu section", + "menu.section.icon.reports": "Section du menu d'accès aux rapports", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "Section du menu relative à la recherche Administrateur", @@ -3699,6 +4008,9 @@ // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Ouvrir/Fermer section Contrôle d'accès", + //"menu.section.toggle.reports": "Toggle Reports section", + "menu.section.toggle.reports": "Ouvrir/Fermer section Rapports", + // "menu.section.toggle.control_panel": "Toggle Control Panel section", "menu.section.toggle.control_panel": "Ouvrir/Fermer section Panneau de configuration", diff --git a/src/assets/i18n/gd.json5 b/src/assets/i18n/gd.json5 index 929ab87d10..4d0e77c086 100644 --- a/src/assets/i18n/gd.json5 +++ b/src/assets/i18n/gd.json5 @@ -710,6 +710,409 @@ + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // "admin.search.breadcrumbs": "Administrative Search", "admin.search.breadcrumbs": "Rannsachadh Rianachd", @@ -3550,6 +3953,18 @@ + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + // "menu.section.admin_search": "Admin Search", "menu.section.admin_search": "Rannsachadh Rianachd", @@ -3629,6 +4044,10 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": " Earrann clàr-iùil Riaghladh Cothruim", + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "Earrann clàr-iùil rannsachadh rianachd", @@ -3735,6 +4154,9 @@ "menu.section.statistics_task": "Obair Staitistigs", + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Suids earrann Riaghladh Cothruim", diff --git a/src/assets/i18n/hi.json5 b/src/assets/i18n/hi.json5 index 68eb6c1f12..b4e23856bf 100644 --- a/src/assets/i18n/hi.json5 +++ b/src/assets/i18n/hi.json5 @@ -297,6 +297,413 @@ "admin.access-control.groups.table.edit.buttons.remove": "\"{{name}}\" हटाएं", + + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + + + "admin.curation-tasks.breadcrumbs": "प्रणाली क्यूरेशन कार्य", + "admin.access-control.groups.table.id": "पहचान", "admin.access-control.groups.table.members": "सदस्य", @@ -2463,6 +2870,20 @@ "menu.header.admin": "प्रबंधन", + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + + "menu.section.admin_search": "व्यवस्थापक खोज", + "menu.header.admin.description": "प्रबंधन मेनू", "menu.header.image.logo": "संग्रहालय चिन्ह", @@ -2511,6 +2932,12 @@ "menu.section.export": "निर्यात करें", + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + + "menu.section.icon.admin_search": "व्यवस्थापक खोज मेनू अनुभाग", + "menu.section.export_collection": "संग्रह", "menu.section.export_community": "समुदाय", @@ -2573,6 +3000,12 @@ "menu.section.pin": "साइडबार नत्थी करें", + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", + + "menu.section.toggle.access_control": "अभिगम नियंत्रण अनुभाग टॉगल करें", + "menu.section.processes": "प्रक्रियाएं", "menu.section.registries": "रजिस्ट्री", diff --git a/src/assets/i18n/hu.json5 b/src/assets/i18n/hu.json5 index afbfa25a13..e1ae33e85b 100644 --- a/src/assets/i18n/hu.json5 +++ b/src/assets/i18n/hu.json5 @@ -759,6 +759,409 @@ // TODO New key - Add a translation "admin.access-control.groups.form.tooltip.editGroup.addSubgroups": "To add or remove a Subgroup to/from this group, either click the 'Browse All' button or use the search bar below to search for users. Then click the plus icon for each user you wish to add in the list below, or the trash can icon for each user you wish to remove. The list below may have several pages: use the page controls below the list to navigate to the next pages. Once you are ready, save your changes by clicking the 'Save' button in the top section.", + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // "admin.search.breadcrumbs": "Administrative Search", "admin.search.breadcrumbs": "Adminisztratív keresés", @@ -4640,6 +5043,20 @@ + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + + + // "menu.section.admin_search": "Admin Search", "menu.section.admin_search": "Admin keresés", @@ -4718,10 +5135,13 @@ // TODO New key - Add a translation "menu.section.export_batch": "Batch Export (ZIP)", - // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "Hozzáférés kontroll menü felület", + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "Admin keresés menü felület", @@ -4839,6 +5259,10 @@ "menu.section.statistics_task": "Statisztikai feladatok", + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", + // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Váltás a Hozzáférés kontrol felületre", diff --git a/src/assets/i18n/it.json5 b/src/assets/i18n/it.json5 index ad2478ae61..0960b9fae1 100644 --- a/src/assets/i18n/it.json5 +++ b/src/assets/i18n/it.json5 @@ -3535,6 +3535,22 @@ // "item.truncatable-part.show-less": "Collapse", "item.truncatable-part.show-less": "Riduci", + // "item.qa-event-notification.check.notification-info": "There are {{num}} pending suggestions related to your account", + // TODO New key - Add a translation + "item.qa-event-notification.check.notification-info": "There are {{num}} pending suggestions related to your account", + + // "item.qa-event-notification-info.check.button": "View", + // TODO New key - Add a translation + "item.qa-event-notification-info.check.button": "View", + + // "mydspace.qa-event-notification.check.notification-info": "There are {{num}} pending suggestions related to your account", + // TODO New key - Add a translation + "mydspace.qa-event-notification.check.notification-info": "There are {{num}} pending suggestions related to your account", + + // "mydspace.qa-event-notification-info.check.button": "View", + // TODO New key - Add a translation + "mydspace.qa-event-notification-info.check.button": "View", + // "workflow-item.search.result.delete-supervision.modal.header": "Delete Supervision Order", "workflow-item.search.result.delete-supervision.modal.header": "Elimina l'ordine di supervisione", diff --git a/src/assets/i18n/ja.json5 b/src/assets/i18n/ja.json5 index 03323eb7ef..c74c8636c7 100644 --- a/src/assets/i18n/ja.json5 +++ b/src/assets/i18n/ja.json5 @@ -878,7 +878,408 @@ // TODO New key - Add a translation "admin.access-control.groups.form.return": "Return to groups", + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", // "admin.search.breadcrumbs": "Administrative Search", // TODO New key - Add a translation @@ -3878,6 +4279,18 @@ + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + // "menu.section.admin_search": "Admin Search", // TODO New key - Add a translation "menu.section.admin_search": "Admin Search", @@ -3980,6 +4393,10 @@ // TODO New key - Add a translation "menu.section.icon.access_control": "Access Control menu section", + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", // TODO New key - Add a translation "menu.section.icon.admin_search": "Admin search menu section", @@ -4113,6 +4530,9 @@ "menu.section.statistics_task": "Statistics Task", + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", // "menu.section.toggle.access_control": "Toggle Access Control section", // TODO New key - Add a translation diff --git a/src/assets/i18n/kk.json5 b/src/assets/i18n/kk.json5 index dbaa8078e2..d6ec02437c 100644 --- a/src/assets/i18n/kk.json5 +++ b/src/assets/i18n/kk.json5 @@ -748,6 +748,411 @@ + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + + + // "admin.search.breadcrumbs": "Administrative Search", "admin.search.breadcrumbs": "Әкімшілік іздеу", @@ -3809,6 +4214,18 @@ "menu.section.access_control_people": "Адамдар", + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + // "menu.section.admin_search": "Admin Search", "menu.section.admin_search": "Әкімші іздеу", @@ -3889,6 +4306,10 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "Қатынасты басқару мәзірі бөлімі", + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "Әкімші іздеу мәзірі бөлімі", @@ -4001,6 +4422,9 @@ "menu.section.statistics_task": "Статистика тапсырмасы", + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Қатынасты басқару бөлімін ауыстырып-қосқыш", diff --git a/src/assets/i18n/lv.json5 b/src/assets/i18n/lv.json5 index 3ceaac7fea..f5fb47777d 100644 --- a/src/assets/i18n/lv.json5 +++ b/src/assets/i18n/lv.json5 @@ -703,6 +703,409 @@ + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // "admin.search.breadcrumbs": "Administrative Search", "admin.search.breadcrumbs": "Administratīvā Meklēšana", @@ -3179,7 +3582,17 @@ // "menu.section.access_control_people": "People", "menu.section.access_control_people": "Personas", + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", // "menu.section.admin_search": "Admin Search", "menu.section.admin_search": "Administratora Meklēšana", @@ -3260,6 +3673,10 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "Piekļuves kontroles izvēlnes sadaļa", + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "Administratoru meklēšanas izvēlnes sadaļa", @@ -3365,6 +3782,9 @@ "menu.section.statistics_task": "Statistikas Uzdevumi", + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Pārslēgt Piekļuvas Kontronles sadaļu", diff --git a/src/assets/i18n/nl.json5 b/src/assets/i18n/nl.json5 index fc52543c38..6c8403b972 100644 --- a/src/assets/i18n/nl.json5 +++ b/src/assets/i18n/nl.json5 @@ -798,7 +798,408 @@ // TODO New key - Add a translation "admin.access-control.groups.form.return": "Return to groups", + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", // "admin.search.breadcrumbs": "Administrative Search", // TODO New key - Add a translation @@ -3450,6 +3851,15 @@ + // "menu.section.reports": "Reports", + "menu.section.reports": "Verslagen", + + // "menu.section.reports.collections": "Filtered Collections", + "menu.section.reports.collections": "Gefilterde collecties", + + // "menu.section.reports.queries": "Metadata Query", + "menu.section.reports.queries": "Metagegevensquery", + // "menu.section.admin_search": "Admin Search", // TODO New key - Add a translation "menu.section.admin_search": "Admin Search", @@ -3530,6 +3940,10 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "Menusectie toegangscontrole", + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", // TODO New key - Add a translation "menu.section.icon.admin_search": "Admin search menu section", @@ -3637,6 +4051,9 @@ "menu.section.statistics_task": "Statistiektaken", + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Sectie Toegangscontrole aan/uit", diff --git a/src/assets/i18n/pl.json5 b/src/assets/i18n/pl.json5 index 7a857ae4fd..951389e1e5 100644 --- a/src/assets/i18n/pl.json5 +++ b/src/assets/i18n/pl.json5 @@ -228,6 +228,410 @@ "admin.access-control.groups.form.subgroups-list.no-items": "Nie znaleziono grup z tą nazwą lub UUID", "admin.access-control.groups.form.subgroups-list.no-subgroups-yet": "Brak podgrup w grupie.", "admin.access-control.groups.form.return": "Powrót", + + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + "admin.search.breadcrumbs": "Wyszukiwanie administracyjne", "admin.search.collection.edit": "Edytuj", "admin.search.community.edit": "Edytuj", @@ -1112,6 +1516,19 @@ "menu.section.access_control_authorizations": "Dostępy", "menu.section.access_control_groups": "Grupy", "menu.section.access_control_people": "Użytkownicy", + + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + "menu.section.admin_search": "Wyszukiwanie administracyjne", "menu.section.browse_community": "Ten zbiór", "menu.section.browse_community_by_author": "Wg autorów", @@ -1135,6 +1552,11 @@ "menu.section.export_item": "Pozycja", "menu.section.export_metadata": "Metadane", "menu.section.icon.access_control": "Sekcja menu Uprawnienia", + + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + "menu.section.icon.admin_search": "Sekcja menu Wyszukiwanie administracyjne", "menu.section.icon.control_panel": "Sekcja menu Panel sterowania", "menu.section.icon.curation_tasks": "Sekcja menu Zadanie administracyjne", @@ -1167,6 +1589,11 @@ "menu.section.statistics": "Statystyki", "menu.section.statistics_task": "Zadanie statystyczne", "menu.section.toggle.access_control": "Przełącz sekcję Uprawnienia", + + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", + "menu.section.toggle.control_panel": "Przełącz sekcję Panel sterowania", "menu.section.toggle.curation_task": "Przełącz sekcję Zadanie kuratora", "menu.section.toggle.edit": "Przełącz sekcję Edytuj", diff --git a/src/assets/i18n/pt-BR.json5 b/src/assets/i18n/pt-BR.json5 index 5061c5a0e9..157da4c8a2 100644 --- a/src/assets/i18n/pt-BR.json5 +++ b/src/assets/i18n/pt-BR.json5 @@ -758,6 +758,409 @@ // "admin.access-control.groups.form.return": "Back", "admin.access-control.groups.form.return": "Voltar", + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // "admin.access-control.groups.form.tooltip.editGroupPage": "On this page, you can modify the properties and members of a group. In the top section, you can edit the group name and description, unless this is an admin group for a collection or community, in which case the group name and description are auto-generated and cannot be edited. In the following sections, you can edit group membership. See [the wiki](https://wiki.lyrasis.org/display/DSDOC7x/Create+or+manage+a+user+group) for more details.", (Auto-Translated) "admin.access-control.groups.form.tooltip.editGroupPage": "Nesta página, você pode modificar as propriedades e os membros de um grupo. Na seção superior, você pode editar o nome e a descrição do grupo, a menos que este seja um grupo de administração para uma coleção ou comunidade; nesse caso, o nome e a descrição do grupo são gerados automaticamente e não podem ser editados. Nas seções a seguir, você pode editar a associação ao grupo.Veja [o wiki] (https://wiki.lyrasis.org/display/DSDOC7x/Create+or+manage+a+user+group) para obter mais detalhes.", @@ -4215,6 +4618,15 @@ // "menu.section.access_control_people": "People", "menu.section.access_control_people": "Pessoas", + // "menu.section.reports": "Reports", + "menu.section.reports": "Relatórios", + + // "menu.section.reports.collections": "Filtered Collections", + "menu.section.reports.collections": "Coleções filtradas", + + // "menu.section.reports.queries": "Metadata Query", + "menu.section.reports.queries": "Consultas de metadados", + // "menu.section.admin_search": "Admin Search", "menu.section.admin_search": "Pesquisa Administrativa", @@ -4293,6 +4705,10 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "Seção do menu Controle de Acesso", + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "Seção do menu de busca administrativa", @@ -4392,6 +4808,10 @@ // "menu.section.statistics_task": "Statistics Task", "menu.section.statistics_task": "Tarefas de Estatísticas", + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", + // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Alternar Seção Controle de Acesso", diff --git a/src/assets/i18n/pt-PT.json5 b/src/assets/i18n/pt-PT.json5 index 328cb20810..9e6d678622 100644 --- a/src/assets/i18n/pt-PT.json5 +++ b/src/assets/i18n/pt-PT.json5 @@ -737,6 +737,409 @@ // "admin.access-control.groups.form.return": "Back", "admin.access-control.groups.form.return": "Voltar", + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // "admin.access-control.groups.form.tooltip.editGroupPage": "On this page, you can modify the properties and members of a group. In the top section, you can edit the group name and description, unless this is an admin group for a collection or community, in which case the group name and description are auto-generated and cannot be edited. In the following sections, you can edit group membership. See [the wiki](https://wiki.lyrasis.org/display/DSDOC7x/Create+or+manage+a+user+group) for more details.", "admin.access-control.groups.form.tooltip.editGroupPage": "Nesta página, pode modificar as propriedades e os membros de um grupo. Na secção superior, pode editar o nome e a descrição do grupo, a menos que se trate de um grupo administrativo para uma coleção ou comunidade, em que o nome e a descrição do grupo são auto-gerados e não podem ser editados. Nas seções seguintes, pode editar o nome e a descrição do grupo. Ver [wiki](https://wiki.lyrasis.org/display/DSDOC7x/Create+ou+gerir+a+utilizador+grupo) para mais detalhes.", @@ -4163,6 +4566,17 @@ // "menu.section.access_control_people": "People", "menu.section.access_control_people": "Pessoas", + + + // "menu.section.reports": "Reports", + "menu.section.reports": "Relatórios", + + // "menu.section.reports.collections": "Filtered Collections", + "menu.section.reports.collections": "Coleções filtradas", + + // "menu.section.reports.queries": "Metadata Query", + "menu.section.reports.queries": "Consultas de metadados", + // "menu.section.admin_search": "Admin Search", "menu.section.admin_search": "Pesquisa administrativa", @@ -4238,6 +4652,10 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "Secção do menu controle de acesso", + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "Secção do menu pesquisa administrativa", @@ -4335,6 +4753,13 @@ "menu.section.statistics": "Estatísticas", // "menu.section.statistics_task": "Statistics Task", + "menu.section.statistics_task": "Tarefas de Estatísticas", + + + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", + "menu.section.statistics_task": "Tarefa de estatísticas", // "menu.section.toggle.access_control": "Toggle Access Control section", diff --git a/src/assets/i18n/sv.json5 b/src/assets/i18n/sv.json5 index d2fe72536c..8c3482764f 100644 --- a/src/assets/i18n/sv.json5 +++ b/src/assets/i18n/sv.json5 @@ -721,6 +721,410 @@ "admin.access-control.groups.form.return": "Tillbaka", + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + + // "admin.search.breadcrumbs": "Administrative Search", "admin.search.breadcrumbs": "Admin sökning", @@ -3618,6 +4022,18 @@ // "menu.section.access_control_people": "People", "menu.section.access_control_people": "EPersoner", + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + // "menu.section.admin_search": "Admin Search", @@ -3699,6 +4115,10 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "Åtkomstkontroll - meny", + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "Admin sök - meny", @@ -3805,6 +4225,9 @@ "menu.section.statistics_task": "Statistik uppgift", + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Växla till åtkomstkontroll", diff --git a/src/assets/i18n/sw.json5 b/src/assets/i18n/sw.json5 index d2d663cdc5..13a1f07b70 100644 --- a/src/assets/i18n/sw.json5 +++ b/src/assets/i18n/sw.json5 @@ -878,7 +878,408 @@ // TODO New key - Add a translation "admin.access-control.groups.form.return": "Return to groups", + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", // "admin.search.breadcrumbs": "Administrative Search", // TODO New key - Add a translation @@ -3878,6 +4279,18 @@ + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + // "menu.section.admin_search": "Admin Search", // TODO New key - Add a translation "menu.section.admin_search": "Admin Search", @@ -3980,6 +4393,10 @@ // TODO New key - Add a translation "menu.section.icon.access_control": "Access Control menu section", + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", // TODO New key - Add a translation "menu.section.icon.admin_search": "Admin search menu section", @@ -4113,6 +4530,9 @@ "menu.section.statistics_task": "Statistics Task", + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", // "menu.section.toggle.access_control": "Toggle Access Control section", // TODO New key - Add a translation diff --git a/src/assets/i18n/tr.json5 b/src/assets/i18n/tr.json5 index 75bc5c9a36..e23e58cdd9 100644 --- a/src/assets/i18n/tr.json5 +++ b/src/assets/i18n/tr.json5 @@ -663,6 +663,407 @@ // "admin.access-control.groups.form.return": "Return to groups", "admin.access-control.groups.form.return": "Gruplara dön", + //"admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + //"admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + //"admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + //"admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + //"admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + //"admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + //"admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + //"admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + //"admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + //"admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + //"admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + //"admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + //"admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + //"admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + //"admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + //"admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + //"admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + //"admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + //"admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + //"admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + //"admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + //"admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + //"admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + //"admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + //"admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + //"admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + //"admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + //"admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + //"admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + //"admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + //"admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + //"admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + //"admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + //"admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + //"admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + //"admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + //"admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + //"admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + //"admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + //"admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + //"admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + //"admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + //"admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + //"admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + //"admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + //"admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + //"admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + //"admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + //"admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + //"admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + //"admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + //"admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + //"admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + //"admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + //"admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + //"admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + //"admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + //"admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + //"admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + //"admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + //"admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + //"admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + //"admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + //"admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + //"admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + //"admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.all_filters.tooltip": "This filter includes all items that matched ALL specified filters", + + //"admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + //"admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + + //"admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + //"admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + //"admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + //"admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + //"admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + //"admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + //"admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + //"admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + //"admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + //"admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + //"admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + //"admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + //"admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + //"admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + //"admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + //"admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + //"admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + //"admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + //"admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + //"admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + //"admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + //"admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + //"admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + + //"admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + // "admin.search.breadcrumbs": "Administrative Search", @@ -2950,7 +3351,17 @@ // "menu.section.access_control_people": "People", "menu.section.access_control_people": "Kişiler", + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", // "menu.section.admin_search": "Admin Search", "menu.section.admin_search": "Yönetici araması", @@ -3031,6 +3442,10 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "Erişim Kontrolü menüsü bölümü", + //"menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "Yönetici arama menüsü bölümü", @@ -3134,6 +3549,9 @@ "menu.section.statistics_task": "İstatistiksel Görev", + //"menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Erişim kontrolü bölümünü aç/kapat", diff --git a/src/assets/i18n/uk.json5 b/src/assets/i18n/uk.json5 index fae770b6bd..63377d8e51 100644 --- a/src/assets/i18n/uk.json5 +++ b/src/assets/i18n/uk.json5 @@ -699,6 +699,407 @@ + // "admin.reports.collections.title": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.title": "Collection Filter Report", + + // "admin.reports.collections.breadcrumbs": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.breadcrumbs": "Collection Filter Report", + + // "admin.reports.collections.head": "Collection Filter Report", + // TODO New key - Add a translation + "admin.reports.collections.head": "Collection Filter Report", + + // "admin.reports.button.show-collections": "Show Collections", + // TODO New key - Add a translation + "admin.reports.button.show-collections": "Show Collections", + + // "admin.reports.collections.collections-report": "Collection Report", + // TODO New key - Add a translation + "admin.reports.collections.collections-report": "Collection Report", + + // "admin.reports.collections.item-results": "Item Results", + // TODO New key - Add a translation + "admin.reports.collections.item-results": "Item Results", + + // "admin.reports.collections.community": "Community", + // TODO New key - Add a translation + "admin.reports.collections.community": "Community", + + // "admin.reports.collections.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.collections.collection": "Collection", + + // "admin.reports.collections.nb_items": "Nb. Items", + // TODO New key - Add a translation + "admin.reports.collections.nb_items": "Nb. Items", + + // "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + // TODO New key - Add a translation + "admin.reports.collections.match_all_selected_filters": "Matching all selected filters", + + + // "admin.reports.items.title": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.title": "Metadata Query Report", + + // "admin.reports.items.breadcrumbs": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.breadcrumbs": "Metadata Query Report", + + // "admin.reports.items.head": "Metadata Query Report", + // TODO New key - Add a translation + "admin.reports.items.head": "Metadata Query Report", + + // "admin.reports.items.run": "Run Item Query", + // TODO New key - Add a translation + "admin.reports.items.run": "Run Item Query", + + // "admin.reports.items.section.collectionSelector": "Collection Selector", + // TODO New key - Add a translation + "admin.reports.items.section.collectionSelector": "Collection Selector", + + // "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + // TODO New key - Add a translation + "admin.reports.items.section.metadataFieldQueries": "Metadata Field Queries", + + // "admin.reports.items.predefinedQueries": "Predefined Queries", + // TODO New key - Add a translation + "admin.reports.items.predefinedQueries": "Predefined Queries", + + // "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + // TODO New key - Add a translation + "admin.reports.items.section.limitPaginateQueries": "Limit/Paginate Queries", + + // "admin.reports.items.limit": "Limit/", + // TODO New key - Add a translation + "admin.reports.items.limit": "Limit/", + + // "admin.reports.items.wholeRepo": "Whole Repository", + // TODO New key - Add a translation + "admin.reports.items.wholeRepo": "Whole Repository", + + // "admin.reports.items.anyField": "Any field", + // TODO New key - Add a translation + "admin.reports.items.anyField": "Any field", + + // "admin.reports.items.predicate.exists": "exists", + // TODO New key - Add a translation + "admin.reports.items.predicate.exists": "exists", + + // "admin.reports.items.predicate.doesNotExist": "does not exist", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotExist": "does not exist", + + // "admin.reports.items.predicate.equals": "equals", + // TODO New key - Add a translation + "admin.reports.items.predicate.equals": "equals", + + // "admin.reports.items.predicate.doesNotEqual": "does not equal", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotEqual": "does not equal", + + // "admin.reports.items.predicate.like": "like", + // TODO New key - Add a translation + "admin.reports.items.predicate.like": "like", + + // "admin.reports.items.predicate.notLike": "not like", + // TODO New key - Add a translation + "admin.reports.items.predicate.notLike": "not like", + + // "admin.reports.items.predicate.contains": "contains", + // TODO New key - Add a translation + "admin.reports.items.predicate.contains": "contains", + + // "admin.reports.items.predicate.doesNotContain": "does not contain", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotContain": "does not contain", + + // "admin.reports.items.predicate.matches": "matches", + // TODO New key - Add a translation + "admin.reports.items.predicate.matches": "matches", + + // "admin.reports.items.predicate.doesNotMatch": "does not match", + // TODO New key - Add a translation + "admin.reports.items.predicate.doesNotMatch": "does not match", + + // "admin.reports.items.preset.new": "New Query", + // TODO New key - Add a translation + "admin.reports.items.preset.new": "New Query", + + // "admin.reports.items.preset.hasNoTitle": "Has No Title", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoTitle": "Has No Title", + + // "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNoIdentifierUri": "Has No dc.identifier.uri", + + // "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundSubject": "Has compound subject", + + // "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundAuthor": "Has compound dc.contributor.author", + + // "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + // TODO New key - Add a translation + "admin.reports.items.preset.hasCompoundCreator": "Has compound dc.creator", + + // "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUrlInDescription": "Has URL in dc.description", + + // "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasFullTextInProvenance": "Has full text in dc.description.provenance", + + // "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonFullTextInProvenance": "Has non-full text in dc.description.provenance", + + // "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasEmptyMetadata": "Has empty metadata", + + // "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + // TODO New key - Add a translation + "admin.reports.items.preset.hasUnbreakingDataInDescription": "Has unbreaking metadata in description", + + // "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasXmlEntityInMetadata": "Has XML entity in metadata", + + // "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + // TODO New key - Add a translation + "admin.reports.items.preset.hasNonAsciiCharInMetadata": "Has non-ascii character in metadata", + + // "admin.reports.items.number": "No.", + // TODO New key - Add a translation + "admin.reports.items.number": "No.", + + // "admin.reports.items.id": "UUID", + // TODO New key - Add a translation + "admin.reports.items.id": "UUID", + + // "admin.reports.items.collection": "Collection", + // TODO New key - Add a translation + "admin.reports.items.collection": "Collection", + + // "admin.reports.items.handle": "URI", + // TODO New key - Add a translation + "admin.reports.items.handle": "URI", + + // "admin.reports.items.title": "Title", + // TODO New key - Add a translation + "admin.reports.items.title": "Title", + + + // "admin.reports.commons.filters": "Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters": "Filters", + + // "admin.reports.commons.additional-data": "Additional data to return", + // TODO New key - Add a translation + "admin.reports.commons.additional-data": "Additional data to return", + + // "admin.reports.commons.previous-page": "Prev Page", + // TODO New key - Add a translation + "admin.reports.commons.previous-page": "Prev Page", + + // "admin.reports.commons.next-page": "Next Page", + // TODO New key - Add a translation + "admin.reports.commons.next-page": "Next Page", + + // "admin.reports.commons.page": "Page", + // TODO New key - Add a translation + "admin.reports.commons.page": "Page", + + // "admin.reports.commons.of": "of", + // TODO New key - Add a translation + "admin.reports.commons.of": "of", + + // "admin.reports.commons.export": "Export for Metadata Update", + // TODO New key - Add a translation + "admin.reports.commons.export": "Export for Metadata Update", + + // "admin.reports.commons.filters.deselect_all": "Deselect all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.deselect_all": "Deselect all filters", + + // "admin.reports.commons.filters.select_all": "Select all filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.select_all": "Select all filters", + + // "admin.reports.commons.filters.matches_all": "Matches all specified filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.matches_all": "Matches all specified filters", + + + // "admin.reports.commons.filters.property": "Item Property Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.property": "Item Property Filters", + + // "admin.reports.commons.filters.property.is_item": "Is Item - always true", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_item": "Is Item - always true", + + // "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_withdrawn": "Withdrawn Items", + + // "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_withdrawn": "Available Items - Not Withdrawn", + + // "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_discoverable": "Discoverable Items - Not Private", + + // "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + // TODO New key - Add a translation + "admin.reports.commons.filters.property.is_not_discoverable": "Not Discoverable - Private Item", + + // "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + // "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + + // "admin.reports.commons.filters.bitstream.has_no_originals": "Item has No Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + // "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream.has_one_original": "Item has One Original Bitstream", + + // "admin.reports.commons.filters.bitstream_mime": "Bitstream Filters by MIME Type", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream": "Basic Bitstream Filters", + + // "admin.reports.commons.filters.bitstream.has_multiple_originals": "Item has Multiple Original Bitstreams", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_original": "Item has a Doc Original Bitstream (PDF, Office, Text, HTML, XML, etc)", + + // "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_image_original": "Item has an Image Original Bitstream", + + // "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "Has Other Bitstream Types (not Doc or Image)", + + // "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "Item has multiple types of Original Bitstreams (Doc, Image, Other)", + + // "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "Item has a PDF Original Bitstream", + + // "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "Item has JPG Original Bitstream", + + // "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "Has unusually small PDF", + + // "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "Has unusually large PDF", + + // "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + // TODO New key - Add a translation + "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "Has document bitstream without TEXT item", + + // "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime": "Supported MIME Type Filters", + + // "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_image_type": "Item Image Bitstreams are Supported", + + // "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_image_type": "Item has Image Bitstream that is Unsupported", + + // "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_only_supp_doc_type": "Item Document Bitstreams are Supported", + + // "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + // TODO New key - Add a translation + "admin.reports.commons.filters.mime.has_unsupp_doc_type": "Item has Document Bitstream that is Unsupported", + + // "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle": "Bitstream Bundle Filters", + + // "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_unsupported_bundle": "Has bitstream in an unsupported bundle", + + // "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_small_thumbnail": "Has unusually small thumbnail", + + // "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "Has original bitstream without thumbnail", + + // "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "Has invalid thumbnail name (assumes one thumbnail for each original)", + + // "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_non_generated_thumb": "Has non-generated thumbnail", + + // "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.no_license": "Doesn't have a license", + + // "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + // TODO New key - Add a translation + "admin.reports.commons.filters.bundle.has_license_documentation": "Has documentation in the license bundle", + + // "admin.reports.commons.filters.permission": "Permission Filters", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission": "Permission Filters", + + // "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original": "Item has Restricted Original Bitstream", + + // "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "Item has at least one original bitstream that is not accessible to Anonymous user", + + // "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + // "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + + // "admin.reports.commons.filters.permission.has_restricted_metadata": "Item has Restricted Metadata", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_thumbnail": "Item has Restricted Thumbnail", + + // "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "Item has at least one thumbnail that is not accessible to Anonymous user", + // TODO New key - Add a translation + "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "Item has metadata that is not accessible to Anonymous user", + + + // "admin.search.breadcrumbs": "Administrative Search", "admin.search.breadcrumbs": "Пошук адміністратора", @@ -3072,6 +3473,18 @@ + // "menu.section.reports": "Reports", + // TODO New key - Add a translation + "menu.section.reports": "Reports", + + // "menu.section.reports.collections": "Filtered Collections", + // TODO New key - Add a translation + "menu.section.reports.collections": "Filtered Collections", + + // "menu.section.reports.queries": "Metadata Query", + // TODO New key - Add a translation + "menu.section.reports.queries": "Metadata Query", + // "menu.section.admin_search": "Admin Search", "menu.section.admin_search": "Пошук адміністратора", @@ -3151,6 +3564,10 @@ // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "Меню контролю доступу", + // "menu.section.icon.reports": "Reports menu section", + // TODO New key - Add a translation + "menu.section.icon.reports": "Reports menu section", + // "menu.section.icon.admin_search": "Admin search menu section", "menu.section.icon.admin_search": "Меню пошуку адміна", @@ -3260,6 +3677,10 @@ // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "Переключити розділ контролю доступу", + // "menu.section.toggle.reports": "Toggle Reports section", + // TODO New key - Add a translation + "menu.section.toggle.reports": "Toggle Reports section", + // "menu.section.toggle.control_panel": "Toggle Control Panel section", "menu.section.toggle.control_panel": "Переключити панель контролю доступу", diff --git a/src/assets/images/n-coar.png b/src/assets/images/n-coar.png new file mode 100644 index 0000000000..5c4c741572 Binary files /dev/null and b/src/assets/images/n-coar.png differ diff --git a/src/assets/images/qa-DSpaceUsers-logo.png b/src/assets/images/qa-DSpaceUsers-logo.png new file mode 100644 index 0000000000..40b59feeaa Binary files /dev/null and b/src/assets/images/qa-DSpaceUsers-logo.png differ diff --git a/src/assets/images/qa-coar-notify-logo.png b/src/assets/images/qa-coar-notify-logo.png new file mode 100644 index 0000000000..0ba021dfd2 Binary files /dev/null and b/src/assets/images/qa-coar-notify-logo.png differ diff --git a/src/assets/images/qa-openaire-logo.png b/src/assets/images/qa-openaire-logo.png new file mode 100644 index 0000000000..359fd73b84 Binary files /dev/null and b/src/assets/images/qa-openaire-logo.png differ diff --git a/src/config/advance-search-config.interface.ts b/src/config/advance-search-config.interface.ts new file mode 100644 index 0000000000..092dc008fc --- /dev/null +++ b/src/config/advance-search-config.interface.ts @@ -0,0 +1,4 @@ +export interface AdvancedSearchConfig { + enabled: boolean; + filter: string[]; +} diff --git a/src/config/app-config.interface.ts b/src/config/app-config.interface.ts index 51a116fa70..3f432bfcad 100644 --- a/src/config/app-config.interface.ts +++ b/src/config/app-config.interface.ts @@ -25,7 +25,7 @@ import { MarkdownConfig } from './markdown-config.interface'; import { FilterVocabularyConfig } from './filter-vocabulary-config'; import { DiscoverySortConfig } from './discovery-sort.config'; import { QualityAssuranceConfig } from './quality-assurance.config'; - +import { SearchConfig } from './search-page-config.interface'; interface AppConfig extends Config { ui: UIServerConfig; rest: ServerConfig; @@ -54,6 +54,7 @@ interface AppConfig extends Config { vocabularies: FilterVocabularyConfig[]; comcolSelectionSort: DiscoverySortConfig; qualityAssuranceConfig: QualityAssuranceConfig; + search: SearchConfig; } /** diff --git a/src/config/default-app-config.ts b/src/config/default-app-config.ts index ae5c6c1d00..9ba5ee9a35 100644 --- a/src/config/default-app-config.ts +++ b/src/config/default-app-config.ts @@ -24,8 +24,8 @@ import { MarkdownConfig } from './markdown-config.interface'; import { FilterVocabularyConfig } from './filter-vocabulary-config'; import { DiscoverySortConfig } from './discovery-sort.config'; import { CommunityPageConfig } from './community-page-config.interface'; -import {QualityAssuranceConfig} from './quality-assurance.config'; - +import { QualityAssuranceConfig } from './quality-assurance.config'; +import { SearchConfig } from './search-page-config.interface'; export class DefaultAppConfig implements AppConfig { production = false; @@ -498,4 +498,12 @@ export class DefaultAppConfig implements AppConfig { }, pageSize: 5, }; + + + search: SearchConfig = { + advancedFilters: { + enabled: false, + filter: ['title', 'author', 'subject', 'entityType'] + } + }; } diff --git a/src/config/search-page-config.interface.ts b/src/config/search-page-config.interface.ts new file mode 100644 index 0000000000..70575c0601 --- /dev/null +++ b/src/config/search-page-config.interface.ts @@ -0,0 +1,11 @@ +import { Config } from './config.interface'; +import { AdvancedSearchConfig } from './advance-search-config.interface'; +export interface SearchConfig extends Config { + + /** + * List of standard filter to select in adding advanced Search + * Used by {@link UploadBitstreamComponent}. + */ + advancedFilters: AdvancedSearchConfig; + +} diff --git a/src/environments/environment.test.ts b/src/environments/environment.test.ts index e0cf1eb207..6f3ab32fa9 100644 --- a/src/environments/environment.test.ts +++ b/src/environments/environment.test.ts @@ -334,5 +334,13 @@ export const environment: BuildConfig = { } ], - suggestion: [] + suggestion: [], + + search: { + advancedFilters: { + enabled: false, + filter: ['title', 'author', 'subject', 'entityType'] + } + } + }; diff --git a/src/styles/_custom_variables.scss b/src/styles/_custom_variables.scss index ce776bb1ac..0dd1fd8e97 100644 --- a/src/styles/_custom_variables.scss +++ b/src/styles/_custom_variables.scss @@ -96,6 +96,7 @@ --ds-footer-padding: 0; --ds-footer-padding-bottom: 0; --ds-footer-logo-height: 50px; + --ds-footer-n-coar-height: 20px; --ds-home-news-link-color: #{$ds-home-news-link-color}; --ds-home-news-link-hover-color: #{darken($ds-home-news-link-color, 15%)}; @@ -137,6 +138,8 @@ --ds-item-page-img-field-default-inline-height: 24px; + --ds-qa-logo-width: 100px; + --ds-process-overview-table-nb-processes-badge-size: 0.5em; --ds-process-overview-table-id-column-width: 120px; --ds-process-overview-table-name-column-width: auto; diff --git a/src/themes/custom/lazy-theme.module.ts b/src/themes/custom/lazy-theme.module.ts index d2bac663b4..14bf19ab96 100644 --- a/src/themes/custom/lazy-theme.module.ts +++ b/src/themes/custom/lazy-theme.module.ts @@ -160,7 +160,6 @@ import {UserMenuComponent} from './app/shared/auth-nav-menu/user-menu/user-menu. import { BrowseByComponent } from './app/shared/browse-by/browse-by.component'; import { RegisterEmailFormComponent } from './app/register-email-form/register-email-form.component'; - const DECLARATIONS = [ FileSectionComponent, HomePageComponent, @@ -305,7 +304,7 @@ const DECLARATIONS = [ NgxGalleryModule, FormModule, RequestCopyModule, - NotificationsModule + NotificationsModule, ], declarations: DECLARATIONS, }) diff --git a/src/themes/dspace/app/navbar/navbar.component.html b/src/themes/dspace/app/navbar/navbar.component.html index d828206e7a..f1c8c66847 100644 --- a/src/themes/dspace/app/navbar/navbar.component.html +++ b/src/themes/dspace/app/navbar/navbar.component.html @@ -1,5 +1,5 @@ - +