From be6dbdec66e6caf000c966a2e1e30f3acf199458 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Mon, 2 Oct 2023 13:31:25 +0200 Subject: [PATCH 0001/1286] 107155: Allow caching null objects --- src/app/core/cache/object-cache.reducer.ts | 31 +++++++++++-------- src/app/core/cache/object-cache.service.ts | 16 +++++++--- .../dspace-rest-response-parsing.service.ts | 7 +++-- src/app/core/index/index.effects.ts | 4 +-- 4 files changed, 36 insertions(+), 22 deletions(-) diff --git a/src/app/core/cache/object-cache.reducer.ts b/src/app/core/cache/object-cache.reducer.ts index dc3f50db68..7f389344fb 100644 --- a/src/app/core/cache/object-cache.reducer.ts +++ b/src/app/core/cache/object-cache.reducer.ts @@ -166,20 +166,25 @@ export function objectCacheReducer(state = initialState, action: ObjectCacheActi * the new state, with the object added, or overwritten. */ function addToObjectCache(state: ObjectCacheState, action: AddToObjectCacheAction): ObjectCacheState { - const existing = state[action.payload.objectToCache._links.self.href] || {} as any; + const cacheLink = hasValue(action.payload.objectToCache) ? action.payload.objectToCache._links.self.href : action.payload.alternativeLink; + const existing = state[cacheLink] || {} as any; const newAltLinks = hasValue(action.payload.alternativeLink) ? [action.payload.alternativeLink] : []; - return Object.assign({}, state, { - [action.payload.objectToCache._links.self.href]: { - data: action.payload.objectToCache, - timeCompleted: action.payload.timeCompleted, - msToLive: action.payload.msToLive, - requestUUIDs: [action.payload.requestUUID, ...(existing.requestUUIDs || [])], - dependentRequestUUIDs: existing.dependentRequestUUIDs || [], - isDirty: isNotEmpty(existing.patches), - patches: existing.patches || [], - alternativeLinks: [...(existing.alternativeLinks || []), ...newAltLinks] - } as ObjectCacheEntry - }); + if (hasValue(cacheLink)) { + return Object.assign({}, state, { + [cacheLink]: { + data: action.payload.objectToCache, + timeCompleted: action.payload.timeCompleted, + msToLive: action.payload.msToLive, + requestUUIDs: [action.payload.requestUUID, ...(existing.requestUUIDs || [])], + dependentRequestUUIDs: existing.dependentRequestUUIDs || [], + isDirty: isNotEmpty(existing.patches), + patches: existing.patches || [], + alternativeLinks: [...(existing.alternativeLinks || []), ...newAltLinks] + } as ObjectCacheEntry + }); + } else { + return state; + } } /** diff --git a/src/app/core/cache/object-cache.service.ts b/src/app/core/cache/object-cache.service.ts index 9ca0216210..0330a03f02 100644 --- a/src/app/core/cache/object-cache.service.ts +++ b/src/app/core/cache/object-cache.service.ts @@ -63,7 +63,9 @@ export class ObjectCacheService { * An optional alternative link to this object */ add(object: CacheableObject, msToLive: number, requestUUID: string, alternativeLink?: string): void { - object = this.linkService.removeResolvedLinks(object); // Ensure the object we're storing has no resolved links + if (hasValue(object)) { + object = this.linkService.removeResolvedLinks(object); // Ensure the object we're storing has no resolved links + } this.store.dispatch(new AddToObjectCacheAction(object, new Date().getTime(), msToLive, requestUUID, alternativeLink)); } @@ -139,11 +141,15 @@ export class ObjectCacheService { } ), map((entry: ObjectCacheEntry) => { - const type: GenericConstructor = getClassForType((entry.data as any).type); - if (typeof type !== 'function') { - throw new Error(`${type} is not a valid constructor for ${JSON.stringify(entry.data)}`); + if (hasValue(entry.data)) { + const type: GenericConstructor = getClassForType((entry.data as any).type); + if (typeof type !== 'function') { + throw new Error(`${type} is not a valid constructor for ${JSON.stringify(entry.data)}`); + } + return Object.assign(new type(), entry.data) as T; + } else { + return null; } - return Object.assign(new type(), entry.data) as T; }) ); } diff --git a/src/app/core/data/dspace-rest-response-parsing.service.ts b/src/app/core/data/dspace-rest-response-parsing.service.ts index 500afc4aff..2f79edd129 100644 --- a/src/app/core/data/dspace-rest-response-parsing.service.ts +++ b/src/app/core/data/dspace-rest-response-parsing.service.ts @@ -109,6 +109,9 @@ export class DspaceRestResponseParsingService implements ResponseParsingService if (hasValue(match)) { embedAltUrl = new URLCombiner(embedAltUrl, `?size=${match.size}`).toString(); } + if (data._embedded[property] == null) { + this.addToObjectCache(null, request, data, embedAltUrl); + } this.process(data._embedded[property], request, embedAltUrl); }); } @@ -226,7 +229,7 @@ export class DspaceRestResponseParsingService implements ResponseParsingService * @param alternativeURL an alternative url that can be used to retrieve the object */ addToObjectCache(co: CacheableObject, request: RestRequest, data: any, alternativeURL?: string): void { - if (!isCacheableObject(co)) { + if (hasValue(co) && !isCacheableObject(co)) { const type = hasValue(data) && hasValue(data.type) ? data.type : 'object'; let dataJSON: string; if (hasValue(data._embedded)) { @@ -240,7 +243,7 @@ export class DspaceRestResponseParsingService implements ResponseParsingService return; } - if (alternativeURL === co._links.self.href) { + if (hasValue(co) && alternativeURL === co._links.self.href) { alternativeURL = undefined; } diff --git a/src/app/core/index/index.effects.ts b/src/app/core/index/index.effects.ts index 18d639023f..9ec013813d 100644 --- a/src/app/core/index/index.effects.ts +++ b/src/app/core/index/index.effects.ts @@ -27,7 +27,7 @@ export class UUIDIndexEffects { addObject$ = createEffect(() => this.actions$ .pipe( ofType(ObjectCacheActionTypes.ADD), - filter((action: AddToObjectCacheAction) => hasValue(action.payload.objectToCache.uuid)), + filter((action: AddToObjectCacheAction) => hasValue(action.payload.objectToCache) && hasValue(action.payload.objectToCache.uuid)), map((action: AddToObjectCacheAction) => { return new AddToIndexAction( IndexName.OBJECT, @@ -46,7 +46,7 @@ export class UUIDIndexEffects { ofType(ObjectCacheActionTypes.ADD), map((action: AddToObjectCacheAction) => { const alternativeLink = action.payload.alternativeLink; - const selfLink = action.payload.objectToCache._links.self.href; + const selfLink = hasValue(action.payload.objectToCache) ? action.payload.objectToCache._links.self.href : alternativeLink; if (hasValue(alternativeLink) && alternativeLink !== selfLink) { return new AddToIndexAction( IndexName.ALTERNATIVE_OBJECT_LINK, From 984c9bfc2a2271e65190e02902ea0589dcfe6c4f Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Thu, 26 Oct 2023 16:33:14 +0200 Subject: [PATCH 0002/1286] 107155: Allow caching of embedded objects without selflink --- src/app/core/cache/object-cache.reducer.ts | 2 +- src/app/core/data/dspace-rest-response-parsing.service.ts | 4 ++++ src/app/core/index/index.effects.ts | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/app/core/cache/object-cache.reducer.ts b/src/app/core/cache/object-cache.reducer.ts index 7f389344fb..21dc729f1b 100644 --- a/src/app/core/cache/object-cache.reducer.ts +++ b/src/app/core/cache/object-cache.reducer.ts @@ -166,7 +166,7 @@ export function objectCacheReducer(state = initialState, action: ObjectCacheActi * the new state, with the object added, or overwritten. */ function addToObjectCache(state: ObjectCacheState, action: AddToObjectCacheAction): ObjectCacheState { - const cacheLink = hasValue(action.payload.objectToCache) ? action.payload.objectToCache._links.self.href : action.payload.alternativeLink; + const cacheLink = hasValue(action.payload.objectToCache?._links?.self) ? action.payload.objectToCache._links.self.href : action.payload.alternativeLink; const existing = state[cacheLink] || {} as any; const newAltLinks = hasValue(action.payload.alternativeLink) ? [action.payload.alternativeLink] : []; if (hasValue(cacheLink)) { diff --git a/src/app/core/data/dspace-rest-response-parsing.service.ts b/src/app/core/data/dspace-rest-response-parsing.service.ts index 2f79edd129..c0e1c70cae 100644 --- a/src/app/core/data/dspace-rest-response-parsing.service.ts +++ b/src/app/core/data/dspace-rest-response-parsing.service.ts @@ -110,7 +110,11 @@ export class DspaceRestResponseParsingService implements ResponseParsingService embedAltUrl = new URLCombiner(embedAltUrl, `?size=${match.size}`).toString(); } if (data._embedded[property] == null) { + // Embedded object is null, meaning it exists (not undefined), but had an empty response (204) -> cache it as null this.addToObjectCache(null, request, data, embedAltUrl); + } else if (!isCacheableObject(data._embedded[property])) { + // Embedded object exists, but doesn't contain a self link -> cache it using the alternative link instead + this.objectCache.add(data._embedded[property], hasValue(request.responseMsToLive) ? request.responseMsToLive : environment.cache.msToLive.default, request.uuid, embedAltUrl); } this.process(data._embedded[property], request, embedAltUrl); }); diff --git a/src/app/core/index/index.effects.ts b/src/app/core/index/index.effects.ts index 9ec013813d..65aa45e571 100644 --- a/src/app/core/index/index.effects.ts +++ b/src/app/core/index/index.effects.ts @@ -46,7 +46,7 @@ export class UUIDIndexEffects { ofType(ObjectCacheActionTypes.ADD), map((action: AddToObjectCacheAction) => { const alternativeLink = action.payload.alternativeLink; - const selfLink = hasValue(action.payload.objectToCache) ? action.payload.objectToCache._links.self.href : alternativeLink; + const selfLink = hasValue(action.payload.objectToCache?._links?.self) ? action.payload.objectToCache._links.self.href : alternativeLink; if (hasValue(alternativeLink) && alternativeLink !== selfLink) { return new AddToIndexAction( IndexName.ALTERNATIVE_OBJECT_LINK, From 038e31ccd1a771e3c720a0dbd264f7ffe4720125 Mon Sep 17 00:00:00 2001 From: "max.nuding" Date: Wed, 15 Nov 2023 10:51:01 +0100 Subject: [PATCH 0003/1286] Submission form now displays custom messages for regex validated fields if they exist --- .../shared/form/builder/parsers/concat-field-parser.ts | 4 +++- .../shared/form/builder/parsers/dropdown-field-parser.ts | 4 +++- src/app/shared/form/builder/parsers/field-parser.ts | 9 +++++++-- src/app/shared/form/builder/parsers/name-field-parser.ts | 6 ++++-- src/app/shared/form/builder/parsers/parser-factory.ts | 2 ++ .../shared/form/builder/parsers/series-field-parser.ts | 6 ++++-- 6 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/app/shared/form/builder/parsers/concat-field-parser.ts b/src/app/shared/form/builder/parsers/concat-field-parser.ts index e86de70c81..c18fa8234e 100644 --- a/src/app/shared/form/builder/parsers/concat-field-parser.ts +++ b/src/app/shared/form/builder/parsers/concat-field-parser.ts @@ -19,6 +19,7 @@ import { SUBMISSION_ID } from './field-parser'; import { DsDynamicInputModel, DsDynamicInputModelConfig } from '../ds-dynamic-form-ui/models/ds-dynamic-input.model'; +import { TranslateService } from '@ngx-translate/core'; export class ConcatFieldParser extends FieldParser { @@ -27,10 +28,11 @@ export class ConcatFieldParser extends FieldParser { @Inject(CONFIG_DATA) configData: FormFieldModel, @Inject(INIT_FORM_VALUES) initFormValues, @Inject(PARSER_OPTIONS) parserOptions: ParserOptions, + translate: TranslateService, protected separator: string, protected firstPlaceholder: string = null, protected secondPlaceholder: string = null) { - super(submissionId, configData, initFormValues, parserOptions); + super(submissionId, configData, initFormValues, parserOptions, translate); this.separator = separator; this.firstPlaceholder = firstPlaceholder; diff --git a/src/app/shared/form/builder/parsers/dropdown-field-parser.ts b/src/app/shared/form/builder/parsers/dropdown-field-parser.ts index 3e5ec0b9da..a4bfb810f3 100644 --- a/src/app/shared/form/builder/parsers/dropdown-field-parser.ts +++ b/src/app/shared/form/builder/parsers/dropdown-field-parser.ts @@ -15,6 +15,7 @@ import { import { isNotEmpty } from '../../../empty.util'; import { FormFieldMetadataValueObject } from '../models/form-field-metadata-value.model'; import { ParserOptions } from './parser-options'; +import { TranslateService } from '@ngx-translate/core'; export class DropdownFieldParser extends FieldParser { @@ -23,8 +24,9 @@ export class DropdownFieldParser extends FieldParser { @Inject(CONFIG_DATA) configData: FormFieldModel, @Inject(INIT_FORM_VALUES) initFormValues, @Inject(PARSER_OPTIONS) parserOptions: ParserOptions, + translate: TranslateService ) { - super(submissionId, configData, initFormValues, parserOptions); + super(submissionId, configData, initFormValues, parserOptions, translate); } public modelFactory(fieldValue?: FormFieldMetadataValueObject | any, label?: boolean): any { diff --git a/src/app/shared/form/builder/parsers/field-parser.ts b/src/app/shared/form/builder/parsers/field-parser.ts index 7ea55d4454..3c4d425df3 100644 --- a/src/app/shared/form/builder/parsers/field-parser.ts +++ b/src/app/shared/form/builder/parsers/field-parser.ts @@ -25,6 +25,7 @@ import { VocabularyOptions } from '../../../../core/submission/vocabularies/mode import { ParserType } from './parser-type'; import { isNgbDateStruct } from '../../../date.util'; import { SubmissionScopeType } from '../../../../core/submission/submission-scope-type'; +import { TranslateService } from '@ngx-translate/core'; export const SUBMISSION_ID: InjectionToken = new InjectionToken('submissionId'); export const CONFIG_DATA: InjectionToken = new InjectionToken('configData'); @@ -50,7 +51,8 @@ export abstract class FieldParser { @Inject(SUBMISSION_ID) protected submissionId: string, @Inject(CONFIG_DATA) protected configData: FormFieldModel, @Inject(INIT_FORM_VALUES) protected initFormValues: any, - @Inject(PARSER_OPTIONS) protected parserOptions: ParserOptions + @Inject(PARSER_OPTIONS) protected parserOptions: ParserOptions, + protected translate: TranslateService ) { } @@ -395,11 +397,14 @@ export abstract class FieldParser { } else { regex = new RegExp(this.configData.input.regex); } + const baseTranslationKey = 'error.validation.pattern'; + const fieldranslationKey = `${baseTranslationKey}.${controlModel.id}`; + const fieldTranslationExists = this.translate.instant(fieldranslationKey) !== fieldranslationKey; controlModel.validators = Object.assign({}, controlModel.validators, { pattern: regex }); controlModel.errorMessages = Object.assign( {}, controlModel.errorMessages, - { pattern: 'error.validation.pattern' }); + { pattern: fieldTranslationExists ? fieldranslationKey : baseTranslationKey }); } protected markAsRequired(controlModel) { diff --git a/src/app/shared/form/builder/parsers/name-field-parser.ts b/src/app/shared/form/builder/parsers/name-field-parser.ts index e5ecb034ea..469b32be92 100644 --- a/src/app/shared/form/builder/parsers/name-field-parser.ts +++ b/src/app/shared/form/builder/parsers/name-field-parser.ts @@ -1,4 +1,5 @@ import { Inject } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; import { FormFieldModel } from '../models/form-field.model'; import { ConcatFieldParser } from './concat-field-parser'; import { CONFIG_DATA, INIT_FORM_VALUES, PARSER_OPTIONS, SUBMISSION_ID } from './field-parser'; @@ -10,8 +11,9 @@ export class NameFieldParser extends ConcatFieldParser { @Inject(SUBMISSION_ID) submissionId: string, @Inject(CONFIG_DATA) configData: FormFieldModel, @Inject(INIT_FORM_VALUES) initFormValues, - @Inject(PARSER_OPTIONS) parserOptions: ParserOptions + @Inject(PARSER_OPTIONS) parserOptions: ParserOptions, + translate: TranslateService ) { - super(submissionId, configData, initFormValues, parserOptions, ',', 'form.last-name', 'form.first-name'); + super(submissionId, configData, initFormValues, parserOptions, translate, ',', 'form.last-name', 'form.first-name'); } } diff --git a/src/app/shared/form/builder/parsers/parser-factory.ts b/src/app/shared/form/builder/parsers/parser-factory.ts index 26a9cb0f28..97fc36cbb4 100644 --- a/src/app/shared/form/builder/parsers/parser-factory.ts +++ b/src/app/shared/form/builder/parsers/parser-factory.ts @@ -19,12 +19,14 @@ import { SeriesFieldParser } from './series-field-parser'; import { TagFieldParser } from './tag-field-parser'; import { TextareaFieldParser } from './textarea-field-parser'; import { DisabledFieldParser } from './disabled-field-parser'; +import { TranslateService } from '@ngx-translate/core'; const fieldParserDeps = [ SUBMISSION_ID, CONFIG_DATA, INIT_FORM_VALUES, PARSER_OPTIONS, + TranslateService ]; /** diff --git a/src/app/shared/form/builder/parsers/series-field-parser.ts b/src/app/shared/form/builder/parsers/series-field-parser.ts index 36ee9c36c1..589a6dc04c 100644 --- a/src/app/shared/form/builder/parsers/series-field-parser.ts +++ b/src/app/shared/form/builder/parsers/series-field-parser.ts @@ -1,4 +1,5 @@ import { Inject } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; import { FormFieldModel } from '../models/form-field.model'; import { ConcatFieldParser } from './concat-field-parser'; import { CONFIG_DATA, INIT_FORM_VALUES, PARSER_OPTIONS, SUBMISSION_ID } from './field-parser'; @@ -10,8 +11,9 @@ export class SeriesFieldParser extends ConcatFieldParser { @Inject(SUBMISSION_ID) submissionId: string, @Inject(CONFIG_DATA) configData: FormFieldModel, @Inject(INIT_FORM_VALUES) initFormValues, - @Inject(PARSER_OPTIONS) parserOptions: ParserOptions + @Inject(PARSER_OPTIONS) parserOptions: ParserOptions, + translate: TranslateService ) { - super(submissionId, configData, initFormValues, parserOptions, ';'); + super(submissionId, configData, initFormValues, parserOptions, translate, ';'); } } From c93a64db838ddc4dce5f73aa9e28f28c457fb14d Mon Sep 17 00:00:00 2001 From: "max.nuding" Date: Wed, 15 Nov 2023 13:27:58 +0100 Subject: [PATCH 0004/1286] Fix tests to include translationservice dependency --- .../form/builder/form-builder.service.spec.ts | 6 +++- .../builder/parsers/date-field-parser.spec.ts | 10 ++++-- .../parsers/disabled-field-parser.spec.ts | 8 +++-- .../parsers/dropdown-field-parser.spec.ts | 8 +++-- .../builder/parsers/list-field-parser.spec.ts | 10 +++--- .../parsers/lookup-field-parser.spec.ts | 8 +++-- .../parsers/lookup-name-field-parser.spec.ts | 8 +++-- .../builder/parsers/name-field-parser.spec.ts | 10 +++--- .../parsers/onebox-field-parser.spec.ts | 12 ++++--- .../relation-group-field-parser.spec.ts | 10 +++--- .../form/builder/parsers/row-parser.spec.ts | 35 ++++++++++++------- .../parsers/series-field-parser.spec.ts | 10 +++--- .../builder/parsers/tag-field-parser.spec.ts | 8 +++-- .../parsers/textarea-field-parser.spec.ts | 8 +++-- 14 files changed, 96 insertions(+), 55 deletions(-) diff --git a/src/app/shared/form/builder/form-builder.service.spec.ts b/src/app/shared/form/builder/form-builder.service.spec.ts index fd3588e73e..94c88aae17 100644 --- a/src/app/shared/form/builder/form-builder.service.spec.ts +++ b/src/app/shared/form/builder/form-builder.service.spec.ts @@ -51,6 +51,8 @@ import { FormRowModel } from '../../../core/config/models/config-submission-form import {ConfigurationDataService} from '../../../core/data/configuration-data.service'; import {createSuccessfulRemoteDataObject$} from '../../remote-data.utils'; import {ConfigurationProperty} from '../../../core/shared/configuration-property.model'; +import { getMockTranslateService } from '../../mocks/translate.service.mock'; +import { TranslateService } from '@ngx-translate/core'; describe('FormBuilderService test suite', () => { @@ -81,6 +83,7 @@ describe('FormBuilderService test suite', () => { beforeEach(() => { configSpy = createConfigSuccessSpy(typeFieldTestValue); + let translateService = getMockTranslateService(); TestBed.configureTestingModule({ imports: [ReactiveFormsModule], providers: [ @@ -88,7 +91,8 @@ describe('FormBuilderService test suite', () => { { provide: DynamicFormValidationService, useValue: {} }, { provide: NG_VALIDATORS, useValue: testValidator, multi: true }, { provide: NG_ASYNC_VALIDATORS, useValue: testAsyncValidator, multi: true }, - { provide: ConfigurationDataService, useValue: configSpy } + { provide: ConfigurationDataService, useValue: configSpy }, + { provide: TranslateService, useValue: translateService }, ] }); diff --git a/src/app/shared/form/builder/parsers/date-field-parser.spec.ts b/src/app/shared/form/builder/parsers/date-field-parser.spec.ts index 9ab43709ad..891bb1d9d4 100644 --- a/src/app/shared/form/builder/parsers/date-field-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/date-field-parser.spec.ts @@ -3,10 +3,14 @@ import { DateFieldParser } from './date-field-parser'; import { DynamicDsDatePickerModel } from '../ds-dynamic-form-ui/models/date-picker/date-picker.model'; import { FormFieldMetadataValueObject } from '../models/form-field-metadata-value.model'; import { ParserOptions } from './parser-options'; +import { getMockTranslateService } from 'src/app/shared/mocks/translate.service.mock'; + + describe('DateFieldParser test suite', () => { let field: FormFieldModel; let initFormValues: any = {}; + let translateService = getMockTranslateService(); const submissionId = '1234'; const parserOptions: ParserOptions = { @@ -37,13 +41,13 @@ describe('DateFieldParser test suite', () => { }); it('should init parser properly', () => { - const parser = new DateFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new DateFieldParser(submissionId, field, initFormValues, parserOptions, translateService); expect(parser instanceof DateFieldParser).toBe(true); }); it('should return a DynamicDsDatePickerModel object when repeatable option is false', () => { - const parser = new DateFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new DateFieldParser(submissionId, field, initFormValues, parserOptions, translateService); const fieldModel = parser.parse(); @@ -56,7 +60,7 @@ describe('DateFieldParser test suite', () => { }; const expectedValue = '1983-11-18'; - const parser = new DateFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new DateFieldParser(submissionId, field, initFormValues, parserOptions, translateService); const fieldModel = parser.parse(); diff --git a/src/app/shared/form/builder/parsers/disabled-field-parser.spec.ts b/src/app/shared/form/builder/parsers/disabled-field-parser.spec.ts index d69f0e48e9..2168d7e2bf 100644 --- a/src/app/shared/form/builder/parsers/disabled-field-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/disabled-field-parser.spec.ts @@ -2,10 +2,12 @@ import { FormFieldModel } from '../models/form-field.model'; import { ParserOptions } from './parser-options'; import { DisabledFieldParser } from './disabled-field-parser'; import { DynamicDisabledModel } from '../ds-dynamic-form-ui/models/disabled/dynamic-disabled.model'; +import { getMockTranslateService } from 'src/app/shared/mocks/translate.service.mock'; describe('DisabledFieldParser test suite', () => { let field: FormFieldModel; let initFormValues: any = {}; + let translateService = getMockTranslateService(); const submissionId = '1234'; const parserOptions: ParserOptions = { @@ -35,13 +37,13 @@ describe('DisabledFieldParser test suite', () => { }); it('should init parser properly', () => { - const parser = new DisabledFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new DisabledFieldParser(submissionId, field, initFormValues, parserOptions, translateService); expect(parser instanceof DisabledFieldParser).toBe(true); }); it('should return a DynamicDisabledModel object when repeatable option is false', () => { - const parser = new DisabledFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new DisabledFieldParser(submissionId, field, initFormValues, parserOptions, translateService); const fieldModel = parser.parse(); @@ -56,7 +58,7 @@ describe('DisabledFieldParser test suite', () => { }; const expectedValue = 'test description'; - const parser = new DisabledFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new DisabledFieldParser(submissionId, field, initFormValues, parserOptions, translateService); const fieldModel = parser.parse(); expect(fieldModel.value.value).toEqual(expectedValue); diff --git a/src/app/shared/form/builder/parsers/dropdown-field-parser.spec.ts b/src/app/shared/form/builder/parsers/dropdown-field-parser.spec.ts index 3dca7558b3..08a93f76d3 100644 --- a/src/app/shared/form/builder/parsers/dropdown-field-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/dropdown-field-parser.spec.ts @@ -2,9 +2,11 @@ import { FormFieldModel } from '../models/form-field.model'; import { DropdownFieldParser } from './dropdown-field-parser'; import { DynamicScrollableDropdownModel } from '../ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.model'; import { ParserOptions } from './parser-options'; +import { getMockTranslateService } from 'src/app/shared/mocks/translate.service.mock'; describe('DropdownFieldParser test suite', () => { let field: FormFieldModel; + let translateService = getMockTranslateService(); const submissionId = '1234'; const initFormValues = {}; @@ -37,13 +39,13 @@ describe('DropdownFieldParser test suite', () => { }); it('should init parser properly', () => { - const parser = new DropdownFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new DropdownFieldParser(submissionId, field, initFormValues, parserOptions, translateService); expect(parser instanceof DropdownFieldParser).toBe(true); }); it('should return a DynamicScrollableDropdownModel object when repeatable option is false', () => { - const parser = new DropdownFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new DropdownFieldParser(submissionId, field, initFormValues, parserOptions, translateService); const fieldModel = parser.parse(); @@ -52,7 +54,7 @@ describe('DropdownFieldParser test suite', () => { it('should throw when authority is not passed', () => { field.selectableMetadata[0].controlledVocabulary = null; - const parser = new DropdownFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new DropdownFieldParser(submissionId, field, initFormValues, parserOptions, translateService); expect(() => parser.parse()) .toThrow(); diff --git a/src/app/shared/form/builder/parsers/list-field-parser.spec.ts b/src/app/shared/form/builder/parsers/list-field-parser.spec.ts index 30d1913a51..ba9f9291cf 100644 --- a/src/app/shared/form/builder/parsers/list-field-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/list-field-parser.spec.ts @@ -4,10 +4,12 @@ import { ListFieldParser } from './list-field-parser'; import { DynamicListCheckboxGroupModel } from '../ds-dynamic-form-ui/models/list/dynamic-list-checkbox-group.model'; import { DynamicListRadioGroupModel } from '../ds-dynamic-form-ui/models/list/dynamic-list-radio-group.model'; import { ParserOptions } from './parser-options'; +import { getMockTranslateService } from 'src/app/shared/mocks/translate.service.mock'; describe('ListFieldParser test suite', () => { let field: FormFieldModel; let initFormValues = {}; + let translateService = getMockTranslateService(); const submissionId = '1234'; const parserOptions: ParserOptions = { @@ -39,13 +41,13 @@ describe('ListFieldParser test suite', () => { }); it('should init parser properly', () => { - const parser = new ListFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new ListFieldParser(submissionId, field, initFormValues, parserOptions, translateService); expect(parser instanceof ListFieldParser).toBe(true); }); it('should return a DynamicListCheckboxGroupModel object when repeatable option is true', () => { - const parser = new ListFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new ListFieldParser(submissionId, field, initFormValues, parserOptions, translateService); const fieldModel = parser.parse(); @@ -54,7 +56,7 @@ describe('ListFieldParser test suite', () => { it('should return a DynamicListRadioGroupModel object when repeatable option is false', () => { field.repeatable = false; - const parser = new ListFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new ListFieldParser(submissionId, field, initFormValues, parserOptions, translateService); const fieldModel = parser.parse(); @@ -67,7 +69,7 @@ describe('ListFieldParser test suite', () => { }; const expectedValue = [new FormFieldMetadataValueObject('test type')]; - const parser = new ListFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new ListFieldParser(submissionId, field, initFormValues, parserOptions, translateService); const fieldModel = parser.parse(); diff --git a/src/app/shared/form/builder/parsers/lookup-field-parser.spec.ts b/src/app/shared/form/builder/parsers/lookup-field-parser.spec.ts index 24efcf3462..a932dc637c 100644 --- a/src/app/shared/form/builder/parsers/lookup-field-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/lookup-field-parser.spec.ts @@ -3,10 +3,12 @@ import { FormFieldMetadataValueObject } from '../models/form-field-metadata-valu import { LookupFieldParser } from './lookup-field-parser'; import { DynamicLookupModel } from '../ds-dynamic-form-ui/models/lookup/dynamic-lookup.model'; import { ParserOptions } from './parser-options'; +import { getMockTranslateService } from 'src/app/shared/mocks/translate.service.mock'; describe('LookupFieldParser test suite', () => { let field: FormFieldModel; let initFormValues = {}; + let translateService = getMockTranslateService(); const submissionId = '1234'; const parserOptions: ParserOptions = { @@ -38,13 +40,13 @@ describe('LookupFieldParser test suite', () => { }); it('should init parser properly', () => { - const parser = new LookupFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new LookupFieldParser(submissionId, field, initFormValues, parserOptions, translateService); expect(parser instanceof LookupFieldParser).toBe(true); }); it('should return a DynamicLookupModel object when repeatable option is false', () => { - const parser = new LookupFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new LookupFieldParser(submissionId, field, initFormValues, parserOptions, translateService); const fieldModel = parser.parse(); @@ -57,7 +59,7 @@ describe('LookupFieldParser test suite', () => { }; const expectedValue = new FormFieldMetadataValueObject('test journal'); - const parser = new LookupFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new LookupFieldParser(submissionId, field, initFormValues, parserOptions, translateService); const fieldModel = parser.parse(); diff --git a/src/app/shared/form/builder/parsers/lookup-name-field-parser.spec.ts b/src/app/shared/form/builder/parsers/lookup-name-field-parser.spec.ts index d0281681ef..6220a6e74c 100644 --- a/src/app/shared/form/builder/parsers/lookup-name-field-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/lookup-name-field-parser.spec.ts @@ -3,10 +3,12 @@ import { FormFieldMetadataValueObject } from '../models/form-field-metadata-valu import { LookupNameFieldParser } from './lookup-name-field-parser'; import { DynamicLookupNameModel } from '../ds-dynamic-form-ui/models/lookup/dynamic-lookup-name.model'; import { ParserOptions } from './parser-options'; +import { getMockTranslateService } from 'src/app/shared/mocks/translate.service.mock'; describe('LookupNameFieldParser test suite', () => { let field: FormFieldModel; let initFormValues = {}; + let translateService = getMockTranslateService(); const submissionId = '1234'; const parserOptions: ParserOptions = { @@ -38,13 +40,13 @@ describe('LookupNameFieldParser test suite', () => { }); it('should init parser properly', () => { - const parser = new LookupNameFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new LookupNameFieldParser(submissionId, field, initFormValues, parserOptions, translateService); expect(parser instanceof LookupNameFieldParser).toBe(true); }); it('should return a DynamicLookupNameModel object when repeatable option is false', () => { - const parser = new LookupNameFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new LookupNameFieldParser(submissionId, field, initFormValues, parserOptions, translateService); const fieldModel = parser.parse(); @@ -57,7 +59,7 @@ describe('LookupNameFieldParser test suite', () => { }; const expectedValue = new FormFieldMetadataValueObject('test author'); - const parser = new LookupNameFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new LookupNameFieldParser(submissionId, field, initFormValues, parserOptions, translateService); const fieldModel = parser.parse(); diff --git a/src/app/shared/form/builder/parsers/name-field-parser.spec.ts b/src/app/shared/form/builder/parsers/name-field-parser.spec.ts index 6b520142cc..e124181b24 100644 --- a/src/app/shared/form/builder/parsers/name-field-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/name-field-parser.spec.ts @@ -3,12 +3,14 @@ import { NameFieldParser } from './name-field-parser'; import { DynamicConcatModel } from '../ds-dynamic-form-ui/models/ds-dynamic-concat.model'; import { FormFieldMetadataValueObject } from '../models/form-field-metadata-value.model'; import { ParserOptions } from './parser-options'; +import { getMockTranslateService } from 'src/app/shared/mocks/translate.service.mock'; describe('NameFieldParser test suite', () => { let field1: FormFieldModel; let field2: FormFieldModel; let field3: FormFieldModel; let initFormValues: any = {}; + let translateService = getMockTranslateService(); const submissionId = '1234'; const parserOptions: ParserOptions = { @@ -71,13 +73,13 @@ describe('NameFieldParser test suite', () => { }); it('should init parser properly', () => { - const parser = new NameFieldParser(submissionId, field1, initFormValues, parserOptions); + const parser = new NameFieldParser(submissionId, field1, initFormValues, parserOptions, translateService); expect(parser instanceof NameFieldParser).toBe(true); }); it('should return a DynamicConcatModel object when repeatable option is false', () => { - const parser = new NameFieldParser(submissionId, field2, initFormValues, parserOptions); + const parser = new NameFieldParser(submissionId, field2, initFormValues, parserOptions, translateService); const fieldModel = parser.parse(); @@ -85,7 +87,7 @@ describe('NameFieldParser test suite', () => { }); it('should return a DynamicConcatModel object with the correct separator', () => { - const parser = new NameFieldParser(submissionId, field2, initFormValues, parserOptions); + const parser = new NameFieldParser(submissionId, field2, initFormValues, parserOptions, translateService); const fieldModel = parser.parse(); @@ -98,7 +100,7 @@ describe('NameFieldParser test suite', () => { }; const expectedValue = new FormFieldMetadataValueObject('test, name', undefined, undefined, 'test'); - const parser = new NameFieldParser(submissionId, field1, initFormValues, parserOptions); + const parser = new NameFieldParser(submissionId, field1, initFormValues, parserOptions, translateService); const fieldModel = parser.parse(); diff --git a/src/app/shared/form/builder/parsers/onebox-field-parser.spec.ts b/src/app/shared/form/builder/parsers/onebox-field-parser.spec.ts index a4c71d1f42..6b7ac65a58 100644 --- a/src/app/shared/form/builder/parsers/onebox-field-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/onebox-field-parser.spec.ts @@ -5,11 +5,13 @@ import { DynamicOneboxModel } from '../ds-dynamic-form-ui/models/onebox/dynamic- import { DsDynamicInputModel } from '../ds-dynamic-form-ui/models/ds-dynamic-input.model'; import { ParserOptions } from './parser-options'; import { FieldParser } from './field-parser'; +import { getMockTranslateService } from 'src/app/shared/mocks/translate.service.mock'; describe('OneboxFieldParser test suite', () => { let field1: FormFieldModel; let field2: FormFieldModel; let field3: FormFieldModel; + let translateService = getMockTranslateService(); const submissionId = '1234'; const initFormValues = {}; @@ -73,13 +75,13 @@ describe('OneboxFieldParser test suite', () => { }); it('should init parser properly', () => { - const parser = new OneboxFieldParser(submissionId, field1, initFormValues, parserOptions); + const parser = new OneboxFieldParser(submissionId, field1, initFormValues, parserOptions, translateService); expect(parser instanceof OneboxFieldParser).toBe(true); }); it('should return a DynamicQualdropModel object when selectableMetadata is multiple', () => { - const parser = new OneboxFieldParser(submissionId, field2, initFormValues, parserOptions); + const parser = new OneboxFieldParser(submissionId, field2, initFormValues, parserOptions, translateService); const fieldModel = parser.parse(); @@ -87,7 +89,7 @@ describe('OneboxFieldParser test suite', () => { }); it('should return a DsDynamicInputModel object when selectableMetadata is not multiple', () => { - const parser = new OneboxFieldParser(submissionId, field3, initFormValues, parserOptions); + const parser = new OneboxFieldParser(submissionId, field3, initFormValues, parserOptions, translateService); const fieldModel = parser.parse(); @@ -95,7 +97,7 @@ describe('OneboxFieldParser test suite', () => { }); it('should return a DynamicOneboxModel object when selectableMetadata has authority', () => { - const parser = new OneboxFieldParser(submissionId, field1, initFormValues, parserOptions); + const parser = new OneboxFieldParser(submissionId, field1, initFormValues, parserOptions, translateService); const fieldModel = parser.parse(); @@ -124,7 +126,7 @@ describe('OneboxFieldParser test suite', () => { languageCodes: [] } as FormFieldModel; - parser = new OneboxFieldParser(submissionId, regexField, initFormValues, parserOptions); + parser = new OneboxFieldParser(submissionId, regexField, initFormValues, parserOptions, translateService); fieldModel = parser.parse(); }); diff --git a/src/app/shared/form/builder/parsers/relation-group-field-parser.spec.ts b/src/app/shared/form/builder/parsers/relation-group-field-parser.spec.ts index 7d48ad2d00..8ae0ccfedf 100644 --- a/src/app/shared/form/builder/parsers/relation-group-field-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/relation-group-field-parser.spec.ts @@ -3,10 +3,12 @@ import { RelationGroupFieldParser } from './relation-group-field-parser'; import { DynamicRelationGroupModel } from '../ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.model'; import { FormFieldMetadataValueObject } from '../models/form-field-metadata-value.model'; import { ParserOptions } from './parser-options'; +import { getMockTranslateService } from 'src/app/shared/mocks/translate.service.mock'; describe('RelationGroupFieldParser test suite', () => { let field: FormFieldModel; let initFormValues = {}; + let translateService = getMockTranslateService(); const submissionId = '1234'; const parserOptions: ParserOptions = { @@ -73,13 +75,13 @@ describe('RelationGroupFieldParser test suite', () => { }); it('should init parser properly', () => { - const parser = new RelationGroupFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new RelationGroupFieldParser(submissionId, field, initFormValues, parserOptions, translateService); expect(parser instanceof RelationGroupFieldParser).toBe(true); }); it('should return a DynamicRelationGroupModel object', () => { - const parser = new RelationGroupFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new RelationGroupFieldParser(submissionId, field, initFormValues, parserOptions, translateService); const fieldModel = parser.parse(); @@ -88,7 +90,7 @@ describe('RelationGroupFieldParser test suite', () => { it('should throw when rows configuration is empty', () => { field.rows = null; - const parser = new RelationGroupFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new RelationGroupFieldParser(submissionId, field, initFormValues, parserOptions, translateService); expect(() => parser.parse()) .toThrow(); @@ -99,7 +101,7 @@ describe('RelationGroupFieldParser test suite', () => { author: [new FormFieldMetadataValueObject('test author')], affiliation: [new FormFieldMetadataValueObject('test affiliation')] }; - const parser = new RelationGroupFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new RelationGroupFieldParser(submissionId, field, initFormValues, parserOptions, translateService); const fieldModel = parser.parse(); const expectedValue = [{ diff --git a/src/app/shared/form/builder/parsers/row-parser.spec.ts b/src/app/shared/form/builder/parsers/row-parser.spec.ts index 1f9bde8a7f..fca16b28e3 100644 --- a/src/app/shared/form/builder/parsers/row-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/row-parser.spec.ts @@ -3,6 +3,10 @@ import { RowParser } from './row-parser'; import { DynamicRowGroupModel } from '../ds-dynamic-form-ui/models/ds-dynamic-row-group-model'; import { DynamicRowArrayModel } from '../ds-dynamic-form-ui/models/ds-dynamic-row-array-model'; import { FormRowModel } from '../../../../core/config/models/config-submission-form.model'; +import { getMockTranslateService } from 'src/app/shared/mocks/translate.service.mock'; +import { TestBed } from '@angular/core/testing'; +import { TranslateService } from '@ngx-translate/core'; +import { Injector } from '@angular/core'; describe('RowParser test suite', () => { @@ -16,6 +20,7 @@ describe('RowParser test suite', () => { let row8: FormRowModel; let row9: FormRowModel; let row10: FormRowModel; + let injector: Injector; const submissionId = '1234'; const scopeUUID = 'testScopeUUID'; @@ -25,6 +30,12 @@ describe('RowParser test suite', () => { const typeField = 'dc_type'; beforeEach(() => { + let translateService = getMockTranslateService(); + injector = Injector.create({ + providers: [ + { provide: TranslateService, useValue: translateService }, + ], + }); row1 = { fields: [ { @@ -330,14 +341,14 @@ describe('RowParser test suite', () => { }); it('should init parser properly', () => { - const parser = new RowParser(undefined); + const parser = new RowParser(injector); expect(parser instanceof RowParser).toBe(true); }); describe('parse', () => { it('should return a DynamicRowGroupModel object', () => { - const parser = new RowParser(undefined); + const parser = new RowParser(injector); const rowModel = parser.parse(submissionId, row1, scopeUUID, initFormValues, submissionScope, readOnly, typeField); @@ -345,7 +356,7 @@ describe('RowParser test suite', () => { }); it('should return a row with three fields', () => { - const parser = new RowParser(undefined); + const parser = new RowParser(injector); const rowModel = parser.parse(submissionId, row1, scopeUUID, initFormValues, submissionScope, readOnly, typeField); @@ -353,7 +364,7 @@ describe('RowParser test suite', () => { }); it('should return a DynamicRowArrayModel object', () => { - const parser = new RowParser(undefined); + const parser = new RowParser(injector); const rowModel = parser.parse(submissionId, row2, scopeUUID, initFormValues, submissionScope, readOnly, typeField); @@ -361,7 +372,7 @@ describe('RowParser test suite', () => { }); it('should return a row that contains only scoped fields', () => { - const parser = new RowParser(undefined); + const parser = new RowParser(injector); const rowModel = parser.parse(submissionId, row3, scopeUUID, initFormValues, submissionScope, readOnly, typeField); @@ -369,7 +380,7 @@ describe('RowParser test suite', () => { }); it('should be able to parse a dropdown combo field', () => { - const parser = new RowParser(undefined); + const parser = new RowParser(injector); const rowModel = parser.parse(submissionId, row4, scopeUUID, initFormValues, submissionScope, readOnly, typeField); @@ -377,7 +388,7 @@ describe('RowParser test suite', () => { }); it('should be able to parse a lookup-name field', () => { - const parser = new RowParser(undefined); + const parser = new RowParser(injector); const rowModel = parser.parse(submissionId, row5, scopeUUID, initFormValues, submissionScope, readOnly, typeField); @@ -385,7 +396,7 @@ describe('RowParser test suite', () => { }); it('should be able to parse a list field', () => { - const parser = new RowParser(undefined); + const parser = new RowParser(injector); const rowModel = parser.parse(submissionId, row6, scopeUUID, initFormValues, submissionScope, readOnly, typeField); @@ -393,7 +404,7 @@ describe('RowParser test suite', () => { }); it('should be able to parse a date field', () => { - const parser = new RowParser(undefined); + const parser = new RowParser(injector); const rowModel = parser.parse(submissionId, row7, scopeUUID, initFormValues, submissionScope, readOnly, typeField); @@ -401,7 +412,7 @@ describe('RowParser test suite', () => { }); it('should be able to parse a tag field', () => { - const parser = new RowParser(undefined); + const parser = new RowParser(injector); const rowModel = parser.parse(submissionId, row8, scopeUUID, initFormValues, submissionScope, readOnly, typeField); @@ -409,7 +420,7 @@ describe('RowParser test suite', () => { }); it('should be able to parse a textarea field', () => { - const parser = new RowParser(undefined); + const parser = new RowParser(injector); const rowModel = parser.parse(submissionId, row9, scopeUUID, initFormValues, submissionScope, readOnly, typeField); @@ -417,7 +428,7 @@ describe('RowParser test suite', () => { }); it('should be able to parse a group field', () => { - const parser = new RowParser(undefined); + const parser = new RowParser(injector); const rowModel = parser.parse(submissionId, row10, scopeUUID, initFormValues, submissionScope, readOnly, typeField); diff --git a/src/app/shared/form/builder/parsers/series-field-parser.spec.ts b/src/app/shared/form/builder/parsers/series-field-parser.spec.ts index 0761cfe60e..0ce50081e4 100644 --- a/src/app/shared/form/builder/parsers/series-field-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/series-field-parser.spec.ts @@ -3,10 +3,12 @@ import { DynamicConcatModel } from '../ds-dynamic-form-ui/models/ds-dynamic-conc import { SeriesFieldParser } from './series-field-parser'; import { FormFieldMetadataValueObject } from '../models/form-field-metadata-value.model'; import { ParserOptions } from './parser-options'; +import { getMockTranslateService } from 'src/app/shared/mocks/translate.service.mock'; describe('SeriesFieldParser test suite', () => { let field: FormFieldModel; let initFormValues: any = {}; + let translateService = getMockTranslateService(); const submissionId = '1234'; const parserOptions: ParserOptions = { @@ -34,13 +36,13 @@ describe('SeriesFieldParser test suite', () => { }); it('should init parser properly', () => { - const parser = new SeriesFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new SeriesFieldParser(submissionId, field, initFormValues, parserOptions, translateService); expect(parser instanceof SeriesFieldParser).toBe(true); }); it('should return a DynamicConcatModel object when repeatable option is false', () => { - const parser = new SeriesFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new SeriesFieldParser(submissionId, field, initFormValues, parserOptions, translateService); const fieldModel = parser.parse(); @@ -48,7 +50,7 @@ describe('SeriesFieldParser test suite', () => { }); it('should return a DynamicConcatModel object with the correct separator', () => { - const parser = new SeriesFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new SeriesFieldParser(submissionId, field, initFormValues, parserOptions, translateService); const fieldModel = parser.parse(); @@ -61,7 +63,7 @@ describe('SeriesFieldParser test suite', () => { }; const expectedValue = new FormFieldMetadataValueObject('test; series', undefined, undefined, 'test'); - const parser = new SeriesFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new SeriesFieldParser(submissionId, field, initFormValues, parserOptions, translateService); const fieldModel = parser.parse(); diff --git a/src/app/shared/form/builder/parsers/tag-field-parser.spec.ts b/src/app/shared/form/builder/parsers/tag-field-parser.spec.ts index 115829f8d3..ae10dbd386 100644 --- a/src/app/shared/form/builder/parsers/tag-field-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/tag-field-parser.spec.ts @@ -3,10 +3,12 @@ import { FormFieldMetadataValueObject } from '../models/form-field-metadata-valu import { TagFieldParser } from './tag-field-parser'; import { DynamicTagModel } from '../ds-dynamic-form-ui/models/tag/dynamic-tag.model'; import { ParserOptions } from './parser-options'; +import { getMockTranslateService } from 'src/app/shared/mocks/translate.service.mock'; describe('TagFieldParser test suite', () => { let field: FormFieldModel; let initFormValues: any = {}; + let translateService = getMockTranslateService(); const submissionId = '1234'; const parserOptions: ParserOptions = { @@ -38,13 +40,13 @@ describe('TagFieldParser test suite', () => { }); it('should init parser properly', () => { - const parser = new TagFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new TagFieldParser(submissionId, field, initFormValues, parserOptions, translateService); expect(parser instanceof TagFieldParser).toBe(true); }); it('should return a DynamicTagModel object when repeatable option is false', () => { - const parser = new TagFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new TagFieldParser(submissionId, field, initFormValues, parserOptions, translateService); const fieldModel = parser.parse(); @@ -59,7 +61,7 @@ describe('TagFieldParser test suite', () => { ], }; - const parser = new TagFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new TagFieldParser(submissionId, field, initFormValues, parserOptions, translateService); const fieldModel = parser.parse(); diff --git a/src/app/shared/form/builder/parsers/textarea-field-parser.spec.ts b/src/app/shared/form/builder/parsers/textarea-field-parser.spec.ts index 855e464f21..259f8a60e1 100644 --- a/src/app/shared/form/builder/parsers/textarea-field-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/textarea-field-parser.spec.ts @@ -3,10 +3,12 @@ import { FormFieldMetadataValueObject } from '../models/form-field-metadata-valu import { TextareaFieldParser } from './textarea-field-parser'; import { DsDynamicTextAreaModel } from '../ds-dynamic-form-ui/models/ds-dynamic-textarea.model'; import { ParserOptions } from './parser-options'; +import { getMockTranslateService } from 'src/app/shared/mocks/translate.service.mock'; describe('TextareaFieldParser test suite', () => { let field: FormFieldModel; let initFormValues: any = {}; + let translateService = getMockTranslateService(); const submissionId = '1234'; const parserOptions: ParserOptions = { @@ -36,13 +38,13 @@ describe('TextareaFieldParser test suite', () => { }); it('should init parser properly', () => { - const parser = new TextareaFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new TextareaFieldParser(submissionId, field, initFormValues, parserOptions, translateService); expect(parser instanceof TextareaFieldParser).toBe(true); }); it('should return a DsDynamicTextAreaModel object when repeatable option is false', () => { - const parser = new TextareaFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new TextareaFieldParser(submissionId, field, initFormValues, parserOptions, translateService); const fieldModel = parser.parse(); @@ -57,7 +59,7 @@ describe('TextareaFieldParser test suite', () => { }; const expectedValue = 'test description'; - const parser = new TextareaFieldParser(submissionId, field, initFormValues, parserOptions); + const parser = new TextareaFieldParser(submissionId, field, initFormValues, parserOptions, translateService); const fieldModel = parser.parse(); From ab23613b799f488a0845aeb309a371eabc3035c6 Mon Sep 17 00:00:00 2001 From: "max.nuding" Date: Wed, 15 Nov 2023 13:42:53 +0100 Subject: [PATCH 0005/1286] Remove unnecessary import --- src/app/shared/form/builder/parsers/row-parser.spec.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/shared/form/builder/parsers/row-parser.spec.ts b/src/app/shared/form/builder/parsers/row-parser.spec.ts index fca16b28e3..f414715f5b 100644 --- a/src/app/shared/form/builder/parsers/row-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/row-parser.spec.ts @@ -4,7 +4,6 @@ import { DynamicRowGroupModel } from '../ds-dynamic-form-ui/models/ds-dynamic-ro import { DynamicRowArrayModel } from '../ds-dynamic-form-ui/models/ds-dynamic-row-array-model'; import { FormRowModel } from '../../../../core/config/models/config-submission-form.model'; import { getMockTranslateService } from 'src/app/shared/mocks/translate.service.mock'; -import { TestBed } from '@angular/core/testing'; import { TranslateService } from '@ngx-translate/core'; import { Injector } from '@angular/core'; From 5a839c2906ef7709409731092ff6d8715cb18649 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 15 Nov 2023 14:37:06 -0600 Subject: [PATCH 0006/1286] Update version tag for development of next release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1ddb27078f..852e5e57f3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dspace-angular", - "version": "7.6.1", + "version": "7.6.2-next", "scripts": { "ng": "ng", "config:watch": "nodemon", From 02eb618c5f8dcb7295301e294901dadcb53cd1fe Mon Sep 17 00:00:00 2001 From: Thomas Misilo Date: Thu, 16 Nov 2023 11:36:06 -0600 Subject: [PATCH 0007/1286] Setup the Docker GH Action for Matrix Building This change enables building of the amd64 and arm64 images simultaneously. Once both images finish, the manifest is sent to Docker Hub, allowing for a single image that has both the amd64/arm64 images. --- .github/workflows/docker.yml | 173 +++++++++++++++++++++++++++++++---- 1 file changed, 153 insertions(+), 20 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 0c36d5af98..18bdef78be 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -17,6 +17,7 @@ permissions: env: + REGISTRY_IMAGE: dspace/dspace-angular # Define tags to use for Docker images based on Git tags/branches (for docker/metadata-action) # For a new commit on default branch (main), use the literal tag 'latest' on Docker image. # For a new commit on other branches, use the branch name as the tag for Docker image. @@ -30,21 +31,30 @@ env: # We manage the 'latest' tag ourselves to the 'main' branch (see settings above) TAGS_FLAVOR: | latest=false - # Architectures / Platforms for which we will build Docker images - # If this is a PR, we ONLY build for AMD64. For PRs we only do a sanity check test to ensure Docker builds work. - # If this is NOT a PR (e.g. a tag or merge commit), also build for ARM64. - PLATFORMS: linux/amd64${{ github.event_name != 'pull_request' && ', linux/arm64' || '' }} - jobs: - ############################################### - # Build/Push the 'dspace/dspace-angular' image - ############################################### + ############################################################# + # Build/Push the '${{ env.REGISTRY_IMAGE }}' image + ############################################################# dspace-angular: # Ensure this job never runs on forked repos. It's only executed for 'dspace/dspace-angular' if: github.repository == 'dspace/dspace-angular' - runs-on: ubuntu-latest + strategy: + matrix: + isPr: + - ${{ github.event_name == 'pull_request' }} + # Architectures / Platforms for which we will build Docker images + # If this is a PR, we ONLY build for AMD64. For PRs we only do a sanity check test to ensure Docker builds work. + # If this is NOT a PR (e.g. a tag or merge commit), also build for ARM64. + arch: ['linux/amd64', 'linux/arm64'] + os: [ubuntu-latest] + exclude: + - isPr: true + os: ubuntu-latest + arch: linux/arm64 + + runs-on: ${{ matrix.os }} steps: # https://github.com/actions/checkout - name: Checkout codebase @@ -61,7 +71,7 @@ jobs: # https://github.com/docker/login-action - name: Login to DockerHub # Only login if not a PR, as PRs only trigger a Docker build and not a push - if: github.event_name != 'pull_request' + if: ${{ ! matrix.isPr }} uses: docker/login-action@v2 with: username: ${{ secrets.DOCKER_USERNAME }} @@ -73,7 +83,7 @@ jobs: id: meta_build uses: docker/metadata-action@v4 with: - images: dspace/dspace-angular + images: ${{ env.REGISTRY_IMAGE }} tags: ${{ env.IMAGE_TAGS }} flavor: ${{ env.TAGS_FLAVOR }} @@ -84,22 +94,89 @@ jobs: with: context: . file: ./Dockerfile - platforms: ${{ env.PLATFORMS }} + platforms: ${{ matrix.arch }} # For pull requests, we run the Docker build (to ensure no PR changes break the build), # but we ONLY do an image push to DockerHub if it's NOT a PR - push: ${{ github.event_name != 'pull_request' }} + push: ${{ ! matrix.isPr }} # Use tags / labels provided by 'docker/metadata-action' above tags: ${{ steps.meta_build.outputs.tags }} labels: ${{ steps.meta_build.outputs.labels }} + - name: Export digest + if: ${{ ! matrix.isPr }} + run: | + mkdir -p /tmp/digests + digest="${{ steps.docker_build.outputs.digest }}" + touch "/tmp/digests/${digest#sha256:}" + + - name: Upload digest + if: ${{ ! matrix.isPr }} + uses: actions/upload-artifact@v3 + with: + name: digests + path: /tmp/digests/* + if-no-files-found: error + retention-days: 1 + + merge: + if: ${{ github.event_name != 'pull_request' }} + runs-on: ubuntu-latest + needs: + - dspace-angular + steps: + - name: Download digests + uses: actions/download-artifact@v3 + with: + name: digests + path: /tmp/digests + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY_IMAGE }} + tags: ${{ env.IMAGE_TAGS }} + flavor: ${{ env.TAGS_FLAVOR }} + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_ACCESS_TOKEN }} + + - name: Create manifest list and push + working-directory: /tmp/digests + run: | + docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ + $(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *) + + - name: Inspect image + run: | + docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }} + ############################################################# - # Build/Push the 'dspace/dspace-angular' image ('-dist' tag) + # Build/Push the '${{ env.REGISTRY_IMAGE }}' image ('-dist' tag) ############################################################# dspace-angular-dist: # Ensure this job never runs on forked repos. It's only executed for 'dspace/dspace-angular' if: github.repository == 'dspace/dspace-angular' - runs-on: ubuntu-latest + strategy: + matrix: + isPr: + - ${{ github.event_name == 'pull_request' }} + # Architectures / Platforms for which we will build Docker images + # If this is a PR, we ONLY build for AMD64. For PRs we only do a sanity check test to ensure Docker builds work. + # If this is NOT a PR (e.g. a tag or merge commit), also build for ARM64. + arch: ['linux/amd64', 'linux/arm64'] + os: [ubuntu-latest] + exclude: + - isPr: true + os: ubuntu-latest + arch: linux/arm64 + + runs-on: ${{ matrix.os }} steps: # https://github.com/actions/checkout - name: Checkout codebase @@ -116,7 +193,7 @@ jobs: # https://github.com/docker/login-action - name: Login to DockerHub # Only login if not a PR, as PRs only trigger a Docker build and not a push - if: github.event_name != 'pull_request' + if: ${{ ! matrix.isPr }} uses: docker/login-action@v2 with: username: ${{ secrets.DOCKER_USERNAME }} @@ -128,10 +205,10 @@ jobs: id: meta_build_dist uses: docker/metadata-action@v4 with: - images: dspace/dspace-angular + images: ${{ env.REGISTRY_IMAGE }} tags: ${{ env.IMAGE_TAGS }} # As this is a "dist" image, its tags are all suffixed with "-dist". Otherwise, it uses the same - # tagging logic as the primary 'dspace/dspace-angular' image above. + # tagging logic as the primary '${{ env.REGISTRY_IMAGE }}' image above. flavor: ${{ env.TAGS_FLAVOR }} suffix=-dist @@ -141,10 +218,66 @@ jobs: with: context: . file: ./Dockerfile.dist - platforms: ${{ env.PLATFORMS }} + platforms: ${{ matrix.arch }} # For pull requests, we run the Docker build (to ensure no PR changes break the build), # but we ONLY do an image push to DockerHub if it's NOT a PR - push: ${{ github.event_name != 'pull_request' }} + push: ${{ ! matrix.isPr }} # Use tags / labels provided by 'docker/metadata-action' above tags: ${{ steps.meta_build_dist.outputs.tags }} labels: ${{ steps.meta_build_dist.outputs.labels }} + + - name: Export digest + if: ${{ ! matrix.isPr }} + run: | + mkdir -p /tmp/digests/dist + digest="${{ steps.docker_build_dist.outputs.digest }}" + touch "/tmp/digests/dist/${digest#sha256:}" + + - name: Upload digest + if: ${{ ! matrix.isPr }} + uses: actions/upload-artifact@v3 + with: + name: digests + path: /tmp/digests/dist/* + if-no-files-found: error + retention-days: 1 + + merge-dist: + if: ${{ github.event_name != 'pull_request' }} + runs-on: ubuntu-latest + needs: + - dspace-angular-dist + steps: + - name: Download digests + uses: actions/download-artifact@v3 + with: + name: digests + path: /tmp/digests + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Docker meta + id: meta_dist + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY_IMAGE }} + tags: ${{ env.IMAGE_TAGS }} + # As this is a "dist" image, its tags are all suffixed with "-dist". Otherwise, it uses the same + # tagging logic as the primary '${{ env.REGISTRY_IMAGE }}' image above. + flavor: ${{ env.TAGS_FLAVOR }} + suffix=-dist + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_ACCESS_TOKEN }} + + - name: Create manifest list and push + working-directory: /tmp/digests/dist + run: | + docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ + $(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *) + + - name: Inspect image + run: | + docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta_dist.outputs.version }} From 526da8cddf45e09bee4df4c73a9c389659a2c6cf Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 17 Nov 2023 09:31:09 -0600 Subject: [PATCH 0008/1286] Fix bug in Docker manifest. Each build must use a separate artifact to store digests. Other minor cleanup & comments added. --- .github/workflows/docker.yml | 81 ++++++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 31 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 18bdef78be..23919d573c 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -42,13 +42,13 @@ jobs: strategy: matrix: - isPr: - - ${{ github.event_name == 'pull_request' }} # Architectures / Platforms for which we will build Docker images - # If this is a PR, we ONLY build for AMD64. For PRs we only do a sanity check test to ensure Docker builds work. - # If this is NOT a PR (e.g. a tag or merge commit), also build for ARM64. arch: ['linux/amd64', 'linux/arm64'] os: [ubuntu-latest] + isPr: + - ${{ github.event_name == 'pull_request' }} + # If this is a PR, we ONLY build for AMD64. For PRs we only do a sanity check test to ensure Docker builds work. + # The below exclude therefore ensures we do NOT build ARM64 for PRs. exclude: - isPr: true os: ubuntu-latest @@ -58,21 +58,21 @@ jobs: steps: # https://github.com/actions/checkout - name: Checkout codebase - uses: actions/checkout@v3 + uses: actions/checkout@v4 # https://github.com/docker/setup-buildx-action - name: Setup Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 # https://github.com/docker/setup-qemu-action - name: Set up QEMU emulation to build for multiple architectures - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 # https://github.com/docker/login-action - name: Login to DockerHub # Only login if not a PR, as PRs only trigger a Docker build and not a push if: ${{ ! matrix.isPr }} - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_ACCESS_TOKEN }} @@ -81,7 +81,7 @@ jobs: # Get Metadata for docker_build step below - name: Sync metadata (tags, labels) from GitHub to Docker for 'dspace-angular' image id: meta_build - uses: docker/metadata-action@v4 + uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY_IMAGE }} tags: ${{ env.IMAGE_TAGS }} @@ -90,7 +90,7 @@ jobs: # https://github.com/docker/build-push-action - name: Build and push 'dspace-angular' image id: docker_build - uses: docker/build-push-action@v4 + uses: docker/build-push-action@v5 with: context: . file: ./Dockerfile @@ -102,6 +102,7 @@ jobs: tags: ${{ steps.meta_build.outputs.tags }} labels: ${{ steps.meta_build.outputs.labels }} + # Export the digest of Docker build locally (for non PRs only) - name: Export digest if: ${{ ! matrix.isPr }} run: | @@ -109,6 +110,7 @@ jobs: digest="${{ steps.docker_build.outputs.digest }}" touch "/tmp/digests/${digest#sha256:}" + # Upload digest to an artifact, so that it can be used in manifest below - name: Upload digest if: ${{ ! matrix.isPr }} uses: actions/upload-artifact@v3 @@ -118,7 +120,12 @@ jobs: if-no-files-found: error retention-days: 1 - merge: + # Merge digests into a manifest. + # This runs after all Docker builds complete above, and it tells hub.docker.com + # that these builds should be all included in the manifest for this tag. + # (e.g. AMD64 and ARM64 should be listed as options under the same tagged Docker image) + # Borrowed from https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners + dspace-angular_manifest: if: ${{ github.event_name != 'pull_request' }} runs-on: ubuntu-latest needs: @@ -129,9 +136,11 @@ jobs: with: name: digests path: /tmp/digests + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - - name: Docker meta + + - name: Add Docker metadata for image id: meta uses: docker/metadata-action@v5 with: @@ -145,7 +154,7 @@ jobs: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_ACCESS_TOKEN }} - - name: Create manifest list and push + - name: Create manifest list from digests and push working-directory: /tmp/digests run: | docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ @@ -164,13 +173,13 @@ jobs: strategy: matrix: - isPr: - - ${{ github.event_name == 'pull_request' }} # Architectures / Platforms for which we will build Docker images - # If this is a PR, we ONLY build for AMD64. For PRs we only do a sanity check test to ensure Docker builds work. - # If this is NOT a PR (e.g. a tag or merge commit), also build for ARM64. arch: ['linux/amd64', 'linux/arm64'] os: [ubuntu-latest] + isPr: + - ${{ github.event_name == 'pull_request' }} + # If this is a PR, we ONLY build for AMD64. For PRs we only do a sanity check test to ensure Docker builds work. + # The below exclude therefore ensures we do NOT build ARM64 for PRs. exclude: - isPr: true os: ubuntu-latest @@ -180,21 +189,21 @@ jobs: steps: # https://github.com/actions/checkout - name: Checkout codebase - uses: actions/checkout@v3 + uses: actions/checkout@v4 # https://github.com/docker/setup-buildx-action - name: Setup Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 # https://github.com/docker/setup-qemu-action - name: Set up QEMU emulation to build for multiple architectures - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 # https://github.com/docker/login-action - name: Login to DockerHub # Only login if not a PR, as PRs only trigger a Docker build and not a push if: ${{ ! matrix.isPr }} - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_ACCESS_TOKEN }} @@ -203,7 +212,7 @@ jobs: # Get Metadata for docker_build_dist step below - name: Sync metadata (tags, labels) from GitHub to Docker for 'dspace-angular-dist' image id: meta_build_dist - uses: docker/metadata-action@v4 + uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY_IMAGE }} tags: ${{ env.IMAGE_TAGS }} @@ -214,7 +223,7 @@ jobs: - name: Build and push 'dspace-angular-dist' image id: docker_build_dist - uses: docker/build-push-action@v4 + uses: docker/build-push-action@v5 with: context: . file: ./Dockerfile.dist @@ -226,6 +235,7 @@ jobs: tags: ${{ steps.meta_build_dist.outputs.tags }} labels: ${{ steps.meta_build_dist.outputs.labels }} + # Export the digest of Docker build locally (for non PRs only) - name: Export digest if: ${{ ! matrix.isPr }} run: | @@ -233,29 +243,38 @@ jobs: digest="${{ steps.docker_build_dist.outputs.digest }}" touch "/tmp/digests/dist/${digest#sha256:}" + # Upload Digest to an artifact, so that it can be used in manifest below - name: Upload digest if: ${{ ! matrix.isPr }} uses: actions/upload-artifact@v3 with: - name: digests - path: /tmp/digests/dist/* + # NOTE: It's important that this artifact has a unique name so that two + # image builds don't upload digests to the same artifact. + name: digests-dist + path: /tmp/digests/* if-no-files-found: error retention-days: 1 - merge-dist: + # Merge *-dist digests into a manifest. + # This runs after all Docker builds complete above, and it tells hub.docker.com + # that these builds should be all included in the manifest for this tag. + # (e.g. AMD64 and ARM64 should be listed as options under the same tagged Docker image) + dspace-angular-dist_manifest: if: ${{ github.event_name != 'pull_request' }} runs-on: ubuntu-latest needs: - dspace-angular-dist steps: - - name: Download digests + - name: Download digests for -dist builds uses: actions/download-artifact@v3 with: - name: digests + name: digests-dist path: /tmp/digests + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - - name: Docker meta + + - name: Add Docker metadata for image id: meta_dist uses: docker/metadata-action@v5 with: @@ -272,8 +291,8 @@ jobs: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_ACCESS_TOKEN }} - - name: Create manifest list and push - working-directory: /tmp/digests/dist + - name: Create manifest list from digests and push + working-directory: /tmp/digests run: | docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ $(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *) From 63e792990f46620f510013fea569a76abb1ba653 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 17 Nov 2023 11:56:48 -0600 Subject: [PATCH 0009/1286] Fix directory structure for -dist digests --- .github/workflows/docker.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 23919d573c..04112f7b70 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -239,9 +239,9 @@ jobs: - name: Export digest if: ${{ ! matrix.isPr }} run: | - mkdir -p /tmp/digests/dist + mkdir -p /tmp/digests digest="${{ steps.docker_build_dist.outputs.digest }}" - touch "/tmp/digests/dist/${digest#sha256:}" + touch "/tmp/digests/${digest#sha256:}" # Upload Digest to an artifact, so that it can be used in manifest below - name: Upload digest From 5ab87ec6c31d736b8eae0891aad92c20228d301d Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 17 Nov 2023 11:05:46 -0600 Subject: [PATCH 0010/1286] Update GH actions to latest versions. Fix bug in codecov to ensure it retries on error. --- .github/workflows/build.yml | 16 ++++++++++------ .github/workflows/codescan.yml | 2 +- .github/workflows/port_merged_pull_request.yml | 4 ++-- .github/workflows/pull_request_opened.yml | 2 +- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 219074780e..e2680420a2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,11 +43,11 @@ jobs: steps: # https://github.com/actions/checkout - name: Checkout codebase - uses: actions/checkout@v3 + uses: actions/checkout@v4 # https://github.com/actions/setup-node - name: Install Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} @@ -118,7 +118,7 @@ jobs: # https://github.com/cypress-io/github-action # (NOTE: to run these e2e tests locally, just use 'ng e2e') - name: Run e2e tests (integration tests) - uses: cypress-io/github-action@v5 + uses: cypress-io/github-action@v6 with: # Run tests in Chrome, headless mode (default) browser: chrome @@ -191,7 +191,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Download artifacts from previous 'tests' job - name: Download coverage artifacts @@ -203,10 +203,14 @@ jobs: # Retry action: https://github.com/marketplace/actions/retry-action # Codecov action: https://github.com/codecov/codecov-action - name: Upload coverage to Codecov.io - uses: Wandalen/wretry.action@v1.0.36 + uses: Wandalen/wretry.action@v1.3.0 with: action: codecov/codecov-action@v3 - # Try upload 5 times max + # Ensure codecov-action throws an error when it fails to upload + # This allows us to auto-restart the action if an error is thrown + with: | + fail_ci_if_error: true + # Try re-running action 5 times max attempt_limit: 5 # Run again in 30 seconds attempt_delay: 30000 diff --git a/.github/workflows/codescan.yml b/.github/workflows/codescan.yml index 8b415296c7..d96e786cc3 100644 --- a/.github/workflows/codescan.yml +++ b/.github/workflows/codescan.yml @@ -35,7 +35,7 @@ jobs: steps: # https://github.com/actions/checkout - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Initializes the CodeQL tools for scanning. # https://github.com/github/codeql-action diff --git a/.github/workflows/port_merged_pull_request.yml b/.github/workflows/port_merged_pull_request.yml index 109835d14d..857f22755e 100644 --- a/.github/workflows/port_merged_pull_request.yml +++ b/.github/workflows/port_merged_pull_request.yml @@ -23,11 +23,11 @@ jobs: if: github.event.pull_request.merged steps: # Checkout code - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 # Port PR to other branch (ONLY if labeled with "port to") # See https://github.com/korthout/backport-action - name: Create backport pull requests - uses: korthout/backport-action@v1 + uses: korthout/backport-action@v2 with: # Trigger based on a "port to [branch]" label on PR # (This label must specify the branch name to port to) diff --git a/.github/workflows/pull_request_opened.yml b/.github/workflows/pull_request_opened.yml index 9b61af72d1..f16e81c9fd 100644 --- a/.github/workflows/pull_request_opened.yml +++ b/.github/workflows/pull_request_opened.yml @@ -21,4 +21,4 @@ jobs: # Assign the PR to whomever created it. This is useful for visualizing assignments on project boards # See https://github.com/toshimaru/auto-author-assign - name: Assign PR to creator - uses: toshimaru/auto-author-assign@v1.6.2 + uses: toshimaru/auto-author-assign@v2.0.1 From 62ccd18345e5be5171bc33479d7aa65e7dfc81f5 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 21 Nov 2023 12:15:42 -0600 Subject: [PATCH 0011/1286] Trigger redeploy of demo/sandbox from GitHub Actions after DockerHub image updated. --- .github/workflows/docker.yml | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 04112f7b70..c482d8f29a 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -23,8 +23,8 @@ env: # For a new commit on other branches, use the branch name as the tag for Docker image. # For a new tag, copy that tag name as the tag for Docker image. IMAGE_TAGS: | - type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }} - type=ref,event=branch,enable=${{ !endsWith(github.ref, github.event.repository.default_branch) }} + type=raw,value=latest,enable=${{ github.ref_name == github.event.repository.default_branch }} + type=ref,event=branch,enable=${{ github.ref_name != github.event.repository.default_branch }} type=ref,event=tag # Define default tag "flavor" for docker/metadata-action per # https://github.com/docker/metadata-action#flavor-input @@ -300,3 +300,25 @@ jobs: - name: Inspect image run: | docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta_dist.outputs.version }} + + # Deploy latest -dist image to Demo or Sandbox site, based on the branch updated + dspace-angular-dist_deploy: + if: ${{ github.event_name != 'pull_request' }} + runs-on: ubuntu-latest + needs: + # Requires manifest to be fully updated on DockerHub + - dspace-angular-dist_manifest + steps: + - name: Redeploy sandbox.dspace.org (based on main branch) + if: ${{ github.ref_name == github.event.repository.default_branch }} + run: | + curl -X POST -d '{}' $REDEPLOY_SANDBOX_URL + env: + REDEPLOY_SANDBOX_URL: ${{ secrets.REDEPLOY_SANDBOX_URL }} + + - name: Redeploy demo.dspace.org (based on maintenace branch) + if: ${{ github.ref_name == 'dspace-7_x' }} + run: | + curl -X POST -d '{}' $REDEPLOY_DEMO_URL + env: + REDEPLOY_DEMO_URL: ${{ secrets.REDEPLOY_DEMO_URL }} From 9c3e3d9c29189b667d49473456e2e5d74ce099f2 Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Wed, 22 Nov 2023 14:51:17 +0100 Subject: [PATCH 0012/1286] 108608: Created new ScopeSelectorModal & ScopeSelectorModalCurrent context --- src/app/core/shared/context.model.ts | 2 ++ ...issue-sidebar-search-list-element.component.ts | 2 ++ ...olume-sidebar-search-list-element.component.ts | 2 ++ ...urnal-sidebar-search-list-element.component.ts | 2 ++ ...-unit-sidebar-search-list-element.component.ts | 2 ++ ...erson-sidebar-search-list-element.component.ts | 2 ++ ...oject-sidebar-search-list-element.component.ts | 2 ++ .../dso-selector/dso-selector.component.ts | 15 ++++++++++++++- ...ction-sidebar-search-list-element.component.ts | 2 ++ ...unity-sidebar-search-list-element.component.ts | 2 ++ ...ation-sidebar-search-list-element.component.ts | 4 ++-- .../scope-selector-modal.component.html | 4 +++- .../scope-selector-modal.component.ts | 4 ++++ 13 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/app/core/shared/context.model.ts b/src/app/core/shared/context.model.ts index 126896e3e1..18d40d9cb6 100644 --- a/src/app/core/shared/context.model.ts +++ b/src/app/core/shared/context.model.ts @@ -15,4 +15,6 @@ export enum Context { AdminWorkflowSearch = 'adminWorkflowSearch', SideBarSearchModal = 'sideBarSearchModal', SideBarSearchModalCurrent = 'sideBarSearchModalCurrent', + ScopeSelectorModal = 'scopeSelectorModal', + ScopeSelectorModalCurrent = 'scopeSelectorModalCurrent', } diff --git a/src/app/entity-groups/journal-entities/item-list-elements/sidebar-search-list-elements/journal-issue/journal-issue-sidebar-search-list-element.component.ts b/src/app/entity-groups/journal-entities/item-list-elements/sidebar-search-list-elements/journal-issue/journal-issue-sidebar-search-list-element.component.ts index 84764e9e60..733cadf0c5 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/sidebar-search-list-elements/journal-issue/journal-issue-sidebar-search-list-element.component.ts +++ b/src/app/entity-groups/journal-entities/item-list-elements/sidebar-search-list-elements/journal-issue/journal-issue-sidebar-search-list-element.component.ts @@ -9,6 +9,8 @@ import { isNotEmpty } from '../../../../../shared/empty.util'; @listableObjectComponent('JournalIssueSearchResult', ViewMode.ListElement, Context.SideBarSearchModal) @listableObjectComponent('JournalIssueSearchResult', ViewMode.ListElement, Context.SideBarSearchModalCurrent) +@listableObjectComponent('JournalIssueSearchResult', ViewMode.ListElement, Context.ScopeSelectorModal) +@listableObjectComponent('JournalIssueSearchResult', ViewMode.ListElement, Context.ScopeSelectorModalCurrent) @Component({ selector: 'ds-journal-issue-sidebar-search-list-element', templateUrl: '../../../../../shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.html' diff --git a/src/app/entity-groups/journal-entities/item-list-elements/sidebar-search-list-elements/journal-volume/journal-volume-sidebar-search-list-element.component.ts b/src/app/entity-groups/journal-entities/item-list-elements/sidebar-search-list-elements/journal-volume/journal-volume-sidebar-search-list-element.component.ts index 7af5487f40..cebb3c1542 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/sidebar-search-list-elements/journal-volume/journal-volume-sidebar-search-list-element.component.ts +++ b/src/app/entity-groups/journal-entities/item-list-elements/sidebar-search-list-elements/journal-volume/journal-volume-sidebar-search-list-element.component.ts @@ -9,6 +9,8 @@ import { isNotEmpty } from '../../../../../shared/empty.util'; @listableObjectComponent('JournalVolumeSearchResult', ViewMode.ListElement, Context.SideBarSearchModal) @listableObjectComponent('JournalVolumeSearchResult', ViewMode.ListElement, Context.SideBarSearchModalCurrent) +@listableObjectComponent('JournalVolumeSearchResult', ViewMode.ListElement, Context.ScopeSelectorModal) +@listableObjectComponent('JournalVolumeSearchResult', ViewMode.ListElement, Context.ScopeSelectorModalCurrent) @Component({ selector: 'ds-journal-volume-sidebar-search-list-element', templateUrl: '../../../../../shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.html' diff --git a/src/app/entity-groups/journal-entities/item-list-elements/sidebar-search-list-elements/journal/journal-sidebar-search-list-element.component.ts b/src/app/entity-groups/journal-entities/item-list-elements/sidebar-search-list-elements/journal/journal-sidebar-search-list-element.component.ts index 4a26b293d9..a3cdaf24a3 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/sidebar-search-list-elements/journal/journal-sidebar-search-list-element.component.ts +++ b/src/app/entity-groups/journal-entities/item-list-elements/sidebar-search-list-elements/journal/journal-sidebar-search-list-element.component.ts @@ -9,6 +9,8 @@ import { isNotEmpty } from '../../../../../shared/empty.util'; @listableObjectComponent('JournalSearchResult', ViewMode.ListElement, Context.SideBarSearchModal) @listableObjectComponent('JournalSearchResult', ViewMode.ListElement, Context.SideBarSearchModalCurrent) +@listableObjectComponent('JournalSearchResult', ViewMode.ListElement, Context.ScopeSelectorModal) +@listableObjectComponent('JournalSearchResult', ViewMode.ListElement, Context.ScopeSelectorModalCurrent) @Component({ selector: 'ds-journal-sidebar-search-list-element', templateUrl: '../../../../../shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.html' diff --git a/src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/org-unit/org-unit-sidebar-search-list-element.component.ts b/src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/org-unit/org-unit-sidebar-search-list-element.component.ts index 17e9790593..2e1d88bf03 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/org-unit/org-unit-sidebar-search-list-element.component.ts +++ b/src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/org-unit/org-unit-sidebar-search-list-element.component.ts @@ -8,6 +8,8 @@ import { Item } from '../../../../../core/shared/item.model'; @listableObjectComponent('OrgUnitSearchResult', ViewMode.ListElement, Context.SideBarSearchModal) @listableObjectComponent('OrgUnitSearchResult', ViewMode.ListElement, Context.SideBarSearchModalCurrent) +@listableObjectComponent('OrgUnitSearchResult', ViewMode.ListElement, Context.ScopeSelectorModal) +@listableObjectComponent('OrgUnitSearchResult', ViewMode.ListElement, Context.ScopeSelectorModalCurrent) @Component({ selector: 'ds-org-unit-sidebar-search-list-element', templateUrl: '../../../../../shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.html' diff --git a/src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/person/person-sidebar-search-list-element.component.ts b/src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/person/person-sidebar-search-list-element.component.ts index 281f22ddb4..2d56d79438 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/person/person-sidebar-search-list-element.component.ts +++ b/src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/person/person-sidebar-search-list-element.component.ts @@ -13,6 +13,8 @@ import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service @listableObjectComponent('PersonSearchResult', ViewMode.ListElement, Context.SideBarSearchModal) @listableObjectComponent('PersonSearchResult', ViewMode.ListElement, Context.SideBarSearchModalCurrent) +@listableObjectComponent('PersonSearchResult', ViewMode.ListElement, Context.ScopeSelectorModal) +@listableObjectComponent('PersonSearchResult', ViewMode.ListElement, Context.ScopeSelectorModalCurrent) @Component({ selector: 'ds-person-sidebar-search-list-element', templateUrl: '../../../../../shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.html' diff --git a/src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/project/project-sidebar-search-list-element.component.ts b/src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/project/project-sidebar-search-list-element.component.ts index 6fbb9d26fc..233216f206 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/project/project-sidebar-search-list-element.component.ts +++ b/src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/project/project-sidebar-search-list-element.component.ts @@ -8,6 +8,8 @@ import { Item } from '../../../../../core/shared/item.model'; @listableObjectComponent('ProjectSearchResult', ViewMode.ListElement, Context.SideBarSearchModal) @listableObjectComponent('ProjectSearchResult', ViewMode.ListElement, Context.SideBarSearchModalCurrent) +@listableObjectComponent('ProjectSearchResult', ViewMode.ListElement, Context.ScopeSelectorModal) +@listableObjectComponent('ProjectSearchResult', ViewMode.ListElement, Context.ScopeSelectorModalCurrent) @Component({ selector: 'ds-project-sidebar-search-list-element', templateUrl: '../../../../../shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.html' diff --git a/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts b/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts index 82ad095cd4..64ee2278c6 100644 --- a/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts +++ b/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts @@ -50,6 +50,12 @@ export class DSOSelectorComponent implements OnInit, OnDestroy { * The view mode of the listed objects */ viewMode = ViewMode.ListElement; + + /** + * The current context + */ + @Input() context: Context; + /** * The initially selected DSO's uuid */ @@ -243,7 +249,14 @@ export class DSOSelectorComponent implements OnInit, OnDestroy { /** * Get the context for element with the given id */ - getContext(id: string) { + getContext(id: string): Context { + if (this.context === Context.ScopeSelectorModal) { + if (id === this.currentDSOId) { + return Context.ScopeSelectorModalCurrent; + } else { + return Context.ScopeSelectorModal; + } + } if (id === this.currentDSOId) { return Context.SideBarSearchModalCurrent; } else { diff --git a/src/app/shared/object-list/sidebar-search-list-element/collection/collection-sidebar-search-list-element.component.ts b/src/app/shared/object-list/sidebar-search-list-element/collection/collection-sidebar-search-list-element.component.ts index 13703240f4..b94b3766c3 100644 --- a/src/app/shared/object-list/sidebar-search-list-element/collection/collection-sidebar-search-list-element.component.ts +++ b/src/app/shared/object-list/sidebar-search-list-element/collection/collection-sidebar-search-list-element.component.ts @@ -8,6 +8,8 @@ import { SidebarSearchListElementComponent } from '../sidebar-search-list-elemen @listableObjectComponent(CollectionSearchResult, ViewMode.ListElement, Context.SideBarSearchModal) @listableObjectComponent(CollectionSearchResult, ViewMode.ListElement, Context.SideBarSearchModalCurrent) +@listableObjectComponent(CollectionSearchResult, ViewMode.ListElement, Context.ScopeSelectorModal) +@listableObjectComponent(CollectionSearchResult, ViewMode.ListElement, Context.ScopeSelectorModalCurrent) @Component({ selector: 'ds-collection-sidebar-search-list-element', templateUrl: '../sidebar-search-list-element.component.html' diff --git a/src/app/shared/object-list/sidebar-search-list-element/community/community-sidebar-search-list-element.component.ts b/src/app/shared/object-list/sidebar-search-list-element/community/community-sidebar-search-list-element.component.ts index 14c8ec09cd..b50e2c6980 100644 --- a/src/app/shared/object-list/sidebar-search-list-element/community/community-sidebar-search-list-element.component.ts +++ b/src/app/shared/object-list/sidebar-search-list-element/community/community-sidebar-search-list-element.component.ts @@ -8,6 +8,8 @@ import { Community } from '../../../../core/shared/community.model'; @listableObjectComponent(CommunitySearchResult, ViewMode.ListElement, Context.SideBarSearchModal) @listableObjectComponent(CommunitySearchResult, ViewMode.ListElement, Context.SideBarSearchModalCurrent) +@listableObjectComponent(CommunitySearchResult, ViewMode.ListElement, Context.ScopeSelectorModal) +@listableObjectComponent(CommunitySearchResult, ViewMode.ListElement, Context.ScopeSelectorModalCurrent) @Component({ selector: 'ds-collection-sidebar-search-list-element', templateUrl: '../sidebar-search-list-element.component.html' diff --git a/src/app/shared/object-list/sidebar-search-list-element/item-types/publication/publication-sidebar-search-list-element.component.ts b/src/app/shared/object-list/sidebar-search-list-element/item-types/publication/publication-sidebar-search-list-element.component.ts index 0822accc50..f77263df40 100644 --- a/src/app/shared/object-list/sidebar-search-list-element/item-types/publication/publication-sidebar-search-list-element.component.ts +++ b/src/app/shared/object-list/sidebar-search-list-element/item-types/publication/publication-sidebar-search-list-element.component.ts @@ -8,8 +8,8 @@ import { SidebarSearchListElementComponent } from '../../sidebar-search-list-ele @listableObjectComponent('PublicationSearchResult', ViewMode.ListElement, Context.SideBarSearchModal) @listableObjectComponent('PublicationSearchResult', ViewMode.ListElement, Context.SideBarSearchModalCurrent) -@listableObjectComponent(ItemSearchResult, ViewMode.ListElement, Context.SideBarSearchModal) -@listableObjectComponent(ItemSearchResult, ViewMode.ListElement, Context.SideBarSearchModalCurrent) +@listableObjectComponent(ItemSearchResult, ViewMode.ListElement, Context.ScopeSelectorModal) +@listableObjectComponent(ItemSearchResult, ViewMode.ListElement, Context.ScopeSelectorModalCurrent) @Component({ selector: 'ds-publication-sidebar-search-list-element', templateUrl: '../../sidebar-search-list-element.component.html' diff --git a/src/app/shared/search-form/scope-selector-modal/scope-selector-modal.component.html b/src/app/shared/search-form/scope-selector-modal/scope-selector-modal.component.html index bf5c15e963..2d8763383b 100644 --- a/src/app/shared/search-form/scope-selector-modal/scope-selector-modal.component.html +++ b/src/app/shared/search-form/scope-selector-modal/scope-selector-modal.component.html @@ -14,6 +14,8 @@
{{'dso-selector.' + action + '.' + objectType.toString().toLowerCase() + '.input-header' | translate}}
- + + diff --git a/src/app/shared/search-form/scope-selector-modal/scope-selector-modal.component.ts b/src/app/shared/search-form/scope-selector-modal/scope-selector-modal.component.ts index 86c3010287..e610d997c7 100644 --- a/src/app/shared/search-form/scope-selector-modal/scope-selector-modal.component.ts +++ b/src/app/shared/search-form/scope-selector-modal/scope-selector-modal.component.ts @@ -4,6 +4,7 @@ import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { DSpaceObjectType } from '../../../core/shared/dspace-object-type.model'; import { DSOSelectorModalWrapperComponent, SelectorActionType } from '../../dso-selector/modal-wrappers/dso-selector-modal-wrapper.component'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; +import { Context } from '../../../core/shared/context.model'; /** * Component to wrap a button - to select the entire repository - @@ -17,6 +18,9 @@ import { DSpaceObject } from '../../../core/shared/dspace-object.model'; templateUrl: './scope-selector-modal.component.html', }) export class ScopeSelectorModalComponent extends DSOSelectorModalWrapperComponent implements OnInit { + + readonly Context = Context; + objectType = DSpaceObjectType.COMMUNITY; /** * The types of DSO that can be selected from this list From bd78acd5594492a4e87e09e3a68d5570368290be Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 22 Nov 2023 10:51:28 -0600 Subject: [PATCH 0013/1286] Redeploy demo/sandbox more quickly by only waiting for AMD64 image --- .github/workflows/docker.yml | 40 ++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index c482d8f29a..a581b63e7b 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -255,6 +255,24 @@ jobs: if-no-files-found: error retention-days: 1 + # If the 'linux/amd64' -dist image was just updated for the 'main' branch, + # Then redeploy https://sandbox.dspace.org using that updated image. + - name: Redeploy sandbox.dspace.org (based on main branch) + if: ${{ ! matrix.isPr && matrix.arch == 'linux/amd64' && github.ref_name == github.event.repository.default_branch }} + run: | + curl -X POST $REDEPLOY_SANDBOX_URL + env: + REDEPLOY_SANDBOX_URL: ${{ secrets.REDEPLOY_SANDBOX_URL }} + + # If the 'linux/amd64' -dist image was just updated for the maintenance branch, + # Then redeploy https://demo.dspace.org using that updated image. + - name: Redeploy demo.dspace.org (based on maintenace branch) + if: ${{ ! matrix.isPr && matrix.arch == 'linux/amd64' && github.ref_name == 'dspace-7_x' }} + run: | + curl -X POST $REDEPLOY_DEMO_URL + env: + REDEPLOY_DEMO_URL: ${{ secrets.REDEPLOY_DEMO_URL }} + # Merge *-dist digests into a manifest. # This runs after all Docker builds complete above, and it tells hub.docker.com # that these builds should be all included in the manifest for this tag. @@ -300,25 +318,3 @@ jobs: - name: Inspect image run: | docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta_dist.outputs.version }} - - # Deploy latest -dist image to Demo or Sandbox site, based on the branch updated - dspace-angular-dist_deploy: - if: ${{ github.event_name != 'pull_request' }} - runs-on: ubuntu-latest - needs: - # Requires manifest to be fully updated on DockerHub - - dspace-angular-dist_manifest - steps: - - name: Redeploy sandbox.dspace.org (based on main branch) - if: ${{ github.ref_name == github.event.repository.default_branch }} - run: | - curl -X POST -d '{}' $REDEPLOY_SANDBOX_URL - env: - REDEPLOY_SANDBOX_URL: ${{ secrets.REDEPLOY_SANDBOX_URL }} - - - name: Redeploy demo.dspace.org (based on maintenace branch) - if: ${{ github.ref_name == 'dspace-7_x' }} - run: | - curl -X POST -d '{}' $REDEPLOY_DEMO_URL - env: - REDEPLOY_DEMO_URL: ${{ secrets.REDEPLOY_DEMO_URL }} From c3f424dae4eaabcbf42d31af5cdd2ffd5f65278c Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Sat, 18 Nov 2023 15:24:56 +0100 Subject: [PATCH 0014/1286] 108587: Deselect all fields on component destruction (cherry picked from commit ecca8286b5e8c4d90d9d04e9ea71238dd5046f8e) --- .../metadata-schema/metadata-schema.component.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/app/admin/admin-registries/metadata-schema/metadata-schema.component.ts b/src/app/admin/admin-registries/metadata-schema/metadata-schema.component.ts index d0827e6e4d..4dec129ead 100644 --- a/src/app/admin/admin-registries/metadata-schema/metadata-schema.component.ts +++ b/src/app/admin/admin-registries/metadata-schema/metadata-schema.component.ts @@ -1,6 +1,6 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, OnDestroy } from '@angular/core'; import { RegistryService } from '../../../core/registry/registry.service'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute } from '@angular/router'; import { BehaviorSubject, combineLatest as observableCombineLatest, @@ -32,7 +32,7 @@ import { PaginationService } from '../../../core/pagination/pagination.service'; * A component used for managing all existing metadata fields within the current metadata schema. * The admin can create, edit or delete metadata fields here. */ -export class MetadataSchemaComponent implements OnInit { +export class MetadataSchemaComponent implements OnInit, OnDestroy { /** * The metadata schema */ @@ -60,7 +60,6 @@ export class MetadataSchemaComponent implements OnInit { constructor(private registryService: RegistryService, private route: ActivatedRoute, private notificationsService: NotificationsService, - private router: Router, private paginationService: PaginationService, private translateService: TranslateService) { @@ -86,7 +85,7 @@ export class MetadataSchemaComponent implements OnInit { */ private updateFields() { this.metadataFields$ = this.paginationService.getCurrentPagination(this.config.id, this.config).pipe( - switchMap((currentPagination) => combineLatest(this.metadataSchema$, this.needsUpdate$, observableOf(currentPagination))), + switchMap((currentPagination) => combineLatest([this.metadataSchema$, this.needsUpdate$, observableOf(currentPagination)])), switchMap(([schema, update, currentPagination]: [MetadataSchema, boolean, PaginationComponentOptions]) => { if (update) { this.needsUpdate$.next(false); @@ -193,10 +192,10 @@ export class MetadataSchemaComponent implements OnInit { showNotification(success: boolean, amount: number) { const prefix = 'admin.registries.schema.notification'; const suffix = success ? 'success' : 'failure'; - const messages = observableCombineLatest( + const messages = observableCombineLatest([ this.translateService.get(success ? `${prefix}.${suffix}` : `${prefix}.${suffix}`), this.translateService.get(`${prefix}.field.deleted.${suffix}`, { amount: amount }) - ); + ]); messages.subscribe(([head, content]) => { if (success) { this.notificationsService.success(head, content); @@ -207,6 +206,7 @@ export class MetadataSchemaComponent implements OnInit { } ngOnDestroy(): void { this.paginationService.clearPagination(this.config.id); + this.registryService.deselectAllMetadataField(); } } From b83a8421a3552efdb2eb92c1a4435f8472d75fe4 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 28 Nov 2023 16:04:50 -0600 Subject: [PATCH 0015/1286] Refactor to simply use the reusable-docker-build.yml from DSpace/DSpace. --- .github/workflows/docker.yml | 305 ++++------------------------------- 1 file changed, 30 insertions(+), 275 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index a581b63e7b..ece1f880c0 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -3,6 +3,9 @@ name: Docker images # Run this Build for all pushes to 'main' or maintenance branches, or tagged releases. # Also run for PRs to ensure PR doesn't break Docker build process +# NOTE: uses "reusable-docker-build.yml" in DSpace/DSpace to actually build each of the Docker images +# https://github.com/DSpace/DSpace/blob/main/.github/workflows/reusable-docker-build.yml +# on: push: branches: @@ -17,7 +20,6 @@ permissions: env: - REGISTRY_IMAGE: dspace/dspace-angular # Define tags to use for Docker images based on Git tags/branches (for docker/metadata-action) # For a new commit on default branch (main), use the literal tag 'latest' on Docker image. # For a new commit on other branches, use the branch name as the tag for Docker image. @@ -34,287 +36,40 @@ env: jobs: ############################################################# - # Build/Push the '${{ env.REGISTRY_IMAGE }}' image + # Build/Push the 'dspace/dspace-angular' image ############################################################# dspace-angular: # Ensure this job never runs on forked repos. It's only executed for 'dspace/dspace-angular' if: github.repository == 'dspace/dspace-angular' - - strategy: - matrix: - # Architectures / Platforms for which we will build Docker images - arch: ['linux/amd64', 'linux/arm64'] - os: [ubuntu-latest] - isPr: - - ${{ github.event_name == 'pull_request' }} - # If this is a PR, we ONLY build for AMD64. For PRs we only do a sanity check test to ensure Docker builds work. - # The below exclude therefore ensures we do NOT build ARM64 for PRs. - exclude: - - isPr: true - os: ubuntu-latest - arch: linux/arm64 - - runs-on: ${{ matrix.os }} - steps: - # https://github.com/actions/checkout - - name: Checkout codebase - uses: actions/checkout@v4 - - # https://github.com/docker/setup-buildx-action - - name: Setup Docker Buildx - uses: docker/setup-buildx-action@v3 - - # https://github.com/docker/setup-qemu-action - - name: Set up QEMU emulation to build for multiple architectures - uses: docker/setup-qemu-action@v3 - - # https://github.com/docker/login-action - - name: Login to DockerHub - # Only login if not a PR, as PRs only trigger a Docker build and not a push - if: ${{ ! matrix.isPr }} - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_ACCESS_TOKEN }} - - # https://github.com/docker/metadata-action - # Get Metadata for docker_build step below - - name: Sync metadata (tags, labels) from GitHub to Docker for 'dspace-angular' image - id: meta_build - uses: docker/metadata-action@v5 - with: - images: ${{ env.REGISTRY_IMAGE }} - tags: ${{ env.IMAGE_TAGS }} - flavor: ${{ env.TAGS_FLAVOR }} - - # https://github.com/docker/build-push-action - - name: Build and push 'dspace-angular' image - id: docker_build - uses: docker/build-push-action@v5 - with: - context: . - file: ./Dockerfile - platforms: ${{ matrix.arch }} - # For pull requests, we run the Docker build (to ensure no PR changes break the build), - # but we ONLY do an image push to DockerHub if it's NOT a PR - push: ${{ ! matrix.isPr }} - # Use tags / labels provided by 'docker/metadata-action' above - tags: ${{ steps.meta_build.outputs.tags }} - labels: ${{ steps.meta_build.outputs.labels }} - - # Export the digest of Docker build locally (for non PRs only) - - name: Export digest - if: ${{ ! matrix.isPr }} - run: | - mkdir -p /tmp/digests - digest="${{ steps.docker_build.outputs.digest }}" - touch "/tmp/digests/${digest#sha256:}" - - # Upload digest to an artifact, so that it can be used in manifest below - - name: Upload digest - if: ${{ ! matrix.isPr }} - uses: actions/upload-artifact@v3 - with: - name: digests - path: /tmp/digests/* - if-no-files-found: error - retention-days: 1 - - # Merge digests into a manifest. - # This runs after all Docker builds complete above, and it tells hub.docker.com - # that these builds should be all included in the manifest for this tag. - # (e.g. AMD64 and ARM64 should be listed as options under the same tagged Docker image) - # Borrowed from https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners - dspace-angular_manifest: - if: ${{ github.event_name != 'pull_request' }} - runs-on: ubuntu-latest - needs: - - dspace-angular - steps: - - name: Download digests - uses: actions/download-artifact@v3 - with: - name: digests - path: /tmp/digests - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Add Docker metadata for image - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.REGISTRY_IMAGE }} - tags: ${{ env.IMAGE_TAGS }} - flavor: ${{ env.TAGS_FLAVOR }} - - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_ACCESS_TOKEN }} - - - name: Create manifest list from digests and push - working-directory: /tmp/digests - run: | - docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - $(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *) - - - name: Inspect image - run: | - docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }} + # Use the reusable-docker-build.yml script from DSpace/DSpace repo to build our Docker image + uses: DSpace/DSpace/.github/workflows/reusable-docker-build.yml@main + with: + build_id: dspace-angular + image_name: dspace/dspace-angular + dockerfile_path: ./Dockerfile + secrets: + DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} + DOCKER_ACCESS_TOKEN: ${{ secrets.DOCKER_ACCESS_TOKEN }} ############################################################# - # Build/Push the '${{ env.REGISTRY_IMAGE }}' image ('-dist' tag) + # Build/Push the 'dspace/dspace-angular' image ('-dist' tag) ############################################################# dspace-angular-dist: # Ensure this job never runs on forked repos. It's only executed for 'dspace/dspace-angular' if: github.repository == 'dspace/dspace-angular' - - strategy: - matrix: - # Architectures / Platforms for which we will build Docker images - arch: ['linux/amd64', 'linux/arm64'] - os: [ubuntu-latest] - isPr: - - ${{ github.event_name == 'pull_request' }} - # If this is a PR, we ONLY build for AMD64. For PRs we only do a sanity check test to ensure Docker builds work. - # The below exclude therefore ensures we do NOT build ARM64 for PRs. - exclude: - - isPr: true - os: ubuntu-latest - arch: linux/arm64 - - runs-on: ${{ matrix.os }} - steps: - # https://github.com/actions/checkout - - name: Checkout codebase - uses: actions/checkout@v4 - - # https://github.com/docker/setup-buildx-action - - name: Setup Docker Buildx - uses: docker/setup-buildx-action@v3 - - # https://github.com/docker/setup-qemu-action - - name: Set up QEMU emulation to build for multiple architectures - uses: docker/setup-qemu-action@v3 - - # https://github.com/docker/login-action - - name: Login to DockerHub - # Only login if not a PR, as PRs only trigger a Docker build and not a push - if: ${{ ! matrix.isPr }} - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_ACCESS_TOKEN }} - - # https://github.com/docker/metadata-action - # Get Metadata for docker_build_dist step below - - name: Sync metadata (tags, labels) from GitHub to Docker for 'dspace-angular-dist' image - id: meta_build_dist - uses: docker/metadata-action@v5 - with: - images: ${{ env.REGISTRY_IMAGE }} - tags: ${{ env.IMAGE_TAGS }} - # As this is a "dist" image, its tags are all suffixed with "-dist". Otherwise, it uses the same - # tagging logic as the primary '${{ env.REGISTRY_IMAGE }}' image above. - flavor: ${{ env.TAGS_FLAVOR }} - suffix=-dist - - - name: Build and push 'dspace-angular-dist' image - id: docker_build_dist - uses: docker/build-push-action@v5 - with: - context: . - file: ./Dockerfile.dist - platforms: ${{ matrix.arch }} - # For pull requests, we run the Docker build (to ensure no PR changes break the build), - # but we ONLY do an image push to DockerHub if it's NOT a PR - push: ${{ ! matrix.isPr }} - # Use tags / labels provided by 'docker/metadata-action' above - tags: ${{ steps.meta_build_dist.outputs.tags }} - labels: ${{ steps.meta_build_dist.outputs.labels }} - - # Export the digest of Docker build locally (for non PRs only) - - name: Export digest - if: ${{ ! matrix.isPr }} - run: | - mkdir -p /tmp/digests - digest="${{ steps.docker_build_dist.outputs.digest }}" - touch "/tmp/digests/${digest#sha256:}" - - # Upload Digest to an artifact, so that it can be used in manifest below - - name: Upload digest - if: ${{ ! matrix.isPr }} - uses: actions/upload-artifact@v3 - with: - # NOTE: It's important that this artifact has a unique name so that two - # image builds don't upload digests to the same artifact. - name: digests-dist - path: /tmp/digests/* - if-no-files-found: error - retention-days: 1 - - # If the 'linux/amd64' -dist image was just updated for the 'main' branch, - # Then redeploy https://sandbox.dspace.org using that updated image. - - name: Redeploy sandbox.dspace.org (based on main branch) - if: ${{ ! matrix.isPr && matrix.arch == 'linux/amd64' && github.ref_name == github.event.repository.default_branch }} - run: | - curl -X POST $REDEPLOY_SANDBOX_URL - env: - REDEPLOY_SANDBOX_URL: ${{ secrets.REDEPLOY_SANDBOX_URL }} - - # If the 'linux/amd64' -dist image was just updated for the maintenance branch, - # Then redeploy https://demo.dspace.org using that updated image. - - name: Redeploy demo.dspace.org (based on maintenace branch) - if: ${{ ! matrix.isPr && matrix.arch == 'linux/amd64' && github.ref_name == 'dspace-7_x' }} - run: | - curl -X POST $REDEPLOY_DEMO_URL - env: - REDEPLOY_DEMO_URL: ${{ secrets.REDEPLOY_DEMO_URL }} - - # Merge *-dist digests into a manifest. - # This runs after all Docker builds complete above, and it tells hub.docker.com - # that these builds should be all included in the manifest for this tag. - # (e.g. AMD64 and ARM64 should be listed as options under the same tagged Docker image) - dspace-angular-dist_manifest: - if: ${{ github.event_name != 'pull_request' }} - runs-on: ubuntu-latest - needs: - - dspace-angular-dist - steps: - - name: Download digests for -dist builds - uses: actions/download-artifact@v3 - with: - name: digests-dist - path: /tmp/digests - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Add Docker metadata for image - id: meta_dist - uses: docker/metadata-action@v5 - with: - images: ${{ env.REGISTRY_IMAGE }} - tags: ${{ env.IMAGE_TAGS }} - # As this is a "dist" image, its tags are all suffixed with "-dist". Otherwise, it uses the same - # tagging logic as the primary '${{ env.REGISTRY_IMAGE }}' image above. - flavor: ${{ env.TAGS_FLAVOR }} - suffix=-dist - - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_ACCESS_TOKEN }} - - - name: Create manifest list from digests and push - working-directory: /tmp/digests - run: | - docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - $(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *) - - - name: Inspect image - run: | - docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta_dist.outputs.version }} + # Use the reusable-docker-build.yml script from DSpace/DSpace repo to build our Docker image + uses: DSpace/DSpace/.github/workflows/reusable-docker-build.yml@main + with: + build_id: dspace-angular-dist + image_name: dspace/dspace-angular + dockerfile_path: ./Dockerfile.dist + # As this is a "dist" image, its tags are all suffixed with "-dist". Otherwise, it uses the same + # tagging logic as the primary 'dspace/dspace-angular' image above. + tags_flavor: suffix=-dist + secrets: + DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} + DOCKER_ACCESS_TOKEN: ${{ secrets.DOCKER_ACCESS_TOKEN }} + # Enable redeploy of sandbox & demo if the branch for this image matches the deployment branch of + # these sites as specified in reusable-docker-build.xml + REDEPLOY_SANDBOX_URL: ${{ secrets.REDEPLOY_SANDBOX_URL }} + REDEPLOY_DEMO_URL: ${{ secrets.REDEPLOY_DEMO_URL }} \ No newline at end of file From 65fff9361cc42e9a8d453f256cc2ad5ef04ce69d Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 28 Nov 2023 16:13:56 -0600 Subject: [PATCH 0016/1286] Use the script from the dspace-7_x branch --- .github/workflows/docker.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index ece1f880c0..5223ab100b 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -4,7 +4,7 @@ name: Docker images # Run this Build for all pushes to 'main' or maintenance branches, or tagged releases. # Also run for PRs to ensure PR doesn't break Docker build process # NOTE: uses "reusable-docker-build.yml" in DSpace/DSpace to actually build each of the Docker images -# https://github.com/DSpace/DSpace/blob/main/.github/workflows/reusable-docker-build.yml +# https://github.com/DSpace/DSpace/blob/dspace-7_x/.github/workflows/reusable-docker-build.yml # on: push: @@ -42,7 +42,7 @@ jobs: # Ensure this job never runs on forked repos. It's only executed for 'dspace/dspace-angular' if: github.repository == 'dspace/dspace-angular' # Use the reusable-docker-build.yml script from DSpace/DSpace repo to build our Docker image - uses: DSpace/DSpace/.github/workflows/reusable-docker-build.yml@main + uses: DSpace/DSpace/.github/workflows/reusable-docker-build.yml@dspace-7_x with: build_id: dspace-angular image_name: dspace/dspace-angular @@ -58,7 +58,7 @@ jobs: # Ensure this job never runs on forked repos. It's only executed for 'dspace/dspace-angular' if: github.repository == 'dspace/dspace-angular' # Use the reusable-docker-build.yml script from DSpace/DSpace repo to build our Docker image - uses: DSpace/DSpace/.github/workflows/reusable-docker-build.yml@main + uses: DSpace/DSpace/.github/workflows/reusable-docker-build.yml@dspace-7_x with: build_id: dspace-angular-dist image_name: dspace/dspace-angular From 92d25dd2a8a2003d53f466761217b8f84ee642b7 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 28 Nov 2023 16:50:55 -0600 Subject: [PATCH 0017/1286] Remove unused env variables --- .github/workflows/docker.yml | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 5223ab100b..3a3183f8cd 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -18,22 +18,6 @@ on: permissions: contents: read # to fetch code (actions/checkout) - -env: - # Define tags to use for Docker images based on Git tags/branches (for docker/metadata-action) - # For a new commit on default branch (main), use the literal tag 'latest' on Docker image. - # For a new commit on other branches, use the branch name as the tag for Docker image. - # For a new tag, copy that tag name as the tag for Docker image. - IMAGE_TAGS: | - type=raw,value=latest,enable=${{ github.ref_name == github.event.repository.default_branch }} - type=ref,event=branch,enable=${{ github.ref_name != github.event.repository.default_branch }} - type=ref,event=tag - # Define default tag "flavor" for docker/metadata-action per - # https://github.com/docker/metadata-action#flavor-input - # We manage the 'latest' tag ourselves to the 'main' branch (see settings above) - TAGS_FLAVOR: | - latest=false - jobs: ############################################################# # Build/Push the 'dspace/dspace-angular' image From 38752d9d71b2441b83bbcb616347df66b7fb5e75 Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Wed, 29 Nov 2023 14:25:36 +0100 Subject: [PATCH 0018/1286] ensure HALEndpointService doesn't use stale requests --- src/app/core/server-check/server-check.guard.spec.ts | 10 ++++++---- src/app/core/server-check/server-check.guard.ts | 6 ++---- src/app/core/shared/hal-endpoint.service.ts | 12 ++++++++---- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/app/core/server-check/server-check.guard.spec.ts b/src/app/core/server-check/server-check.guard.spec.ts index 044609ef42..f65a7deca7 100644 --- a/src/app/core/server-check/server-check.guard.spec.ts +++ b/src/app/core/server-check/server-check.guard.spec.ts @@ -9,7 +9,7 @@ import SpyObj = jasmine.SpyObj; describe('ServerCheckGuard', () => { let guard: ServerCheckGuard; let router: Router; - const eventSubject = new ReplaySubject(1); + let eventSubject: ReplaySubject; let rootDataServiceStub: SpyObj; let testScheduler: TestScheduler; let redirectUrlTree: UrlTree; @@ -24,6 +24,7 @@ describe('ServerCheckGuard', () => { findRoot: jasmine.createSpy('findRoot') }); redirectUrlTree = new UrlTree(); + eventSubject = new ReplaySubject(1); router = { events: eventSubject.asObservable(), navigateByUrl: jasmine.createSpy('navigateByUrl'), @@ -64,10 +65,10 @@ describe('ServerCheckGuard', () => { }); describe(`listenForRouteChanges`, () => { - it(`should retrieve the root endpoint, without using the cache, when the method is first called`, () => { + it(`should invalidate the root cache, when the method is first called`, () => { testScheduler.run(() => { guard.listenForRouteChanges(); - expect(rootDataServiceStub.findRoot).toHaveBeenCalledWith(false); + expect(rootDataServiceStub.invalidateRootCache).toHaveBeenCalledTimes(1); }); }); @@ -80,7 +81,8 @@ describe('ServerCheckGuard', () => { eventSubject.next(new NavigationEnd(2,'', '')); eventSubject.next(new NavigationStart(3,'')); }); - expect(rootDataServiceStub.invalidateRootCache).toHaveBeenCalledTimes(3); + // once when the method is first called, and then 3 times for NavigationStart events + expect(rootDataServiceStub.invalidateRootCache).toHaveBeenCalledTimes(1 + 3); }); }); }); diff --git a/src/app/core/server-check/server-check.guard.ts b/src/app/core/server-check/server-check.guard.ts index 65ca2b0c49..79c34c3659 100644 --- a/src/app/core/server-check/server-check.guard.ts +++ b/src/app/core/server-check/server-check.guard.ts @@ -53,10 +53,8 @@ export class ServerCheckGuard implements CanActivateChild { */ listenForRouteChanges(): void { // we'll always be too late for the first NavigationStart event with the router subscribe below, - // so this statement is for the very first route operation. A `find` without using the cache, - // rather than an invalidateRootCache, because invalidating as the app is bootstrapping can - // break other features - this.rootDataService.findRoot(false); + // so this statement is for the very first route operation. + this.rootDataService.invalidateRootCache(); this.router.events.pipe( filter(event => event instanceof NavigationStart), diff --git a/src/app/core/shared/hal-endpoint.service.ts b/src/app/core/shared/hal-endpoint.service.ts index 8b6316a6ce..98ab6a16ea 100644 --- a/src/app/core/shared/hal-endpoint.service.ts +++ b/src/app/core/shared/hal-endpoint.service.ts @@ -1,5 +1,5 @@ import { Observable } from 'rxjs'; -import { distinctUntilChanged, map, startWith, switchMap, take } from 'rxjs/operators'; +import { distinctUntilChanged, map, startWith, switchMap, take, skipWhile } from 'rxjs/operators'; import { RequestService } from '../data/request.service'; import { EndpointMapRequest } from '../data/request.models'; import { hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util'; @@ -9,7 +9,7 @@ import { EndpointMap } from '../cache/response.models'; import { getFirstCompletedRemoteData } from './operators'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { RemoteData } from '../data/remote-data'; -import { UnCacheableObject } from './uncacheable-object.model'; +import { CacheableObject } from '../cache/cacheable-object.model'; @Injectable() export class HALEndpointService { @@ -33,9 +33,13 @@ export class HALEndpointService { this.requestService.send(request, true); - return this.rdbService.buildFromHref(href).pipe( + return this.rdbService.buildFromHref(href).pipe( + // This skip ensures that if a stale object is present in the cache when you do a + // call it isn't immediately returned, but we wait until the remote data for the new request + // is created. + skipWhile((rd: RemoteData) => rd.isStale), getFirstCompletedRemoteData(), - map((response: RemoteData) => { + map((response: RemoteData) => { if (hasValue(response.payload)) { return response.payload._links; } else { From 9c69a77d435a8b19de86ceb4f0a66a2a8e036c99 Mon Sep 17 00:00:00 2001 From: Michael Spalti Date: Wed, 29 Nov 2023 15:42:30 -0800 Subject: [PATCH 0019/1286] Fix for thumbnail images in items. Revert changes in html template Revert changes in html template Revert changes in html template (cherry picked from commit 88c39e8b26d4418c370185467e2fee006c3cd811) --- src/app/item-page/media-viewer/media-viewer.component.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/item-page/media-viewer/media-viewer.component.ts b/src/app/item-page/media-viewer/media-viewer.component.ts index 242e50646e..5a17c4f01b 100644 --- a/src/app/item-page/media-viewer/media-viewer.component.ts +++ b/src/app/item-page/media-viewer/media-viewer.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnDestroy, OnInit } from '@angular/core'; +import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core'; import { BehaviorSubject, Observable } from 'rxjs'; import { filter, take } from 'rxjs/operators'; import { BitstreamDataService } from '../../core/data/bitstream-data.service'; @@ -42,6 +42,7 @@ export class MediaViewerComponent implements OnDestroy, OnInit { constructor( protected bitstreamDataService: BitstreamDataService, + protected changeDetectorRef: ChangeDetectorRef ) { } @@ -85,6 +86,7 @@ export class MediaViewerComponent implements OnDestroy, OnInit { })); } this.isLoading = false; + this.changeDetectorRef.detectChanges(); })); } })); From 3b568f7d32fc10fd003caf07a7af588817b24155 Mon Sep 17 00:00:00 2001 From: Michael Spalti Date: Mon, 4 Dec 2023 11:37:14 -0800 Subject: [PATCH 0020/1286] Updated bitstream read description in en.json5 (cherry picked from commit 2592f87356d1caa4f7d396f8e7f9188393e5efb7) --- src/assets/i18n/en.json5 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 6dee5d54e6..c39106ff1b 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1258,7 +1258,7 @@ "comcol-role.edit.bitstream_read.name": "Default bitstream read access", - "comcol-role.edit.bitstream_read.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", + "comcol-role.edit.bitstream_read.description": "E-People and Groups that can read new bitstreams submitted to this collection. Changes to this role are not retroactive. Existing bitstreams in the system will still be viewable by those who had read access at the time of their addition.", "comcol-role.edit.bitstream_read.anonymous-group": "Default read for incoming bitstreams is currently set to Anonymous.", From 9f95eb452ccc6a30047d8acd2441d33e73786981 Mon Sep 17 00:00:00 2001 From: "max.nuding" Date: Wed, 6 Dec 2023 09:57:43 +0100 Subject: [PATCH 0021/1286] enable type-bind for checkbox inputs during submission --- .../models/list/dynamic-list-radio-group.model.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list-radio-group.model.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list-radio-group.model.ts index 0a32498173..2bcf8b5f13 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list-radio-group.model.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list-radio-group.model.ts @@ -1,5 +1,6 @@ import { DynamicFormControlLayout, + DynamicFormControlRelation, DynamicRadioGroupModel, DynamicRadioGroupModelConfig, serializable @@ -15,12 +16,14 @@ export interface DynamicListModelConfig extends DynamicRadioGroupModelConfig { @serializable() vocabularyOptions: VocabularyOptions; @serializable() repeatable: boolean; + @serializable() typeBindRelations: DynamicFormControlRelation[]; @serializable() groupLength: number; @serializable() required: boolean; @serializable() hint: string; @@ -35,6 +38,7 @@ export class DynamicListRadioGroupModel extends DynamicRadioGroupModel { this.required = config.required; this.hint = config.hint; this.value = config.value; + this.typeBindRelations = config.typeBindRelations ? config.typeBindRelations : []; } get hasAuthority(): boolean { From c8ac260b783d6bd9426325f7e2893e4b4f8d6f0d Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Fri, 1 Dec 2023 16:19:12 +0100 Subject: [PATCH 0022/1286] also skip loading hal requests --- src/app/core/shared/hal-endpoint.service.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/app/core/shared/hal-endpoint.service.ts b/src/app/core/shared/hal-endpoint.service.ts index 98ab6a16ea..5cdd7ccfad 100644 --- a/src/app/core/shared/hal-endpoint.service.ts +++ b/src/app/core/shared/hal-endpoint.service.ts @@ -6,7 +6,6 @@ import { hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util'; import { RESTURLCombiner } from '../url-combiner/rest-url-combiner'; import { Injectable } from '@angular/core'; import { EndpointMap } from '../cache/response.models'; -import { getFirstCompletedRemoteData } from './operators'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { RemoteData } from '../data/remote-data'; import { CacheableObject } from '../cache/cacheable-object.model'; @@ -37,8 +36,8 @@ export class HALEndpointService { // This skip ensures that if a stale object is present in the cache when you do a // call it isn't immediately returned, but we wait until the remote data for the new request // is created. - skipWhile((rd: RemoteData) => rd.isStale), - getFirstCompletedRemoteData(), + skipWhile((rd: RemoteData) => rd.isLoading || rd.isStale), + take(1), map((response: RemoteData) => { if (hasValue(response.payload)) { return response.payload._links; From 790e7171992f2cefc6999306703e52586204986b Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Wed, 6 Dec 2023 11:14:41 +0100 Subject: [PATCH 0023/1286] add ResponsePendingStale state --- .../core/data/base/base-data.service.spec.ts | 98 ++++---- src/app/core/data/base/base-data.service.ts | 4 +- .../data/request-entry-state.model.spec.ts | 186 ++++++++++++++ .../core/data/request-entry-state.model.ts | 25 +- src/app/core/data/request.reducer.spec.ts | 230 +++++++++++++++--- src/app/core/data/request.reducer.ts | 55 +++-- src/app/core/data/request.service.ts | 2 +- .../core/shared/hal-endpoint.service.spec.ts | 176 ++++++++++++-- src/app/core/shared/hal-endpoint.service.ts | 25 +- 9 files changed, 660 insertions(+), 141 deletions(-) create mode 100644 src/app/core/data/request-entry-state.model.spec.ts diff --git a/src/app/core/data/base/base-data.service.spec.ts b/src/app/core/data/base/base-data.service.spec.ts index 098f075c10..75662a691f 100644 --- a/src/app/core/data/base/base-data.service.spec.ts +++ b/src/app/core/data/base/base-data.service.spec.ts @@ -95,6 +95,7 @@ describe('BaseDataService', () => { remoteDataMocks = { RequestPending: new RemoteData(undefined, msToLive, timeStamp, RequestEntryState.RequestPending, undefined, undefined, undefined), ResponsePending: new RemoteData(undefined, msToLive, timeStamp, RequestEntryState.ResponsePending, undefined, undefined, undefined), + ResponsePendingStale: new RemoteData(undefined, msToLive, timeStamp, RequestEntryState.ResponsePendingStale, undefined, undefined, undefined), Success: new RemoteData(timeStamp, msToLive, timeStamp, RequestEntryState.Success, undefined, payload, statusCodeSuccess), SuccessStale: new RemoteData(timeStamp, msToLive, timeStamp, RequestEntryState.SuccessStale, undefined, payload, statusCodeSuccess), Error: new RemoteData(timeStamp, msToLive, timeStamp, RequestEntryState.Error, errorMessage, undefined, statusCodeError), @@ -303,19 +304,21 @@ describe('BaseDataService', () => { it(`should not emit a cached stale RemoteData, but only start emitting after the state first changes to RequestPending`, () => { testScheduler.run(({ cold, expectObservable }) => { - spyOn(rdbService, 'buildSingle').and.returnValue(cold('a-b-c-d-e', { - a: remoteDataMocks.SuccessStale, - b: remoteDataMocks.RequestPending, - c: remoteDataMocks.ResponsePending, - d: remoteDataMocks.Success, - e: remoteDataMocks.SuccessStale, + spyOn(rdbService, 'buildSingle').and.returnValue(cold('a-b-c-d-e-f-g', { + a: remoteDataMocks.ResponsePendingStale, + b: remoteDataMocks.SuccessStale, + c: remoteDataMocks.ErrorStale, + d: remoteDataMocks.RequestPending, + e: remoteDataMocks.ResponsePending, + f: remoteDataMocks.Success, + g: remoteDataMocks.SuccessStale, })); - const expected = '--b-c-d-e'; + const expected = '------d-e-f-g'; const values = { - b: remoteDataMocks.RequestPending, - c: remoteDataMocks.ResponsePending, - d: remoteDataMocks.Success, - e: remoteDataMocks.SuccessStale, + d: remoteDataMocks.RequestPending, + e: remoteDataMocks.ResponsePending, + f: remoteDataMocks.Success, + g: remoteDataMocks.SuccessStale, }; expectObservable(service.findByHref(selfLink, true, true, ...linksToFollow)).toBe(expected, values); @@ -354,19 +357,21 @@ describe('BaseDataService', () => { it(`should not emit a cached stale RemoteData, but only start emitting after the state first changes to RequestPending`, () => { testScheduler.run(({ cold, expectObservable }) => { - spyOn(rdbService, 'buildSingle').and.returnValue(cold('a-b-c-d-e', { - a: remoteDataMocks.SuccessStale, - b: remoteDataMocks.RequestPending, - c: remoteDataMocks.ResponsePending, - d: remoteDataMocks.Success, - e: remoteDataMocks.SuccessStale, + spyOn(rdbService, 'buildSingle').and.returnValue(cold('a-b-c-d-e-f-g', { + a: remoteDataMocks.ResponsePendingStale, + b: remoteDataMocks.SuccessStale, + c: remoteDataMocks.ErrorStale, + d: remoteDataMocks.RequestPending, + e: remoteDataMocks.ResponsePending, + f: remoteDataMocks.Success, + g: remoteDataMocks.SuccessStale, })); - const expected = '--b-c-d-e'; + const expected = '------d-e-f-g'; const values = { - b: remoteDataMocks.RequestPending, - c: remoteDataMocks.ResponsePending, - d: remoteDataMocks.Success, - e: remoteDataMocks.SuccessStale, + d: remoteDataMocks.RequestPending, + e: remoteDataMocks.ResponsePending, + f: remoteDataMocks.Success, + g: remoteDataMocks.SuccessStale, }; expectObservable(service.findByHref(selfLink, false, true, ...linksToFollow)).toBe(expected, values); @@ -487,19 +492,21 @@ describe('BaseDataService', () => { it(`should not emit a cached stale RemoteData, but only start emitting after the state first changes to RequestPending`, () => { testScheduler.run(({ cold, expectObservable }) => { - spyOn(rdbService, 'buildList').and.returnValue(cold('a-b-c-d-e', { - a: remoteDataMocks.SuccessStale, - b: remoteDataMocks.RequestPending, - c: remoteDataMocks.ResponsePending, - d: remoteDataMocks.Success, - e: remoteDataMocks.SuccessStale, + spyOn(rdbService, 'buildList').and.returnValue(cold('a-b-c-d-e-f-g', { + a: remoteDataMocks.ResponsePendingStale, + b: remoteDataMocks.SuccessStale, + c: remoteDataMocks.ErrorStale, + d: remoteDataMocks.RequestPending, + e: remoteDataMocks.ResponsePending, + f: remoteDataMocks.Success, + g: remoteDataMocks.SuccessStale, })); - const expected = '--b-c-d-e'; + const expected = '------d-e-f-g'; const values = { - b: remoteDataMocks.RequestPending, - c: remoteDataMocks.ResponsePending, - d: remoteDataMocks.Success, - e: remoteDataMocks.SuccessStale, + d: remoteDataMocks.RequestPending, + e: remoteDataMocks.ResponsePending, + f: remoteDataMocks.Success, + g: remoteDataMocks.SuccessStale, }; expectObservable(service.findListByHref(selfLink, findListOptions, true, true, ...linksToFollow)).toBe(expected, values); @@ -538,21 +545,24 @@ describe('BaseDataService', () => { it(`should not emit a cached stale RemoteData, but only start emitting after the state first changes to RequestPending`, () => { testScheduler.run(({ cold, expectObservable }) => { - spyOn(rdbService, 'buildList').and.returnValue(cold('a-b-c-d-e', { - a: remoteDataMocks.SuccessStale, - b: remoteDataMocks.RequestPending, - c: remoteDataMocks.ResponsePending, - d: remoteDataMocks.Success, - e: remoteDataMocks.SuccessStale, + spyOn(rdbService, 'buildList').and.returnValue(cold('a-b-c-d-e-f-g', { + a: remoteDataMocks.ResponsePendingStale, + b: remoteDataMocks.SuccessStale, + c: remoteDataMocks.ErrorStale, + d: remoteDataMocks.RequestPending, + e: remoteDataMocks.ResponsePending, + f: remoteDataMocks.Success, + g: remoteDataMocks.SuccessStale, })); - const expected = '--b-c-d-e'; + const expected = '------d-e-f-g'; const values = { - b: remoteDataMocks.RequestPending, - c: remoteDataMocks.ResponsePending, - d: remoteDataMocks.Success, - e: remoteDataMocks.SuccessStale, + d: remoteDataMocks.RequestPending, + e: remoteDataMocks.ResponsePending, + f: remoteDataMocks.Success, + g: remoteDataMocks.SuccessStale, }; + expectObservable(service.findListByHref(selfLink, findListOptions, false, true, ...linksToFollow)).toBe(expected, values); }); }); diff --git a/src/app/core/data/base/base-data.service.ts b/src/app/core/data/base/base-data.service.ts index edd6d9e2a4..c7cd5b0a70 100644 --- a/src/app/core/data/base/base-data.service.ts +++ b/src/app/core/data/base/base-data.service.ts @@ -273,7 +273,7 @@ export class BaseDataService implements HALDataServic // call it isn't immediately returned, but we wait until the remote data for the new request // is created. If useCachedVersionIfAvailable is false it also ensures you don't get a // cached completed object - skipWhile((rd: RemoteData) => useCachedVersionIfAvailable ? rd.isStale : rd.hasCompleted), + skipWhile((rd: RemoteData) => rd.isStale || (!useCachedVersionIfAvailable && rd.hasCompleted)), this.reRequestStaleRemoteData(reRequestOnStale, () => this.findByHref(href$, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow)), ); @@ -307,7 +307,7 @@ export class BaseDataService implements HALDataServic // call it isn't immediately returned, but we wait until the remote data for the new request // is created. If useCachedVersionIfAvailable is false it also ensures you don't get a // cached completed object - skipWhile((rd: RemoteData>) => useCachedVersionIfAvailable ? rd.isStale : rd.hasCompleted), + skipWhile((rd: RemoteData>) => rd.isStale || (!useCachedVersionIfAvailable && rd.hasCompleted)), this.reRequestStaleRemoteData(reRequestOnStale, () => this.findListByHref(href$, options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow)), ); diff --git a/src/app/core/data/request-entry-state.model.spec.ts b/src/app/core/data/request-entry-state.model.spec.ts new file mode 100644 index 0000000000..7daa655566 --- /dev/null +++ b/src/app/core/data/request-entry-state.model.spec.ts @@ -0,0 +1,186 @@ +import { + isRequestPending, + isError, + isSuccess, + isErrorStale, + isSuccessStale, + isResponsePending, + isResponsePendingStale, + isLoading, + isStale, + hasFailed, + hasSucceeded, + hasCompleted, + RequestEntryState +} from './request-entry-state.model'; + +describe(`isRequestPending`, () => { + it(`should only return true if the given state is RequestPending`, () => { + expect(isRequestPending(RequestEntryState.RequestPending)).toBeTrue(); + + expect(isRequestPending(RequestEntryState.ResponsePending)).toBeFalse(); + expect(isRequestPending(RequestEntryState.Error)).toBeFalse(); + expect(isRequestPending(RequestEntryState.Success)).toBeFalse(); + expect(isRequestPending(RequestEntryState.ResponsePendingStale)).toBeFalse(); + expect(isRequestPending(RequestEntryState.ErrorStale)).toBeFalse(); + expect(isRequestPending(RequestEntryState.SuccessStale)).toBeFalse(); + }); +}); + +describe(`isError`, () => { + it(`should only return true if the given state is Error`, () => { + expect(isError(RequestEntryState.Error)).toBeTrue(); + + expect(isError(RequestEntryState.RequestPending)).toBeFalse(); + expect(isError(RequestEntryState.ResponsePending)).toBeFalse(); + expect(isError(RequestEntryState.Success)).toBeFalse(); + expect(isError(RequestEntryState.ResponsePendingStale)).toBeFalse(); + expect(isError(RequestEntryState.ErrorStale)).toBeFalse(); + expect(isError(RequestEntryState.SuccessStale)).toBeFalse(); + }); +}); + +describe(`isSuccess`, () => { + it(`should only return true if the given state is Success`, () => { + expect(isSuccess(RequestEntryState.Success)).toBeTrue(); + + expect(isSuccess(RequestEntryState.RequestPending)).toBeFalse(); + expect(isSuccess(RequestEntryState.ResponsePending)).toBeFalse(); + expect(isSuccess(RequestEntryState.Error)).toBeFalse(); + expect(isSuccess(RequestEntryState.ResponsePendingStale)).toBeFalse(); + expect(isSuccess(RequestEntryState.ErrorStale)).toBeFalse(); + expect(isSuccess(RequestEntryState.SuccessStale)).toBeFalse(); + }); +}); + +describe(`isErrorStale`, () => { + it(`should only return true if the given state is ErrorStale`, () => { + expect(isErrorStale(RequestEntryState.ErrorStale)).toBeTrue(); + + expect(isErrorStale(RequestEntryState.RequestPending)).toBeFalse(); + expect(isErrorStale(RequestEntryState.ResponsePending)).toBeFalse(); + expect(isErrorStale(RequestEntryState.Error)).toBeFalse(); + expect(isErrorStale(RequestEntryState.Success)).toBeFalse(); + expect(isErrorStale(RequestEntryState.ResponsePendingStale)).toBeFalse(); + expect(isErrorStale(RequestEntryState.SuccessStale)).toBeFalse(); + }); +}); + +describe(`isSuccessStale`, () => { + it(`should only return true if the given state is SuccessStale`, () => { + expect(isSuccessStale(RequestEntryState.SuccessStale)).toBeTrue(); + + expect(isSuccessStale(RequestEntryState.RequestPending)).toBeFalse(); + expect(isSuccessStale(RequestEntryState.ResponsePending)).toBeFalse(); + expect(isSuccessStale(RequestEntryState.Error)).toBeFalse(); + expect(isSuccessStale(RequestEntryState.Success)).toBeFalse(); + expect(isSuccessStale(RequestEntryState.ResponsePendingStale)).toBeFalse(); + expect(isSuccessStale(RequestEntryState.ErrorStale)).toBeFalse(); + }); +}); + +describe(`isResponsePending`, () => { + it(`should only return true if the given state is ResponsePending`, () => { + expect(isResponsePending(RequestEntryState.ResponsePending)).toBeTrue(); + + expect(isResponsePending(RequestEntryState.RequestPending)).toBeFalse(); + expect(isResponsePending(RequestEntryState.Error)).toBeFalse(); + expect(isResponsePending(RequestEntryState.Success)).toBeFalse(); + expect(isResponsePending(RequestEntryState.ResponsePendingStale)).toBeFalse(); + expect(isResponsePending(RequestEntryState.ErrorStale)).toBeFalse(); + expect(isResponsePending(RequestEntryState.SuccessStale)).toBeFalse(); + }); +}); + +describe(`isResponsePendingStale`, () => { + it(`should only return true if the given state is requestPending`, () => { + expect(isResponsePendingStale(RequestEntryState.ResponsePendingStale)).toBeTrue(); + + expect(isResponsePendingStale(RequestEntryState.RequestPending)).toBeFalse(); + expect(isResponsePendingStale(RequestEntryState.ResponsePending)).toBeFalse(); + expect(isResponsePendingStale(RequestEntryState.Error)).toBeFalse(); + expect(isResponsePendingStale(RequestEntryState.Success)).toBeFalse(); + expect(isResponsePendingStale(RequestEntryState.ErrorStale)).toBeFalse(); + expect(isResponsePendingStale(RequestEntryState.SuccessStale)).toBeFalse(); + }); +}); + +describe(`isLoading`, () => { + it(`should only return true if the given state is RequestPending, ResponsePending or ResponsePendingStale`, () => { + expect(isLoading(RequestEntryState.RequestPending)).toBeTrue(); + expect(isLoading(RequestEntryState.ResponsePending)).toBeTrue(); + expect(isLoading(RequestEntryState.ResponsePendingStale)).toBeTrue(); + + expect(isLoading(RequestEntryState.Error)).toBeFalse(); + expect(isLoading(RequestEntryState.Success)).toBeFalse(); + expect(isLoading(RequestEntryState.ErrorStale)).toBeFalse(); + expect(isLoading(RequestEntryState.SuccessStale)).toBeFalse(); + }); +}); + +describe(`hasFailed`, () => { + describe(`when the state is loading`, () => { + it(`should return undefined`, () => { + expect(hasFailed(RequestEntryState.RequestPending)).toBeUndefined(); + expect(hasFailed(RequestEntryState.ResponsePending)).toBeUndefined(); + expect(hasFailed(RequestEntryState.ResponsePendingStale)).toBeUndefined(); + }); + }); + + describe(`when the state has completed`, () => { + it(`should only return true if the given state is Error or ErrorStale`, () => { + expect(hasFailed(RequestEntryState.Error)).toBeTrue(); + expect(hasFailed(RequestEntryState.ErrorStale)).toBeTrue(); + + expect(hasFailed(RequestEntryState.Success)).toBeFalse(); + expect(hasFailed(RequestEntryState.SuccessStale)).toBeFalse(); + }); + }); +}); + +describe(`hasSucceeded`, () => { + describe(`when the state is loading`, () => { + it(`should return undefined`, () => { + expect(hasSucceeded(RequestEntryState.RequestPending)).toBeUndefined(); + expect(hasSucceeded(RequestEntryState.ResponsePending)).toBeUndefined(); + expect(hasSucceeded(RequestEntryState.ResponsePendingStale)).toBeUndefined(); + }); + }); + + describe(`when the state has completed`, () => { + it(`should only return true if the given state is Error or ErrorStale`, () => { + expect(hasSucceeded(RequestEntryState.Success)).toBeTrue(); + expect(hasSucceeded(RequestEntryState.SuccessStale)).toBeTrue(); + + expect(hasSucceeded(RequestEntryState.Error)).toBeFalse(); + expect(hasSucceeded(RequestEntryState.ErrorStale)).toBeFalse(); + }); + }); +}); + + +describe(`hasCompleted`, () => { + it(`should only return true if the given state is Error, Success, ErrorStale or SuccessStale`, () => { + expect(hasCompleted(RequestEntryState.Error)).toBeTrue(); + expect(hasCompleted(RequestEntryState.Success)).toBeTrue(); + expect(hasCompleted(RequestEntryState.ErrorStale)).toBeTrue(); + expect(hasCompleted(RequestEntryState.SuccessStale)).toBeTrue(); + + expect(hasCompleted(RequestEntryState.RequestPending)).toBeFalse(); + expect(hasCompleted(RequestEntryState.ResponsePending)).toBeFalse(); + expect(hasCompleted(RequestEntryState.ResponsePendingStale)).toBeFalse(); + }); +}); + +describe(`isStale`, () => { + it(`should only return true if the given state is ResponsePendingStale, SuccessStale or ErrorStale`, () => { + expect(isStale(RequestEntryState.ResponsePendingStale)).toBeTrue(); + expect(isStale(RequestEntryState.SuccessStale)).toBeTrue(); + expect(isStale(RequestEntryState.ErrorStale)).toBeTrue(); + + expect(isStale(RequestEntryState.RequestPending)).toBeFalse(); + expect(isStale(RequestEntryState.ResponsePending)).toBeFalse(); + expect(isStale(RequestEntryState.Error)).toBeFalse(); + expect(isStale(RequestEntryState.Success)).toBeFalse(); + }); +}); diff --git a/src/app/core/data/request-entry-state.model.ts b/src/app/core/data/request-entry-state.model.ts index a813b6e743..3aeace39d2 100644 --- a/src/app/core/data/request-entry-state.model.ts +++ b/src/app/core/data/request-entry-state.model.ts @@ -3,8 +3,9 @@ export enum RequestEntryState { ResponsePending = 'ResponsePending', Error = 'Error', Success = 'Success', + ResponsePendingStale = 'ResponsePendingStale', ErrorStale = 'ErrorStale', - SuccessStale = 'SuccessStale' + SuccessStale = 'SuccessStale', } /** @@ -42,12 +43,21 @@ export const isSuccessStale = (state: RequestEntryState) => */ export const isResponsePending = (state: RequestEntryState) => state === RequestEntryState.ResponsePending; + /** - * Returns true if the given state is RequestPending or ResponsePending, - * false otherwise + * Returns true if the given state is ResponsePendingStale, false otherwise + */ +export const isResponsePendingStale = (state: RequestEntryState) => + state === RequestEntryState.ResponsePendingStale; + +/** + * Returns true if the given state is RequestPending, RequestPendingStale, ResponsePending, or + * ResponsePendingStale, false otherwise */ export const isLoading = (state: RequestEntryState) => - isRequestPending(state) || isResponsePending(state); + isRequestPending(state) || + isResponsePending(state) || + isResponsePendingStale(state); /** * If isLoading is true for the given state, this method returns undefined, we can't know yet. @@ -82,7 +92,10 @@ export const hasCompleted = (state: RequestEntryState) => !isLoading(state); /** - * Returns true if the given state is SuccessStale or ErrorStale, false otherwise + * Returns true if the given state is isRequestPendingStale, isResponsePendingStale, SuccessStale or + * ErrorStale, false otherwise */ export const isStale = (state: RequestEntryState) => - isSuccessStale(state) || isErrorStale(state); + isResponsePendingStale(state) || + isSuccessStale(state) || + isErrorStale(state); diff --git a/src/app/core/data/request.reducer.spec.ts b/src/app/core/data/request.reducer.spec.ts index 05f074a96a..86b9c4cd5d 100644 --- a/src/app/core/data/request.reducer.spec.ts +++ b/src/app/core/data/request.reducer.spec.ts @@ -48,9 +48,16 @@ describe('requestReducer', () => { lastUpdated: 0 } }; + const testResponsePendingState = { + [id1]: { + state: RequestEntryState.ResponsePending, + lastUpdated: 0 + } + }; deepFreeze(testInitState); deepFreeze(testSuccessState); deepFreeze(testErrorState); + deepFreeze(testResponsePendingState); it('should return the current state when no valid actions have been made', () => { const action = new NullAction(); @@ -91,29 +98,94 @@ describe('requestReducer', () => { expect(newState[id1].response).toEqual(undefined); }); - it('should set state to Success for the given RestRequest in the state, in response to a SUCCESS action', () => { - const state = testInitState; + describe(`in response to a SUCCESS action`, () => { + let startState; + describe(`when the entry isn't stale`, () => { + beforeEach(() => { + startState = Object.assign({}, testInitState, { + [id1]: Object.assign({}, testInitState[id1], { + state: RequestEntryState.ResponsePending + }) + }); + deepFreeze(startState); + }); + it('should set state to Success for the given RestRequest in the state', () => { + const action = new RequestSuccessAction(id1, 200); + const newState = requestReducer(startState, action); - const action = new RequestSuccessAction(id1, 200); - const newState = requestReducer(state, action); + expect(newState[id1].request.uuid).toEqual(id1); + expect(newState[id1].request.href).toEqual(link1); + expect(newState[id1].state).toEqual(RequestEntryState.Success); + expect(newState[id1].response.statusCode).toEqual(200); + }); + }); + + describe(`when the entry is stale`, () => { + beforeEach(() => { + startState = Object.assign({}, testInitState, { + [id1]: Object.assign({}, testInitState[id1], { + state: RequestEntryState.ResponsePendingStale + }) + }); + deepFreeze(startState); + }); + it('should set state to SuccessStale for the given RestRequest in the state', () => { + const action = new RequestSuccessAction(id1, 200); + const newState = requestReducer(startState, action); + + expect(newState[id1].request.uuid).toEqual(id1); + expect(newState[id1].request.href).toEqual(link1); + expect(newState[id1].state).toEqual(RequestEntryState.SuccessStale); + expect(newState[id1].response.statusCode).toEqual(200); + }); + }); - expect(newState[id1].request.uuid).toEqual(id1); - expect(newState[id1].request.href).toEqual(link1); - expect(newState[id1].state).toEqual(RequestEntryState.Success); - expect(newState[id1].response.statusCode).toEqual(200); }); - it('should set state to Error for the given RestRequest in the state, in response to an ERROR action', () => { - const state = testInitState; + describe(`in response to an ERROR action`, () => { + let startState; + describe(`when the entry isn't stale`, () => { + beforeEach(() => { + startState = Object.assign({}, testInitState, { + [id1]: Object.assign({}, testInitState[id1], { + state: RequestEntryState.ResponsePending + }) + }); + deepFreeze(startState); + }); + it('should set state to Error for the given RestRequest in the state', () => { + const action = new RequestErrorAction(id1, 404, 'Not Found'); + const newState = requestReducer(startState, action); - const action = new RequestErrorAction(id1, 404, 'Not Found'); - const newState = requestReducer(state, action); + expect(newState[id1].request.uuid).toEqual(id1); + expect(newState[id1].request.href).toEqual(link1); + expect(newState[id1].state).toEqual(RequestEntryState.Error); + expect(newState[id1].response.statusCode).toEqual(404); + expect(newState[id1].response.errorMessage).toEqual('Not Found'); + }); + }); - expect(newState[id1].request.uuid).toEqual(id1); - expect(newState[id1].request.href).toEqual(link1); - expect(newState[id1].state).toEqual(RequestEntryState.Error); - expect(newState[id1].response.statusCode).toEqual(404); - expect(newState[id1].response.errorMessage).toEqual('Not Found'); + describe(`when the entry is stale`, () => { + beforeEach(() => { + startState = Object.assign({}, testInitState, { + [id1]: Object.assign({}, testInitState[id1], { + state: RequestEntryState.ResponsePendingStale + }) + }); + deepFreeze(startState); + }); + it('should set state to ErrorStale for the given RestRequest in the state', () => { + const action = new RequestErrorAction(id1, 404, 'Not Found'); + const newState = requestReducer(startState, action); + + expect(newState[id1].request.uuid).toEqual(id1); + expect(newState[id1].request.href).toEqual(link1); + expect(newState[id1].state).toEqual(RequestEntryState.ErrorStale); + expect(newState[id1].response.statusCode).toEqual(404); + expect(newState[id1].response.errorMessage).toEqual('Not Found'); + }); + + }); }); it('should update the response\'s timeCompleted for the given RestRequest in the state, in response to a RESET_TIMESTAMPS action', () => { @@ -145,28 +217,112 @@ describe('requestReducer', () => { expect(newState[id1]).toBeNull(); }); - describe(`for an entry with state: Success`, () => { - it(`should set the state to SuccessStale, in response to a STALE action`, () => { - const state = testSuccessState; + describe(`in response to a STALE action`, () => { + describe(`when the entry has been removed`, () => { + it(`shouldn't do anything`, () => { + const startState = { + [id1]: null + }; + deepFreeze(startState); - const action = new RequestStaleAction(id1); - const newState = requestReducer(state, action); + const action = new RequestStaleAction(id1); + const newState = requestReducer(startState, action); - expect(newState[id1].state).toEqual(RequestEntryState.SuccessStale); - expect(newState[id1].lastUpdated).toBe(action.lastUpdated); + expect(newState[id1]).toBeNull(); + }); + }); + + describe(`for stale entries`, () => { + it(`shouldn't do anything`, () => { + const rpsStartState = Object.assign({}, testInitState, { + [id1]: Object.assign({}, testInitState[id1], { + state: RequestEntryState.ResponsePendingStale + }) + }); + deepFreeze(rpsStartState); + + const action = new RequestStaleAction(id1); + let newState = requestReducer(rpsStartState, action); + + expect(newState[id1].state).toEqual(rpsStartState[id1].state); + expect(newState[id1].lastUpdated).toBe(rpsStartState[id1].lastUpdated); + + const ssStartState = Object.assign({}, testInitState, { + [id1]: Object.assign({}, testInitState[id1], { + state: RequestEntryState.SuccessStale + }) + }); + + newState = requestReducer(ssStartState, action); + + expect(newState[id1].state).toEqual(ssStartState[id1].state); + expect(newState[id1].lastUpdated).toBe(ssStartState[id1].lastUpdated); + + const esStartState = Object.assign({}, testInitState, { + [id1]: Object.assign({}, testInitState[id1], { + state: RequestEntryState.ErrorStale + }) + }); + + newState = requestReducer(esStartState, action); + + expect(newState[id1].state).toEqual(esStartState[id1].state); + expect(newState[id1].lastUpdated).toBe(esStartState[id1].lastUpdated); + + }); + }); + + describe(`for and entry with state: RequestPending`, () => { + it(`shouldn't do anything`, () => { + const startState = Object.assign({}, testInitState, { + [id1]: Object.assign({}, testInitState[id1], { + state: RequestEntryState.RequestPending + }) + }); + + const action = new RequestStaleAction(id1); + const newState = requestReducer(startState, action); + + expect(newState[id1].state).toEqual(startState[id1].state); + expect(newState[id1].lastUpdated).toBe(startState[id1].lastUpdated); + + }); + }); + + describe(`for an entry with state: ResponsePending`, () => { + it(`should set the state to ResponsePendingStale`, () => { + const state = testResponsePendingState; + + const action = new RequestStaleAction(id1); + const newState = requestReducer(state, action); + + expect(newState[id1].state).toEqual(RequestEntryState.ResponsePendingStale); + expect(newState[id1].lastUpdated).toBe(action.lastUpdated); + }); + }); + + describe(`for an entry with state: Success`, () => { + it(`should set the state to SuccessStale`, () => { + const state = testSuccessState; + + const action = new RequestStaleAction(id1); + const newState = requestReducer(state, action); + + expect(newState[id1].state).toEqual(RequestEntryState.SuccessStale); + expect(newState[id1].lastUpdated).toBe(action.lastUpdated); + }); + }); + + describe(`for an entry with state: Error`, () => { + it(`should set the state to ErrorStale`, () => { + const state = testErrorState; + + const action = new RequestStaleAction(id1); + const newState = requestReducer(state, action); + + expect(newState[id1].state).toEqual(RequestEntryState.ErrorStale); + expect(newState[id1].lastUpdated).toBe(action.lastUpdated); + }); }); }); - - describe(`for an entry with state: Error`, () => { - it(`should set the state to ErrorStale, in response to a STALE action`, () => { - const state = testErrorState; - - const action = new RequestStaleAction(id1); - const newState = requestReducer(state, action); - - expect(newState[id1].state).toEqual(RequestEntryState.ErrorStale); - expect(newState[id1].lastUpdated).toBe(action.lastUpdated); - }); - }); - }); diff --git a/src/app/core/data/request.reducer.ts b/src/app/core/data/request.reducer.ts index 9bf17faf8d..9cf4fee0e2 100644 --- a/src/app/core/data/request.reducer.ts +++ b/src/app/core/data/request.reducer.ts @@ -11,7 +11,13 @@ import { ResetResponseTimestampsAction } from './request.actions'; import { isNull } from '../../shared/empty.util'; -import { hasSucceeded, isStale, RequestEntryState } from './request-entry-state.model'; +import { + hasSucceeded, + isStale, + RequestEntryState, + isRequestPending, + isResponsePending +} from './request-entry-state.model'; import { RequestState } from './request-state.model'; // Object.create(null) ensures the object has no default js properties (e.g. `__proto__`) @@ -91,14 +97,17 @@ function executeRequest(storeState: RequestState, action: RequestExecuteAction): * the new storeState, with the response added to the request */ function completeSuccessRequest(storeState: RequestState, action: RequestSuccessAction): RequestState { - if (isNull(storeState[action.payload.uuid])) { + const prevEntry = storeState[action.payload.uuid]; + if (isNull(prevEntry)) { // after a request has been removed it's possible pending changes still come in. // Don't store them return storeState; } else { return Object.assign({}, storeState, { - [action.payload.uuid]: Object.assign({}, storeState[action.payload.uuid], { - state: RequestEntryState.Success, + [action.payload.uuid]: Object.assign({}, prevEntry, { + // If a response comes in for a request that's already stale, still store it otherwise + // components that are waiting for it might freeze + state: isStale(prevEntry.state) ? RequestEntryState.SuccessStale : RequestEntryState.Success, response: { timeCompleted: action.payload.timeCompleted, lastUpdated: action.payload.timeCompleted, @@ -124,14 +133,17 @@ function completeSuccessRequest(storeState: RequestState, action: RequestSuccess * the new storeState, with the response added to the request */ function completeFailedRequest(storeState: RequestState, action: RequestErrorAction): RequestState { - if (isNull(storeState[action.payload.uuid])) { + const prevEntry = storeState[action.payload.uuid]; + if (isNull(prevEntry)) { // after a request has been removed it's possible pending changes still come in. // Don't store them return storeState; } else { return Object.assign({}, storeState, { - [action.payload.uuid]: Object.assign({}, storeState[action.payload.uuid], { - state: RequestEntryState.Error, + [action.payload.uuid]: Object.assign({}, prevEntry, { + // If a response comes in for a request that's already stale, still store it otherwise + // components that are waiting for it might freeze + state: isStale(prevEntry.state) ? RequestEntryState.ErrorStale : RequestEntryState.Error, response: { timeCompleted: action.payload.timeCompleted, lastUpdated: action.payload.timeCompleted, @@ -155,22 +167,27 @@ function completeFailedRequest(storeState: RequestState, action: RequestErrorAct * the new storeState, set to stale */ function expireRequest(storeState: RequestState, action: RequestStaleAction): RequestState { - if (isNull(storeState[action.payload.uuid])) { - // after a request has been removed it's possible pending changes still come in. - // Don't store them + const prevEntry = storeState[action.payload.uuid]; + if (isNull(prevEntry) || isStale(prevEntry.state) || isRequestPending(prevEntry.state)) { + // No need to do anything if the entry doesn't exist, is already stale, or if the request is + // still pending, because that means it still needs to be sent to the server. Any response + // is guaranteed to have been generated after the request was set to stale. return storeState; } else { - const prevEntry = storeState[action.payload.uuid]; - if (isStale(prevEntry.state)) { - return storeState; + let nextRequestEntryState: RequestEntryState; + if (isResponsePending(prevEntry.state)) { + nextRequestEntryState = RequestEntryState.ResponsePendingStale; + } else if (hasSucceeded(prevEntry.state)) { + nextRequestEntryState = RequestEntryState.SuccessStale; } else { - return Object.assign({}, storeState, { - [action.payload.uuid]: Object.assign({}, prevEntry, { - state: hasSucceeded(prevEntry.state) ? RequestEntryState.SuccessStale : RequestEntryState.ErrorStale, - lastUpdated: action.lastUpdated - }) - }); + nextRequestEntryState = RequestEntryState.ErrorStale; } + return Object.assign({}, storeState, { + [action.payload.uuid]: Object.assign({}, prevEntry, { + state: nextRequestEntryState, + lastUpdated: action.lastUpdated + }) + }); } } diff --git a/src/app/core/data/request.service.ts b/src/app/core/data/request.service.ts index 27176390d7..c908c696db 100644 --- a/src/app/core/data/request.service.ts +++ b/src/app/core/data/request.service.ts @@ -164,7 +164,7 @@ export class RequestService { this.getByHref(request.href).pipe( take(1)) .subscribe((re: RequestEntry) => { - isPending = (hasValue(re) && isLoading(re.state)); + isPending = (hasValue(re) && isLoading(re.state) && !isStale(re.state)); }); return isPending; } diff --git a/src/app/core/shared/hal-endpoint.service.spec.ts b/src/app/core/shared/hal-endpoint.service.spec.ts index 56e890b318..b81d0806df 100644 --- a/src/app/core/shared/hal-endpoint.service.spec.ts +++ b/src/app/core/shared/hal-endpoint.service.spec.ts @@ -1,4 +1,3 @@ -import { cold, hot } from 'jasmine-marbles'; import { getMockRequestService } from '../../shared/mocks/request.service.mock'; import { RequestService } from '../data/request.service'; import { HALEndpointService } from './hal-endpoint.service'; @@ -7,12 +6,17 @@ import { combineLatest as observableCombineLatest, of as observableOf } from 'rx import { environment } from '../../../environments/environment'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; +import { TestScheduler } from 'rxjs/testing'; +import { RemoteData } from '../data/remote-data'; +import { RequestEntryState } from '../data/request-entry-state.model'; describe('HALEndpointService', () => { let service: HALEndpointService; let requestService: RequestService; let rdbService: RemoteDataBuildService; let envConfig; + let testScheduler; + let remoteDataMocks; const endpointMap = { test: { href: 'https://rest.api/test' @@ -68,7 +72,30 @@ describe('HALEndpointService', () => { }; const linkPath = 'test'; + const timeStamp = new Date().getTime(); + const msToLive = 15 * 60 * 1000; + const payload = { + _links: endpointMaps[one] + }; + const statusCodeSuccess = 200; + const statusCodeError = 404; + const errorMessage = 'not found'; + remoteDataMocks = { + RequestPending: new RemoteData(undefined, msToLive, timeStamp, RequestEntryState.RequestPending, undefined, undefined, undefined), + ResponsePending: new RemoteData(undefined, msToLive, timeStamp, RequestEntryState.ResponsePending, undefined, undefined, undefined), + ResponsePendingStale: new RemoteData(undefined, msToLive, timeStamp, RequestEntryState.ResponsePendingStale, undefined, undefined, undefined), + Success: new RemoteData(timeStamp, msToLive, timeStamp, RequestEntryState.Success, undefined, payload, statusCodeSuccess), + SuccessStale: new RemoteData(timeStamp, msToLive, timeStamp, RequestEntryState.SuccessStale, undefined, payload, statusCodeSuccess), + Error: new RemoteData(timeStamp, msToLive, timeStamp, RequestEntryState.Error, errorMessage, undefined, statusCodeError), + ErrorStale: new RemoteData(timeStamp, msToLive, timeStamp, RequestEntryState.ErrorStale, errorMessage, undefined, statusCodeError), + }; + beforeEach(() => { + testScheduler = new TestScheduler((actual, expected) => { + // asserting the two objects are equal + // e.g. using chai. + expect(actual).toEqual(expected); + }); requestService = getMockRequestService(); rdbService = jasmine.createSpyObj('rdbService', { buildFromHref: createSuccessfulRemoteDataObject$({ @@ -111,20 +138,28 @@ describe('HALEndpointService', () => { }); it(`should return the endpoint URL for the service's linkPath`, () => { - spyOn(service as any, 'getEndpointAt').and - .returnValue(hot('a-', { a: 'https://rest.api/test' })); - const result = service.getEndpoint(linkPath); + testScheduler.run(({ cold, expectObservable }) => { + spyOn(service as any, 'getEndpointAt').and + .returnValue(cold('a-', { a: 'https://rest.api/test' })); + const result = service.getEndpoint(linkPath); - const expected = cold('(b|)', { b: endpointMap.test.href }); - expect(result).toBeObservable(expected); + const expected = '(b|)'; + const values = { + b: endpointMap.test.href + }; + expectObservable(result).toBe(expected, values); + }); }); it('should return undefined for a linkPath that isn\'t in the endpoint map', () => { - spyOn(service as any, 'getEndpointAt').and - .returnValue(hot('a-', { a: undefined })); - const result = service.getEndpoint('unknown'); - const expected = cold('(b|)', { b: undefined }); - expect(result).toBeObservable(expected); + testScheduler.run(({ cold, expectObservable }) => { + spyOn(service as any, 'getEndpointAt').and + .returnValue(cold('a-', { a: undefined })); + const result = service.getEndpoint('unknown'); + const expected = '(b|)'; + const values = { b: undefined }; + expectObservable(result).toBe(expected, values); + }); }); }); @@ -183,29 +218,118 @@ describe('HALEndpointService', () => { }); it('should return undefined as long as getRootEndpointMap hasn\'t fired', () => { - spyOn(service as any, 'getRootEndpointMap').and - .returnValue(hot('----')); + testScheduler.run(({ cold, expectObservable }) => { + spyOn(service as any, 'getRootEndpointMap').and + .returnValue(cold('----')); - const result = service.isEnabledOnRestApi(linkPath); - const expected = cold('b---', { b: undefined }); - expect(result).toBeObservable(expected); + const result = service.isEnabledOnRestApi(linkPath); + const expected = 'b---'; + const values = { b: undefined }; + expectObservable(result).toBe(expected, values); + }); }); it('should return true if the service\'s linkPath is in the endpoint map', () => { - spyOn(service as any, 'getRootEndpointMap').and - .returnValue(hot('--a-', { a: endpointMap })); - const result = service.isEnabledOnRestApi(linkPath); - const expected = cold('b-c-', { b: undefined, c: true }); - expect(result).toBeObservable(expected); + testScheduler.run(({ cold, expectObservable }) => { + spyOn(service as any, 'getRootEndpointMap').and + .returnValue(cold('--a-', { a: endpointMap })); + const result = service.isEnabledOnRestApi(linkPath); + const expected = 'b-c-'; + const values = { b: undefined, c: true }; + expectObservable(result).toBe(expected, values); + }); }); it('should return false if the service\'s linkPath isn\'t in the endpoint map', () => { - spyOn(service as any, 'getRootEndpointMap').and - .returnValue(hot('--a-', { a: endpointMap })); + testScheduler.run(({ cold, expectObservable }) => { + spyOn(service as any, 'getRootEndpointMap').and + .returnValue(cold('--a-', { a: endpointMap })); - const result = service.isEnabledOnRestApi('unknown'); - const expected = cold('b-c-', { b: undefined, c: false }); - expect(result).toBeObservable(expected); + const result = service.isEnabledOnRestApi('unknown'); + const expected = 'b-c-'; + const values = { b: undefined, c: false }; + expectObservable(result).toBe(expected, values); + }); + }); + + }); + + describe(`getEndpointMapAt`, () => { + const href = 'https://rest.api/some/sub/path'; + + it(`should call requestService.send with a new EndpointMapRequest for the given href. useCachedVersionIfAvailable should be true`, () => { + testScheduler.run(() => { + (service as any).getEndpointMapAt(href); + }); + const expected = new EndpointMapRequest(requestService.generateRequestId(), href); + expect(requestService.send).toHaveBeenCalledWith(expected, true); + }); + + it(`should call rdbService.buildFromHref with the given href`, () => { + testScheduler.run(() => { + (service as any).getEndpointMapAt(href); + }); + expect(rdbService.buildFromHref).toHaveBeenCalledWith(href); + }); + + describe(`when the RemoteData returned from rdbService is stale`, () => { + it(`should re-request it`, () => { + spyOn(service as any, 'getEndpointMapAt').and.callThrough(); + testScheduler.run(({ cold }) => { + (rdbService.buildFromHref as jasmine.Spy).and.returnValue(cold('a', { a: remoteDataMocks.ResponsePendingStale })); + // we need to subscribe to the result, to ensure the "tap" that does the re-request can fire + (service as any).getEndpointMapAt(href).subscribe(); + }); + expect((service as any).getEndpointMapAt).toHaveBeenCalledTimes(2); + }); + }); + + describe(`when the RemoteData returned from rdbService isn't stale`, () => { + it(`should not re-request it`, () => { + spyOn(service as any, 'getEndpointMapAt').and.callThrough(); + testScheduler.run(({ cold }) => { + (rdbService.buildFromHref as jasmine.Spy).and.returnValue(cold('a', { a: remoteDataMocks.ResponsePending })); + // we need to subscribe to the result, to ensure the "tap" that does the re-request can fire + (service as any).getEndpointMapAt(href).subscribe(); + }); + expect((service as any).getEndpointMapAt).toHaveBeenCalledTimes(1); + }); + }); + + it(`should emit exactly once, returning the endpoint map in the response, when the RemoteData completes`, () => { + testScheduler.run(({ cold, expectObservable }) => { + (rdbService.buildFromHref as jasmine.Spy).and.returnValue(cold('a-b-c-d-e-f-g-h-i-j-k-l', { + a: remoteDataMocks.RequestPending, + b: remoteDataMocks.ResponsePending, + c: remoteDataMocks.ResponsePendingStale, + d: remoteDataMocks.SuccessStale, + e: remoteDataMocks.RequestPending, + f: remoteDataMocks.ResponsePending, + g: remoteDataMocks.Success, + h: remoteDataMocks.SuccessStale, + i: remoteDataMocks.RequestPending, + k: remoteDataMocks.ResponsePending, + l: remoteDataMocks.Error, + })); + const expected = '------------(g|)'; + const values = { + g: endpointMaps[one] + }; + expectObservable((service as any).getEndpointMapAt(one)).toBe(expected, values); + }); + }); + + it(`should emit undefined when the response doesn't have a payload`, () => { + testScheduler.run(({ cold, expectObservable }) => { + (rdbService.buildFromHref as jasmine.Spy).and.returnValue(cold('a', { + a: remoteDataMocks.Error, + })); + const expected = '(a|)'; + const values = { + g: undefined + }; + expectObservable((service as any).getEndpointMapAt(href)).toBe(expected, values); + }); }); }); diff --git a/src/app/core/shared/hal-endpoint.service.ts b/src/app/core/shared/hal-endpoint.service.ts index 5cdd7ccfad..07754616c7 100644 --- a/src/app/core/shared/hal-endpoint.service.ts +++ b/src/app/core/shared/hal-endpoint.service.ts @@ -1,11 +1,19 @@ import { Observable } from 'rxjs'; -import { distinctUntilChanged, map, startWith, switchMap, take, skipWhile } from 'rxjs/operators'; +import { + distinctUntilChanged, + map, + startWith, + switchMap, + take, + tap, filter +} from 'rxjs/operators'; import { RequestService } from '../data/request.service'; import { EndpointMapRequest } from '../data/request.models'; import { hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util'; import { RESTURLCombiner } from '../url-combiner/rest-url-combiner'; import { Injectable } from '@angular/core'; import { EndpointMap } from '../cache/response.models'; +import { getFirstCompletedRemoteData } from './operators'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { RemoteData } from '../data/remote-data'; import { CacheableObject } from '../cache/cacheable-object.model'; @@ -33,11 +41,16 @@ export class HALEndpointService { this.requestService.send(request, true); return this.rdbService.buildFromHref(href).pipe( - // This skip ensures that if a stale object is present in the cache when you do a - // call it isn't immediately returned, but we wait until the remote data for the new request - // is created. - skipWhile((rd: RemoteData) => rd.isLoading || rd.isStale), - take(1), + // Re-request stale responses + tap((rd: RemoteData) => { + if (hasValue(rd) && rd.isStale) { + this.getEndpointMapAt(href); + } + }), + // Filter out all stale responses. We're only interested in a single, non-stale, + // completed RemoteData + filter((rd: RemoteData) => !rd.isStale), + getFirstCompletedRemoteData(), map((response: RemoteData) => { if (hasValue(response.payload)) { return response.payload._links; From d32303bf47413cc2a98faf25ab42410a73657938 Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Sat, 25 Nov 2023 14:21:57 +0100 Subject: [PATCH 0024/1286] Added missing aria labels to edit bitstream tab (cherry picked from commit e229be44d6450f9c50ed2d53f4b5d9cb7939fcd1) --- .../item-bitstreams/item-bitstreams.component.html | 7 +++++++ .../item-edit-bitstream-bundle.component.html | 1 + 2 files changed, 8 insertions(+) diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html index 4cb9577fcb..bd4c9334ad 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html @@ -1,21 +1,25 @@
diff --git a/src/app/admin/admin-sidebar/admin-sidebar.component.spec.ts b/src/app/admin/admin-sidebar/admin-sidebar.component.spec.ts index 88efd2a711..9522be29ce 100644 --- a/src/app/admin/admin-sidebar/admin-sidebar.component.spec.ts +++ b/src/app/admin/admin-sidebar/admin-sidebar.component.spec.ts @@ -143,7 +143,7 @@ describe('AdminSidebarComponent', () => { describe('when the collapse link is clicked', () => { beforeEach(() => { spyOn(menuService, 'toggleMenu'); - const sidebarToggler = fixture.debugElement.query(By.css('#sidebar-collapse-toggle > a')); + const sidebarToggler = fixture.debugElement.query(By.css('#sidebar-collapse-toggle > button')); sidebarToggler.triggerEventHandler('click', { preventDefault: () => {/**/ } diff --git a/src/app/footer/footer.component.html b/src/app/footer/footer.component.html index 13d84e6e2e..d4c0cd1a37 100644 --- a/src/app/footer/footer.component.html +++ b/src/app/footer/footer.component.html @@ -62,10 +62,11 @@ {{ 'footer.link.lyrasis' | translate}}

-
diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts index 7572d3ac8b..eb7a703cc2 100644 --- a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts @@ -36,7 +36,7 @@ import { getFirstSucceededRemoteDataPayload, } from '../../../core/shared/operators'; import { PageInfo } from '../../../core/shared/page-info.model'; -import { DisabledDirective } from '../../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../shared/btn-disabled.directive'; import { hasValue } from '../../../shared/empty.util'; import { HostWindowService } from '../../../shared/host-window.service'; import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils'; @@ -71,7 +71,7 @@ export interface ExternalSourceData { InfiniteScrollModule, NgbDropdownModule, FormsModule, - DisabledDirective, + BtnDisabledDirective, ], standalone: true, }) diff --git a/src/app/submission/sections/cc-license/submission-section-cc-licenses.component.ts b/src/app/submission/sections/cc-license/submission-section-cc-licenses.component.ts index 62546e1835..7618de5173 100644 --- a/src/app/submission/sections/cc-license/submission-section-cc-licenses.component.ts +++ b/src/app/submission/sections/cc-license/submission-section-cc-licenses.component.ts @@ -40,7 +40,7 @@ import { import { WorkspaceitemSectionCcLicenseObject } from '../../../core/submission/models/workspaceitem-section-cc-license.model'; import { SubmissionCcLicenseDataService } from '../../../core/submission/submission-cc-license-data.service'; import { SubmissionCcLicenseUrlDataService } from '../../../core/submission/submission-cc-license-url-data.service'; -import { DisabledDirective } from '../../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../shared/btn-disabled.directive'; import { DsSelectComponent } from '../../../shared/ds-select/ds-select.component'; import { isNotEmpty } from '../../../shared/empty.util'; import { ThemedLoadingComponent } from '../../../shared/loading/themed-loading.component'; @@ -65,7 +65,7 @@ import { SectionsType } from '../sections-type'; VarDirective, NgForOf, DsSelectComponent, - DisabledDirective, + BtnDisabledDirective, ], standalone: true, }) diff --git a/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.html b/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.html index 91b89e8435..b03504c6be 100644 --- a/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.html +++ b/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.html @@ -1,7 +1,7 @@
diff --git a/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.ts b/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.ts index c7ba64e4b9..0a6c1bd44d 100644 --- a/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.ts +++ b/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.ts @@ -39,7 +39,7 @@ import { JsonPatchOperationsBuilder } from '../../../../../core/json-patch/build import { WorkspaceitemSectionUploadFileObject } from '../../../../../core/submission/models/workspaceitem-section-upload-file.model'; import { SubmissionJsonPatchOperationsService } from '../../../../../core/submission/submission-json-patch-operations.service'; import { dateToISOFormat } from '../../../../../shared/date.util'; -import { DisabledDirective } from '../../../../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../../../shared/btn-disabled.directive'; import { hasNoValue, hasValue, @@ -81,7 +81,7 @@ import { FormComponent, NgIf, TranslateModule, - DisabledDirective, + BtnDisabledDirective, ], standalone: true, }) diff --git a/src/app/submission/sections/upload/file/section-upload-file.component.html b/src/app/submission/sections/upload/file/section-upload-file.component.html index f8d6b9ca93..bfc09e86c1 100644 --- a/src/app/submission/sections/upload/file/section-upload-file.component.html +++ b/src/app/submission/sections/upload/file/section-upload-file.component.html @@ -35,7 +35,7 @@ -
diff --git a/src/app/system-wide-alert/alert-form/system-wide-alert-form.component.ts b/src/app/system-wide-alert/alert-form/system-wide-alert-form.component.ts index b695bb47ed..ea1c0a55f0 100644 --- a/src/app/system-wide-alert/alert-form/system-wide-alert-form.component.ts +++ b/src/app/system-wide-alert/alert-form/system-wide-alert-form.component.ts @@ -43,7 +43,7 @@ import { RemoteData } from '../../core/data/remote-data'; import { RequestService } from '../../core/data/request.service'; import { SystemWideAlertDataService } from '../../core/data/system-wide-alert-data.service'; import { getFirstCompletedRemoteData } from '../../core/shared/operators'; -import { DisabledDirective } from '../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../shared/btn-disabled.directive'; import { hasValue, isNotEmpty, @@ -60,7 +60,7 @@ import { SystemWideAlert } from '../system-wide-alert.model'; styleUrls: ['./system-wide-alert-form.component.scss'], templateUrl: './system-wide-alert-form.component.html', standalone: true, - imports: [FormsModule, ReactiveFormsModule, UiSwitchModule, NgIf, NgbDatepickerModule, NgbTimepickerModule, AsyncPipe, TranslateModule, DisabledDirective], + imports: [FormsModule, ReactiveFormsModule, UiSwitchModule, NgIf, NgbDatepickerModule, NgbTimepickerModule, AsyncPipe, TranslateModule, BtnDisabledDirective], }) export class SystemWideAlertFormComponent implements OnInit { diff --git a/src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.ts b/src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.ts index e87a292c0c..57e8c73031 100644 --- a/src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.ts +++ b/src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.ts @@ -45,7 +45,7 @@ import { Group } from '../../../../core/eperson/models/group.model'; import { PaginationService } from '../../../../core/pagination/pagination.service'; import { getFirstSucceededRemoteDataPayload } from '../../../../core/shared/operators'; import { ContextHelpDirective } from '../../../../shared/context-help.directive'; -import { DisabledDirective } from '../../../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../../shared/btn-disabled.directive'; import { hasValue } from '../../../../shared/empty.util'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { PaginationComponent } from '../../../../shared/pagination/pagination.component'; @@ -77,7 +77,7 @@ enum SubKey { RouterLink, NgClass, NgForOf, - DisabledDirective, + BtnDisabledDirective, ], }) export class ReviewersListComponent extends MembersListComponent implements OnInit, OnChanges, OnDestroy { diff --git a/src/themes/custom/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts b/src/themes/custom/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts index 40a6264e4e..f74a73a4b8 100644 --- a/src/themes/custom/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts +++ b/src/themes/custom/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts @@ -13,7 +13,7 @@ import { DsoEditMetadataValueComponent } from '../../../../../app/dso-shared/dso import { DsoEditMetadataValueHeadersComponent } from '../../../../../app/dso-shared/dso-edit-metadata/dso-edit-metadata-value-headers/dso-edit-metadata-value-headers.component'; import { MetadataFieldSelectorComponent } from '../../../../../app/dso-shared/dso-edit-metadata/metadata-field-selector/metadata-field-selector.component'; import { AlertComponent } from '../../../../../app/shared/alert/alert.component'; -import { DisabledDirective } from '../../../../../app/shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../../../app/shared/btn-disabled.directive'; import { ThemedLoadingComponent } from '../../../../../app/shared/loading/themed-loading.component'; @Component({ @@ -23,7 +23,7 @@ import { ThemedLoadingComponent } from '../../../../../app/shared/loading/themed // templateUrl: './dso-edit-metadata.component.html', templateUrl: '../../../../../app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.html', standalone: true, - imports: [NgIf, DsoEditMetadataHeadersComponent, MetadataFieldSelectorComponent, DsoEditMetadataValueHeadersComponent, DsoEditMetadataValueComponent, NgFor, DsoEditMetadataFieldValuesComponent, AlertComponent, ThemedLoadingComponent, AsyncPipe, TranslateModule, DisabledDirective], + imports: [NgIf, DsoEditMetadataHeadersComponent, MetadataFieldSelectorComponent, DsoEditMetadataValueHeadersComponent, DsoEditMetadataValueComponent, NgFor, DsoEditMetadataFieldValuesComponent, AlertComponent, ThemedLoadingComponent, AsyncPipe, TranslateModule, BtnDisabledDirective], }) export class DsoEditMetadataComponent extends BaseComponent { } diff --git a/src/themes/custom/app/forgot-password/forgot-password-form/forgot-password-form.component.ts b/src/themes/custom/app/forgot-password/forgot-password-form/forgot-password-form.component.ts index ff64b09664..37fb383429 100644 --- a/src/themes/custom/app/forgot-password/forgot-password-form/forgot-password-form.component.ts +++ b/src/themes/custom/app/forgot-password/forgot-password-form/forgot-password-form.component.ts @@ -7,7 +7,7 @@ import { TranslateModule } from '@ngx-translate/core'; import { ForgotPasswordFormComponent as BaseComponent } from '../../../../../app/forgot-password/forgot-password-form/forgot-password-form.component'; import { ProfilePageSecurityFormComponent } from '../../../../../app/profile-page/profile-page-security-form/profile-page-security-form.component'; -import { DisabledDirective } from '../../../../../app/shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../../../app/shared/btn-disabled.directive'; import { BrowserOnlyPipe } from '../../../../../app/shared/utils/browser-only.pipe'; @Component({ @@ -23,7 +23,7 @@ import { BrowserOnlyPipe } from '../../../../../app/shared/utils/browser-only.pi ProfilePageSecurityFormComponent, AsyncPipe, NgIf, - DisabledDirective, + BtnDisabledDirective, ], }) /** diff --git a/src/themes/custom/app/info/end-user-agreement/end-user-agreement.component.ts b/src/themes/custom/app/info/end-user-agreement/end-user-agreement.component.ts index e557fc466c..2b78006f65 100644 --- a/src/themes/custom/app/info/end-user-agreement/end-user-agreement.component.ts +++ b/src/themes/custom/app/info/end-user-agreement/end-user-agreement.component.ts @@ -4,7 +4,7 @@ import { TranslateModule } from '@ngx-translate/core'; import { EndUserAgreementComponent as BaseComponent } from '../../../../../app/info/end-user-agreement/end-user-agreement.component'; import { EndUserAgreementContentComponent } from '../../../../../app/info/end-user-agreement/end-user-agreement-content/end-user-agreement-content.component'; -import { DisabledDirective } from '../../../../../app/shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../../../app/shared/btn-disabled.directive'; @Component({ selector: 'ds-themed-end-user-agreement', @@ -13,7 +13,7 @@ import { DisabledDirective } from '../../../../../app/shared/disabled-directive' // templateUrl: './end-user-agreement.component.html' templateUrl: '../../../../../app/info/end-user-agreement/end-user-agreement.component.html', standalone: true, - imports: [EndUserAgreementContentComponent, FormsModule, TranslateModule, DisabledDirective], + imports: [EndUserAgreementContentComponent, FormsModule, TranslateModule, BtnDisabledDirective], }) /** diff --git a/src/themes/custom/app/info/feedback/feedback-form/feedback-form.component.ts b/src/themes/custom/app/info/feedback/feedback-form/feedback-form.component.ts index b86fecae7a..3835667111 100644 --- a/src/themes/custom/app/info/feedback/feedback-form/feedback-form.component.ts +++ b/src/themes/custom/app/info/feedback/feedback-form/feedback-form.component.ts @@ -7,7 +7,7 @@ import { import { TranslateModule } from '@ngx-translate/core'; import { FeedbackFormComponent as BaseComponent } from '../../../../../../app/info/feedback/feedback-form/feedback-form.component'; -import { DisabledDirective } from '../../../../../../app/shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../../../../app/shared/btn-disabled.directive'; import { ErrorComponent } from '../../../../../../app/shared/error/error.component'; @Component({ @@ -17,7 +17,7 @@ import { ErrorComponent } from '../../../../../../app/shared/error/error.compone // styleUrls: ['./feedback-form.component.scss'], styleUrls: ['../../../../../../app/info/feedback/feedback-form/feedback-form.component.scss'], standalone: true, - imports: [FormsModule, ReactiveFormsModule, NgIf, ErrorComponent, TranslateModule, DisabledDirective], + imports: [FormsModule, ReactiveFormsModule, NgIf, ErrorComponent, TranslateModule, BtnDisabledDirective], }) export class FeedbackFormComponent extends BaseComponent { } diff --git a/src/themes/custom/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.ts b/src/themes/custom/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.ts index 020293214e..0efa013064 100644 --- a/src/themes/custom/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.ts +++ b/src/themes/custom/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.ts @@ -7,7 +7,7 @@ import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'; import { TranslateModule } from '@ngx-translate/core'; import { MediaViewerVideoComponent as BaseComponent } from '../../../../../../app/item-page/media-viewer/media-viewer-video/media-viewer-video.component'; -import { DisabledDirective } from '../../../../../../app/shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../../../../app/shared/btn-disabled.directive'; @Component({ selector: 'ds-themed-media-viewer-video', @@ -21,7 +21,7 @@ import { DisabledDirective } from '../../../../../../app/shared/disabled-directi NgbDropdownModule, TranslateModule, NgIf, - DisabledDirective, + BtnDisabledDirective, ], }) export class MediaViewerVideoComponent extends BaseComponent { diff --git a/src/themes/custom/app/register-email-form/register-email-form.component.ts b/src/themes/custom/app/register-email-form/register-email-form.component.ts index d9be35f39d..d1f4a6d3ff 100644 --- a/src/themes/custom/app/register-email-form/register-email-form.component.ts +++ b/src/themes/custom/app/register-email-form/register-email-form.component.ts @@ -12,14 +12,14 @@ import { AlertComponent } from 'src/app/shared/alert/alert.component'; import { GoogleRecaptchaComponent } from 'src/app/shared/google-recaptcha/google-recaptcha.component'; import { RegisterEmailFormComponent as BaseComponent } from '../../../../app/register-email-form/register-email-form.component'; -import { DisabledDirective } from '../../../../app/shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../../app/shared/btn-disabled.directive'; @Component({ selector: 'ds-themed-register-email-form', // templateUrl: './register-email-form.component.html', templateUrl: '../../../../app/register-email-form/register-email-form.component.html', standalone: true, - imports: [NgIf, FormsModule, ReactiveFormsModule, AlertComponent, GoogleRecaptchaComponent, AsyncPipe, TranslateModule, DisabledDirective], + imports: [NgIf, FormsModule, ReactiveFormsModule, AlertComponent, GoogleRecaptchaComponent, AsyncPipe, TranslateModule, BtnDisabledDirective], }) export class RegisterEmailFormComponent extends BaseComponent { } diff --git a/src/themes/custom/app/register-page/create-profile/create-profile.component.ts b/src/themes/custom/app/register-page/create-profile/create-profile.component.ts index 659e260b1c..7c1ff908c3 100644 --- a/src/themes/custom/app/register-page/create-profile/create-profile.component.ts +++ b/src/themes/custom/app/register-page/create-profile/create-profile.component.ts @@ -9,7 +9,7 @@ import { TranslateModule } from '@ngx-translate/core'; import { ProfilePageSecurityFormComponent } from '../../../../../app/profile-page/profile-page-security-form/profile-page-security-form.component'; import { CreateProfileComponent as BaseComponent } from '../../../../../app/register-page/create-profile/create-profile.component'; -import { DisabledDirective } from '../../../../../app/shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../../../app/shared/btn-disabled.directive'; /** * Component that renders the create profile page to be used by a user registering through a token @@ -28,7 +28,7 @@ import { DisabledDirective } from '../../../../../app/shared/disabled-directive' AsyncPipe, ReactiveFormsModule, NgForOf, - DisabledDirective, + BtnDisabledDirective, ], }) export class CreateProfileComponent extends BaseComponent { diff --git a/src/themes/custom/app/request-copy/email-request-copy/email-request-copy.component.ts b/src/themes/custom/app/request-copy/email-request-copy/email-request-copy.component.ts index a299e47a27..cf4981d289 100644 --- a/src/themes/custom/app/request-copy/email-request-copy/email-request-copy.component.ts +++ b/src/themes/custom/app/request-copy/email-request-copy/email-request-copy.component.ts @@ -7,7 +7,7 @@ import { FormsModule } from '@angular/forms'; import { TranslateModule } from '@ngx-translate/core'; import { EmailRequestCopyComponent as BaseComponent } from 'src/app/request-copy/email-request-copy/email-request-copy.component'; -import { DisabledDirective } from '../../../../../app/shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../../../app/shared/btn-disabled.directive'; @Component({ selector: 'ds-themed-email-request-copy', @@ -16,7 +16,7 @@ import { DisabledDirective } from '../../../../../app/shared/disabled-directive' // templateUrl: './email-request-copy.component.html', templateUrl: './../../../../../app/request-copy/email-request-copy/email-request-copy.component.html', standalone: true, - imports: [FormsModule, NgClass, NgIf, TranslateModule, DisabledDirective], + imports: [FormsModule, NgClass, NgIf, TranslateModule, BtnDisabledDirective], }) export class EmailRequestCopyComponent extends BaseComponent { diff --git a/src/themes/custom/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts b/src/themes/custom/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts index 7936deb406..aec7bfd6db 100644 --- a/src/themes/custom/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts +++ b/src/themes/custom/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts @@ -5,7 +5,7 @@ import { import { Component } from '@angular/core'; import { TranslateModule } from '@ngx-translate/core'; -import { DisabledDirective } from '../../../../../../../../../../app/shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../../../../../../../../app/shared/btn-disabled.directive'; import { ExternalSourceEntryImportModalComponent as BaseComponent } from '../../../../../../../../../../app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component'; import { ThemedSearchResultsComponent } from '../../../../../../../../../../app/shared/search/search-results/themed-search-results.component'; @@ -20,7 +20,7 @@ import { ThemedSearchResultsComponent } from '../../../../../../../../../../app/ ThemedSearchResultsComponent, NgIf, AsyncPipe, - DisabledDirective, + BtnDisabledDirective, ], }) export class ExternalSourceEntryImportModalComponent extends BaseComponent { diff --git a/src/themes/custom/app/submission/sections/upload/file/section-upload-file.component.ts b/src/themes/custom/app/submission/sections/upload/file/section-upload-file.component.ts index 17bc5d9136..cea515102a 100644 --- a/src/themes/custom/app/submission/sections/upload/file/section-upload-file.component.ts +++ b/src/themes/custom/app/submission/sections/upload/file/section-upload-file.component.ts @@ -6,7 +6,7 @@ import { Component } from '@angular/core'; import { TranslateModule } from '@ngx-translate/core'; import { SubmissionSectionUploadFileComponent as BaseComponent } from 'src/app/submission/sections/upload/file/section-upload-file.component'; -import { DisabledDirective } from '../../../../../../../app/shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../../../../../app/shared/btn-disabled.directive'; import { ThemedFileDownloadLinkComponent } from '../../../../../../../app/shared/file-download-link/themed-file-download-link.component'; import { FileSizePipe } from '../../../../../../../app/shared/utils/file-size-pipe'; import { SubmissionSectionUploadFileViewComponent } from '../../../../../../../app/submission/sections/upload/file/view/section-upload-file-view.component'; @@ -28,7 +28,7 @@ import { SubmissionSectionUploadFileViewComponent } from '../../../../../../../a AsyncPipe, ThemedFileDownloadLinkComponent, FileSizePipe, - DisabledDirective, + BtnDisabledDirective, ], }) export class SubmissionSectionUploadFileComponent From 0928dc1ca95065482c6fc190b287b5841a55ed55 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Mon, 16 Sep 2024 14:11:59 +0200 Subject: [PATCH 0427/1286] 117544: linting --- .../epeople-registry/eperson-form/eperson-form.component.ts | 2 +- .../group-form/members-list/members-list.component.ts | 2 +- .../delete-collection-page/delete-collection-page.component.ts | 2 +- .../delete-community-page/delete-community-page.component.ts | 2 +- .../profile-page-researcher-form.component.ts | 2 +- src/app/register-email-form/register-email-form.component.ts | 2 +- .../access-control-array-form.component.ts | 2 +- .../external-source-entry-import-modal.component.ts | 2 +- .../form/resource-policy-form.component.spec.ts | 2 +- .../resource-policies/form/resource-policy-form.component.ts | 2 +- .../subscription-view/subscription-view.component.ts | 2 +- .../collection/submission-form-collection.component.spec.ts | 2 +- .../form/collection/submission-form-collection.component.ts | 2 +- .../upload/file/edit/section-upload-file-edit.component.ts | 2 +- .../reviewers-list/reviewers-list.component.ts | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts b/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts index 1c6f1929f3..c8236ca22d 100644 --- a/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts +++ b/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts @@ -65,8 +65,8 @@ import { import { PageInfo } from '../../../core/shared/page-info.model'; import { Registration } from '../../../core/shared/registration.model'; import { TYPE_REQUEST_FORGOT } from '../../../register-email-form/register-email-form.component'; -import { ConfirmationModalComponent } from '../../../shared/confirmation-modal/confirmation-modal.component'; import { BtnDisabledDirective } from '../../../shared/btn-disabled.directive'; +import { ConfirmationModalComponent } from '../../../shared/confirmation-modal/confirmation-modal.component'; import { hasValue } from '../../../shared/empty.util'; import { FormBuilderService } from '../../../shared/form/builder/form-builder.service'; import { FormComponent } from '../../../shared/form/form.component'; diff --git a/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts b/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts index 6563a765d2..22934394c8 100644 --- a/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts +++ b/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts @@ -54,8 +54,8 @@ import { getFirstCompletedRemoteData, getRemoteDataPayload, } from '../../../../core/shared/operators'; -import { ContextHelpDirective } from '../../../../shared/context-help.directive'; import { BtnDisabledDirective } from '../../../../shared/btn-disabled.directive'; +import { ContextHelpDirective } from '../../../../shared/context-help.directive'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { PaginationComponent } from '../../../../shared/pagination/pagination.component'; import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model'; diff --git a/src/app/collection-page/delete-collection-page/delete-collection-page.component.ts b/src/app/collection-page/delete-collection-page/delete-collection-page.component.ts index 3d4d4abb5f..acc716b52a 100644 --- a/src/app/collection-page/delete-collection-page/delete-collection-page.component.ts +++ b/src/app/collection-page/delete-collection-page/delete-collection-page.component.ts @@ -15,8 +15,8 @@ import { import { DSONameService } from '../../core/breadcrumbs/dso-name.service'; import { CollectionDataService } from '../../core/data/collection-data.service'; import { Collection } from '../../core/shared/collection.model'; -import { DeleteComColPageComponent } from '../../shared/comcol/comcol-forms/delete-comcol-page/delete-comcol-page.component'; import { BtnDisabledDirective } from '../../shared/btn-disabled.directive'; +import { DeleteComColPageComponent } from '../../shared/comcol/comcol-forms/delete-comcol-page/delete-comcol-page.component'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { VarDirective } from '../../shared/utils/var.directive'; diff --git a/src/app/community-page/delete-community-page/delete-community-page.component.ts b/src/app/community-page/delete-community-page/delete-community-page.component.ts index b2fa5956cb..9c19a5eb47 100644 --- a/src/app/community-page/delete-community-page/delete-community-page.component.ts +++ b/src/app/community-page/delete-community-page/delete-community-page.component.ts @@ -15,8 +15,8 @@ import { import { DSONameService } from '../../core/breadcrumbs/dso-name.service'; import { CommunityDataService } from '../../core/data/community-data.service'; import { Community } from '../../core/shared/community.model'; -import { DeleteComColPageComponent } from '../../shared/comcol/comcol-forms/delete-comcol-page/delete-comcol-page.component'; import { BtnDisabledDirective } from '../../shared/btn-disabled.directive'; +import { DeleteComColPageComponent } from '../../shared/comcol/comcol-forms/delete-comcol-page/delete-comcol-page.component'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { VarDirective } from '../../shared/utils/var.directive'; diff --git a/src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.ts b/src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.ts index 925ed6d5a6..5d09097e6b 100644 --- a/src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.ts +++ b/src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.ts @@ -36,8 +36,8 @@ import { getFirstCompletedRemoteData, getFirstSucceededRemoteDataPayload, } from '../../core/shared/operators'; -import { ConfirmationModalComponent } from '../../shared/confirmation-modal/confirmation-modal.component'; import { BtnDisabledDirective } from '../../shared/btn-disabled.directive'; +import { ConfirmationModalComponent } from '../../shared/confirmation-modal/confirmation-modal.component'; import { isNotEmpty } from '../../shared/empty.util'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { followLink } from '../../shared/utils/follow-link-config.model'; diff --git a/src/app/register-email-form/register-email-form.component.ts b/src/app/register-email-form/register-email-form.component.ts index 37ce725778..585ca71c24 100644 --- a/src/app/register-email-form/register-email-form.component.ts +++ b/src/app/register-email-form/register-email-form.component.ts @@ -54,8 +54,8 @@ import { import { Registration } from '../core/shared/registration.model'; import { AlertComponent } from '../shared/alert/alert.component'; import { AlertType } from '../shared/alert/alert-type'; -import { KlaroService } from '../shared/cookies/klaro.service'; import { BtnDisabledDirective } from '../shared/btn-disabled.directive'; +import { KlaroService } from '../shared/cookies/klaro.service'; import { isNotEmpty } from '../shared/empty.util'; import { GoogleRecaptchaComponent } from '../shared/google-recaptcha/google-recaptcha.component'; import { NotificationsService } from '../shared/notifications/notifications.service'; diff --git a/src/app/shared/access-control-form-container/access-control-array-form/access-control-array-form.component.ts b/src/app/shared/access-control-form-container/access-control-array-form/access-control-array-form.component.ts index 8f7f640c28..3dc84a833a 100644 --- a/src/app/shared/access-control-form-container/access-control-array-form/access-control-array-form.component.ts +++ b/src/app/shared/access-control-form-container/access-control-array-form/access-control-array-form.component.ts @@ -16,8 +16,8 @@ import { NgbDatepickerModule } from '@ng-bootstrap/ng-bootstrap'; import { TranslateModule } from '@ngx-translate/core'; import { AccessesConditionOption } from '../../../core/config/models/config-accesses-conditions-options.model'; -import { dateToISOFormat } from '../../date.util'; import { BtnDisabledDirective } from '../../btn-disabled.directive'; +import { dateToISOFormat } from '../../date.util'; import { ToDatePipe } from './to-date.pipe'; @Component({ diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts index c666baf21f..e0cc90ceaa 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts @@ -37,8 +37,8 @@ import { getRemoteDataPayload, } from '../../../../../../../core/shared/operators'; import { SubmissionImportExternalCollectionComponent } from '../../../../../../../submission/import-external/import-external-collection/submission-import-external-collection.component'; -import { CollectionListEntry } from '../../../../../../collection-dropdown/collection-dropdown.component'; import { BtnDisabledDirective } from '../../../../../../btn-disabled.directive'; +import { CollectionListEntry } from '../../../../../../collection-dropdown/collection-dropdown.component'; import { NotificationsService } from '../../../../../../notifications/notifications.service'; import { CollectionElementLinkType } from '../../../../../../object-collection/collection-element-link.type'; import { ItemSearchResult } from '../../../../../../object-collection/shared/item-search-result.model'; diff --git a/src/app/shared/resource-policies/form/resource-policy-form.component.spec.ts b/src/app/shared/resource-policies/form/resource-policy-form.component.spec.ts index d4dac77d72..deaef6c611 100644 --- a/src/app/shared/resource-policies/form/resource-policy-form.component.spec.ts +++ b/src/app/shared/resource-policies/form/resource-policy-form.component.spec.ts @@ -45,11 +45,11 @@ import { ResourcePolicy } from '../../../core/resource-policy/models/resource-po import { RESOURCE_POLICY } from '../../../core/resource-policy/models/resource-policy.resource-type'; import { SubmissionObjectDataService } from '../../../core/submission/submission-object-data.service'; import { SubmissionService } from '../../../submission/submission.service'; +import { BtnDisabledDirective } from '../../btn-disabled.directive'; import { dateToISOFormat, stringToNgbDateStruct, } from '../../date.util'; -import { BtnDisabledDirective } from '../../btn-disabled.directive'; import { isNotEmptyOperator } from '../../empty.util'; import { EpersonGroupListComponent } from '../../eperson-group-list/eperson-group-list.component'; import { dsDynamicFormControlMapFn } from '../../form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-map-fn'; diff --git a/src/app/shared/resource-policies/form/resource-policy-form.component.ts b/src/app/shared/resource-policies/form/resource-policy-form.component.ts index e13ba9ecc7..08a7f18492 100644 --- a/src/app/shared/resource-policies/form/resource-policy-form.component.ts +++ b/src/app/shared/resource-policies/form/resource-policy-form.component.ts @@ -47,11 +47,11 @@ import { ResourcePolicy } from '../../../core/resource-policy/models/resource-po import { RESOURCE_POLICY } from '../../../core/resource-policy/models/resource-policy.resource-type'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { getFirstSucceededRemoteData } from '../../../core/shared/operators'; +import { BtnDisabledDirective } from '../../btn-disabled.directive'; import { dateToISOFormat, stringToNgbDateStruct, } from '../../date.util'; -import { BtnDisabledDirective } from '../../btn-disabled.directive'; import { hasValue, hasValueOperator, diff --git a/src/app/shared/subscriptions/subscription-view/subscription-view.component.ts b/src/app/shared/subscriptions/subscription-view/subscription-view.component.ts index 9d9ce08905..f940e69795 100644 --- a/src/app/shared/subscriptions/subscription-view/subscription-view.component.ts +++ b/src/app/shared/subscriptions/subscription-view/subscription-view.component.ts @@ -19,8 +19,8 @@ import { getDSORoute } from 'src/app/app-routing-paths'; import { DSONameService } from '../../../core/breadcrumbs/dso-name.service'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; -import { ConfirmationModalComponent } from '../../confirmation-modal/confirmation-modal.component'; import { BtnDisabledDirective } from '../../btn-disabled.directive'; +import { ConfirmationModalComponent } from '../../confirmation-modal/confirmation-modal.component'; import { hasValue } from '../../empty.util'; import { ThemedTypeBadgeComponent } from '../../object-collection/shared/badges/type-badge/themed-type-badge.component'; import { Subscription } from '../models/subscription.model'; diff --git a/src/app/submission/form/collection/submission-form-collection.component.spec.ts b/src/app/submission/form/collection/submission-form-collection.component.spec.ts index 61bad0439f..3a5ae8a18d 100644 --- a/src/app/submission/form/collection/submission-form-collection.component.spec.ts +++ b/src/app/submission/form/collection/submission-form-collection.component.spec.ts @@ -30,8 +30,8 @@ import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder'; import { Collection } from '../../../core/shared/collection.model'; import { SubmissionJsonPatchOperationsService } from '../../../core/submission/submission-json-patch-operations.service'; -import { ThemedCollectionDropdownComponent } from '../../../shared/collection-dropdown/themed-collection-dropdown.component'; import { BtnDisabledDirective } from '../../../shared/btn-disabled.directive'; +import { ThemedCollectionDropdownComponent } from '../../../shared/collection-dropdown/themed-collection-dropdown.component'; import { DSONameServiceMock } from '../../../shared/mocks/dso-name.service.mock'; import { mockSubmissionId, diff --git a/src/app/submission/form/collection/submission-form-collection.component.ts b/src/app/submission/form/collection/submission-form-collection.component.ts index 10b1f815dc..1736b474d5 100644 --- a/src/app/submission/form/collection/submission-form-collection.component.ts +++ b/src/app/submission/form/collection/submission-form-collection.component.ts @@ -34,9 +34,9 @@ import { Collection } from '../../../core/shared/collection.model'; import { getFirstSucceededRemoteDataPayload } from '../../../core/shared/operators'; import { SubmissionObject } from '../../../core/submission/models/submission-object.model'; import { SubmissionJsonPatchOperationsService } from '../../../core/submission/submission-json-patch-operations.service'; +import { BtnDisabledDirective } from '../../../shared/btn-disabled.directive'; import { CollectionDropdownComponent } from '../../../shared/collection-dropdown/collection-dropdown.component'; import { ThemedCollectionDropdownComponent } from '../../../shared/collection-dropdown/themed-collection-dropdown.component'; -import { BtnDisabledDirective } from '../../../shared/btn-disabled.directive'; import { hasValue, isNotEmpty, diff --git a/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.ts b/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.ts index 0a6c1bd44d..79b3d3a565 100644 --- a/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.ts +++ b/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.ts @@ -38,8 +38,8 @@ import { JsonPatchOperationPathCombiner } from '../../../../../core/json-patch/b import { JsonPatchOperationsBuilder } from '../../../../../core/json-patch/builder/json-patch-operations-builder'; import { WorkspaceitemSectionUploadFileObject } from '../../../../../core/submission/models/workspaceitem-section-upload-file.model'; import { SubmissionJsonPatchOperationsService } from '../../../../../core/submission/submission-json-patch-operations.service'; -import { dateToISOFormat } from '../../../../../shared/date.util'; import { BtnDisabledDirective } from '../../../../../shared/btn-disabled.directive'; +import { dateToISOFormat } from '../../../../../shared/date.util'; import { hasNoValue, hasValue, diff --git a/src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.ts b/src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.ts index 57e8c73031..c43fabdb83 100644 --- a/src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.ts +++ b/src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.ts @@ -44,8 +44,8 @@ import { EpersonDtoModel } from '../../../../core/eperson/models/eperson-dto.mod import { Group } from '../../../../core/eperson/models/group.model'; import { PaginationService } from '../../../../core/pagination/pagination.service'; import { getFirstSucceededRemoteDataPayload } from '../../../../core/shared/operators'; -import { ContextHelpDirective } from '../../../../shared/context-help.directive'; import { BtnDisabledDirective } from '../../../../shared/btn-disabled.directive'; +import { ContextHelpDirective } from '../../../../shared/context-help.directive'; import { hasValue } from '../../../../shared/empty.util'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { PaginationComponent } from '../../../../shared/pagination/pagination.component'; From e7d050d3ebe92b20223259a657077b72f0247402 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Mon, 16 Sep 2024 13:44:06 +0200 Subject: [PATCH 0428/1286] 117544: PR feedback - added typedocs - changed directive to only be present for buttons - various other small fixes --- .../filtered-items.component.html | 2 +- .../dso-edit-metadata-value.component.html | 2 +- .../dso-edit-metadata-value.component.spec.ts | 3 +- .../item-delete/item-delete.component.html | 2 +- .../access-control-array-form.component.html | 2 +- ...cess-control-form-container.component.html | 12 ++++---- src/app/shared/disabled-directive.spec.ts | 8 ++++++ src/app/shared/disabled-directive.ts | 28 ++++++++++++++++++- ...amic-form-control-container.component.html | 2 +- .../date-picker/date-picker.component.html | 6 ++-- .../disabled/dynamic-disabled.component.html | 2 +- .../dynamic-disabled.component.spec.ts | 2 +- .../lookup/dynamic-lookup.component.html | 4 +-- .../onebox/dynamic-onebox.component.html | 4 +-- ...dynamic-scrollable-dropdown.component.html | 2 +- .../number-picker.component.html | 2 +- .../vocabulary-treeview.component.html | 4 +-- .../collection-select.component.html | 2 +- .../item-select/item-select.component.html | 2 +- .../item-select/item-select.component.spec.ts | 3 +- .../pagination/pagination.component.html | 2 +- ...mission-section-cc-licenses.component.html | 4 +-- .../file/section-upload-file.component.html | 2 +- 23 files changed, 67 insertions(+), 35 deletions(-) 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 index 38591b0fcd..1750975c9a 100644 --- a/src/app/admin/admin-reports/filtered-items/filtered-items.component.html +++ b/src/app/admin/admin-reports/filtered-items/filtered-items.component.html @@ -12,7 +12,7 @@
diff --git a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-value/dso-edit-metadata-value.component.html b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-value/dso-edit-metadata-value.component.html index 450dfae98c..221ae13451 100644 --- a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-value/dso-edit-metadata-value.component.html +++ b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-value/dso-edit-metadata-value.component.html @@ -36,7 +36,7 @@ [authorityValue]="mdValue.newValue.confidence" [iconMode]="true" > - -
diff --git a/src/app/access-control/bulk-access/bulk-access.component.ts b/src/app/access-control/bulk-access/bulk-access.component.ts index 10be65f24a..a1608d27d0 100644 --- a/src/app/access-control/bulk-access/bulk-access.component.ts +++ b/src/app/access-control/bulk-access/bulk-access.component.ts @@ -14,7 +14,7 @@ import { } from 'rxjs/operators'; import { BulkAccessControlService } from '../../shared/access-control-form-container/bulk-access-control.service'; -import { DisabledDirective } from '../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../shared/btn-disabled.directive'; import { SelectableListState } from '../../shared/object-list/selectable-list/selectable-list.reducer'; import { SelectableListService } from '../../shared/object-list/selectable-list/selectable-list.service'; import { BulkAccessBrowseComponent } from './browse/bulk-access-browse.component'; @@ -28,7 +28,7 @@ import { BulkAccessSettingsComponent } from './settings/bulk-access-settings.com TranslateModule, BulkAccessSettingsComponent, BulkAccessBrowseComponent, - DisabledDirective, + BtnDisabledDirective, ], standalone: true, }) diff --git a/src/app/access-control/epeople-registry/epeople-registry.component.spec.ts b/src/app/access-control/epeople-registry/epeople-registry.component.spec.ts index 9ce1674e23..cd7441022c 100644 --- a/src/app/access-control/epeople-registry/epeople-registry.component.spec.ts +++ b/src/app/access-control/epeople-registry/epeople-registry.component.spec.ts @@ -42,7 +42,7 @@ import { EPersonDataService } from '../../core/eperson/eperson-data.service'; import { EPerson } from '../../core/eperson/models/eperson.model'; import { PaginationService } from '../../core/pagination/pagination.service'; import { PageInfo } from '../../core/shared/page-info.model'; -import { DisabledDirective } from '../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../shared/btn-disabled.directive'; import { FormBuilderService } from '../../shared/form/builder/form-builder.service'; import { ThemedLoadingComponent } from '../../shared/loading/themed-loading.component'; import { getMockFormBuilderService } from '../../shared/mocks/form-builder-service.mock'; @@ -152,7 +152,7 @@ describe('EPeopleRegistryComponent', () => { paginationService = new PaginationServiceStub(); TestBed.configureTestingModule({ imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule, RouterTestingModule.withRoutes([]), - TranslateModule.forRoot(), EPeopleRegistryComponent, DisabledDirective], + TranslateModule.forRoot(), EPeopleRegistryComponent, BtnDisabledDirective], providers: [ { provide: EPersonDataService, useValue: ePersonDataServiceStub }, { provide: NotificationsService, useValue: new NotificationsServiceStub() }, diff --git a/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.html b/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.html index 694fe9d7c5..98ff328884 100644 --- a/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.html +++ b/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.html @@ -25,7 +25,7 @@
-
diff --git a/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts b/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts index 0b5a6ec752..2e9427df9c 100644 --- a/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts +++ b/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts @@ -45,7 +45,7 @@ import { GroupDataService } from '../../../core/eperson/group-data.service'; import { EPerson } from '../../../core/eperson/models/eperson.model'; import { PaginationService } from '../../../core/pagination/pagination.service'; import { PageInfo } from '../../../core/shared/page-info.model'; -import { DisabledDirective } from '../../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../shared/btn-disabled.directive'; import { FormBuilderService } from '../../../shared/form/builder/form-builder.service'; import { FormComponent } from '../../../shared/form/form.component'; import { ThemedLoadingComponent } from '../../../shared/loading/themed-loading.component'; @@ -228,7 +228,7 @@ describe('EPersonFormComponent', () => { route = new ActivatedRouteStub(); router = new RouterStub(); TestBed.configureTestingModule({ - imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, DisabledDirective, BrowserModule, + imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BtnDisabledDirective, BrowserModule, TranslateModule.forRoot({ loader: { provide: TranslateLoader, diff --git a/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts b/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts index 40f920f8d8..1c6f1929f3 100644 --- a/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts +++ b/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts @@ -66,7 +66,7 @@ import { PageInfo } from '../../../core/shared/page-info.model'; import { Registration } from '../../../core/shared/registration.model'; import { TYPE_REQUEST_FORGOT } from '../../../register-email-form/register-email-form.component'; import { ConfirmationModalComponent } from '../../../shared/confirmation-modal/confirmation-modal.component'; -import { DisabledDirective } from '../../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../shared/btn-disabled.directive'; import { hasValue } from '../../../shared/empty.util'; import { FormBuilderService } from '../../../shared/form/builder/form-builder.service'; import { FormComponent } from '../../../shared/form/form.component'; @@ -93,7 +93,7 @@ import { ValidateEmailNotTaken } from './validators/email-taken.validator'; PaginationComponent, RouterLink, HasNoValuePipe, - DisabledDirective, + BtnDisabledDirective, ], standalone: true, }) diff --git a/src/app/access-control/group-registry/group-form/members-list/members-list.component.html b/src/app/access-control/group-registry/group-form/members-list/members-list.component.html index e531b35f9e..d289d036bb 100644 --- a/src/app/access-control/group-registry/group-form/members-list/members-list.component.html +++ b/src/app/access-control/group-registry/group-form/members-list/members-list.component.html @@ -35,14 +35,14 @@
  - +
@@ -158,8 +158,8 @@ {{'admin.reports.commons.page' | translate}} {{ currentPage + 1 }} {{'admin.reports.commons.of' | translate}} {{ pageCount() }}
- - + + 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 index 73b0eeb771..04ee4894ec 100644 --- a/src/app/admin/admin-reports/filtered-items/filtered-items.component.ts +++ b/src/app/admin/admin-reports/filtered-items/filtered-items.component.ts @@ -43,7 +43,7 @@ import { getFirstSucceededRemoteListPayload } from 'src/app/core/shared/operator import { isEmpty } from 'src/app/shared/empty.util'; import { environment } from 'src/environments/environment'; -import { DisabledDirective } from '../../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../shared/btn-disabled.directive'; import { FiltersComponent } from '../filters-section/filters-section.component'; import { FilteredItems } from './filtered-items-model'; import { OptionVO } from './option-vo.model'; @@ -65,7 +65,7 @@ import { QueryPredicate } from './query-predicate.model'; NgIf, NgForOf, FiltersComponent, - DisabledDirective, + BtnDisabledDirective, ], standalone: true, }) diff --git a/src/app/collection-page/delete-collection-page/delete-collection-page.component.html b/src/app/collection-page/delete-collection-page/delete-collection-page.component.html index ab1bff0849..0cdba00f03 100644 --- a/src/app/collection-page/delete-collection-page/delete-collection-page.component.html +++ b/src/app/collection-page/delete-collection-page/delete-collection-page.component.html @@ -6,10 +6,10 @@

{{ 'collection.delete.text' | translate:{ dso: dsoNameService.getName(dso) } }}

- - diff --git a/src/app/collection-page/delete-collection-page/delete-collection-page.component.ts b/src/app/collection-page/delete-collection-page/delete-collection-page.component.ts index 1fab715aa4..3d4d4abb5f 100644 --- a/src/app/collection-page/delete-collection-page/delete-collection-page.component.ts +++ b/src/app/collection-page/delete-collection-page/delete-collection-page.component.ts @@ -16,7 +16,7 @@ import { DSONameService } from '../../core/breadcrumbs/dso-name.service'; import { CollectionDataService } from '../../core/data/collection-data.service'; import { Collection } from '../../core/shared/collection.model'; import { DeleteComColPageComponent } from '../../shared/comcol/comcol-forms/delete-comcol-page/delete-comcol-page.component'; -import { DisabledDirective } from '../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../shared/btn-disabled.directive'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { VarDirective } from '../../shared/utils/var.directive'; @@ -32,7 +32,7 @@ import { VarDirective } from '../../shared/utils/var.directive'; AsyncPipe, NgIf, VarDirective, - DisabledDirective, + BtnDisabledDirective, ], standalone: true, }) diff --git a/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.html b/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.html index cc01848290..1e09758bd1 100644 --- a/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.html +++ b/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.html @@ -19,32 +19,32 @@
diff --git a/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.spec.ts b/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.spec.ts index 22012263e0..2e3cf5477c 100644 --- a/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.spec.ts +++ b/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.spec.ts @@ -22,7 +22,7 @@ import { Collection } from '../../../../core/shared/collection.model'; import { ContentSource } from '../../../../core/shared/content-source.model'; import { ContentSourceSetSerializer } from '../../../../core/shared/content-source-set-serializer'; import { Process } from '../../../../process-page/processes/process.model'; -import { DisabledDirective } from '../../../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../../shared/btn-disabled.directive'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { createSuccessfulRemoteDataObject$ } from '../../../../shared/remote-data.utils'; import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub'; @@ -105,7 +105,7 @@ describe('CollectionSourceControlsComponent', () => { requestService = jasmine.createSpyObj('requestService', ['removeByHrefSubstring', 'setStaleByHrefSubstring']); TestBed.configureTestingModule({ - imports: [TranslateModule.forRoot(), RouterTestingModule, CollectionSourceControlsComponent, VarDirective, DisabledDirective], + imports: [TranslateModule.forRoot(), RouterTestingModule, CollectionSourceControlsComponent, VarDirective, BtnDisabledDirective], providers: [ { provide: ScriptDataService, useValue: scriptDataService }, { provide: ProcessDataService, useValue: processDataService }, diff --git a/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.ts b/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.ts index 06dd537d9d..e35a64af16 100644 --- a/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.ts +++ b/src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.ts @@ -40,7 +40,7 @@ import { } from '../../../../core/shared/operators'; import { Process } from '../../../../process-page/processes/process.model'; import { ProcessStatus } from '../../../../process-page/processes/process-status.model'; -import { DisabledDirective } from '../../../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../../shared/btn-disabled.directive'; import { hasValue } from '../../../../shared/empty.util'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { VarDirective } from '../../../../shared/utils/var.directive'; @@ -57,7 +57,7 @@ import { VarDirective } from '../../../../shared/utils/var.directive'; AsyncPipe, NgIf, VarDirective, - DisabledDirective, + BtnDisabledDirective, ], standalone: true, }) diff --git a/src/app/collection-page/edit-collection-page/collection-source/collection-source.component.html b/src/app/collection-page/edit-collection-page/collection-source/collection-source.component.html index 5b13401d22..7aa1f1a8b7 100644 --- a/src/app/collection-page/edit-collection-page/collection-source/collection-source.component.html +++ b/src/app/collection-page/edit-collection-page/collection-source/collection-source.component.html @@ -1,7 +1,7 @@
- diff --git a/src/app/community-page/delete-community-page/delete-community-page.component.ts b/src/app/community-page/delete-community-page/delete-community-page.component.ts index 59fb75fa97..b2fa5956cb 100644 --- a/src/app/community-page/delete-community-page/delete-community-page.component.ts +++ b/src/app/community-page/delete-community-page/delete-community-page.component.ts @@ -16,7 +16,7 @@ import { DSONameService } from '../../core/breadcrumbs/dso-name.service'; import { CommunityDataService } from '../../core/data/community-data.service'; import { Community } from '../../core/shared/community.model'; import { DeleteComColPageComponent } from '../../shared/comcol/comcol-forms/delete-comcol-page/delete-comcol-page.component'; -import { DisabledDirective } from '../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../shared/btn-disabled.directive'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { VarDirective } from '../../shared/utils/var.directive'; @@ -32,7 +32,7 @@ import { VarDirective } from '../../shared/utils/var.directive'; AsyncPipe, VarDirective, NgIf, - DisabledDirective, + BtnDisabledDirective, ], standalone: true, }) diff --git a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-value/dso-edit-metadata-value.component.html b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-value/dso-edit-metadata-value.component.html index 221ae13451..57cad2e9a7 100644 --- a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-value/dso-edit-metadata-value.component.html +++ b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-value/dso-edit-metadata-value.component.html @@ -71,29 +71,29 @@ - - @@ -77,13 +77,13 @@
- - diff --git a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.spec.ts b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.spec.ts index 7f54c6eeeb..cbe2c18792 100644 --- a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.spec.ts +++ b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.spec.ts @@ -22,7 +22,7 @@ import { Item } from '../../core/shared/item.model'; import { ITEM } from '../../core/shared/item.resource-type'; import { MetadataValue } from '../../core/shared/metadata.models'; import { AlertComponent } from '../../shared/alert/alert.component'; -import { DisabledDirective } from '../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../shared/btn-disabled.directive'; import { ThemedLoadingComponent } from '../../shared/loading/themed-loading.component'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { TestDataService } from '../../shared/testing/test-data-service.mock'; @@ -95,7 +95,7 @@ describe('DsoEditMetadataComponent', () => { RouterTestingModule.withRoutes([]), DsoEditMetadataComponent, VarDirective, - DisabledDirective, + BtnDisabledDirective, ], providers: [ { provide: APP_DATA_SERVICES_MAP, useValue: mockDataServiceMap }, diff --git a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts index 12d77ab24f..2b8f42567c 100644 --- a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts +++ b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts @@ -47,7 +47,7 @@ import { getFirstCompletedRemoteData } from '../../core/shared/operators'; import { ResourceType } from '../../core/shared/resource-type'; import { AlertComponent } from '../../shared/alert/alert.component'; import { AlertType } from '../../shared/alert/alert-type'; -import { DisabledDirective } from '../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../shared/btn-disabled.directive'; import { hasNoValue, hasValue, @@ -67,7 +67,7 @@ import { MetadataFieldSelectorComponent } from './metadata-field-selector/metada styleUrls: ['./dso-edit-metadata.component.scss'], templateUrl: './dso-edit-metadata.component.html', standalone: true, - imports: [NgIf, DsoEditMetadataHeadersComponent, MetadataFieldSelectorComponent, DsoEditMetadataValueHeadersComponent, DsoEditMetadataValueComponent, NgFor, DsoEditMetadataFieldValuesComponent, AlertComponent, ThemedLoadingComponent, AsyncPipe, TranslateModule, DisabledDirective], + imports: [NgIf, DsoEditMetadataHeadersComponent, MetadataFieldSelectorComponent, DsoEditMetadataValueHeadersComponent, DsoEditMetadataValueComponent, NgFor, DsoEditMetadataFieldValuesComponent, AlertComponent, ThemedLoadingComponent, AsyncPipe, TranslateModule, BtnDisabledDirective], }) /** * Component showing a table of all metadata on a DSpaceObject and options to modify them diff --git a/src/app/forgot-password/forgot-password-form/forgot-password-form.component.html b/src/app/forgot-password/forgot-password-form/forgot-password-form.component.html index 1f3df7e333..6cff2903b9 100644 --- a/src/app/forgot-password/forgot-password-form/forgot-password-form.component.html +++ b/src/app/forgot-password/forgot-password-form/forgot-password-form.component.html @@ -28,7 +28,7 @@
diff --git a/src/app/forgot-password/forgot-password-form/forgot-password-form.component.ts b/src/app/forgot-password/forgot-password-form/forgot-password-form.component.ts index 4b70fce18f..68f0f9d203 100644 --- a/src/app/forgot-password/forgot-password-form/forgot-password-form.component.ts +++ b/src/app/forgot-password/forgot-password-form/forgot-password-form.component.ts @@ -29,7 +29,7 @@ import { } from '../../core/shared/operators'; import { Registration } from '../../core/shared/registration.model'; import { ProfilePageSecurityFormComponent } from '../../profile-page/profile-page-security-form/profile-page-security-form.component'; -import { DisabledDirective } from '../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../shared/btn-disabled.directive'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { BrowserOnlyPipe } from '../../shared/utils/browser-only.pipe'; @@ -43,7 +43,7 @@ import { BrowserOnlyPipe } from '../../shared/utils/browser-only.pipe'; ProfilePageSecurityFormComponent, AsyncPipe, NgIf, - DisabledDirective, + BtnDisabledDirective, ], standalone: true, }) diff --git a/src/app/info/end-user-agreement/end-user-agreement.component.html b/src/app/info/end-user-agreement/end-user-agreement.component.html index 4b93d631b7..ceb2ad23a4 100644 --- a/src/app/info/end-user-agreement/end-user-agreement.component.html +++ b/src/app/info/end-user-agreement/end-user-agreement.component.html @@ -7,7 +7,7 @@
- +
diff --git a/src/app/info/end-user-agreement/end-user-agreement.component.spec.ts b/src/app/info/end-user-agreement/end-user-agreement.component.spec.ts index 8195ce75eb..88cb46e377 100644 --- a/src/app/info/end-user-agreement/end-user-agreement.component.spec.ts +++ b/src/app/info/end-user-agreement/end-user-agreement.component.spec.ts @@ -16,7 +16,7 @@ import { of as observableOf } from 'rxjs'; import { LogOutAction } from '../../core/auth/auth.actions'; import { AuthService } from '../../core/auth/auth.service'; import { EndUserAgreementService } from '../../core/end-user-agreement/end-user-agreement.service'; -import { DisabledDirective } from '../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../shared/btn-disabled.directive'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { ActivatedRouteStub } from '../../shared/testing/active-router.stub'; import { EndUserAgreementComponent } from './end-user-agreement.component'; @@ -58,7 +58,7 @@ describe('EndUserAgreementComponent', () => { beforeEach(waitForAsync(() => { init(); TestBed.configureTestingModule({ - imports: [TranslateModule.forRoot(), EndUserAgreementComponent, DisabledDirective], + imports: [TranslateModule.forRoot(), EndUserAgreementComponent, BtnDisabledDirective], providers: [ { provide: EndUserAgreementService, useValue: endUserAgreementService }, { provide: NotificationsService, useValue: notificationsService }, diff --git a/src/app/info/end-user-agreement/end-user-agreement.component.ts b/src/app/info/end-user-agreement/end-user-agreement.component.ts index 7a02f10039..e9835945f5 100644 --- a/src/app/info/end-user-agreement/end-user-agreement.component.ts +++ b/src/app/info/end-user-agreement/end-user-agreement.component.ts @@ -23,7 +23,7 @@ import { AppState } from '../../app.reducer'; import { LogOutAction } from '../../core/auth/auth.actions'; import { AuthService } from '../../core/auth/auth.service'; import { EndUserAgreementService } from '../../core/end-user-agreement/end-user-agreement.service'; -import { DisabledDirective } from '../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../shared/btn-disabled.directive'; import { isNotEmpty } from '../../shared/empty.util'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { EndUserAgreementContentComponent } from './end-user-agreement-content/end-user-agreement-content.component'; @@ -33,7 +33,7 @@ import { EndUserAgreementContentComponent } from './end-user-agreement-content/e templateUrl: './end-user-agreement.component.html', styleUrls: ['./end-user-agreement.component.scss'], standalone: true, - imports: [EndUserAgreementContentComponent, FormsModule, TranslateModule, DisabledDirective], + imports: [EndUserAgreementContentComponent, FormsModule, TranslateModule, BtnDisabledDirective], }) /** * Component displaying the End User Agreement and an option to accept it diff --git a/src/app/info/feedback/feedback-form/feedback-form.component.html b/src/app/info/feedback/feedback-form/feedback-form.component.html index 3fdc66820a..c5c4b460a2 100644 --- a/src/app/info/feedback/feedback-form/feedback-form.component.html +++ b/src/app/info/feedback/feedback-form/feedback-form.component.html @@ -41,7 +41,7 @@
- +
diff --git a/src/app/info/feedback/feedback-form/feedback-form.component.spec.ts b/src/app/info/feedback/feedback-form/feedback-form.component.spec.ts index 0b1f3439f4..56275ad5a3 100644 --- a/src/app/info/feedback/feedback-form/feedback-form.component.spec.ts +++ b/src/app/info/feedback/feedback-form/feedback-form.component.spec.ts @@ -18,7 +18,7 @@ import { FeedbackDataService } from '../../../core/feedback/feedback-data.servic import { Feedback } from '../../../core/feedback/models/feedback.model'; import { RouteService } from '../../../core/services/route.service'; import { NativeWindowService } from '../../../core/services/window.service'; -import { DisabledDirective } from '../../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../shared/btn-disabled.directive'; import { NativeWindowMockFactory } from '../../../shared/mocks/mock-native-window-ref'; import { RouterMock } from '../../../shared/mocks/router.mock'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; @@ -46,7 +46,7 @@ describe('FeedbackFormComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ - imports: [TranslateModule.forRoot(), FeedbackFormComponent, DisabledDirective], + imports: [TranslateModule.forRoot(), FeedbackFormComponent, BtnDisabledDirective], providers: [ { provide: RouteService, useValue: routeServiceStub }, { provide: UntypedFormBuilder, useValue: new UntypedFormBuilder() }, diff --git a/src/app/info/feedback/feedback-form/feedback-form.component.ts b/src/app/info/feedback/feedback-form/feedback-form.component.ts index f33ef35352..db98a2ee01 100644 --- a/src/app/info/feedback/feedback-form/feedback-form.component.ts +++ b/src/app/info/feedback/feedback-form/feedback-form.component.ts @@ -30,7 +30,7 @@ import { import { NoContent } from '../../../core/shared/NoContent.model'; import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; import { URLCombiner } from '../../../core/url-combiner/url-combiner'; -import { DisabledDirective } from '../../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../shared/btn-disabled.directive'; import { ErrorComponent } from '../../../shared/error/error.component'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; @@ -39,7 +39,7 @@ import { NotificationsService } from '../../../shared/notifications/notification templateUrl: './feedback-form.component.html', styleUrls: ['./feedback-form.component.scss'], standalone: true, - imports: [FormsModule, ReactiveFormsModule, NgIf, ErrorComponent, TranslateModule, DisabledDirective], + imports: [FormsModule, ReactiveFormsModule, NgIf, ErrorComponent, TranslateModule, BtnDisabledDirective], }) /** * Component displaying the contents of the Feedback Statement diff --git a/src/app/item-page/bitstreams/request-a-copy/bitstream-request-a-copy-page.component.html b/src/app/item-page/bitstreams/request-a-copy/bitstream-request-a-copy-page.component.html index a67dfb18be..5f42ccee74 100644 --- a/src/app/item-page/bitstreams/request-a-copy/bitstream-request-a-copy-page.component.html +++ b/src/app/item-page/bitstreams/request-a-copy/bitstream-request-a-copy-page.component.html @@ -79,7 +79,7 @@
diff --git a/src/app/item-page/bitstreams/request-a-copy/bitstream-request-a-copy-page.component.ts b/src/app/item-page/bitstreams/request-a-copy/bitstream-request-a-copy-page.component.ts index 35fd357da2..dcc999e938 100644 --- a/src/app/item-page/bitstreams/request-a-copy/bitstream-request-a-copy-page.component.ts +++ b/src/app/item-page/bitstreams/request-a-copy/bitstream-request-a-copy-page.component.ts @@ -55,7 +55,7 @@ import { getFirstCompletedRemoteData, getFirstSucceededRemoteDataPayload, } from '../../../core/shared/operators'; -import { DisabledDirective } from '../../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../shared/btn-disabled.directive'; import { hasValue, isNotEmpty, @@ -72,7 +72,7 @@ import { getItemPageRoute } from '../../item-page-routing-paths'; AsyncPipe, ReactiveFormsModule, NgIf, - DisabledDirective, + BtnDisabledDirective, ], standalone: true, }) diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html index f068864b45..76b1f1096c 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html @@ -12,7 +12,7 @@ class="fas fa-undo-alt">  {{"item.edit.bitstreams.reinstate-button" | translate}} - - - - - diff --git a/src/app/item-page/edit-item-page/item-delete/item-delete.component.ts b/src/app/item-page/edit-item-page/item-delete/item-delete.component.ts index 4e09a0b9ea..c54ca32a53 100644 --- a/src/app/item-page/edit-item-page/item-delete/item-delete.component.ts +++ b/src/app/item-page/edit-item-page/item-delete/item-delete.component.ts @@ -56,7 +56,7 @@ import { getRemoteDataPayload, } from '../../../core/shared/operators'; import { ViewMode } from '../../../core/shared/view-mode.model'; -import { DisabledDirective } from '../../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../shared/btn-disabled.directive'; import { hasValue, isNotEmpty, @@ -110,7 +110,7 @@ class RelationshipDTO { VarDirective, NgForOf, RouterLink, - DisabledDirective, + BtnDisabledDirective, ], standalone: true, }) diff --git a/src/app/item-page/edit-item-page/item-move/item-move.component.html b/src/app/item-page/edit-item-page/item-move/item-move.component.html index 0812c36f2d..63378f5afe 100644 --- a/src/app/item-page/edit-item-page/item-move/item-move.component.html +++ b/src/app/item-page/edit-item-page/item-move/item-move.component.html @@ -40,7 +40,7 @@ - -
diff --git a/src/app/item-page/edit-item-page/item-move/item-move.component.ts b/src/app/item-page/edit-item-page/item-move/item-move.component.ts index 5e2d355bba..07098aab11 100644 --- a/src/app/item-page/edit-item-page/item-move/item-move.component.ts +++ b/src/app/item-page/edit-item-page/item-move/item-move.component.ts @@ -37,7 +37,7 @@ import { getRemoteDataPayload, } from '../../../core/shared/operators'; import { SearchService } from '../../../core/shared/search/search.service'; -import { DisabledDirective } from '../../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../shared/btn-disabled.directive'; import { AuthorizedCollectionSelectorComponent } from '../../../shared/dso-selector/dso-selector/authorized-collection-selector/authorized-collection-selector.component'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; import { followLink } from '../../../shared/utils/follow-link-config.model'; @@ -57,7 +57,7 @@ import { AsyncPipe, AuthorizedCollectionSelectorComponent, NgIf, - DisabledDirective, + BtnDisabledDirective, ], standalone: true, }) diff --git a/src/app/item-page/edit-item-page/item-operation/item-operation.component.html b/src/app/item-page/edit-item-page/item-operation/item-operation.component.html index 88acec3171..75f0736bbc 100644 --- a/src/app/item-page/edit-item-page/item-operation/item-operation.component.html +++ b/src/app/item-page/edit-item-page/item-operation/item-operation.component.html @@ -5,12 +5,12 @@
- - diff --git a/src/app/item-page/edit-item-page/item-operation/item-operation.component.spec.ts b/src/app/item-page/edit-item-page/item-operation/item-operation.component.spec.ts index 42765f4d74..85ad62de93 100644 --- a/src/app/item-page/edit-item-page/item-operation/item-operation.component.spec.ts +++ b/src/app/item-page/edit-item-page/item-operation/item-operation.component.spec.ts @@ -6,7 +6,7 @@ import { By } from '@angular/platform-browser'; import { RouterTestingModule } from '@angular/router/testing'; import { TranslateModule } from '@ngx-translate/core'; -import { DisabledDirective } from '../../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../shared/btn-disabled.directive'; import { ItemOperationComponent } from './item-operation.component'; import { ItemOperation } from './itemOperation.model'; @@ -18,7 +18,7 @@ describe('ItemOperationComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ - imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), ItemOperationComponent, DisabledDirective], + imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), ItemOperationComponent, BtnDisabledDirective], }).compileComponents(); })); diff --git a/src/app/item-page/edit-item-page/item-operation/item-operation.component.ts b/src/app/item-page/edit-item-page/item-operation/item-operation.component.ts index b82fb154bf..7c3793cc57 100644 --- a/src/app/item-page/edit-item-page/item-operation/item-operation.component.ts +++ b/src/app/item-page/edit-item-page/item-operation/item-operation.component.ts @@ -7,7 +7,7 @@ import { RouterLink } from '@angular/router'; import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'; import { TranslateModule } from '@ngx-translate/core'; -import { DisabledDirective } from '../../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../shared/btn-disabled.directive'; import { ItemOperation } from './itemOperation.model'; @Component({ @@ -18,7 +18,7 @@ import { ItemOperation } from './itemOperation.model'; RouterLink, NgbTooltipModule, NgIf, - DisabledDirective, + BtnDisabledDirective, ], standalone: true, }) diff --git a/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.html b/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.html index b0157cb989..06e3a4ace7 100644 --- a/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.html +++ b/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.html @@ -1,6 +1,6 @@

{{relationshipMessageKey$ | async | translate}} - diff --git a/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.ts b/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.ts index 1bc95291c7..79b57cee10 100644 --- a/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.ts +++ b/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.ts @@ -65,7 +65,7 @@ import { getFirstSucceededRemoteDataPayload, getRemoteDataPayload, } from '../../../../core/shared/operators'; -import { DisabledDirective } from '../../../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../../shared/btn-disabled.directive'; import { hasNoValue, hasValue, @@ -101,7 +101,7 @@ import { EditRelationshipComponent } from '../edit-relationship/edit-relationshi TranslateModule, NgClass, ThemedLoadingComponent, - DisabledDirective, + BtnDisabledDirective, ], standalone: true, }) diff --git a/src/app/item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.html b/src/app/item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.html index 169a171d3f..8cd86d597b 100644 --- a/src/app/item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.html +++ b/src/app/item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.html @@ -9,12 +9,12 @@

- -
@@ -8,7 +8,7 @@ ngbDropdown *ngIf="(moreThanOne$ | async)"> - + +
@@ -66,6 +66,6 @@
- +
diff --git a/src/app/notifications/qa/project-entry-import-modal/project-entry-import-modal.component.ts b/src/app/notifications/qa/project-entry-import-modal/project-entry-import-modal.component.ts index 6f6feb8f28..6e156eee7e 100644 --- a/src/app/notifications/qa/project-entry-import-modal/project-entry-import-modal.component.ts +++ b/src/app/notifications/qa/project-entry-import-modal/project-entry-import-modal.component.ts @@ -30,7 +30,7 @@ import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { Item } from '../../../core/shared/item.model'; import { SearchService } from '../../../core/shared/search/search.service'; import { AlertComponent } from '../../../shared/alert/alert.component'; -import { DisabledDirective } from '../../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../shared/btn-disabled.directive'; import { hasValue, isNotEmpty, @@ -106,7 +106,7 @@ export interface QualityAssuranceEventData { styleUrls: ['./project-entry-import-modal.component.scss'], templateUrl: './project-entry-import-modal.component.html', standalone: true, - imports: [RouterLink, NgIf, FormsModule, ThemedLoadingComponent, ThemedSearchResultsComponent, AlertComponent, AsyncPipe, TranslateModule, DisabledDirective], + imports: [RouterLink, NgIf, FormsModule, ThemedLoadingComponent, ThemedSearchResultsComponent, AlertComponent, AsyncPipe, TranslateModule, BtnDisabledDirective], }) /** * Component to display a modal window for linking a project to an Quality Assurance event diff --git a/src/app/notifications/suggestion-actions/suggestion-actions.component.html b/src/app/notifications/suggestion-actions/suggestion-actions.component.html index e83d0a4123..342919d4ae 100644 --- a/src/app/notifications/suggestion-actions/suggestion-actions.component.html +++ b/src/app/notifications/suggestion-actions/suggestion-actions.component.html @@ -21,7 +21,7 @@ - diff --git a/src/app/process-page/overview/process-overview.component.ts b/src/app/process-page/overview/process-overview.component.ts index 09bc00d6f1..47efe888bf 100644 --- a/src/app/process-page/overview/process-overview.component.ts +++ b/src/app/process-page/overview/process-overview.component.ts @@ -16,7 +16,7 @@ import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { TranslateModule } from '@ngx-translate/core'; import { Subscription } from 'rxjs'; -import { DisabledDirective } from '../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../shared/btn-disabled.directive'; import { hasValue } from '../../shared/empty.util'; import { PaginationComponent } from '../../shared/pagination/pagination.component'; import { VarDirective } from '../../shared/utils/var.directive'; @@ -32,7 +32,7 @@ import { ProcessOverviewTableComponent } from './table/process-overview-table.co selector: 'ds-process-overview', templateUrl: './process-overview.component.html', standalone: true, - imports: [NgIf, RouterLink, PaginationComponent, NgFor, VarDirective, AsyncPipe, DatePipe, TranslateModule, NgTemplateOutlet, ProcessOverviewTableComponent, DisabledDirective], + imports: [NgIf, RouterLink, PaginationComponent, NgFor, VarDirective, AsyncPipe, DatePipe, TranslateModule, NgTemplateOutlet, ProcessOverviewTableComponent, BtnDisabledDirective], }) /** * Component displaying a list of all processes in a paginated table diff --git a/src/app/profile-page/profile-claim-item-modal/profile-claim-item-modal.component.html b/src/app/profile-page/profile-claim-item-modal/profile-claim-item-modal.component.html index a118cd680d..3233aa5555 100644 --- a/src/app/profile-page/profile-claim-item-modal/profile-claim-item-modal.component.html +++ b/src/app/profile-page/profile-claim-item-modal/profile-claim-item-modal.component.html @@ -29,7 +29,7 @@ {{ 'dso-selector.claim.item.not-mine-label' | translate }} - diff --git a/src/app/profile-page/profile-claim-item-modal/profile-claim-item-modal.component.ts b/src/app/profile-page/profile-claim-item-modal/profile-claim-item-modal.component.ts index 53a013e7d3..7730b1e4dd 100644 --- a/src/app/profile-page/profile-claim-item-modal/profile-claim-item-modal.component.ts +++ b/src/app/profile-page/profile-claim-item-modal/profile-claim-item-modal.component.ts @@ -25,7 +25,7 @@ import { Item } from '../../core/shared/item.model'; import { getFirstCompletedRemoteData } from '../../core/shared/operators'; import { ViewMode } from '../../core/shared/view-mode.model'; import { getItemPageRoute } from '../../item-page/item-page-routing-paths'; -import { DisabledDirective } from '../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../shared/btn-disabled.directive'; import { DSOSelectorModalWrapperComponent } from '../../shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component'; import { CollectionElementLinkType } from '../../shared/object-collection/collection-element-link.type'; import { ListableObjectComponentLoaderComponent } from '../../shared/object-collection/shared/listable-object/listable-object-component-loader.component'; @@ -43,7 +43,7 @@ import { ProfileClaimService } from '../profile-claim/profile-claim.service'; AsyncPipe, TranslateModule, NgForOf, - DisabledDirective, + BtnDisabledDirective, ], standalone: true, }) diff --git a/src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.html b/src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.html index 2a2b356b31..d0279d9c5f 100644 --- a/src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.html +++ b/src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.html @@ -13,7 +13,7 @@

{{'researcher.profile.not.associated' | translate}}

- - - diff --git a/src/app/register-email-form/register-email-form.component.ts b/src/app/register-email-form/register-email-form.component.ts index 302c6bc9c5..37ce725778 100644 --- a/src/app/register-email-form/register-email-form.component.ts +++ b/src/app/register-email-form/register-email-form.component.ts @@ -55,7 +55,7 @@ import { Registration } from '../core/shared/registration.model'; import { AlertComponent } from '../shared/alert/alert.component'; import { AlertType } from '../shared/alert/alert-type'; import { KlaroService } from '../shared/cookies/klaro.service'; -import { DisabledDirective } from '../shared/disabled-directive'; +import { BtnDisabledDirective } from '../shared/btn-disabled.directive'; import { isNotEmpty } from '../shared/empty.util'; import { GoogleRecaptchaComponent } from '../shared/google-recaptcha/google-recaptcha.component'; import { NotificationsService } from '../shared/notifications/notifications.service'; @@ -67,7 +67,7 @@ export const TYPE_REQUEST_REGISTER = 'register'; selector: 'ds-base-register-email-form', templateUrl: './register-email-form.component.html', standalone: true, - imports: [NgIf, FormsModule, ReactiveFormsModule, AlertComponent, GoogleRecaptchaComponent, AsyncPipe, TranslateModule, DisabledDirective], + imports: [NgIf, FormsModule, ReactiveFormsModule, AlertComponent, GoogleRecaptchaComponent, AsyncPipe, TranslateModule, BtnDisabledDirective], }) /** * Component responsible to render an email registration form. diff --git a/src/app/register-page/create-profile/create-profile.component.html b/src/app/register-page/create-profile/create-profile.component.html index dbdb006785..e5cf6c3e2e 100644 --- a/src/app/register-page/create-profile/create-profile.component.html +++ b/src/app/register-page/create-profile/create-profile.component.html @@ -81,7 +81,7 @@
diff --git a/src/app/register-page/create-profile/create-profile.component.ts b/src/app/register-page/create-profile/create-profile.component.ts index 1ec95c8f52..43ee0c8cd3 100644 --- a/src/app/register-page/create-profile/create-profile.component.ts +++ b/src/app/register-page/create-profile/create-profile.component.ts @@ -43,7 +43,7 @@ import { } from '../../core/shared/operators'; import { Registration } from '../../core/shared/registration.model'; import { ProfilePageSecurityFormComponent } from '../../profile-page/profile-page-security-form/profile-page-security-form.component'; -import { DisabledDirective } from '../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../shared/btn-disabled.directive'; import { isEmpty } from '../../shared/empty.util'; import { NotificationsService } from '../../shared/notifications/notifications.service'; @@ -61,7 +61,7 @@ import { NotificationsService } from '../../shared/notifications/notifications.s AsyncPipe, ReactiveFormsModule, NgForOf, - DisabledDirective, + BtnDisabledDirective, ], standalone: true, }) diff --git a/src/app/request-copy/email-request-copy/email-request-copy.component.html b/src/app/request-copy/email-request-copy/email-request-copy.component.html index 815a9a9691..b2227bfbae 100644 --- a/src/app/request-copy/email-request-copy/email-request-copy.component.html +++ b/src/app/request-copy/email-request-copy/email-request-copy.component.html @@ -13,7 +13,7 @@
@@ -76,7 +76,7 @@
@@ -93,7 +93,7 @@ @@ -103,7 +103,7 @@ diff --git a/src/app/shared/access-control-form-container/access-control-form-container.component.ts b/src/app/shared/access-control-form-container/access-control-form-container.component.ts index 11313dfc99..46895b8532 100644 --- a/src/app/shared/access-control-form-container/access-control-form-container.component.ts +++ b/src/app/shared/access-control-form-container/access-control-form-container.component.ts @@ -31,7 +31,7 @@ import { Item } from '../../core/shared/item.model'; import { getFirstCompletedRemoteData } from '../../core/shared/operators'; import { AlertComponent } from '../alert/alert.component'; import { AlertType } from '../alert/alert-type'; -import { DisabledDirective } from '../disabled-directive'; +import { BtnDisabledDirective } from '../btn-disabled.directive'; import { SelectableListService } from '../object-list/selectable-list/selectable-list.service'; import { AccessControlArrayFormComponent } from './access-control-array-form/access-control-array-form.component'; import { createAccessControlInitialFormState } from './access-control-form-container-intial-state'; @@ -47,7 +47,7 @@ import { styleUrls: ['./access-control-form-container.component.scss'], exportAs: 'dsAccessControlForm', standalone: true, - imports: [NgIf, AlertComponent, UiSwitchModule, FormsModule, AccessControlArrayFormComponent, AsyncPipe, TranslateModule, DisabledDirective], + imports: [NgIf, AlertComponent, UiSwitchModule, FormsModule, AccessControlArrayFormComponent, AsyncPipe, TranslateModule, BtnDisabledDirective], }) export class AccessControlFormContainerComponent implements OnDestroy { diff --git a/src/app/shared/disabled-directive.ts b/src/app/shared/btn-disabled.directive.ts similarity index 96% rename from src/app/shared/disabled-directive.ts rename to src/app/shared/btn-disabled.directive.ts index 3563afbaf1..f73422a9d5 100644 --- a/src/app/shared/disabled-directive.ts +++ b/src/app/shared/btn-disabled.directive.ts @@ -6,7 +6,7 @@ import { } from '@angular/core'; @Directive({ - selector: '[dsDisabled]', + selector: '[dsBtnDisabled]', standalone: true, }) @@ -16,7 +16,7 @@ import { * * This directive should always be used instead of the HTML disabled attribute as it is more accessible. */ -export class DisabledDirective { +export class BtnDisabledDirective { @Input() set dsDisabled(value: boolean) { this.isDisabled = !!value; diff --git a/src/app/shared/disabled-directive.spec.ts b/src/app/shared/disabled-directive.spec.ts index 0443ca84dd..96f760fc46 100644 --- a/src/app/shared/disabled-directive.spec.ts +++ b/src/app/shared/disabled-directive.spec.ts @@ -8,11 +8,11 @@ import { } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; -import { DisabledDirective } from './disabled-directive'; +import { BtnDisabledDirective } from './btn-disabled.directive'; @Component({ template: ` - + `, }) class TestComponent { @@ -26,7 +26,7 @@ describe('DisabledDirective', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [DisabledDirective], + imports: [BtnDisabledDirective], declarations: [TestComponent], }); fixture = TestBed.createComponent(TestComponent); diff --git a/src/app/shared/ds-select/ds-select.component.html b/src/app/shared/ds-select/ds-select.component.html index de53ef0792..e87b7c5cc6 100644 --- a/src/app/shared/ds-select/ds-select.component.html +++ b/src/app/shared/ds-select/ds-select.component.html @@ -13,7 +13,7 @@ class="btn btn-outline-primary selection" (blur)="close.emit($event)" (click)="close.emit($event)" - [dsDisabled]="disabled" + [dsBtnDisabled]="disabled" ngbDropdownToggle> diff --git a/src/app/shared/ds-select/ds-select.component.ts b/src/app/shared/ds-select/ds-select.component.ts index c7a8fafa72..2616ce4a9f 100644 --- a/src/app/shared/ds-select/ds-select.component.ts +++ b/src/app/shared/ds-select/ds-select.component.ts @@ -8,7 +8,7 @@ import { import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'; import { TranslateModule } from '@ngx-translate/core'; -import { DisabledDirective } from '../disabled-directive'; +import { BtnDisabledDirective } from '../btn-disabled.directive'; /** * Component which represent a DSpace dropdown selector. @@ -18,7 +18,7 @@ import { DisabledDirective } from '../disabled-directive'; templateUrl: './ds-select.component.html', styleUrls: ['./ds-select.component.scss'], standalone: true, - imports: [NgbDropdownModule, NgIf, TranslateModule, DisabledDirective], + imports: [NgbDropdownModule, NgIf, TranslateModule, BtnDisabledDirective], }) export class DsSelectComponent { diff --git a/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.html b/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.html index 747d14cac6..0503281329 100644 --- a/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.html +++ b/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.html @@ -1,7 +1,7 @@
-
    diff --git a/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.ts b/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.ts index d2ed04641e..fadaee8b22 100644 --- a/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.ts +++ b/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.ts @@ -22,7 +22,7 @@ import { MenuID } from 'src/app/shared/menu/menu-id.model'; import { MenuSection } from 'src/app/shared/menu/menu-section.model'; import { MenuSectionComponent } from 'src/app/shared/menu/menu-section/menu-section.component'; -import { DisabledDirective } from '../../../disabled-directive'; +import { BtnDisabledDirective } from '../../../btn-disabled.directive'; import { hasValue } from '../../../empty.util'; import { MenuService } from '../../../menu/menu.service'; @@ -34,7 +34,7 @@ import { MenuService } from '../../../menu/menu.service'; templateUrl: './dso-edit-menu-expandable-section.component.html', styleUrls: ['./dso-edit-menu-expandable-section.component.scss'], standalone: true, - imports: [NgbDropdownModule, NgbTooltipModule, NgFor, NgIf, NgComponentOutlet, TranslateModule, AsyncPipe, DisabledDirective], + imports: [NgbDropdownModule, NgbTooltipModule, NgFor, NgIf, NgComponentOutlet, TranslateModule, AsyncPipe, BtnDisabledDirective], }) export class DsoEditMenuExpandableSectionComponent extends MenuSectionComponent implements OnInit { diff --git a/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu-section/dso-edit-menu-section.component.html b/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu-section/dso-edit-menu-section.component.html index 9f796c35ce..0738e2f28a 100644 --- a/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu-section/dso-edit-menu-section.component.html +++ b/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu-section/dso-edit-menu-section.component.html @@ -5,7 +5,7 @@ {{itemModel.text | translate}} - @@ -13,7 +13,7 @@
    - @@ -60,7 +60,7 @@ type="button" ngbTooltip="{{'form.clear-help' | translate}}" placement="top" - [dsDisabled]="model.readOnly" + [dsBtnDisabled]="model.readOnly" (click)="remove()">{{'form.clear' | translate}}
    @@ -69,14 +69,14 @@ type="button" ngbTooltip="{{'form.edit-help' | translate}}" placement="top" - [dsDisabled]="isEditDisabled()" + [dsBtnDisabled]="isEditDisabled()" (click)="switchEditMode()">{{'form.edit' | translate}}
diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts index 77de7953f1..493c56e29d 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts @@ -33,7 +33,7 @@ import { of as observableOf } from 'rxjs'; import { VocabularyEntry } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry.model'; import { VocabularyOptions } from '../../../../../../core/submission/vocabularies/models/vocabulary-options.model'; import { VocabularyService } from '../../../../../../core/submission/vocabularies/vocabulary.service'; -import { DisabledDirective } from '../../../../../disabled-directive'; +import { BtnDisabledDirective } from '../../../../../btn-disabled.directive'; import { mockDynamicFormLayoutService, mockDynamicFormValidationService, @@ -175,7 +175,7 @@ describe('Dynamic Lookup component', () => { TestComponent, AuthorityConfidenceStateDirective, ObjNgFor, - DisabledDirective, + BtnDisabledDirective, ], providers: [ ChangeDetectorRef, diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts index b16ec0e537..39c39cf8bc 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts @@ -46,7 +46,7 @@ import { getFirstSucceededRemoteDataPayload } from '../../../../../../core/share import { PageInfo } from '../../../../../../core/shared/page-info.model'; import { VocabularyEntry } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry.model'; import { VocabularyService } from '../../../../../../core/submission/vocabularies/vocabulary.service'; -import { DisabledDirective } from '../../../../../disabled-directive'; +import { BtnDisabledDirective } from '../../../../../btn-disabled.directive'; import { hasValue, isEmpty, @@ -77,7 +77,7 @@ import { DynamicLookupNameModel } from './dynamic-lookup-name.model'; NgForOf, NgTemplateOutlet, ObjNgFor, - DisabledDirective, + BtnDisabledDirective, ], standalone: true, }) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.ts index 055e5c9c19..de6b50d589 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.ts @@ -59,7 +59,7 @@ import { Vocabulary } from '../../../../../../core/submission/vocabularies/model import { VocabularyEntry } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry.model'; import { VocabularyEntryDetail } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry-detail.model'; import { VocabularyService } from '../../../../../../core/submission/vocabularies/vocabulary.service'; -import { DisabledDirective } from '../../../../../disabled-directive'; +import { BtnDisabledDirective } from '../../../../../btn-disabled.directive'; import { hasValue, isEmpty, @@ -91,7 +91,7 @@ import { DynamicOneboxModel } from './dynamic-onebox.model'; ObjNgFor, NgForOf, FormsModule, - DisabledDirective, + BtnDisabledDirective, ], standalone: true, }) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.component.html index bad0f1ab91..1cb8ee1e1a 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.component.html @@ -32,21 +32,21 @@ @@ -73,18 +73,18 @@ {{ ('submission.sections.describe.relationship-lookup.selected' | translate: {size: (selection$ | async)?.length || 0}) }}
-
- +
diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts index 89504ccdfc..c666baf21f 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts @@ -38,7 +38,7 @@ import { } from '../../../../../../../core/shared/operators'; import { SubmissionImportExternalCollectionComponent } from '../../../../../../../submission/import-external/import-external-collection/submission-import-external-collection.component'; import { CollectionListEntry } from '../../../../../../collection-dropdown/collection-dropdown.component'; -import { DisabledDirective } from '../../../../../../disabled-directive'; +import { BtnDisabledDirective } from '../../../../../../btn-disabled.directive'; import { NotificationsService } from '../../../../../../notifications/notifications.service'; import { CollectionElementLinkType } from '../../../../../../object-collection/collection-element-link.type'; import { ItemSearchResult } from '../../../../../../object-collection/shared/item-search-result.model'; @@ -70,7 +70,7 @@ export enum ImportType { ThemedSearchResultsComponent, NgIf, AsyncPipe, - DisabledDirective, + BtnDisabledDirective, ], standalone: true, }) diff --git a/src/app/shared/form/form.component.html b/src/app/shared/form/form.component.html index 92b0e05552..85e32e66ea 100644 --- a/src/app/shared/form/form.component.html +++ b/src/app/shared/form/form.component.html @@ -41,7 +41,7 @@ title="{{'form.discard' | translate}}" attr.aria-label="{{'form.discard' | translate}}" (click)="removeItem($event, context, index)" - [dsDisabled]="group.context.groups.length === 1 || isItemReadOnly(context, index)"> + [dsBtnDisabled]="group.context.groups.length === 1 || isItemReadOnly(context, index)"> {{'form.discard' | translate}}
@@ -62,7 +62,7 @@ diff --git a/src/app/shared/form/form.component.ts b/src/app/shared/form/form.component.ts index d96f16044a..a757239aea 100644 --- a/src/app/shared/form/form.component.ts +++ b/src/app/shared/form/form.component.ts @@ -39,7 +39,7 @@ import { map, } from 'rxjs/operators'; -import { DisabledDirective } from '../disabled-directive'; +import { BtnDisabledDirective } from '../btn-disabled.directive'; import { hasValue, isNotEmpty, @@ -70,7 +70,7 @@ import { FormService } from './form.service'; DynamicFormsCoreModule, NgIf, AsyncPipe, - DisabledDirective, + BtnDisabledDirective, ], standalone: true, }) diff --git a/src/app/shared/form/number-picker/number-picker.component.html b/src/app/shared/form/number-picker/number-picker.component.html index 8f2a875685..9b9d038e86 100644 --- a/src/app/shared/form/number-picker/number-picker.component.html +++ b/src/app/shared/form/number-picker/number-picker.component.html @@ -3,7 +3,7 @@ class="btn btn-link-focus" type="button" tabindex="0" - [dsDisabled]="disabled" + [dsBtnDisabled]="disabled" (click)="toggleUp()"> {{'form.number-picker.increment' | translate: {field: name} }} @@ -30,7 +30,7 @@ class="btn btn-link-focus" type="button" tabindex="0" - [dsDisabled]="disabled" + [dsBtnDisabled]="disabled" (click)="toggleDown()"> {{'form.number-picker.decrement' | translate: {field: name} }} diff --git a/src/app/shared/form/number-picker/number-picker.component.ts b/src/app/shared/form/number-picker/number-picker.component.ts index 70ad484680..ef35e1ee79 100644 --- a/src/app/shared/form/number-picker/number-picker.component.ts +++ b/src/app/shared/form/number-picker/number-picker.component.ts @@ -20,7 +20,7 @@ import { TranslateService, } from '@ngx-translate/core'; -import { DisabledDirective } from '../../disabled-directive'; +import { BtnDisabledDirective } from '../../btn-disabled.directive'; import { isEmpty } from '../../empty.util'; @Component({ @@ -34,7 +34,7 @@ import { isEmpty } from '../../empty.util'; NgClass, FormsModule, TranslateModule, - DisabledDirective, + BtnDisabledDirective, ], standalone: true, }) diff --git a/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.html b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.html index f8ad321d31..4798a43a87 100644 --- a/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.html +++ b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.html @@ -5,7 +5,7 @@
- -
@@ -48,7 +48,7 @@ + [dsBtnDisabled]="!form.valid"> {{"login.form.submit" | translate}} diff --git a/src/app/shared/log-in/methods/password/log-in-password.component.ts b/src/app/shared/log-in/methods/password/log-in-password.component.ts index 84d618cb79..25ec0cba74 100644 --- a/src/app/shared/log-in/methods/password/log-in-password.component.ts +++ b/src/app/shared/log-in/methods/password/log-in-password.component.ts @@ -49,7 +49,7 @@ import { AuthorizationDataService } from '../../../../core/data/feature-authoriz import { FeatureID } from '../../../../core/data/feature-authorization/feature-id'; import { HardRedirectService } from '../../../../core/services/hard-redirect.service'; import { fadeOut } from '../../../animations/fade'; -import { DisabledDirective } from '../../../disabled-directive'; +import { BtnDisabledDirective } from '../../../btn-disabled.directive'; import { isNotEmpty } from '../../../empty.util'; import { BrowserOnlyPipe } from '../../../utils/browser-only.pipe'; @@ -63,7 +63,7 @@ import { BrowserOnlyPipe } from '../../../utils/browser-only.pipe'; styleUrls: ['./log-in-password.component.scss'], animations: [fadeOut], standalone: true, - imports: [FormsModule, ReactiveFormsModule, NgIf, RouterLink, AsyncPipe, TranslateModule, BrowserOnlyPipe, DisabledDirective], + imports: [FormsModule, ReactiveFormsModule, NgIf, RouterLink, AsyncPipe, TranslateModule, BrowserOnlyPipe, BtnDisabledDirective], }) export class LogInPasswordComponent implements OnInit { diff --git a/src/app/shared/mydspace-actions/claimed-task/approve/claimed-task-actions-approve.component.html b/src/app/shared/mydspace-actions/claimed-task/approve/claimed-task-actions-approve.component.html index a672763a86..affbec108c 100644 --- a/src/app/shared/mydspace-actions/claimed-task/approve/claimed-task-actions-approve.component.html +++ b/src/app/shared/mydspace-actions/claimed-task/approve/claimed-task-actions-approve.component.html @@ -1,7 +1,7 @@ diff --git a/src/app/shared/object-select/collection-select/collection-select.component.ts b/src/app/shared/object-select/collection-select/collection-select.component.ts index f11fc45c13..69d32bb93f 100644 --- a/src/app/shared/object-select/collection-select/collection-select.component.ts +++ b/src/app/shared/object-select/collection-select/collection-select.component.ts @@ -20,7 +20,7 @@ import { getCollectionPageRoute } from '../../../collection-page/collection-page import { PaginatedList } from '../../../core/data/paginated-list.model'; import { Collection } from '../../../core/shared/collection.model'; import { getAllSucceededRemoteDataPayload } from '../../../core/shared/operators'; -import { DisabledDirective } from '../../disabled-directive'; +import { BtnDisabledDirective } from '../../btn-disabled.directive'; import { hasValueOperator, isNotEmpty, @@ -37,7 +37,7 @@ import { ObjectSelectComponent } from '../object-select/object-select.component' templateUrl: './collection-select.component.html', styleUrls: ['./collection-select.component.scss'], standalone: true, - imports: [VarDirective, NgIf, PaginationComponent, NgFor, FormsModule, RouterLink, ErrorComponent, ThemedLoadingComponent, NgClass, AsyncPipe, TranslateModule, DisabledDirective], + imports: [VarDirective, NgIf, PaginationComponent, NgFor, FormsModule, RouterLink, ErrorComponent, ThemedLoadingComponent, NgClass, AsyncPipe, TranslateModule, BtnDisabledDirective], }) /** diff --git a/src/app/shared/object-select/item-select/item-select.component.html b/src/app/shared/object-select/item-select/item-select.component.html index c74fe26afd..6f3d31703d 100644 --- a/src/app/shared/object-select/item-select/item-select.component.html +++ b/src/app/shared/object-select/item-select/item-select.component.html @@ -42,7 +42,7 @@ diff --git a/src/app/shared/object-select/item-select/item-select.component.spec.ts b/src/app/shared/object-select/item-select/item-select.component.spec.ts index 7aa6c7a639..656e0716e9 100644 --- a/src/app/shared/object-select/item-select/item-select.component.spec.ts +++ b/src/app/shared/object-select/item-select/item-select.component.spec.ts @@ -18,7 +18,7 @@ import { LinkHeadService } from '../../../core/services/link-head.service'; import { ConfigurationProperty } from '../../../core/shared/configuration-property.model'; import { Item } from '../../../core/shared/item.model'; import { SearchConfigurationService } from '../../../core/shared/search/search-configuration.service'; -import { DisabledDirective } from '../../disabled-directive'; +import { BtnDisabledDirective } from '../../btn-disabled.directive'; import { HostWindowService } from '../../host-window.service'; import { PaginationComponentOptions } from '../../pagination/pagination-component-options.model'; import { createSuccessfulRemoteDataObject$ } from '../../remote-data.utils'; @@ -102,7 +102,7 @@ describe('ItemSelectComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ - imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), DisabledDirective], + imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), BtnDisabledDirective], providers: [ { provide: ObjectSelectService, useValue: new ObjectSelectServiceStub([mockItemList[1].id]) }, { provide: HostWindowService, useValue: new HostWindowServiceStub(0) }, diff --git a/src/app/shared/object-select/item-select/item-select.component.ts b/src/app/shared/object-select/item-select/item-select.component.ts index 64d6a9b2ba..f5d8a4f9b3 100644 --- a/src/app/shared/object-select/item-select/item-select.component.ts +++ b/src/app/shared/object-select/item-select/item-select.component.ts @@ -19,7 +19,7 @@ import { PaginatedList } from '../../../core/data/paginated-list.model'; import { Item } from '../../../core/shared/item.model'; import { getAllSucceededRemoteDataPayload } from '../../../core/shared/operators'; import { getItemPageRoute } from '../../../item-page/item-page-routing-paths'; -import { DisabledDirective } from '../../disabled-directive'; +import { BtnDisabledDirective } from '../../btn-disabled.directive'; import { hasValueOperator, isNotEmpty, @@ -35,7 +35,7 @@ import { ObjectSelectComponent } from '../object-select/object-select.component' selector: 'ds-item-select', templateUrl: './item-select.component.html', standalone: true, - imports: [VarDirective, NgIf, PaginationComponent, NgFor, FormsModule, RouterLink, ErrorComponent, ThemedLoadingComponent, NgClass, AsyncPipe, TranslateModule, DisabledDirective], + imports: [VarDirective, NgIf, PaginationComponent, NgFor, FormsModule, RouterLink, ErrorComponent, ThemedLoadingComponent, NgClass, AsyncPipe, TranslateModule, BtnDisabledDirective], }) /** diff --git a/src/app/shared/pagination/pagination.component.html b/src/app/shared/pagination/pagination.component.html index 2ce7f34166..9dd093be2b 100644 --- a/src/app/shared/pagination/pagination.component.html +++ b/src/app/shared/pagination/pagination.component.html @@ -55,12 +55,12 @@
diff --git a/src/app/shared/search/advanced-search/advanced-search.component.ts b/src/app/shared/search/advanced-search/advanced-search.component.ts index dfc934ad9c..99eaa23a0d 100644 --- a/src/app/shared/search/advanced-search/advanced-search.component.ts +++ b/src/app/shared/search/advanced-search/advanced-search.component.ts @@ -31,7 +31,7 @@ import { SearchService } from '../../../core/shared/search/search.service'; import { SearchConfigurationService } from '../../../core/shared/search/search-configuration.service'; import { SearchFilterService } from '../../../core/shared/search/search-filter.service'; import { FilterConfig } from '../../../core/shared/search/search-filters/search-config.model'; -import { DisabledDirective } from '../../disabled-directive'; +import { BtnDisabledDirective } from '../../btn-disabled.directive'; import { hasValue, isNotEmpty, @@ -56,7 +56,7 @@ import { SearchFilterConfig } from '../models/search-filter-config.model'; KeyValuePipe, NgForOf, TranslateModule, - DisabledDirective, + BtnDisabledDirective, ], }) export class AdvancedSearchComponent implements OnInit, OnDestroy { diff --git a/src/app/shared/subscriptions/subscription-modal/subscription-modal.component.html b/src/app/shared/subscriptions/subscription-modal/subscription-modal.component.html index f44dc2ce3f..37a7a3f431 100644 --- a/src/app/shared/subscriptions/subscription-modal/subscription-modal.component.html +++ b/src/app/shared/subscriptions/subscription-modal/subscription-modal.component.html @@ -34,7 +34,7 @@ (click)="activeModal.close()"> {{'subscriptions.modal.close' | translate}} - diff --git a/src/app/shared/upload/uploader/uploader.component.ts b/src/app/shared/upload/uploader/uploader.component.ts index ec66981f16..fbafe811eb 100644 --- a/src/app/shared/upload/uploader/uploader.component.ts +++ b/src/app/shared/upload/uploader/uploader.component.ts @@ -27,7 +27,7 @@ import { XSRF_REQUEST_HEADER, XSRF_RESPONSE_HEADER, } from '../../../core/xsrf/xsrf.constants'; -import { DisabledDirective } from '../../disabled-directive'; +import { BtnDisabledDirective } from '../../btn-disabled.directive'; import { hasValue, isNotEmpty, @@ -43,7 +43,7 @@ import { UploaderProperties } from './uploader-properties.model'; changeDetection: ChangeDetectionStrategy.Default, encapsulation: ViewEncapsulation.Emulated, standalone: true, - imports: [TranslateModule, FileUploadModule, CommonModule, DisabledDirective], + imports: [TranslateModule, FileUploadModule, CommonModule, BtnDisabledDirective], }) export class UploaderComponent implements OnInit, AfterViewInit { diff --git a/src/app/submission/form/collection/submission-form-collection.component.html b/src/app/submission/form/collection/submission-form-collection.component.html index 2af47497b2..db33afc76a 100644 --- a/src/app/submission/form/collection/submission-form-collection.component.html +++ b/src/app/submission/form/collection/submission-form-collection.component.html @@ -25,7 +25,7 @@ class="btn btn-outline-primary" (blur)="onClose()" (click)="onClose()" - [dsDisabled]="(processingChange$ | async) || collectionModifiable === false || isReadonly" + [dsBtnDisabled]="(processingChange$ | async) || collectionModifiable === false || isReadonly" ngbDropdownToggle> {{ selectedCollectionName$ | async }} diff --git a/src/app/submission/form/collection/submission-form-collection.component.spec.ts b/src/app/submission/form/collection/submission-form-collection.component.spec.ts index 9ff048a626..61bad0439f 100644 --- a/src/app/submission/form/collection/submission-form-collection.component.spec.ts +++ b/src/app/submission/form/collection/submission-form-collection.component.spec.ts @@ -31,7 +31,7 @@ import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/jso import { Collection } from '../../../core/shared/collection.model'; import { SubmissionJsonPatchOperationsService } from '../../../core/submission/submission-json-patch-operations.service'; import { ThemedCollectionDropdownComponent } from '../../../shared/collection-dropdown/themed-collection-dropdown.component'; -import { DisabledDirective } from '../../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../shared/btn-disabled.directive'; import { DSONameServiceMock } from '../../../shared/mocks/dso-name.service.mock'; import { mockSubmissionId, @@ -153,7 +153,7 @@ describe('SubmissionFormCollectionComponent Component', () => { TranslateModule.forRoot(), SubmissionFormCollectionComponent, TestComponent, - DisabledDirective, + BtnDisabledDirective, ], providers: [ { provide: DSONameService, useValue: new DSONameServiceMock() }, diff --git a/src/app/submission/form/collection/submission-form-collection.component.ts b/src/app/submission/form/collection/submission-form-collection.component.ts index 7e574a00d5..10b1f815dc 100644 --- a/src/app/submission/form/collection/submission-form-collection.component.ts +++ b/src/app/submission/form/collection/submission-form-collection.component.ts @@ -36,7 +36,7 @@ import { SubmissionObject } from '../../../core/submission/models/submission-obj import { SubmissionJsonPatchOperationsService } from '../../../core/submission/submission-json-patch-operations.service'; import { CollectionDropdownComponent } from '../../../shared/collection-dropdown/collection-dropdown.component'; import { ThemedCollectionDropdownComponent } from '../../../shared/collection-dropdown/themed-collection-dropdown.component'; -import { DisabledDirective } from '../../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../shared/btn-disabled.directive'; import { hasValue, isNotEmpty, @@ -58,7 +58,7 @@ import { SubmissionService } from '../../submission.service'; TranslateModule, NgbDropdownModule, ThemedCollectionDropdownComponent, - DisabledDirective, + BtnDisabledDirective, ], }) export class SubmissionFormCollectionComponent implements OnDestroy, OnChanges, OnInit { diff --git a/src/app/submission/form/footer/submission-form-footer.component.html b/src/app/submission/form/footer/submission-form-footer.component.html index 4d3e76ff51..c860fb557b 100644 --- a/src/app/submission/form/footer/submission-form-footer.component.html +++ b/src/app/submission/form/footer/submission-form-footer.component.html @@ -5,7 +5,7 @@ id="discard" [attr.data-test]="'discard' | dsBrowserOnly" class="btn btn-danger" - [dsDisabled]="(processingSaveStatus | async) || (processingDepositStatus | async)" + [dsBtnDisabled]="(processingSaveStatus | async) || (processingDepositStatus | async)" (click)="$event.preventDefault();confirmDiscard(content)"> {{'submission.general.discard.submit' | translate}} @@ -28,7 +28,7 @@ class="btn btn-secondary" id="save" [attr.data-test]="'save' | dsBrowserOnly" - [dsDisabled]="(processingSaveStatus | async) || (hasUnsavedModification | async) !== true" + [dsBtnDisabled]="(processingSaveStatus | async) || (hasUnsavedModification | async) !== true" (click)="save($event)"> {{'submission.general.save' | translate}} @@ -38,7 +38,7 @@ class="btn" id="saveForLater" [attr.data-test]="'save-for-later' | dsBrowserOnly" - [dsDisabled]="(processingSaveStatus | async) || (processingDepositStatus | async)" + [dsBtnDisabled]="(processingSaveStatus | async) || (processingDepositStatus | async)" (click)="saveLater($event)"> {{'submission.general.save-later' | translate}} @@ -47,7 +47,7 @@ id="deposit" [attr.data-test]="'deposit' | dsBrowserOnly" class="btn btn-success" - [dsDisabled]="(processingSaveStatus | async) || (processingDepositStatus | async)" + [dsBtnDisabled]="(processingSaveStatus | async) || (processingDepositStatus | async)" (click)="deposit($event)"> {{'submission.general.deposit' | translate}} diff --git a/src/app/submission/form/footer/submission-form-footer.component.spec.ts b/src/app/submission/form/footer/submission-form-footer.component.spec.ts index 3b36d56aca..82bc309cc8 100644 --- a/src/app/submission/form/footer/submission-form-footer.component.spec.ts +++ b/src/app/submission/form/footer/submission-form-footer.component.spec.ts @@ -25,7 +25,7 @@ import { of as observableOf } from 'rxjs'; import { TestScheduler } from 'rxjs/testing'; import { SubmissionRestService } from '../../../core/submission/submission-rest.service'; -import { DisabledDirective } from '../../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../shared/btn-disabled.directive'; import { mockSubmissionId } from '../../../shared/mocks/submission.mock'; import { SubmissionRestServiceStub } from '../../../shared/testing/submission-rest-service.stub'; import { SubmissionServiceStub } from '../../../shared/testing/submission-service.stub'; @@ -52,7 +52,7 @@ describe('SubmissionFormFooterComponent', () => { TranslateModule.forRoot(), SubmissionFormFooterComponent, TestComponent, - DisabledDirective, + BtnDisabledDirective, ], providers: [ { provide: SubmissionService, useValue: submissionServiceStub }, diff --git a/src/app/submission/form/footer/submission-form-footer.component.ts b/src/app/submission/form/footer/submission-form-footer.component.ts index adaf5c85ef..8645003783 100644 --- a/src/app/submission/form/footer/submission-form-footer.component.ts +++ b/src/app/submission/form/footer/submission-form-footer.component.ts @@ -15,7 +15,7 @@ import { map } from 'rxjs/operators'; import { SubmissionRestService } from '../../../core/submission/submission-rest.service'; import { SubmissionScopeType } from '../../../core/submission/submission-scope-type'; -import { DisabledDirective } from '../../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../shared/btn-disabled.directive'; import { isNotEmpty } from '../../../shared/empty.util'; import { BrowserOnlyPipe } from '../../../shared/utils/browser-only.pipe'; import { SubmissionService } from '../../submission.service'; @@ -28,7 +28,7 @@ import { SubmissionService } from '../../submission.service'; styleUrls: ['./submission-form-footer.component.scss'], templateUrl: './submission-form-footer.component.html', standalone: true, - imports: [CommonModule, BrowserOnlyPipe, TranslateModule, DisabledDirective], + imports: [CommonModule, BrowserOnlyPipe, TranslateModule, BtnDisabledDirective], }) export class SubmissionFormFooterComponent implements OnChanges { diff --git a/src/app/submission/form/section-add/submission-form-section-add.component.html b/src/app/submission/form/section-add/submission-form-section-add.component.html index c5f8d25fc2..563044d270 100644 --- a/src/app/submission/form/section-add/submission-form-section-add.component.html +++ b/src/app/submission/form/section-add/submission-form-section-add.component.html @@ -6,7 +6,7 @@ + diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts index 7572d3ac8b..eb7a703cc2 100644 --- a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts @@ -36,7 +36,7 @@ import { getFirstSucceededRemoteDataPayload, } from '../../../core/shared/operators'; import { PageInfo } from '../../../core/shared/page-info.model'; -import { DisabledDirective } from '../../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../shared/btn-disabled.directive'; import { hasValue } from '../../../shared/empty.util'; import { HostWindowService } from '../../../shared/host-window.service'; import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils'; @@ -71,7 +71,7 @@ export interface ExternalSourceData { InfiniteScrollModule, NgbDropdownModule, FormsModule, - DisabledDirective, + BtnDisabledDirective, ], standalone: true, }) diff --git a/src/app/submission/sections/cc-license/submission-section-cc-licenses.component.ts b/src/app/submission/sections/cc-license/submission-section-cc-licenses.component.ts index 62546e1835..7618de5173 100644 --- a/src/app/submission/sections/cc-license/submission-section-cc-licenses.component.ts +++ b/src/app/submission/sections/cc-license/submission-section-cc-licenses.component.ts @@ -40,7 +40,7 @@ import { import { WorkspaceitemSectionCcLicenseObject } from '../../../core/submission/models/workspaceitem-section-cc-license.model'; import { SubmissionCcLicenseDataService } from '../../../core/submission/submission-cc-license-data.service'; import { SubmissionCcLicenseUrlDataService } from '../../../core/submission/submission-cc-license-url-data.service'; -import { DisabledDirective } from '../../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../shared/btn-disabled.directive'; import { DsSelectComponent } from '../../../shared/ds-select/ds-select.component'; import { isNotEmpty } from '../../../shared/empty.util'; import { ThemedLoadingComponent } from '../../../shared/loading/themed-loading.component'; @@ -65,7 +65,7 @@ import { SectionsType } from '../sections-type'; VarDirective, NgForOf, DsSelectComponent, - DisabledDirective, + BtnDisabledDirective, ], standalone: true, }) diff --git a/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.html b/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.html index 91b89e8435..b03504c6be 100644 --- a/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.html +++ b/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.html @@ -1,7 +1,7 @@
diff --git a/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.ts b/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.ts index c7ba64e4b9..0a6c1bd44d 100644 --- a/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.ts +++ b/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.ts @@ -39,7 +39,7 @@ import { JsonPatchOperationsBuilder } from '../../../../../core/json-patch/build import { WorkspaceitemSectionUploadFileObject } from '../../../../../core/submission/models/workspaceitem-section-upload-file.model'; import { SubmissionJsonPatchOperationsService } from '../../../../../core/submission/submission-json-patch-operations.service'; import { dateToISOFormat } from '../../../../../shared/date.util'; -import { DisabledDirective } from '../../../../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../../../shared/btn-disabled.directive'; import { hasNoValue, hasValue, @@ -81,7 +81,7 @@ import { FormComponent, NgIf, TranslateModule, - DisabledDirective, + BtnDisabledDirective, ], standalone: true, }) diff --git a/src/app/submission/sections/upload/file/section-upload-file.component.html b/src/app/submission/sections/upload/file/section-upload-file.component.html index f8d6b9ca93..bfc09e86c1 100644 --- a/src/app/submission/sections/upload/file/section-upload-file.component.html +++ b/src/app/submission/sections/upload/file/section-upload-file.component.html @@ -35,7 +35,7 @@ -
diff --git a/src/app/system-wide-alert/alert-form/system-wide-alert-form.component.ts b/src/app/system-wide-alert/alert-form/system-wide-alert-form.component.ts index b695bb47ed..ea1c0a55f0 100644 --- a/src/app/system-wide-alert/alert-form/system-wide-alert-form.component.ts +++ b/src/app/system-wide-alert/alert-form/system-wide-alert-form.component.ts @@ -43,7 +43,7 @@ import { RemoteData } from '../../core/data/remote-data'; import { RequestService } from '../../core/data/request.service'; import { SystemWideAlertDataService } from '../../core/data/system-wide-alert-data.service'; import { getFirstCompletedRemoteData } from '../../core/shared/operators'; -import { DisabledDirective } from '../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../shared/btn-disabled.directive'; import { hasValue, isNotEmpty, @@ -60,7 +60,7 @@ import { SystemWideAlert } from '../system-wide-alert.model'; styleUrls: ['./system-wide-alert-form.component.scss'], templateUrl: './system-wide-alert-form.component.html', standalone: true, - imports: [FormsModule, ReactiveFormsModule, UiSwitchModule, NgIf, NgbDatepickerModule, NgbTimepickerModule, AsyncPipe, TranslateModule, DisabledDirective], + imports: [FormsModule, ReactiveFormsModule, UiSwitchModule, NgIf, NgbDatepickerModule, NgbTimepickerModule, AsyncPipe, TranslateModule, BtnDisabledDirective], }) export class SystemWideAlertFormComponent implements OnInit { diff --git a/src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.ts b/src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.ts index e87a292c0c..57e8c73031 100644 --- a/src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.ts +++ b/src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.ts @@ -45,7 +45,7 @@ import { Group } from '../../../../core/eperson/models/group.model'; import { PaginationService } from '../../../../core/pagination/pagination.service'; import { getFirstSucceededRemoteDataPayload } from '../../../../core/shared/operators'; import { ContextHelpDirective } from '../../../../shared/context-help.directive'; -import { DisabledDirective } from '../../../../shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../../shared/btn-disabled.directive'; import { hasValue } from '../../../../shared/empty.util'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { PaginationComponent } from '../../../../shared/pagination/pagination.component'; @@ -77,7 +77,7 @@ enum SubKey { RouterLink, NgClass, NgForOf, - DisabledDirective, + BtnDisabledDirective, ], }) export class ReviewersListComponent extends MembersListComponent implements OnInit, OnChanges, OnDestroy { diff --git a/src/themes/custom/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts b/src/themes/custom/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts index 40a6264e4e..f74a73a4b8 100644 --- a/src/themes/custom/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts +++ b/src/themes/custom/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts @@ -13,7 +13,7 @@ import { DsoEditMetadataValueComponent } from '../../../../../app/dso-shared/dso import { DsoEditMetadataValueHeadersComponent } from '../../../../../app/dso-shared/dso-edit-metadata/dso-edit-metadata-value-headers/dso-edit-metadata-value-headers.component'; import { MetadataFieldSelectorComponent } from '../../../../../app/dso-shared/dso-edit-metadata/metadata-field-selector/metadata-field-selector.component'; import { AlertComponent } from '../../../../../app/shared/alert/alert.component'; -import { DisabledDirective } from '../../../../../app/shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../../../app/shared/btn-disabled.directive'; import { ThemedLoadingComponent } from '../../../../../app/shared/loading/themed-loading.component'; @Component({ @@ -23,7 +23,7 @@ import { ThemedLoadingComponent } from '../../../../../app/shared/loading/themed // templateUrl: './dso-edit-metadata.component.html', templateUrl: '../../../../../app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.html', standalone: true, - imports: [NgIf, DsoEditMetadataHeadersComponent, MetadataFieldSelectorComponent, DsoEditMetadataValueHeadersComponent, DsoEditMetadataValueComponent, NgFor, DsoEditMetadataFieldValuesComponent, AlertComponent, ThemedLoadingComponent, AsyncPipe, TranslateModule, DisabledDirective], + imports: [NgIf, DsoEditMetadataHeadersComponent, MetadataFieldSelectorComponent, DsoEditMetadataValueHeadersComponent, DsoEditMetadataValueComponent, NgFor, DsoEditMetadataFieldValuesComponent, AlertComponent, ThemedLoadingComponent, AsyncPipe, TranslateModule, BtnDisabledDirective], }) export class DsoEditMetadataComponent extends BaseComponent { } diff --git a/src/themes/custom/app/forgot-password/forgot-password-form/forgot-password-form.component.ts b/src/themes/custom/app/forgot-password/forgot-password-form/forgot-password-form.component.ts index ff64b09664..37fb383429 100644 --- a/src/themes/custom/app/forgot-password/forgot-password-form/forgot-password-form.component.ts +++ b/src/themes/custom/app/forgot-password/forgot-password-form/forgot-password-form.component.ts @@ -7,7 +7,7 @@ import { TranslateModule } from '@ngx-translate/core'; import { ForgotPasswordFormComponent as BaseComponent } from '../../../../../app/forgot-password/forgot-password-form/forgot-password-form.component'; import { ProfilePageSecurityFormComponent } from '../../../../../app/profile-page/profile-page-security-form/profile-page-security-form.component'; -import { DisabledDirective } from '../../../../../app/shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../../../app/shared/btn-disabled.directive'; import { BrowserOnlyPipe } from '../../../../../app/shared/utils/browser-only.pipe'; @Component({ @@ -23,7 +23,7 @@ import { BrowserOnlyPipe } from '../../../../../app/shared/utils/browser-only.pi ProfilePageSecurityFormComponent, AsyncPipe, NgIf, - DisabledDirective, + BtnDisabledDirective, ], }) /** diff --git a/src/themes/custom/app/info/end-user-agreement/end-user-agreement.component.ts b/src/themes/custom/app/info/end-user-agreement/end-user-agreement.component.ts index e557fc466c..2b78006f65 100644 --- a/src/themes/custom/app/info/end-user-agreement/end-user-agreement.component.ts +++ b/src/themes/custom/app/info/end-user-agreement/end-user-agreement.component.ts @@ -4,7 +4,7 @@ import { TranslateModule } from '@ngx-translate/core'; import { EndUserAgreementComponent as BaseComponent } from '../../../../../app/info/end-user-agreement/end-user-agreement.component'; import { EndUserAgreementContentComponent } from '../../../../../app/info/end-user-agreement/end-user-agreement-content/end-user-agreement-content.component'; -import { DisabledDirective } from '../../../../../app/shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../../../app/shared/btn-disabled.directive'; @Component({ selector: 'ds-themed-end-user-agreement', @@ -13,7 +13,7 @@ import { DisabledDirective } from '../../../../../app/shared/disabled-directive' // templateUrl: './end-user-agreement.component.html' templateUrl: '../../../../../app/info/end-user-agreement/end-user-agreement.component.html', standalone: true, - imports: [EndUserAgreementContentComponent, FormsModule, TranslateModule, DisabledDirective], + imports: [EndUserAgreementContentComponent, FormsModule, TranslateModule, BtnDisabledDirective], }) /** diff --git a/src/themes/custom/app/info/feedback/feedback-form/feedback-form.component.ts b/src/themes/custom/app/info/feedback/feedback-form/feedback-form.component.ts index b86fecae7a..3835667111 100644 --- a/src/themes/custom/app/info/feedback/feedback-form/feedback-form.component.ts +++ b/src/themes/custom/app/info/feedback/feedback-form/feedback-form.component.ts @@ -7,7 +7,7 @@ import { import { TranslateModule } from '@ngx-translate/core'; import { FeedbackFormComponent as BaseComponent } from '../../../../../../app/info/feedback/feedback-form/feedback-form.component'; -import { DisabledDirective } from '../../../../../../app/shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../../../../app/shared/btn-disabled.directive'; import { ErrorComponent } from '../../../../../../app/shared/error/error.component'; @Component({ @@ -17,7 +17,7 @@ import { ErrorComponent } from '../../../../../../app/shared/error/error.compone // styleUrls: ['./feedback-form.component.scss'], styleUrls: ['../../../../../../app/info/feedback/feedback-form/feedback-form.component.scss'], standalone: true, - imports: [FormsModule, ReactiveFormsModule, NgIf, ErrorComponent, TranslateModule, DisabledDirective], + imports: [FormsModule, ReactiveFormsModule, NgIf, ErrorComponent, TranslateModule, BtnDisabledDirective], }) export class FeedbackFormComponent extends BaseComponent { } diff --git a/src/themes/custom/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.ts b/src/themes/custom/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.ts index 020293214e..0efa013064 100644 --- a/src/themes/custom/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.ts +++ b/src/themes/custom/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.ts @@ -7,7 +7,7 @@ import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'; import { TranslateModule } from '@ngx-translate/core'; import { MediaViewerVideoComponent as BaseComponent } from '../../../../../../app/item-page/media-viewer/media-viewer-video/media-viewer-video.component'; -import { DisabledDirective } from '../../../../../../app/shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../../../../app/shared/btn-disabled.directive'; @Component({ selector: 'ds-themed-media-viewer-video', @@ -21,7 +21,7 @@ import { DisabledDirective } from '../../../../../../app/shared/disabled-directi NgbDropdownModule, TranslateModule, NgIf, - DisabledDirective, + BtnDisabledDirective, ], }) export class MediaViewerVideoComponent extends BaseComponent { diff --git a/src/themes/custom/app/register-email-form/register-email-form.component.ts b/src/themes/custom/app/register-email-form/register-email-form.component.ts index d9be35f39d..d1f4a6d3ff 100644 --- a/src/themes/custom/app/register-email-form/register-email-form.component.ts +++ b/src/themes/custom/app/register-email-form/register-email-form.component.ts @@ -12,14 +12,14 @@ import { AlertComponent } from 'src/app/shared/alert/alert.component'; import { GoogleRecaptchaComponent } from 'src/app/shared/google-recaptcha/google-recaptcha.component'; import { RegisterEmailFormComponent as BaseComponent } from '../../../../app/register-email-form/register-email-form.component'; -import { DisabledDirective } from '../../../../app/shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../../app/shared/btn-disabled.directive'; @Component({ selector: 'ds-themed-register-email-form', // templateUrl: './register-email-form.component.html', templateUrl: '../../../../app/register-email-form/register-email-form.component.html', standalone: true, - imports: [NgIf, FormsModule, ReactiveFormsModule, AlertComponent, GoogleRecaptchaComponent, AsyncPipe, TranslateModule, DisabledDirective], + imports: [NgIf, FormsModule, ReactiveFormsModule, AlertComponent, GoogleRecaptchaComponent, AsyncPipe, TranslateModule, BtnDisabledDirective], }) export class RegisterEmailFormComponent extends BaseComponent { } diff --git a/src/themes/custom/app/register-page/create-profile/create-profile.component.ts b/src/themes/custom/app/register-page/create-profile/create-profile.component.ts index 659e260b1c..7c1ff908c3 100644 --- a/src/themes/custom/app/register-page/create-profile/create-profile.component.ts +++ b/src/themes/custom/app/register-page/create-profile/create-profile.component.ts @@ -9,7 +9,7 @@ import { TranslateModule } from '@ngx-translate/core'; import { ProfilePageSecurityFormComponent } from '../../../../../app/profile-page/profile-page-security-form/profile-page-security-form.component'; import { CreateProfileComponent as BaseComponent } from '../../../../../app/register-page/create-profile/create-profile.component'; -import { DisabledDirective } from '../../../../../app/shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../../../app/shared/btn-disabled.directive'; /** * Component that renders the create profile page to be used by a user registering through a token @@ -28,7 +28,7 @@ import { DisabledDirective } from '../../../../../app/shared/disabled-directive' AsyncPipe, ReactiveFormsModule, NgForOf, - DisabledDirective, + BtnDisabledDirective, ], }) export class CreateProfileComponent extends BaseComponent { diff --git a/src/themes/custom/app/request-copy/email-request-copy/email-request-copy.component.ts b/src/themes/custom/app/request-copy/email-request-copy/email-request-copy.component.ts index a299e47a27..cf4981d289 100644 --- a/src/themes/custom/app/request-copy/email-request-copy/email-request-copy.component.ts +++ b/src/themes/custom/app/request-copy/email-request-copy/email-request-copy.component.ts @@ -7,7 +7,7 @@ import { FormsModule } from '@angular/forms'; import { TranslateModule } from '@ngx-translate/core'; import { EmailRequestCopyComponent as BaseComponent } from 'src/app/request-copy/email-request-copy/email-request-copy.component'; -import { DisabledDirective } from '../../../../../app/shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../../../app/shared/btn-disabled.directive'; @Component({ selector: 'ds-themed-email-request-copy', @@ -16,7 +16,7 @@ import { DisabledDirective } from '../../../../../app/shared/disabled-directive' // templateUrl: './email-request-copy.component.html', templateUrl: './../../../../../app/request-copy/email-request-copy/email-request-copy.component.html', standalone: true, - imports: [FormsModule, NgClass, NgIf, TranslateModule, DisabledDirective], + imports: [FormsModule, NgClass, NgIf, TranslateModule, BtnDisabledDirective], }) export class EmailRequestCopyComponent extends BaseComponent { diff --git a/src/themes/custom/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts b/src/themes/custom/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts index 7936deb406..aec7bfd6db 100644 --- a/src/themes/custom/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts +++ b/src/themes/custom/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts @@ -5,7 +5,7 @@ import { import { Component } from '@angular/core'; import { TranslateModule } from '@ngx-translate/core'; -import { DisabledDirective } from '../../../../../../../../../../app/shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../../../../../../../../app/shared/btn-disabled.directive'; import { ExternalSourceEntryImportModalComponent as BaseComponent } from '../../../../../../../../../../app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component'; import { ThemedSearchResultsComponent } from '../../../../../../../../../../app/shared/search/search-results/themed-search-results.component'; @@ -20,7 +20,7 @@ import { ThemedSearchResultsComponent } from '../../../../../../../../../../app/ ThemedSearchResultsComponent, NgIf, AsyncPipe, - DisabledDirective, + BtnDisabledDirective, ], }) export class ExternalSourceEntryImportModalComponent extends BaseComponent { diff --git a/src/themes/custom/app/submission/sections/upload/file/section-upload-file.component.ts b/src/themes/custom/app/submission/sections/upload/file/section-upload-file.component.ts index 17bc5d9136..cea515102a 100644 --- a/src/themes/custom/app/submission/sections/upload/file/section-upload-file.component.ts +++ b/src/themes/custom/app/submission/sections/upload/file/section-upload-file.component.ts @@ -6,7 +6,7 @@ import { Component } from '@angular/core'; import { TranslateModule } from '@ngx-translate/core'; import { SubmissionSectionUploadFileComponent as BaseComponent } from 'src/app/submission/sections/upload/file/section-upload-file.component'; -import { DisabledDirective } from '../../../../../../../app/shared/disabled-directive'; +import { BtnDisabledDirective } from '../../../../../../../app/shared/btn-disabled.directive'; import { ThemedFileDownloadLinkComponent } from '../../../../../../../app/shared/file-download-link/themed-file-download-link.component'; import { FileSizePipe } from '../../../../../../../app/shared/utils/file-size-pipe'; import { SubmissionSectionUploadFileViewComponent } from '../../../../../../../app/submission/sections/upload/file/view/section-upload-file-view.component'; @@ -28,7 +28,7 @@ import { SubmissionSectionUploadFileViewComponent } from '../../../../../../../a AsyncPipe, ThemedFileDownloadLinkComponent, FileSizePipe, - DisabledDirective, + BtnDisabledDirective, ], }) export class SubmissionSectionUploadFileComponent From eb5aadaf8ac9f5a4928997983aee00098d9ca8cd Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Mon, 16 Sep 2024 14:11:59 +0200 Subject: [PATCH 0430/1286] 117544: linting --- .../epeople-registry/eperson-form/eperson-form.component.ts | 2 +- .../group-form/members-list/members-list.component.ts | 2 +- .../delete-collection-page/delete-collection-page.component.ts | 2 +- .../delete-community-page/delete-community-page.component.ts | 2 +- .../profile-page-researcher-form.component.ts | 2 +- src/app/register-email-form/register-email-form.component.ts | 2 +- .../access-control-array-form.component.ts | 2 +- .../external-source-entry-import-modal.component.ts | 2 +- .../form/resource-policy-form.component.spec.ts | 2 +- .../resource-policies/form/resource-policy-form.component.ts | 2 +- .../subscription-view/subscription-view.component.ts | 2 +- .../collection/submission-form-collection.component.spec.ts | 2 +- .../form/collection/submission-form-collection.component.ts | 2 +- .../upload/file/edit/section-upload-file-edit.component.ts | 2 +- .../reviewers-list/reviewers-list.component.ts | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts b/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts index 1c6f1929f3..c8236ca22d 100644 --- a/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts +++ b/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts @@ -65,8 +65,8 @@ import { import { PageInfo } from '../../../core/shared/page-info.model'; import { Registration } from '../../../core/shared/registration.model'; import { TYPE_REQUEST_FORGOT } from '../../../register-email-form/register-email-form.component'; -import { ConfirmationModalComponent } from '../../../shared/confirmation-modal/confirmation-modal.component'; import { BtnDisabledDirective } from '../../../shared/btn-disabled.directive'; +import { ConfirmationModalComponent } from '../../../shared/confirmation-modal/confirmation-modal.component'; import { hasValue } from '../../../shared/empty.util'; import { FormBuilderService } from '../../../shared/form/builder/form-builder.service'; import { FormComponent } from '../../../shared/form/form.component'; diff --git a/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts b/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts index 6563a765d2..22934394c8 100644 --- a/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts +++ b/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts @@ -54,8 +54,8 @@ import { getFirstCompletedRemoteData, getRemoteDataPayload, } from '../../../../core/shared/operators'; -import { ContextHelpDirective } from '../../../../shared/context-help.directive'; import { BtnDisabledDirective } from '../../../../shared/btn-disabled.directive'; +import { ContextHelpDirective } from '../../../../shared/context-help.directive'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { PaginationComponent } from '../../../../shared/pagination/pagination.component'; import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model'; diff --git a/src/app/collection-page/delete-collection-page/delete-collection-page.component.ts b/src/app/collection-page/delete-collection-page/delete-collection-page.component.ts index 3d4d4abb5f..acc716b52a 100644 --- a/src/app/collection-page/delete-collection-page/delete-collection-page.component.ts +++ b/src/app/collection-page/delete-collection-page/delete-collection-page.component.ts @@ -15,8 +15,8 @@ import { import { DSONameService } from '../../core/breadcrumbs/dso-name.service'; import { CollectionDataService } from '../../core/data/collection-data.service'; import { Collection } from '../../core/shared/collection.model'; -import { DeleteComColPageComponent } from '../../shared/comcol/comcol-forms/delete-comcol-page/delete-comcol-page.component'; import { BtnDisabledDirective } from '../../shared/btn-disabled.directive'; +import { DeleteComColPageComponent } from '../../shared/comcol/comcol-forms/delete-comcol-page/delete-comcol-page.component'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { VarDirective } from '../../shared/utils/var.directive'; diff --git a/src/app/community-page/delete-community-page/delete-community-page.component.ts b/src/app/community-page/delete-community-page/delete-community-page.component.ts index b2fa5956cb..9c19a5eb47 100644 --- a/src/app/community-page/delete-community-page/delete-community-page.component.ts +++ b/src/app/community-page/delete-community-page/delete-community-page.component.ts @@ -15,8 +15,8 @@ import { import { DSONameService } from '../../core/breadcrumbs/dso-name.service'; import { CommunityDataService } from '../../core/data/community-data.service'; import { Community } from '../../core/shared/community.model'; -import { DeleteComColPageComponent } from '../../shared/comcol/comcol-forms/delete-comcol-page/delete-comcol-page.component'; import { BtnDisabledDirective } from '../../shared/btn-disabled.directive'; +import { DeleteComColPageComponent } from '../../shared/comcol/comcol-forms/delete-comcol-page/delete-comcol-page.component'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { VarDirective } from '../../shared/utils/var.directive'; diff --git a/src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.ts b/src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.ts index 925ed6d5a6..5d09097e6b 100644 --- a/src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.ts +++ b/src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.ts @@ -36,8 +36,8 @@ import { getFirstCompletedRemoteData, getFirstSucceededRemoteDataPayload, } from '../../core/shared/operators'; -import { ConfirmationModalComponent } from '../../shared/confirmation-modal/confirmation-modal.component'; import { BtnDisabledDirective } from '../../shared/btn-disabled.directive'; +import { ConfirmationModalComponent } from '../../shared/confirmation-modal/confirmation-modal.component'; import { isNotEmpty } from '../../shared/empty.util'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { followLink } from '../../shared/utils/follow-link-config.model'; diff --git a/src/app/register-email-form/register-email-form.component.ts b/src/app/register-email-form/register-email-form.component.ts index 37ce725778..585ca71c24 100644 --- a/src/app/register-email-form/register-email-form.component.ts +++ b/src/app/register-email-form/register-email-form.component.ts @@ -54,8 +54,8 @@ import { import { Registration } from '../core/shared/registration.model'; import { AlertComponent } from '../shared/alert/alert.component'; import { AlertType } from '../shared/alert/alert-type'; -import { KlaroService } from '../shared/cookies/klaro.service'; import { BtnDisabledDirective } from '../shared/btn-disabled.directive'; +import { KlaroService } from '../shared/cookies/klaro.service'; import { isNotEmpty } from '../shared/empty.util'; import { GoogleRecaptchaComponent } from '../shared/google-recaptcha/google-recaptcha.component'; import { NotificationsService } from '../shared/notifications/notifications.service'; diff --git a/src/app/shared/access-control-form-container/access-control-array-form/access-control-array-form.component.ts b/src/app/shared/access-control-form-container/access-control-array-form/access-control-array-form.component.ts index 8f7f640c28..3dc84a833a 100644 --- a/src/app/shared/access-control-form-container/access-control-array-form/access-control-array-form.component.ts +++ b/src/app/shared/access-control-form-container/access-control-array-form/access-control-array-form.component.ts @@ -16,8 +16,8 @@ import { NgbDatepickerModule } from '@ng-bootstrap/ng-bootstrap'; import { TranslateModule } from '@ngx-translate/core'; import { AccessesConditionOption } from '../../../core/config/models/config-accesses-conditions-options.model'; -import { dateToISOFormat } from '../../date.util'; import { BtnDisabledDirective } from '../../btn-disabled.directive'; +import { dateToISOFormat } from '../../date.util'; import { ToDatePipe } from './to-date.pipe'; @Component({ diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts index c666baf21f..e0cc90ceaa 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts @@ -37,8 +37,8 @@ import { getRemoteDataPayload, } from '../../../../../../../core/shared/operators'; import { SubmissionImportExternalCollectionComponent } from '../../../../../../../submission/import-external/import-external-collection/submission-import-external-collection.component'; -import { CollectionListEntry } from '../../../../../../collection-dropdown/collection-dropdown.component'; import { BtnDisabledDirective } from '../../../../../../btn-disabled.directive'; +import { CollectionListEntry } from '../../../../../../collection-dropdown/collection-dropdown.component'; import { NotificationsService } from '../../../../../../notifications/notifications.service'; import { CollectionElementLinkType } from '../../../../../../object-collection/collection-element-link.type'; import { ItemSearchResult } from '../../../../../../object-collection/shared/item-search-result.model'; diff --git a/src/app/shared/resource-policies/form/resource-policy-form.component.spec.ts b/src/app/shared/resource-policies/form/resource-policy-form.component.spec.ts index d4dac77d72..deaef6c611 100644 --- a/src/app/shared/resource-policies/form/resource-policy-form.component.spec.ts +++ b/src/app/shared/resource-policies/form/resource-policy-form.component.spec.ts @@ -45,11 +45,11 @@ import { ResourcePolicy } from '../../../core/resource-policy/models/resource-po import { RESOURCE_POLICY } from '../../../core/resource-policy/models/resource-policy.resource-type'; import { SubmissionObjectDataService } from '../../../core/submission/submission-object-data.service'; import { SubmissionService } from '../../../submission/submission.service'; +import { BtnDisabledDirective } from '../../btn-disabled.directive'; import { dateToISOFormat, stringToNgbDateStruct, } from '../../date.util'; -import { BtnDisabledDirective } from '../../btn-disabled.directive'; import { isNotEmptyOperator } from '../../empty.util'; import { EpersonGroupListComponent } from '../../eperson-group-list/eperson-group-list.component'; import { dsDynamicFormControlMapFn } from '../../form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-map-fn'; diff --git a/src/app/shared/resource-policies/form/resource-policy-form.component.ts b/src/app/shared/resource-policies/form/resource-policy-form.component.ts index e13ba9ecc7..08a7f18492 100644 --- a/src/app/shared/resource-policies/form/resource-policy-form.component.ts +++ b/src/app/shared/resource-policies/form/resource-policy-form.component.ts @@ -47,11 +47,11 @@ import { ResourcePolicy } from '../../../core/resource-policy/models/resource-po import { RESOURCE_POLICY } from '../../../core/resource-policy/models/resource-policy.resource-type'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { getFirstSucceededRemoteData } from '../../../core/shared/operators'; +import { BtnDisabledDirective } from '../../btn-disabled.directive'; import { dateToISOFormat, stringToNgbDateStruct, } from '../../date.util'; -import { BtnDisabledDirective } from '../../btn-disabled.directive'; import { hasValue, hasValueOperator, diff --git a/src/app/shared/subscriptions/subscription-view/subscription-view.component.ts b/src/app/shared/subscriptions/subscription-view/subscription-view.component.ts index 9d9ce08905..f940e69795 100644 --- a/src/app/shared/subscriptions/subscription-view/subscription-view.component.ts +++ b/src/app/shared/subscriptions/subscription-view/subscription-view.component.ts @@ -19,8 +19,8 @@ import { getDSORoute } from 'src/app/app-routing-paths'; import { DSONameService } from '../../../core/breadcrumbs/dso-name.service'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; -import { ConfirmationModalComponent } from '../../confirmation-modal/confirmation-modal.component'; import { BtnDisabledDirective } from '../../btn-disabled.directive'; +import { ConfirmationModalComponent } from '../../confirmation-modal/confirmation-modal.component'; import { hasValue } from '../../empty.util'; import { ThemedTypeBadgeComponent } from '../../object-collection/shared/badges/type-badge/themed-type-badge.component'; import { Subscription } from '../models/subscription.model'; diff --git a/src/app/submission/form/collection/submission-form-collection.component.spec.ts b/src/app/submission/form/collection/submission-form-collection.component.spec.ts index 61bad0439f..3a5ae8a18d 100644 --- a/src/app/submission/form/collection/submission-form-collection.component.spec.ts +++ b/src/app/submission/form/collection/submission-form-collection.component.spec.ts @@ -30,8 +30,8 @@ import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder'; import { Collection } from '../../../core/shared/collection.model'; import { SubmissionJsonPatchOperationsService } from '../../../core/submission/submission-json-patch-operations.service'; -import { ThemedCollectionDropdownComponent } from '../../../shared/collection-dropdown/themed-collection-dropdown.component'; import { BtnDisabledDirective } from '../../../shared/btn-disabled.directive'; +import { ThemedCollectionDropdownComponent } from '../../../shared/collection-dropdown/themed-collection-dropdown.component'; import { DSONameServiceMock } from '../../../shared/mocks/dso-name.service.mock'; import { mockSubmissionId, diff --git a/src/app/submission/form/collection/submission-form-collection.component.ts b/src/app/submission/form/collection/submission-form-collection.component.ts index 10b1f815dc..1736b474d5 100644 --- a/src/app/submission/form/collection/submission-form-collection.component.ts +++ b/src/app/submission/form/collection/submission-form-collection.component.ts @@ -34,9 +34,9 @@ import { Collection } from '../../../core/shared/collection.model'; import { getFirstSucceededRemoteDataPayload } from '../../../core/shared/operators'; import { SubmissionObject } from '../../../core/submission/models/submission-object.model'; import { SubmissionJsonPatchOperationsService } from '../../../core/submission/submission-json-patch-operations.service'; +import { BtnDisabledDirective } from '../../../shared/btn-disabled.directive'; import { CollectionDropdownComponent } from '../../../shared/collection-dropdown/collection-dropdown.component'; import { ThemedCollectionDropdownComponent } from '../../../shared/collection-dropdown/themed-collection-dropdown.component'; -import { BtnDisabledDirective } from '../../../shared/btn-disabled.directive'; import { hasValue, isNotEmpty, diff --git a/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.ts b/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.ts index 0a6c1bd44d..79b3d3a565 100644 --- a/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.ts +++ b/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.ts @@ -38,8 +38,8 @@ import { JsonPatchOperationPathCombiner } from '../../../../../core/json-patch/b import { JsonPatchOperationsBuilder } from '../../../../../core/json-patch/builder/json-patch-operations-builder'; import { WorkspaceitemSectionUploadFileObject } from '../../../../../core/submission/models/workspaceitem-section-upload-file.model'; import { SubmissionJsonPatchOperationsService } from '../../../../../core/submission/submission-json-patch-operations.service'; -import { dateToISOFormat } from '../../../../../shared/date.util'; import { BtnDisabledDirective } from '../../../../../shared/btn-disabled.directive'; +import { dateToISOFormat } from '../../../../../shared/date.util'; import { hasNoValue, hasValue, diff --git a/src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.ts b/src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.ts index 57e8c73031..c43fabdb83 100644 --- a/src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.ts +++ b/src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.ts @@ -44,8 +44,8 @@ import { EpersonDtoModel } from '../../../../core/eperson/models/eperson-dto.mod import { Group } from '../../../../core/eperson/models/group.model'; import { PaginationService } from '../../../../core/pagination/pagination.service'; import { getFirstSucceededRemoteDataPayload } from '../../../../core/shared/operators'; -import { ContextHelpDirective } from '../../../../shared/context-help.directive'; import { BtnDisabledDirective } from '../../../../shared/btn-disabled.directive'; +import { ContextHelpDirective } from '../../../../shared/context-help.directive'; import { hasValue } from '../../../../shared/empty.util'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { PaginationComponent } from '../../../../shared/pagination/pagination.component'; From 80e1daeb659cfe7461845d4680bed747994e720a Mon Sep 17 00:00:00 2001 From: Andrea Barbasso <´andrea.barbasso@4science.com´> Date: Mon, 16 Sep 2024 14:22:13 +0200 Subject: [PATCH 0431/1286] [CST-15593] allow orejime to start if privacy statement is disabled --- src/app/shared/cookies/browser-orejime.service.ts | 3 +++ src/assets/i18n/en.json5 | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/app/shared/cookies/browser-orejime.service.ts b/src/app/shared/cookies/browser-orejime.service.ts index aa9d56d9ee..4a7a182e0a 100644 --- a/src/app/shared/cookies/browser-orejime.service.ts +++ b/src/app/shared/cookies/browser-orejime.service.ts @@ -117,6 +117,9 @@ export class BrowserOrejimeService extends OrejimeService { * - Add and translate orejime configuration messages */ initialize() { + if (!environment.info.enablePrivacyStatement) { + this.orejimeConfig.translations.zz.consentModal.privacyPolicy.text = 'cookies.consent.content-modal.no-privacy-policy.text'; + } const hideGoogleAnalytics$ = this.configService.findByPropertyName(this.GOOGLE_ANALYTICS_KEY).pipe( getFirstCompletedRemoteData(), diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 5d06f4c19b..8ced30954b 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1604,6 +1604,8 @@ "cookies.consent.content-modal.privacy-policy.text": "To learn more, please read our {privacyPolicy}.", + "cookies.consent.content-modal.no-privacy-policy.text": "", + "cookies.consent.content-modal.title": "Information that we collect", "cookies.consent.app.title.authentication": "Authentication", From 685e6d83c5a85269d0c47678ab4a282346184d99 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Mon, 16 Sep 2024 13:44:06 +0200 Subject: [PATCH 0432/1286] 117544: PR feedback - added typedocs - changed directive to only be present for buttons - various other small fixes --- .../filtered-items.component.html | 0 .../dso-edit-metadata-value.component.html | 47 +++++++++++++++++++ .../item-delete/item-delete.component.html | 2 +- .../access-control-array-form.component.html | 2 +- ...cess-control-form-container.component.html | 12 ++--- src/app/shared/disabled-directive.spec.ts | 8 ++++ src/app/shared/disabled-directive.ts | 28 ++++++++++- ...amic-form-control-container.component.html | 2 +- .../date-picker/date-picker.component.html | 6 +-- .../disabled/dynamic-disabled.component.html | 2 +- .../dynamic-disabled.component.spec.ts | 2 +- .../lookup/dynamic-lookup.component.html | 4 +- .../onebox/dynamic-onebox.component.html | 4 +- ...dynamic-scrollable-dropdown.component.html | 2 +- .../number-picker.component.html | 2 +- .../vocabulary-treeview.component.html | 4 +- .../collection-select.component.html | 2 +- .../item-select/item-select.component.html | 2 +- .../item-select/item-select.component.spec.ts | 3 +- .../pagination/pagination.component.html | 2 +- ...mission-section-cc-licenses.component.html | 4 +- 21 files changed, 110 insertions(+), 30 deletions(-) create mode 100644 src/app/admin/admin-reports/filtered-items/filtered-items.component.html 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..e69de29bb2 diff --git a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-value/dso-edit-metadata-value.component.html b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-value/dso-edit-metadata-value.component.html index f3d92ace2d..1837801902 100644 --- a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-value/dso-edit-metadata-value.component.html +++ b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-value/dso-edit-metadata-value.component.html @@ -6,6 +6,53 @@ + + + + +
+ + + {{ dsoType + '.edit.metadata.authority.label' | translate }} {{ mdValue.newValue.authority }} + +
+
+
+ + + + +
+
{{ mdRepresentationName$ | async }} diff --git a/src/app/item-page/edit-item-page/item-delete/item-delete.component.html b/src/app/item-page/edit-item-page/item-delete/item-delete.component.html index eadec9babf..667363a381 100644 --- a/src/app/item-page/edit-item-page/item-delete/item-delete.component.html +++ b/src/app/item-page/edit-item-page/item-delete/item-delete.component.html @@ -18,7 +18,7 @@
diff --git a/src/app/shared/access-control-form-container/access-control-array-form/access-control-array-form.component.html b/src/app/shared/access-control-form-container/access-control-array-form/access-control-array-form.component.html index 630812c345..f2a5bdd422 100644 --- a/src/app/shared/access-control-form-container/access-control-array-form/access-control-array-form.component.html +++ b/src/app/shared/access-control-form-container/access-control-array-form/access-control-array-form.component.html @@ -13,7 +13,7 @@
- - diff --git a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.spec.ts b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.spec.ts index 3a431705c3..eef3e45fa9 100644 --- a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.spec.ts +++ b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.spec.ts @@ -16,7 +16,7 @@ import { DATA_SERVICE_FACTORY } from '../../core/data/base/data-service.decorato import { Operation } from 'fast-json-patch'; import { RemoteData } from '../../core/data/remote-data'; import { Observable } from 'rxjs/internal/Observable'; -import {DisabledDirective} from '../../shared/disabled-directive'; +import {BtnDisabledDirective} from '../../shared/btn-disabled.directive'; const ADD_BTN = 'add'; const REINSTATE_BTN = 'reinstate'; @@ -72,7 +72,7 @@ describe('DsoEditMetadataComponent', () => { notificationsService = jasmine.createSpyObj('notificationsService', ['error', 'success']); TestBed.configureTestingModule({ - declarations: [DsoEditMetadataComponent, VarDirective, DisabledDirective], + declarations: [DsoEditMetadataComponent, VarDirective, BtnDisabledDirective], imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([])], providers: [ TestDataService, diff --git a/src/app/forgot-password/forgot-password-form/forgot-password-form.component.html b/src/app/forgot-password/forgot-password-form/forgot-password-form.component.html index 1f3df7e333..6cff2903b9 100644 --- a/src/app/forgot-password/forgot-password-form/forgot-password-form.component.html +++ b/src/app/forgot-password/forgot-password-form/forgot-password-form.component.html @@ -28,7 +28,7 @@
diff --git a/src/app/info/end-user-agreement/end-user-agreement.component.html b/src/app/info/end-user-agreement/end-user-agreement.component.html index 4b93d631b7..ceb2ad23a4 100644 --- a/src/app/info/end-user-agreement/end-user-agreement.component.html +++ b/src/app/info/end-user-agreement/end-user-agreement.component.html @@ -7,7 +7,7 @@
- +
diff --git a/src/app/info/end-user-agreement/end-user-agreement.component.spec.ts b/src/app/info/end-user-agreement/end-user-agreement.component.spec.ts index 153fe4a51f..c7735f0579 100644 --- a/src/app/info/end-user-agreement/end-user-agreement.component.spec.ts +++ b/src/app/info/end-user-agreement/end-user-agreement.component.spec.ts @@ -11,7 +11,7 @@ import { Store } from '@ngrx/store'; import { By } from '@angular/platform-browser'; import { LogOutAction } from '../../core/auth/auth.actions'; import { ActivatedRouteStub } from '../../shared/testing/active-router.stub'; -import {DisabledDirective} from '../../shared/disabled-directive'; +import {BtnDisabledDirective} from '../../shared/btn-disabled.directive'; describe('EndUserAgreementComponent', () => { let component: EndUserAgreementComponent; @@ -50,7 +50,7 @@ describe('EndUserAgreementComponent', () => { init(); TestBed.configureTestingModule({ imports: [TranslateModule.forRoot()], - declarations: [EndUserAgreementComponent, DisabledDirective], + declarations: [EndUserAgreementComponent, BtnDisabledDirective], providers: [ { provide: EndUserAgreementService, useValue: endUserAgreementService }, { provide: NotificationsService, useValue: notificationsService }, diff --git a/src/app/info/feedback/feedback-form/feedback-form.component.html b/src/app/info/feedback/feedback-form/feedback-form.component.html index 3fdc66820a..c5c4b460a2 100644 --- a/src/app/info/feedback/feedback-form/feedback-form.component.html +++ b/src/app/info/feedback/feedback-form/feedback-form.component.html @@ -41,7 +41,7 @@
- +
diff --git a/src/app/info/feedback/feedback-form/feedback-form.component.spec.ts b/src/app/info/feedback/feedback-form/feedback-form.component.spec.ts index 0507b7173b..7b7c6e28b6 100644 --- a/src/app/info/feedback/feedback-form/feedback-form.component.spec.ts +++ b/src/app/info/feedback/feedback-form/feedback-form.component.spec.ts @@ -18,7 +18,7 @@ import { Router } from '@angular/router'; import { RouterMock } from '../../../shared/mocks/router.mock'; import { NativeWindowService } from '../../../core/services/window.service'; import { NativeWindowMockFactory } from '../../../shared/mocks/mock-native-window-ref'; -import {DisabledDirective} from '../../../shared/disabled-directive'; +import {BtnDisabledDirective} from '../../../shared/btn-disabled.directive'; describe('FeedbackFormComponent', () => { @@ -39,7 +39,7 @@ describe('FeedbackFormComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot()], - declarations: [FeedbackFormComponent, DisabledDirective], + declarations: [FeedbackFormComponent, BtnDisabledDirective], providers: [ { provide: RouteService, useValue: routeServiceStub }, { provide: UntypedFormBuilder, useValue: new UntypedFormBuilder() }, diff --git a/src/app/item-page/bitstreams/request-a-copy/bitstream-request-a-copy-page.component.html b/src/app/item-page/bitstreams/request-a-copy/bitstream-request-a-copy-page.component.html index feffb1066f..5b4b1bda52 100644 --- a/src/app/item-page/bitstreams/request-a-copy/bitstream-request-a-copy-page.component.html +++ b/src/app/item-page/bitstreams/request-a-copy/bitstream-request-a-copy-page.component.html @@ -79,7 +79,7 @@
diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html index c52d99b439..ab20c3c22b 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html @@ -12,7 +12,7 @@ class="fas fa-undo-alt">
 {{"item.edit.bitstreams.reinstate-button" | translate}} - - - - - diff --git a/src/app/item-page/edit-item-page/item-move/item-move.component.html b/src/app/item-page/edit-item-page/item-move/item-move.component.html index 2df52c6651..e8061ae88b 100644 --- a/src/app/item-page/edit-item-page/item-move/item-move.component.html +++ b/src/app/item-page/edit-item-page/item-move/item-move.component.html @@ -40,7 +40,7 @@ - -
diff --git a/src/app/item-page/edit-item-page/item-operation/item-operation.component.html b/src/app/item-page/edit-item-page/item-operation/item-operation.component.html index 88acec3171..75f0736bbc 100644 --- a/src/app/item-page/edit-item-page/item-operation/item-operation.component.html +++ b/src/app/item-page/edit-item-page/item-operation/item-operation.component.html @@ -5,12 +5,12 @@
- - diff --git a/src/app/item-page/edit-item-page/item-operation/item-operation.component.spec.ts b/src/app/item-page/edit-item-page/item-operation/item-operation.component.spec.ts index 8c2774ad6c..7d7087e02d 100644 --- a/src/app/item-page/edit-item-page/item-operation/item-operation.component.spec.ts +++ b/src/app/item-page/edit-item-page/item-operation/item-operation.component.spec.ts @@ -4,7 +4,7 @@ import { ItemOperationComponent } from './item-operation.component'; import { TranslateModule } from '@ngx-translate/core'; import { By } from '@angular/platform-browser'; import { RouterTestingModule } from '@angular/router/testing'; -import {DisabledDirective} from '../../../shared/disabled-directive'; +import {BtnDisabledDirective} from '../../../shared/btn-disabled.directive'; describe('ItemOperationComponent', () => { let itemOperation: ItemOperation; @@ -15,7 +15,7 @@ describe('ItemOperationComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([])], - declarations: [ItemOperationComponent, DisabledDirective] + declarations: [ItemOperationComponent, BtnDisabledDirective] }).compileComponents(); })); diff --git a/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.html b/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.html index b9a01c6b38..27faee89a7 100644 --- a/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.html +++ b/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.html @@ -1,6 +1,6 @@

{{relationshipMessageKey$ | async | translate}} - diff --git a/src/app/item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.html b/src/app/item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.html index 169a171d3f..8cd86d597b 100644 --- a/src/app/item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.html +++ b/src/app/item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.html @@ -9,12 +9,12 @@

- -
@@ -8,7 +8,7 @@ ngbDropdown *ngIf="(moreThanOne$ | async)">
-
diff --git a/src/app/profile-page/profile-claim-item-modal/profile-claim-item-modal.component.html b/src/app/profile-page/profile-claim-item-modal/profile-claim-item-modal.component.html index a118cd680d..3233aa5555 100644 --- a/src/app/profile-page/profile-claim-item-modal/profile-claim-item-modal.component.html +++ b/src/app/profile-page/profile-claim-item-modal/profile-claim-item-modal.component.html @@ -29,7 +29,7 @@ {{ 'dso-selector.claim.item.not-mine-label' | translate }}
- diff --git a/src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.html b/src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.html index aa2b81f057..d14a9edfec 100644 --- a/src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.html +++ b/src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.html @@ -13,7 +13,7 @@

{{'researcher.profile.not.associated' | translate}}

- -
- - diff --git a/src/app/register-page/create-profile/create-profile.component.html b/src/app/register-page/create-profile/create-profile.component.html index dbdb006785..e5cf6c3e2e 100644 --- a/src/app/register-page/create-profile/create-profile.component.html +++ b/src/app/register-page/create-profile/create-profile.component.html @@ -81,7 +81,7 @@
diff --git a/src/app/request-copy/email-request-copy/email-request-copy.component.html b/src/app/request-copy/email-request-copy/email-request-copy.component.html index 815a9a9691..b2227bfbae 100644 --- a/src/app/request-copy/email-request-copy/email-request-copy.component.html +++ b/src/app/request-copy/email-request-copy/email-request-copy.component.html @@ -13,7 +13,7 @@
@@ -76,7 +76,7 @@
@@ -93,7 +93,7 @@ @@ -103,7 +103,7 @@ diff --git a/src/app/shared/disabled-directive.ts b/src/app/shared/btn-disabled.directive.ts similarity index 96% rename from src/app/shared/disabled-directive.ts rename to src/app/shared/btn-disabled.directive.ts index e5ae820e50..ab37643c02 100644 --- a/src/app/shared/disabled-directive.ts +++ b/src/app/shared/btn-disabled.directive.ts @@ -1,7 +1,7 @@ import { Directive, Input, HostBinding, HostListener } from '@angular/core'; @Directive({ - selector: '[dsDisabled]' + selector: '[dsBtnDisabled]' }) /** @@ -10,7 +10,7 @@ import { Directive, Input, HostBinding, HostListener } from '@angular/core'; * * This directive should always be used instead of the HTML disabled attribute as it is more accessible. */ -export class DisabledDirective { +export class BtnDisabledDirective { @Input() set dsDisabled(value: boolean) { this.isDisabled = !!value; diff --git a/src/app/shared/disabled-directive.spec.ts b/src/app/shared/disabled-directive.spec.ts index 514011cebd..71515c48ff 100644 --- a/src/app/shared/disabled-directive.spec.ts +++ b/src/app/shared/disabled-directive.spec.ts @@ -1,11 +1,11 @@ import { Component, DebugElement } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; -import { DisabledDirective } from './disabled-directive'; +import { BtnDisabledDirective } from './btn-disabled.directive'; @Component({ template: ` - + ` }) class TestComponent { @@ -19,7 +19,7 @@ describe('DisabledDirective', () => { beforeEach(() => { TestBed.configureTestingModule({ - declarations: [TestComponent, DisabledDirective] + declarations: [TestComponent, BtnDisabledDirective] }); fixture = TestBed.createComponent(TestComponent); component = fixture.componentInstance; diff --git a/src/app/shared/ds-select/ds-select.component.html b/src/app/shared/ds-select/ds-select.component.html index de53ef0792..e87b7c5cc6 100644 --- a/src/app/shared/ds-select/ds-select.component.html +++ b/src/app/shared/ds-select/ds-select.component.html @@ -13,7 +13,7 @@ class="btn btn-outline-primary selection" (blur)="close.emit($event)" (click)="close.emit($event)" - [dsDisabled]="disabled" + [dsBtnDisabled]="disabled" ngbDropdownToggle> diff --git a/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.html b/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.html index 747d14cac6..0503281329 100644 --- a/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.html +++ b/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.html @@ -1,7 +1,7 @@
-
    diff --git a/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu-section/dso-edit-menu-section.component.html b/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu-section/dso-edit-menu-section.component.html index 9f796c35ce..0738e2f28a 100644 --- a/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu-section/dso-edit-menu-section.component.html +++ b/src/app/shared/dso-page/dso-edit-menu/dso-edit-menu-section/dso-edit-menu-section.component.html @@ -5,7 +5,7 @@ {{itemModel.text | translate}} - @@ -13,7 +13,7 @@
    - @@ -60,7 +60,7 @@ type="button" ngbTooltip="{{'form.clear-help' | translate}}" placement="top" - [dsDisabled]="model.readOnly" + [dsBtnDisabled]="model.readOnly" (click)="remove()">{{'form.clear' | translate}}
    @@ -69,14 +69,14 @@ type="button" ngbTooltip="{{'form.edit-help' | translate}}" placement="top" - [dsDisabled]="isEditDisabled()" + [dsBtnDisabled]="isEditDisabled()" (click)="switchEditMode()">{{'form.edit' | translate}}
diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts index 2fb6488e93..81db85f863 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts @@ -26,7 +26,7 @@ import { mockDynamicFormLayoutService, mockDynamicFormValidationService } from '../../../../../testing/dynamic-form-mock-services'; -import {DisabledDirective} from '../../../../../disabled-directive'; +import {BtnDisabledDirective} from '../../../../../btn-disabled.directive'; let LOOKUP_TEST_MODEL_CONFIG: DynamicLookupModelConfig = { vocabularyOptions: { @@ -155,7 +155,7 @@ describe('Dynamic Lookup component', () => { TestComponent, AuthorityConfidenceStateDirective, ObjNgFor, - DisabledDirective + BtnDisabledDirective ], // declare the test component providers: [ ChangeDetectorRef, diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.component.html index 92c68fd9b9..6a0e34f671 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.component.html @@ -32,21 +32,21 @@ @@ -73,18 +73,18 @@ {{ ('submission.sections.describe.relationship-lookup.selected' | translate: {size: (selection$ | async)?.length || 0}) }}
-
- +
diff --git a/src/app/shared/form/form.component.html b/src/app/shared/form/form.component.html index 4099cdb915..fca41bc252 100644 --- a/src/app/shared/form/form.component.html +++ b/src/app/shared/form/form.component.html @@ -41,7 +41,7 @@ title="{{'form.discard' | translate}}" attr.aria-label="{{'form.discard' | translate}}" (click)="removeItem($event, context, index)" - [dsDisabled]="group.context.groups.length === 1 || isItemReadOnly(context, index)"> + [dsBtnDisabled]="group.context.groups.length === 1 || isItemReadOnly(context, index)"> {{'form.discard' | translate}}
@@ -62,7 +62,7 @@ diff --git a/src/app/shared/form/number-picker/number-picker.component.html b/src/app/shared/form/number-picker/number-picker.component.html index 8f2a875685..9b9d038e86 100644 --- a/src/app/shared/form/number-picker/number-picker.component.html +++ b/src/app/shared/form/number-picker/number-picker.component.html @@ -3,7 +3,7 @@ class="btn btn-link-focus" type="button" tabindex="0" - [dsDisabled]="disabled" + [dsBtnDisabled]="disabled" (click)="toggleUp()"> {{'form.number-picker.increment' | translate: {field: name} }} @@ -30,7 +30,7 @@ class="btn btn-link-focus" type="button" tabindex="0" - [dsDisabled]="disabled" + [dsBtnDisabled]="disabled" (click)="toggleDown()"> {{'form.number-picker.decrement' | translate: {field: name} }} diff --git a/src/app/shared/form/number-picker/number-picker.component.spec.ts b/src/app/shared/form/number-picker/number-picker.component.spec.ts index 5857d9e4a5..b6d623d70b 100644 --- a/src/app/shared/form/number-picker/number-picker.component.spec.ts +++ b/src/app/shared/form/number-picker/number-picker.component.spec.ts @@ -44,7 +44,7 @@ describe('NumberPickerComponent test suite', () => { beforeEach(() => { html = `
- -
@@ -45,7 +45,7 @@
+ [dsBtnDisabled]="!form.valid"> {{"login.form.submit" | translate}}
diff --git a/src/app/shared/mydspace-actions/claimed-task/approve/claimed-task-actions-approve.component.html b/src/app/shared/mydspace-actions/claimed-task/approve/claimed-task-actions-approve.component.html index e4f52cf361..9785715ee8 100644 --- a/src/app/shared/mydspace-actions/claimed-task/approve/claimed-task-actions-approve.component.html +++ b/src/app/shared/mydspace-actions/claimed-task/approve/claimed-task-actions-approve.component.html @@ -1,7 +1,7 @@ diff --git a/src/app/shared/object-select/item-select/item-select.component.html b/src/app/shared/object-select/item-select/item-select.component.html index 58eed6ae4a..d1c2986076 100644 --- a/src/app/shared/object-select/item-select/item-select.component.html +++ b/src/app/shared/object-select/item-select/item-select.component.html @@ -42,7 +42,7 @@ diff --git a/src/app/shared/object-select/item-select/item-select.component.spec.ts b/src/app/shared/object-select/item-select/item-select.component.spec.ts index 7d2e5c4146..9fb9a0260a 100644 --- a/src/app/shared/object-select/item-select/item-select.component.spec.ts +++ b/src/app/shared/object-select/item-select/item-select.component.spec.ts @@ -24,7 +24,7 @@ import { LinkHeadService } from '../../../core/services/link-head.service'; import { GroupDataService } from '../../../core/eperson/group-data.service'; import { SearchConfigurationServiceStub } from '../../testing/search-configuration-service.stub'; import { ConfigurationProperty } from '../../../core/shared/configuration-property.model'; -import {DisabledDirective} from '../../disabled-directive'; +import {BtnDisabledDirective} from '../../btn-disabled.directive'; describe('ItemSelectComponent', () => { let comp: ItemSelectComponent; @@ -99,7 +99,7 @@ describe('ItemSelectComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), SharedModule, RouterTestingModule.withRoutes([])], - declarations: [DisabledDirective], + declarations: [BtnDisabledDirective], providers: [ { provide: ObjectSelectService, useValue: new ObjectSelectServiceStub([mockItemList[1].id]) }, { provide: HostWindowService, useValue: new HostWindowServiceStub(0) }, diff --git a/src/app/shared/pagination/pagination.component.html b/src/app/shared/pagination/pagination.component.html index b85dcb01ee..f7f2c64e2c 100644 --- a/src/app/shared/pagination/pagination.component.html +++ b/src/app/shared/pagination/pagination.component.html @@ -55,12 +55,12 @@
-
diff --git a/src/app/submission/form/collection/submission-form-collection.component.html b/src/app/submission/form/collection/submission-form-collection.component.html index 7f50e5a341..fe9527c266 100644 --- a/src/app/submission/form/collection/submission-form-collection.component.html +++ b/src/app/submission/form/collection/submission-form-collection.component.html @@ -25,7 +25,7 @@ class="btn btn-outline-primary" (blur)="onClose()" (click)="onClose()" - [dsDisabled]="(processingChange$ | async) || collectionModifiable == false || isReadonly" + [dsBtnDisabled]="(processingChange$ | async) || collectionModifiable == false || isReadonly" ngbDropdownToggle> {{ selectedCollectionName$ | async }} diff --git a/src/app/submission/form/collection/submission-form-collection.component.spec.ts b/src/app/submission/form/collection/submission-form-collection.component.spec.ts index 4cb40e2293..467f164f89 100644 --- a/src/app/submission/form/collection/submission-form-collection.component.spec.ts +++ b/src/app/submission/form/collection/submission-form-collection.component.spec.ts @@ -25,7 +25,7 @@ import { Collection } from '../../../core/shared/collection.model'; import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; import { DSONameService } from '../../../core/breadcrumbs/dso-name.service'; import { DSONameServiceMock } from '../../../shared/mocks/dso-name.service.mock'; -import {DisabledDirective} from '../../../shared/disabled-directive'; +import {BtnDisabledDirective} from '../../../shared/btn-disabled.directive'; describe('SubmissionFormCollectionComponent Component', () => { @@ -137,7 +137,7 @@ describe('SubmissionFormCollectionComponent Component', () => { declarations: [ SubmissionFormCollectionComponent, TestComponent, - DisabledDirective + BtnDisabledDirective ], providers: [ { provide: DSONameService, useValue: new DSONameServiceMock() }, diff --git a/src/app/submission/form/footer/submission-form-footer.component.html b/src/app/submission/form/footer/submission-form-footer.component.html index f7e8bae792..457a56cc76 100644 --- a/src/app/submission/form/footer/submission-form-footer.component.html +++ b/src/app/submission/form/footer/submission-form-footer.component.html @@ -5,7 +5,7 @@ id="discard" [attr.data-test]="'discard' | dsBrowserOnly" class="btn btn-danger" - [dsDisabled]="(processingSaveStatus | async) || (processingDepositStatus | async)" + [dsBtnDisabled]="(processingSaveStatus | async) || (processingDepositStatus | async)" (click)="$event.preventDefault();confirmDiscard(content)"> {{'submission.general.discard.submit' | translate}} @@ -28,7 +28,7 @@ class="btn btn-secondary" id="save" [attr.data-test]="'save' | dsBrowserOnly" - [dsDisabled]="(processingSaveStatus | async) || !(hasUnsavedModification | async)" + [dsBtnDisabled]="(processingSaveStatus | async) || !(hasUnsavedModification | async)" (click)="save($event)"> {{'submission.general.save' | translate}} @@ -38,7 +38,7 @@ class="btn" id="saveForLater" [attr.data-test]="'save-for-later' | dsBrowserOnly" - [dsDisabled]="(processingSaveStatus | async) || (processingDepositStatus | async)" + [dsBtnDisabled]="(processingSaveStatus | async) || (processingDepositStatus | async)" (click)="saveLater($event)"> {{'submission.general.save-later' | translate}} @@ -47,7 +47,7 @@ id="deposit" [attr.data-test]="'deposit' | dsBrowserOnly" class="btn btn-success" - [dsDisabled]="(processingSaveStatus | async) || (processingDepositStatus | async)" + [dsBtnDisabled]="(processingSaveStatus | async) || (processingDepositStatus | async)" (click)="deposit($event)"> {{'submission.general.deposit' | translate}} diff --git a/src/app/submission/form/footer/submission-form-footer.component.spec.ts b/src/app/submission/form/footer/submission-form-footer.component.spec.ts index 9071805514..658926834c 100644 --- a/src/app/submission/form/footer/submission-form-footer.component.spec.ts +++ b/src/app/submission/form/footer/submission-form-footer.component.spec.ts @@ -16,7 +16,7 @@ import { SubmissionFormFooterComponent } from './submission-form-footer.componen import { SubmissionRestService } from '../../../core/submission/submission-rest.service'; import { createTestComponent } from '../../../shared/testing/utils.test'; import { BrowserOnlyMockPipe } from '../../../shared/testing/browser-only-mock.pipe'; -import {DisabledDirective} from '../../../shared/disabled-directive'; +import {BtnDisabledDirective} from '../../../shared/btn-disabled.directive'; const submissionServiceStub: SubmissionServiceStub = new SubmissionServiceStub(); @@ -40,7 +40,7 @@ describe('SubmissionFormFooterComponent', () => { SubmissionFormFooterComponent, TestComponent, BrowserOnlyMockPipe, - DisabledDirective + BtnDisabledDirective ], providers: [ { provide: SubmissionService, useValue: submissionServiceStub }, diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html index 28fa4695fb..cb8dde18c5 100644 --- a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.html @@ -23,6 +23,6 @@

{{'submission.import-external.source.loading' | translate}}

- +
diff --git a/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.html b/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.html index 1ce811ce66..b529d9aee4 100644 --- a/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.html +++ b/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.html @@ -1,7 +1,7 @@
diff --git a/src/app/submission/sections/upload/file/section-upload-file.component.html b/src/app/submission/sections/upload/file/section-upload-file.component.html index 589e7b6ebf..3567ef5c64 100644 --- a/src/app/submission/sections/upload/file/section-upload-file.component.html +++ b/src/app/submission/sections/upload/file/section-upload-file.component.html @@ -19,7 +19,7 @@ -
From 1209b40ac9370453a53b4d0097999f3a0934a937 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Mon, 16 Sep 2024 16:09:41 +0200 Subject: [PATCH 0434/1286] 117544: fix remaining bug --- src/app/shared/btn-disabled.directive.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/shared/btn-disabled.directive.ts b/src/app/shared/btn-disabled.directive.ts index f73422a9d5..427d1654da 100644 --- a/src/app/shared/btn-disabled.directive.ts +++ b/src/app/shared/btn-disabled.directive.ts @@ -18,7 +18,7 @@ import { */ export class BtnDisabledDirective { - @Input() set dsDisabled(value: boolean) { + @Input() set dsBtnDisabled(value: boolean) { this.isDisabled = !!value; } From d3e87c68fdb6cc797e641d45d2040a94b6302232 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Mon, 16 Sep 2024 16:09:41 +0200 Subject: [PATCH 0435/1286] 117544: fix remaining bug --- src/app/shared/btn-disabled.directive.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/shared/btn-disabled.directive.ts b/src/app/shared/btn-disabled.directive.ts index f73422a9d5..427d1654da 100644 --- a/src/app/shared/btn-disabled.directive.ts +++ b/src/app/shared/btn-disabled.directive.ts @@ -18,7 +18,7 @@ import { */ export class BtnDisabledDirective { - @Input() set dsDisabled(value: boolean) { + @Input() set dsBtnDisabled(value: boolean) { this.isDisabled = !!value; } From 4a7ebeea16cdd902f99da11ba2dc9e5ab155620e Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Mon, 16 Sep 2024 16:09:41 +0200 Subject: [PATCH 0436/1286] 117544: fix remaining bug --- src/app/shared/btn-disabled.directive.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/shared/btn-disabled.directive.ts b/src/app/shared/btn-disabled.directive.ts index ab37643c02..512aa87ede 100644 --- a/src/app/shared/btn-disabled.directive.ts +++ b/src/app/shared/btn-disabled.directive.ts @@ -12,7 +12,7 @@ import { Directive, Input, HostBinding, HostListener } from '@angular/core'; */ export class BtnDisabledDirective { - @Input() set dsDisabled(value: boolean) { + @Input() set dsBtnDisabled(value: boolean) { this.isDisabled = !!value; } From c419dd608b8b183c7aa4c9b04485d023d5d0c57d Mon Sep 17 00:00:00 2001 From: nwoodward Date: Mon, 16 Sep 2024 15:07:08 -0500 Subject: [PATCH 0437/1286] updates isbot dependency to newest version --- package-lock.json | 10 +++++----- package.json | 2 +- server.ts | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index f3d6856745..75016e4b85 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52,7 +52,7 @@ "filesize": "^6.1.0", "http-proxy-middleware": "^1.0.5", "http-terminator": "^3.2.0", - "isbot": "^3.6.10", + "isbot": "^5.1.17", "js-cookie": "2.2.1", "js-yaml": "^4.1.0", "json5": "^2.2.3", @@ -14436,11 +14436,11 @@ } }, "node_modules/isbot": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/isbot/-/isbot-3.8.0.tgz", - "integrity": "sha512-vne1mzQUTR+qsMLeCBL9+/tgnDXRyc2pygLGl/WsgA+EZKIiB5Ehu0CiVTHIIk30zhJ24uGz4M5Ppse37aR0Hg==", + "version": "5.1.17", + "resolved": "https://registry.npmjs.org/isbot/-/isbot-5.1.17.tgz", + "integrity": "sha512-/wch8pRKZE+aoVhRX/hYPY1C7dMCeeMyhkQLNLNlYAbGQn9bkvMB8fOUXNnk5I0m4vDYbBJ9ciVtkr9zfBJ7qA==", "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/isexe": { diff --git a/package.json b/package.json index d85644ad23..9fdc97ff63 100644 --- a/package.json +++ b/package.json @@ -139,7 +139,7 @@ "filesize": "^6.1.0", "http-proxy-middleware": "^1.0.5", "http-terminator": "^3.2.0", - "isbot": "^3.6.10", + "isbot": "^5.1.17", "js-cookie": "2.2.1", "js-yaml": "^4.1.0", "json5": "^2.2.3", diff --git a/server.ts b/server.ts index d0c17166ad..07a05656d8 100644 --- a/server.ts +++ b/server.ts @@ -27,7 +27,7 @@ import * as expressStaticGzip from 'express-static-gzip'; /* eslint-enable import/no-namespace */ import axios from 'axios'; import LRU from 'lru-cache'; -import isbot from 'isbot'; +import { isbot } from 'isbot'; import { createCertificate } from 'pem'; import { createServer } from 'https'; import { json } from 'body-parser'; From 7ade45321814218c02e40047318703c1799b2471 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Wed, 18 Sep 2024 09:46:38 +0200 Subject: [PATCH 0438/1286] lint rule with autofix to disallow the disabled input on button elements --- .eslintrc.json | 3 +- lint/src/rules/html/index.ts | 3 + lint/src/rules/html/no-disabled-attr.ts | 144 ++++++++++++++++++++++++ 3 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 lint/src/rules/html/no-disabled-attr.ts diff --git a/.eslintrc.json b/.eslintrc.json index 5fb4c12171..a9e44c5937 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -293,7 +293,8 @@ ], "rules": { // Custom DSpace Angular rules - "dspace-angular-html/themed-component-usages": "error" + "dspace-angular-html/themed-component-usages": "error", + "dspace-angular-html/no-disabled-attr": "error" } }, { diff --git a/lint/src/rules/html/index.ts b/lint/src/rules/html/index.ts index 7c1370ae2d..120751d65a 100644 --- a/lint/src/rules/html/index.ts +++ b/lint/src/rules/html/index.ts @@ -10,10 +10,13 @@ import { bundle, RuleExports, } from '../../util/structure'; +import * as noDisabledAttr from './no-disabled-attr'; import * as themedComponentUsages from './themed-component-usages'; const index = [ themedComponentUsages, + noDisabledAttr, + ] as unknown as RuleExports[]; export = { diff --git a/lint/src/rules/html/no-disabled-attr.ts b/lint/src/rules/html/no-disabled-attr.ts new file mode 100644 index 0000000000..22f987d52b --- /dev/null +++ b/lint/src/rules/html/no-disabled-attr.ts @@ -0,0 +1,144 @@ +import { + TmplAstBoundAttribute, + TmplAstTextAttribute +} from '@angular-eslint/bundled-angular-compiler'; +import { TemplateParserServices } from '@angular-eslint/utils'; +import { + ESLintUtils, + TSESLint, +} from '@typescript-eslint/utils'; +import { + DSpaceESLintRuleInfo, + NamedTests, +} from '../../util/structure'; +import { getSourceCode } from '../../util/typescript'; + +export enum Message { + USE_DSBTN_DISABLED = 'mustUseDsBtnDisabled', +} + +export const info = { + name: 'no-disabled-attr', + meta: { + docs: { + description: `Buttons should use the \`dsBtnDisabled\` directive instead of the HTML \`disabled\` attribute for accessibility reasons.`, + }, + type: 'problem', + fixable: 'code', + schema: [], + messages: { + [Message.USE_DSBTN_DISABLED]: 'Buttons should use the `dsBtnDisabled` directive instead of the `disabled` attribute.', + }, + }, + defaultOptions: [], +} as DSpaceESLintRuleInfo; + +export const rule = ESLintUtils.RuleCreator.withoutDocs({ + ...info, + create(context: TSESLint.RuleContext) { + const parserServices = getSourceCode(context).parserServices as TemplateParserServices; + + /** + * Some dynamic angular inputs will have disabled as name because of how Angular handles this internally (e.g [class.disabled]="isDisabled") + * But these aren't actually the disabled attribute we're looking for, we can determine this by checking the details of the keySpan + */ + function isOtherAttributeDisabled(node: TmplAstBoundAttribute | TmplAstTextAttribute): boolean { + // if the details are not null, and the details are not 'disabled', then it's not the disabled attribute we're looking for + return node.keySpan?.details !== null && node.keySpan?.details !== 'disabled'; + } + + /** + * Replace the disabled text with [dsBtnDisabled] in the template + */ + function replaceDisabledText(text: string ): string { + const hasBrackets = text.includes('[') && text.includes(']'); + const newDisabledText = hasBrackets ? 'dsBtnDisabled' : '[dsBtnDisabled]'; + return text.replace('disabled', newDisabledText); + } + + function inputIsChildOfButton(node: any): boolean { + return (node.parent?.tagName === 'button' || node.parent?.name === 'button'); + } + + function reportAndFix(node: TmplAstBoundAttribute | TmplAstTextAttribute) { + if (!inputIsChildOfButton(node) || isOtherAttributeDisabled(node)) { + return; + } + + const sourceSpan = node.sourceSpan; + context.report({ + messageId: Message.USE_DSBTN_DISABLED, + loc: parserServices.convertNodeSourceSpanToLoc(sourceSpan), + fix(fixer) { + const templateText = sourceSpan.start.file.content; + const disabledText = templateText.slice(sourceSpan.start.offset, sourceSpan.end.offset); + const newText = replaceDisabledText(disabledText); + return fixer.replaceTextRange([sourceSpan.start.offset, sourceSpan.end.offset], newText); + }, + }); + } + + return { + 'BoundAttribute[name="disabled"]'(node: TmplAstBoundAttribute) { + reportAndFix(node); + }, + 'TextAttribute[name="disabled"]'(node: TmplAstTextAttribute) { + reportAndFix(node); + }, + }; + }, +}); + +export const tests = { + plugin: info.name, + valid: [ + { + name: 'should use [dsBtnDisabled] in HTML templates', + code: ` + + `, + }, + { + name: 'disabled attribute is still valid on non-button elements', + code: ` + + `, + }, + { + name: '[disabled] attribute is still valid on non-button elements', + code: ` + + `, + }, + { + name: 'angular dynamic attributes that use disabled are still valid', + code: ` + + `, + }, + ], + invalid: [ + { + name: 'should not use disabled attribute in HTML templates', + code: ` + + `, + errors: [{ messageId: Message.USE_DSBTN_DISABLED }], + output: ` + + `, + }, + { + name: 'should not use [disabled] attribute in HTML templates', + code: ` + + `, + errors: [{ messageId: Message.USE_DSBTN_DISABLED }], + output: ` + + `, + }, + ], +} as NamedTests; + +export default rule; From c249afdb3f0d50facec699606b5e4ccbd4ccd716 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Wed, 18 Sep 2024 09:46:38 +0200 Subject: [PATCH 0439/1286] lint rule with autofix to disallow the disabled input on button elements --- .eslintrc.json | 3 +- lint/src/rules/html/index.ts | 3 + lint/src/rules/html/no-disabled-attr.ts | 144 ++++++++++++++++++++++++ 3 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 lint/src/rules/html/no-disabled-attr.ts diff --git a/.eslintrc.json b/.eslintrc.json index 5fb4c12171..a9e44c5937 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -293,7 +293,8 @@ ], "rules": { // Custom DSpace Angular rules - "dspace-angular-html/themed-component-usages": "error" + "dspace-angular-html/themed-component-usages": "error", + "dspace-angular-html/no-disabled-attr": "error" } }, { diff --git a/lint/src/rules/html/index.ts b/lint/src/rules/html/index.ts index 7c1370ae2d..120751d65a 100644 --- a/lint/src/rules/html/index.ts +++ b/lint/src/rules/html/index.ts @@ -10,10 +10,13 @@ import { bundle, RuleExports, } from '../../util/structure'; +import * as noDisabledAttr from './no-disabled-attr'; import * as themedComponentUsages from './themed-component-usages'; const index = [ themedComponentUsages, + noDisabledAttr, + ] as unknown as RuleExports[]; export = { diff --git a/lint/src/rules/html/no-disabled-attr.ts b/lint/src/rules/html/no-disabled-attr.ts new file mode 100644 index 0000000000..22f987d52b --- /dev/null +++ b/lint/src/rules/html/no-disabled-attr.ts @@ -0,0 +1,144 @@ +import { + TmplAstBoundAttribute, + TmplAstTextAttribute +} from '@angular-eslint/bundled-angular-compiler'; +import { TemplateParserServices } from '@angular-eslint/utils'; +import { + ESLintUtils, + TSESLint, +} from '@typescript-eslint/utils'; +import { + DSpaceESLintRuleInfo, + NamedTests, +} from '../../util/structure'; +import { getSourceCode } from '../../util/typescript'; + +export enum Message { + USE_DSBTN_DISABLED = 'mustUseDsBtnDisabled', +} + +export const info = { + name: 'no-disabled-attr', + meta: { + docs: { + description: `Buttons should use the \`dsBtnDisabled\` directive instead of the HTML \`disabled\` attribute for accessibility reasons.`, + }, + type: 'problem', + fixable: 'code', + schema: [], + messages: { + [Message.USE_DSBTN_DISABLED]: 'Buttons should use the `dsBtnDisabled` directive instead of the `disabled` attribute.', + }, + }, + defaultOptions: [], +} as DSpaceESLintRuleInfo; + +export const rule = ESLintUtils.RuleCreator.withoutDocs({ + ...info, + create(context: TSESLint.RuleContext) { + const parserServices = getSourceCode(context).parserServices as TemplateParserServices; + + /** + * Some dynamic angular inputs will have disabled as name because of how Angular handles this internally (e.g [class.disabled]="isDisabled") + * But these aren't actually the disabled attribute we're looking for, we can determine this by checking the details of the keySpan + */ + function isOtherAttributeDisabled(node: TmplAstBoundAttribute | TmplAstTextAttribute): boolean { + // if the details are not null, and the details are not 'disabled', then it's not the disabled attribute we're looking for + return node.keySpan?.details !== null && node.keySpan?.details !== 'disabled'; + } + + /** + * Replace the disabled text with [dsBtnDisabled] in the template + */ + function replaceDisabledText(text: string ): string { + const hasBrackets = text.includes('[') && text.includes(']'); + const newDisabledText = hasBrackets ? 'dsBtnDisabled' : '[dsBtnDisabled]'; + return text.replace('disabled', newDisabledText); + } + + function inputIsChildOfButton(node: any): boolean { + return (node.parent?.tagName === 'button' || node.parent?.name === 'button'); + } + + function reportAndFix(node: TmplAstBoundAttribute | TmplAstTextAttribute) { + if (!inputIsChildOfButton(node) || isOtherAttributeDisabled(node)) { + return; + } + + const sourceSpan = node.sourceSpan; + context.report({ + messageId: Message.USE_DSBTN_DISABLED, + loc: parserServices.convertNodeSourceSpanToLoc(sourceSpan), + fix(fixer) { + const templateText = sourceSpan.start.file.content; + const disabledText = templateText.slice(sourceSpan.start.offset, sourceSpan.end.offset); + const newText = replaceDisabledText(disabledText); + return fixer.replaceTextRange([sourceSpan.start.offset, sourceSpan.end.offset], newText); + }, + }); + } + + return { + 'BoundAttribute[name="disabled"]'(node: TmplAstBoundAttribute) { + reportAndFix(node); + }, + 'TextAttribute[name="disabled"]'(node: TmplAstTextAttribute) { + reportAndFix(node); + }, + }; + }, +}); + +export const tests = { + plugin: info.name, + valid: [ + { + name: 'should use [dsBtnDisabled] in HTML templates', + code: ` + + `, + }, + { + name: 'disabled attribute is still valid on non-button elements', + code: ` + + `, + }, + { + name: '[disabled] attribute is still valid on non-button elements', + code: ` + + `, + }, + { + name: 'angular dynamic attributes that use disabled are still valid', + code: ` + + `, + }, + ], + invalid: [ + { + name: 'should not use disabled attribute in HTML templates', + code: ` + + `, + errors: [{ messageId: Message.USE_DSBTN_DISABLED }], + output: ` + + `, + }, + { + name: 'should not use [disabled] attribute in HTML templates', + code: ` + + `, + errors: [{ messageId: Message.USE_DSBTN_DISABLED }], + output: ` + + `, + }, + ], +} as NamedTests; + +export default rule; From e2dc89c737abbea43ed195f7f7d31b3844c077ff Mon Sep 17 00:00:00 2001 From: Andrea Barbasso <´andrea.barbasso@4science.com´> Date: Fri, 20 Sep 2024 10:26:46 +0200 Subject: [PATCH 0440/1286] [CST-15595] fix tests --- src/app/shared/cookies/browser-orejime.service.spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/shared/cookies/browser-orejime.service.spec.ts b/src/app/shared/cookies/browser-orejime.service.spec.ts index d0fe608c3f..a281805238 100644 --- a/src/app/shared/cookies/browser-orejime.service.spec.ts +++ b/src/app/shared/cookies/browser-orejime.service.spec.ts @@ -126,6 +126,7 @@ describe('BrowserOrejimeService', () => { }; service.orejimeConfig = mockConfig; + service.createCategories(); }); it('should be created', () => { From 83a44ba924fb20065f0bb62fc2a09a7aaec391bc Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Mon, 16 Sep 2024 15:46:07 +0200 Subject: [PATCH 0441/1286] 118220: Add live-region service and component --- config/config.example.yml | 16 ++- .../live-region/live-region.component.html | 3 + .../live-region/live-region.component.scss | 13 ++ .../live-region/live-region.component.ts | 25 ++++ .../shared/live-region/live-region.config.ts | 9 ++ .../shared/live-region/live-region.service.ts | 118 ++++++++++++++++++ src/app/shared/shared.module.ts | 4 +- src/config/app-config.interface.ts | 2 + src/config/default-app-config.ts | 7 ++ src/environments/environment.test.ts | 7 +- src/styles/_custom_variables.scss | 1 + 11 files changed, 202 insertions(+), 3 deletions(-) create mode 100644 src/app/shared/live-region/live-region.component.html create mode 100644 src/app/shared/live-region/live-region.component.scss create mode 100644 src/app/shared/live-region/live-region.component.ts create mode 100644 src/app/shared/live-region/live-region.config.ts create mode 100644 src/app/shared/live-region/live-region.service.ts diff --git a/config/config.example.yml b/config/config.example.yml index ea38303fa3..58eb6ff33d 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -379,4 +379,18 @@ vocabularies: # Default collection/community sorting order at Advanced search, Create/update community and collection when there are not a query. comcolSelectionSort: sortField: 'dc.title' - sortDirection: 'ASC' \ No newline at end of file + sortDirection: 'ASC' + +# Live Region configuration +# Live Region as defined by w3c, https://www.w3.org/TR/wai-aria-1.1/#terms: +# Live regions are perceivable regions of a web page that are typically updated as a +# result of an external event when user focus may be elsewhere. +# +# The DSpace live region is a component present at the bottom of all pages that is invisible by default, but is useful +# for screen readers. Any message pushed to the live region will be announced by the screen reader. These messages +# usually contain information about changes on the page that might not be in focus. +liveRegion: + # The duration after which messages disappear from the live region in milliseconds + messageTimeOutDurationMs: 30000 + # The visibility of the live region. Setting this to true is only useful for debugging purposes. + isVisible: false diff --git a/src/app/shared/live-region/live-region.component.html b/src/app/shared/live-region/live-region.component.html new file mode 100644 index 0000000000..a48f3ad52e --- /dev/null +++ b/src/app/shared/live-region/live-region.component.html @@ -0,0 +1,3 @@ +
+
{{ message }}
+
diff --git a/src/app/shared/live-region/live-region.component.scss b/src/app/shared/live-region/live-region.component.scss new file mode 100644 index 0000000000..69844a93e1 --- /dev/null +++ b/src/app/shared/live-region/live-region.component.scss @@ -0,0 +1,13 @@ +.live-region { + position: fixed; + bottom: 0; + left: 0; + right: 0; + padding-left: 60px; + height: 90px; + line-height: 18px; + color: var(--bs-white); + background-color: var(--bs-dark); + opacity: 0.94; + z-index: var(--ds-live-region-z-index); +} diff --git a/src/app/shared/live-region/live-region.component.ts b/src/app/shared/live-region/live-region.component.ts new file mode 100644 index 0000000000..d7bd5eb806 --- /dev/null +++ b/src/app/shared/live-region/live-region.component.ts @@ -0,0 +1,25 @@ +import { Component, OnInit } from '@angular/core'; +import { LiveRegionService } from './live-region.service'; +import { Observable } from 'rxjs'; + +@Component({ + selector: `ds-live-region`, + templateUrl: './live-region.component.html', + styleUrls: ['./live-region.component.scss'], +}) +export class LiveRegionComponent implements OnInit { + + protected isVisible: boolean; + + protected messages$: Observable; + + constructor( + protected liveRegionService: LiveRegionService, + ) { + } + + ngOnInit() { + this.isVisible = this.liveRegionService.getLiveRegionVisibility(); + this.messages$ = this.liveRegionService.getMessages$(); + } +} diff --git a/src/app/shared/live-region/live-region.config.ts b/src/app/shared/live-region/live-region.config.ts new file mode 100644 index 0000000000..e545bfd254 --- /dev/null +++ b/src/app/shared/live-region/live-region.config.ts @@ -0,0 +1,9 @@ +import { Config } from '../../../config/config.interface'; + +/** + * Configuration interface used by the LiveRegionService + */ +export class LiveRegionConfig implements Config { + messageTimeOutDurationMs: number; + isVisible: boolean; +} diff --git a/src/app/shared/live-region/live-region.service.ts b/src/app/shared/live-region/live-region.service.ts new file mode 100644 index 0000000000..482d1ca1bb --- /dev/null +++ b/src/app/shared/live-region/live-region.service.ts @@ -0,0 +1,118 @@ +import { Injectable } from '@angular/core'; +import { BehaviorSubject } from 'rxjs'; +import { environment } from '../../../environments/environment'; + +@Injectable({ + providedIn: 'root', +}) +export class LiveRegionService { + + /** + * The duration after which the messages disappear in milliseconds + * @protected + */ + protected messageTimeOutDurationMs: number = environment.liveRegion.messageTimeOutDurationMs; + + /** + * Array containing the messages that should be shown in the live region + * @protected + */ + protected messages: string[] = []; + + /** + * BehaviorSubject emitting the array with messages every time the array updates + * @protected + */ + protected messages$: BehaviorSubject = new BehaviorSubject([]); + + /** + * Whether the live region should be visible + * @protected + */ + protected liveRegionIsVisible: boolean = environment.liveRegion.isVisible; + + /** + * Returns a copy of the array with the current live region messages + */ + getMessages() { + return [...this.messages]; + } + + /** + * Returns the BehaviorSubject emitting the array with messages every time the array updates + */ + getMessages$() { + return this.messages$; + } + + /** + * Adds a message to the live-region messages array + * @param message + */ + addMessage(message: string) { + this.messages.push(message); + this.emitCurrentMessages(); + + // Clear the message once the timeOut has passed + setTimeout(() => this.pop(), this.messageTimeOutDurationMs); + } + + /** + * Clears the live-region messages array + */ + clear() { + this.messages = []; + this.emitCurrentMessages(); + } + + /** + * Removes the longest living message from the array. + * @protected + */ + protected pop() { + if (this.messages.length > 0) { + this.messages.shift(); + this.emitCurrentMessages(); + } + } + + /** + * Makes the messages$ BehaviorSubject emit the current messages array + * @protected + */ + protected emitCurrentMessages() { + this.messages$.next(this.getMessages()); + } + + /** + * Returns a boolean specifying whether the live region should be visible. + * Returns 'true' if the region should be visible and false otherwise. + */ + getLiveRegionVisibility(): boolean { + return this.liveRegionIsVisible; + } + + /** + * Sets the visibility of the live region. + * Setting this to true will make the live region visible which is useful for debugging purposes. + * @param isVisible + */ + setLiveRegionVisibility(isVisible: boolean) { + this.liveRegionIsVisible = isVisible; + } + + /** + * Gets the current message timeOut duration in milliseconds + */ + getMessageTimeOutMs(): number { + return this.messageTimeOutDurationMs; + } + + /** + * Sets the message timeOut duration + * @param timeOutMs the message timeOut duration in milliseconds + */ + setMessageTimeOutMs(timeOutMs: number) { + this.messageTimeOutDurationMs = timeOutMs; + } +} diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 0f7871f7f9..db5b778722 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -284,6 +284,7 @@ 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 { LiveRegionComponent } from './live-region/live-region.component'; const MODULES = [ CommonModule, @@ -465,7 +466,8 @@ const ENTRY_COMPONENTS = [ AdvancedClaimedTaskActionRatingComponent, EpersonGroupListComponent, EpersonSearchBoxComponent, - GroupSearchBoxComponent + GroupSearchBoxComponent, + LiveRegionComponent, ]; const PROVIDERS = [ diff --git a/src/config/app-config.interface.ts b/src/config/app-config.interface.ts index 84a30549a7..aa3033ecec 100644 --- a/src/config/app-config.interface.ts +++ b/src/config/app-config.interface.ts @@ -22,6 +22,7 @@ import { HomeConfig } from './homepage-config.interface'; import { MarkdownConfig } from './markdown-config.interface'; import { FilterVocabularyConfig } from './filter-vocabulary-config'; import { DiscoverySortConfig } from './discovery-sort.config'; +import { LiveRegionConfig } from '../app/shared/live-region/live-region.config'; interface AppConfig extends Config { ui: UIServerConfig; @@ -48,6 +49,7 @@ interface AppConfig extends Config { markdown: MarkdownConfig; vocabularies: FilterVocabularyConfig[]; comcolSelectionSort: DiscoverySortConfig; + liveRegion: LiveRegionConfig; } /** diff --git a/src/config/default-app-config.ts b/src/config/default-app-config.ts index a6e9e092e4..1c0f88cf47 100644 --- a/src/config/default-app-config.ts +++ b/src/config/default-app-config.ts @@ -22,6 +22,7 @@ import { HomeConfig } from './homepage-config.interface'; import { MarkdownConfig } from './markdown-config.interface'; import { FilterVocabularyConfig } from './filter-vocabulary-config'; import { DiscoverySortConfig } from './discovery-sort.config'; +import { LiveRegionConfig } from '../app/shared/live-region/live-region.config'; export class DefaultAppConfig implements AppConfig { production = false; @@ -432,4 +433,10 @@ export class DefaultAppConfig implements AppConfig { sortField:'dc.title', sortDirection:'ASC', }; + + // Live Region configuration, used by the LiveRegionService + liveRegion: LiveRegionConfig = { + messageTimeOutDurationMs: 30000, + isVisible: false, + }; } diff --git a/src/environments/environment.test.ts b/src/environments/environment.test.ts index cb9d2c7130..498799a454 100644 --- a/src/environments/environment.test.ts +++ b/src/environments/environment.test.ts @@ -313,5 +313,10 @@ export const environment: BuildConfig = { vocabulary: 'srsc', enabled: true } - ] + ], + + liveRegion: { + messageTimeOutDurationMs: 30000, + isVisible: false, + }, }; diff --git a/src/styles/_custom_variables.scss b/src/styles/_custom_variables.scss index ddf490c7a7..09267d15ae 100644 --- a/src/styles/_custom_variables.scss +++ b/src/styles/_custom_variables.scss @@ -13,6 +13,7 @@ --ds-login-logo-width:72px; --ds-submission-header-z-index: 1001; --ds-submission-footer-z-index: 999; + --ds-live-region-z-index: 1030; --ds-main-z-index: 1; --ds-nav-z-index: 10; From e987c35450f2a03e73fe5a9951ec412fb9675e33 Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Tue, 17 Sep 2024 09:07:02 +0200 Subject: [PATCH 0442/1286] 118220: Add liveRegionComponent & Service tests --- .../live-region/live-region.component.spec.ts | 57 +++++++ .../live-region/live-region.service.spec.ts | 140 ++++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 src/app/shared/live-region/live-region.component.spec.ts create mode 100644 src/app/shared/live-region/live-region.service.spec.ts diff --git a/src/app/shared/live-region/live-region.component.spec.ts b/src/app/shared/live-region/live-region.component.spec.ts new file mode 100644 index 0000000000..2e9797f9c3 --- /dev/null +++ b/src/app/shared/live-region/live-region.component.spec.ts @@ -0,0 +1,57 @@ +import { LiveRegionComponent } from './live-region.component'; +import { ComponentFixture, waitForAsync, TestBed } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { LiveRegionService } from './live-region.service'; +import { of } from 'rxjs'; +import { By } from '@angular/platform-browser'; + +describe('liveRegionComponent', () => { + let fixture: ComponentFixture; + let liveRegionService: LiveRegionService; + + beforeEach(waitForAsync(() => { + liveRegionService = jasmine.createSpyObj('liveRegionService', { + getMessages$: of(['message1', 'message2']), + getLiveRegionVisibility: false, + setLiveRegionVisibility: undefined, + }); + + void TestBed.configureTestingModule({ + imports: [ + TranslateModule.forRoot(), + ], + declarations: [LiveRegionComponent], + providers: [ + { provide: LiveRegionService, useValue: liveRegionService }, + ], + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(LiveRegionComponent); + fixture.detectChanges(); + }); + + it('should contain the current live region messages', () => { + const messages = fixture.debugElement.queryAll(By.css('.live-region-message')); + + expect(messages.length).toEqual(2); + expect(messages[0].nativeElement.textContent).toEqual('message1'); + expect(messages[1].nativeElement.textContent).toEqual('message2'); + }); + + it('should respect the live region visibility', () => { + const liveRegion = fixture.debugElement.query(By.css('.live-region')); + expect(liveRegion).toBeDefined(); + + const liveRegionHidden = fixture.debugElement.query(By.css('.visually-hidden')); + expect(liveRegionHidden).toBeDefined(); + + liveRegionService.getLiveRegionVisibility = jasmine.createSpy('getLiveRegionVisibility').and.returnValue(true); + fixture = TestBed.createComponent(LiveRegionComponent); + fixture.detectChanges(); + + const liveRegionVisible = fixture.debugElement.query(By.css('.visually-hidden')); + expect(liveRegionVisible).toBeNull(); + }); +}); diff --git a/src/app/shared/live-region/live-region.service.spec.ts b/src/app/shared/live-region/live-region.service.spec.ts new file mode 100644 index 0000000000..fe5e8b8d8c --- /dev/null +++ b/src/app/shared/live-region/live-region.service.spec.ts @@ -0,0 +1,140 @@ +import { LiveRegionService } from './live-region.service'; +import { fakeAsync, tick, flush } from '@angular/core/testing'; + +describe('liveRegionService', () => { + let service: LiveRegionService; + + + beforeEach(() => { + service = new LiveRegionService(); + }); + + describe('addMessage', () => { + it('should correctly add messages', () => { + expect(service.getMessages().length).toEqual(0); + + service.addMessage('Message One'); + expect(service.getMessages().length).toEqual(1); + expect(service.getMessages()[0]).toEqual('Message One'); + + service.addMessage('Message Two'); + expect(service.getMessages().length).toEqual(2); + expect(service.getMessages()[1]).toEqual('Message Two'); + }); + }); + + describe('clearMessages', () => { + it('should clear the messages', () => { + expect(service.getMessages().length).toEqual(0); + + service.addMessage('Message One'); + service.addMessage('Message Two'); + expect(service.getMessages().length).toEqual(2); + + service.clear(); + expect(service.getMessages().length).toEqual(0); + }); + }); + + describe('messages$', () => { + it('should emit when a message is added and when a message is removed after the timeOut', fakeAsync(() => { + const results: string[][] = []; + + service.getMessages$().subscribe((messages) => { + results.push(messages); + }); + + expect(results.length).toEqual(1); + expect(results[0]).toEqual([]); + + service.addMessage('message'); + + tick(); + + expect(results.length).toEqual(2); + expect(results[1]).toEqual(['message']); + + tick(service.getMessageTimeOutMs()); + + expect(results.length).toEqual(3); + expect(results[2]).toEqual([]); + })); + + it('should only emit once when the messages are cleared', fakeAsync(() => { + const results: string[][] = []; + + service.getMessages$().subscribe((messages) => { + results.push(messages); + }); + + expect(results.length).toEqual(1); + expect(results[0]).toEqual([]); + + service.addMessage('Message One'); + service.addMessage('Message Two'); + + tick(); + + expect(results.length).toEqual(3); + expect(results[2]).toEqual(['Message One', 'Message Two']); + + service.clear(); + flush(); + + expect(results.length).toEqual(4); + expect(results[3]).toEqual([]); + })); + + it('should respect configured timeOut', fakeAsync(() => { + const results: string[][] = []; + + service.getMessages$().subscribe((messages) => { + results.push(messages); + }); + + expect(results.length).toEqual(1); + expect(results[0]).toEqual([]); + + const timeOutMs = 500; + service.setMessageTimeOutMs(timeOutMs); + + service.addMessage('Message One'); + tick(timeOutMs - 1); + + expect(results.length).toEqual(2); + expect(results[1]).toEqual(['Message One']); + + tick(1); + + expect(results.length).toEqual(3); + expect(results[2]).toEqual([]); + + const timeOutMsTwo = 50000; + service.setMessageTimeOutMs(timeOutMsTwo); + + service.addMessage('Message Two'); + tick(timeOutMsTwo - 1); + + expect(results.length).toEqual(4); + expect(results[3]).toEqual(['Message Two']); + + tick(1); + + expect(results.length).toEqual(5); + expect(results[4]).toEqual([]); + })); + }); + + describe('liveRegionVisibility', () => { + it('should be false by default', () => { + expect(service.getLiveRegionVisibility()).toBeFalse(); + }); + + it('should correctly update', () => { + service.setLiveRegionVisibility(true); + expect(service.getLiveRegionVisibility()).toBeTrue(); + service.setLiveRegionVisibility(false); + expect(service.getLiveRegionVisibility()).toBeFalse(); + }); + }); +}); From 35d29c84258e1656ed17c53e6e7054c69b7878d1 Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Fri, 20 Sep 2024 09:38:31 +0200 Subject: [PATCH 0443/1286] 118220: Add LiveRegion to RootComponent --- src/app/root/root.component.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/app/root/root.component.html b/src/app/root/root.component.html index bf49e507c0..d59bea1db4 100644 --- a/src/app/root/root.component.html +++ b/src/app/root/root.component.html @@ -27,3 +27,5 @@
+ + From 2380d4e751563181b341c5a225bae5a9be40d7e3 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Fri, 20 Sep 2024 16:45:05 +0200 Subject: [PATCH 0444/1286] fix bug in lint rule, add docs for rule and update name so it's clear this is only for buttons currently --- .eslintrc.json | 2 +- docs/lint/html/index.md | 1 + lint/src/rules/html/index.ts | 4 ++-- ...attr.ts => no-disabled-attribute-on-button.ts} | 15 +++++++++------ 4 files changed, 13 insertions(+), 9 deletions(-) rename lint/src/rules/html/{no-disabled-attr.ts => no-disabled-attribute-on-button.ts} (89%) diff --git a/.eslintrc.json b/.eslintrc.json index a9e44c5937..888c968b5c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -294,7 +294,7 @@ "rules": { // Custom DSpace Angular rules "dspace-angular-html/themed-component-usages": "error", - "dspace-angular-html/no-disabled-attr": "error" + "dspace-angular-html/no-disabled-attribute-on-button": "error" } }, { diff --git a/docs/lint/html/index.md b/docs/lint/html/index.md index 15d693843c..e134e1070f 100644 --- a/docs/lint/html/index.md +++ b/docs/lint/html/index.md @@ -2,3 +2,4 @@ _______ - [`dspace-angular-html/themed-component-usages`](./rules/themed-component-usages.md): Themeable components should be used via the selector of their `ThemedComponent` wrapper class +- [`dspace-angular-html/no-disabled-attribute-on-button`](./rules/no-disabled-attribute-on-button.md): Buttons should use the `dsBtnDisabled` directive instead of the HTML `disabled` attribute. diff --git a/lint/src/rules/html/index.ts b/lint/src/rules/html/index.ts index 120751d65a..3d425c3ad4 100644 --- a/lint/src/rules/html/index.ts +++ b/lint/src/rules/html/index.ts @@ -10,12 +10,12 @@ import { bundle, RuleExports, } from '../../util/structure'; -import * as noDisabledAttr from './no-disabled-attr'; +import * as noDisabledAttributeOnButton from './no-disabled-attribute-on-button'; import * as themedComponentUsages from './themed-component-usages'; const index = [ themedComponentUsages, - noDisabledAttr, + noDisabledAttributeOnButton, ] as unknown as RuleExports[]; diff --git a/lint/src/rules/html/no-disabled-attr.ts b/lint/src/rules/html/no-disabled-attribute-on-button.ts similarity index 89% rename from lint/src/rules/html/no-disabled-attr.ts rename to lint/src/rules/html/no-disabled-attribute-on-button.ts index 22f987d52b..bf1a72d70d 100644 --- a/lint/src/rules/html/no-disabled-attr.ts +++ b/lint/src/rules/html/no-disabled-attribute-on-button.ts @@ -1,12 +1,13 @@ import { TmplAstBoundAttribute, - TmplAstTextAttribute + TmplAstTextAttribute, } from '@angular-eslint/bundled-angular-compiler'; import { TemplateParserServices } from '@angular-eslint/utils'; import { ESLintUtils, TSESLint, } from '@typescript-eslint/utils'; + import { DSpaceESLintRuleInfo, NamedTests, @@ -18,10 +19,12 @@ export enum Message { } export const info = { - name: 'no-disabled-attr', + name: 'no-disabled-attribute-on-button', meta: { docs: { - description: `Buttons should use the \`dsBtnDisabled\` directive instead of the HTML \`disabled\` attribute for accessibility reasons.`, + description: `Buttons should use the \`dsBtnDisabled\` directive instead of the HTML \`disabled\` attribute. + This should be done to ensure that users with a screen reader are able to understand that the a button button is present, and that it is disabled. + The native html disabled attribute does not allow users to navigate to the button by keyboard, and thus they have no way of knowing that the button is present.`, }, type: 'problem', fixable: 'code', @@ -52,7 +55,7 @@ export const rule = ESLintUtils.RuleCreator.withoutDocs({ */ function replaceDisabledText(text: string ): string { const hasBrackets = text.includes('[') && text.includes(']'); - const newDisabledText = hasBrackets ? 'dsBtnDisabled' : '[dsBtnDisabled]'; + const newDisabledText = hasBrackets ? 'dsBtnDisabled' : '[dsBtnDisabled]="true"'; return text.replace('disabled', newDisabledText); } @@ -101,7 +104,7 @@ export const tests = { { name: 'disabled attribute is still valid on non-button elements', code: ` - + `, }, { @@ -121,7 +124,7 @@ export const tests = { { name: 'should not use disabled attribute in HTML templates', code: ` - + `, errors: [{ messageId: Message.USE_DSBTN_DISABLED }], output: ` From ee83beae94d8ef35838fe00c11359164800a0e51 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Fri, 20 Sep 2024 16:45:05 +0200 Subject: [PATCH 0445/1286] fix bug in lint rule, add docs for rule and update name so it's clear this is only for buttons currently (cherry picked from commit 2380d4e751563181b341c5a225bae5a9be40d7e3) --- .eslintrc.json | 2 +- docs/lint/html/index.md | 1 + lint/src/rules/html/index.ts | 4 ++-- ...attr.ts => no-disabled-attribute-on-button.ts} | 15 +++++++++------ 4 files changed, 13 insertions(+), 9 deletions(-) rename lint/src/rules/html/{no-disabled-attr.ts => no-disabled-attribute-on-button.ts} (89%) diff --git a/.eslintrc.json b/.eslintrc.json index a9e44c5937..888c968b5c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -294,7 +294,7 @@ "rules": { // Custom DSpace Angular rules "dspace-angular-html/themed-component-usages": "error", - "dspace-angular-html/no-disabled-attr": "error" + "dspace-angular-html/no-disabled-attribute-on-button": "error" } }, { diff --git a/docs/lint/html/index.md b/docs/lint/html/index.md index 15d693843c..e134e1070f 100644 --- a/docs/lint/html/index.md +++ b/docs/lint/html/index.md @@ -2,3 +2,4 @@ _______ - [`dspace-angular-html/themed-component-usages`](./rules/themed-component-usages.md): Themeable components should be used via the selector of their `ThemedComponent` wrapper class +- [`dspace-angular-html/no-disabled-attribute-on-button`](./rules/no-disabled-attribute-on-button.md): Buttons should use the `dsBtnDisabled` directive instead of the HTML `disabled` attribute. diff --git a/lint/src/rules/html/index.ts b/lint/src/rules/html/index.ts index 120751d65a..3d425c3ad4 100644 --- a/lint/src/rules/html/index.ts +++ b/lint/src/rules/html/index.ts @@ -10,12 +10,12 @@ import { bundle, RuleExports, } from '../../util/structure'; -import * as noDisabledAttr from './no-disabled-attr'; +import * as noDisabledAttributeOnButton from './no-disabled-attribute-on-button'; import * as themedComponentUsages from './themed-component-usages'; const index = [ themedComponentUsages, - noDisabledAttr, + noDisabledAttributeOnButton, ] as unknown as RuleExports[]; diff --git a/lint/src/rules/html/no-disabled-attr.ts b/lint/src/rules/html/no-disabled-attribute-on-button.ts similarity index 89% rename from lint/src/rules/html/no-disabled-attr.ts rename to lint/src/rules/html/no-disabled-attribute-on-button.ts index 22f987d52b..bf1a72d70d 100644 --- a/lint/src/rules/html/no-disabled-attr.ts +++ b/lint/src/rules/html/no-disabled-attribute-on-button.ts @@ -1,12 +1,13 @@ import { TmplAstBoundAttribute, - TmplAstTextAttribute + TmplAstTextAttribute, } from '@angular-eslint/bundled-angular-compiler'; import { TemplateParserServices } from '@angular-eslint/utils'; import { ESLintUtils, TSESLint, } from '@typescript-eslint/utils'; + import { DSpaceESLintRuleInfo, NamedTests, @@ -18,10 +19,12 @@ export enum Message { } export const info = { - name: 'no-disabled-attr', + name: 'no-disabled-attribute-on-button', meta: { docs: { - description: `Buttons should use the \`dsBtnDisabled\` directive instead of the HTML \`disabled\` attribute for accessibility reasons.`, + description: `Buttons should use the \`dsBtnDisabled\` directive instead of the HTML \`disabled\` attribute. + This should be done to ensure that users with a screen reader are able to understand that the a button button is present, and that it is disabled. + The native html disabled attribute does not allow users to navigate to the button by keyboard, and thus they have no way of knowing that the button is present.`, }, type: 'problem', fixable: 'code', @@ -52,7 +55,7 @@ export const rule = ESLintUtils.RuleCreator.withoutDocs({ */ function replaceDisabledText(text: string ): string { const hasBrackets = text.includes('[') && text.includes(']'); - const newDisabledText = hasBrackets ? 'dsBtnDisabled' : '[dsBtnDisabled]'; + const newDisabledText = hasBrackets ? 'dsBtnDisabled' : '[dsBtnDisabled]="true"'; return text.replace('disabled', newDisabledText); } @@ -101,7 +104,7 @@ export const tests = { { name: 'disabled attribute is still valid on non-button elements', code: ` - + `, }, { @@ -121,7 +124,7 @@ export const tests = { { name: 'should not use disabled attribute in HTML templates', code: ` - + `, errors: [{ messageId: Message.USE_DSBTN_DISABLED }], output: ` From ed5ac47f886fb0e2ad7ef29c2152abcbe414cca1 Mon Sep 17 00:00:00 2001 From: Julia Date: Mon, 23 Sep 2024 15:53:55 -0400 Subject: [PATCH 0446/1286] Update en.json5 - fixed typo for occurred --- src/assets/i18n/en.json5 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index bf866950bc..31e45d4624 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1460,7 +1460,7 @@ "community.edit.notifications.unauthorized": "You do not have privileges to make this change", - "community.edit.notifications.error": "An error occured while editing the community", + "community.edit.notifications.error": "An error occurred while editing the community", "community.edit.return": "Back", @@ -1670,7 +1670,7 @@ "curation.form.submit.error.head": "Running the curation task failed", - "curation.form.submit.error.content": "An error occured when trying to start the curation task.", + "curation.form.submit.error.content": "An error occurred when trying to start the curation task.", "curation.form.submit.error.invalid-handle": "Couldn't determine the handle for this object", @@ -1934,7 +1934,7 @@ "forgot-email.form.error.head": "Error when trying to reset password", - "forgot-email.form.error.content": "An error occured when attempting to reset the password for the account associated with the following email address: {{ email }}", + "forgot-email.form.error.content": "An error occurred when attempting to reset the password for the account associated with the following email address: {{ email }}", "forgot-password.title": "Forgot Password", @@ -4110,7 +4110,7 @@ "register-page.registration.error.head": "Error when trying to register email", - "register-page.registration.error.content": "An error occured when registering the following email address: {{ email }}", + "register-page.registration.error.content": "An error occurred when registering the following email address: {{ email }}", "register-page.registration.error.recaptcha": "Error when trying to authenticate with recaptcha", From e6a02bcbea39f44211d6bcf6d5b95be76498cf30 Mon Sep 17 00:00:00 2001 From: Andrea Barbasso <´andrea.barbasso@4science.com´> Date: Mon, 23 Sep 2024 18:15:39 +0200 Subject: [PATCH 0447/1286] [CST-15077] add orcid icon with tooltip --- ...-item-metadata-list-element.component.html | 5 ++ ...on-item-metadata-list-element.component.ts | 3 +- .../orcid-badge-and-tooltip.component.html | 11 +++ .../orcid-badge-and-tooltip.component.scss | 11 +++ .../orcid-badge-and-tooltip.component.spec.ts | 71 +++++++++++++++++++ .../orcid-badge-and-tooltip.component.ts | 65 +++++++++++++++++ src/assets/i18n/en.json5 | 4 ++ 7 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.html create mode 100644 src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.scss create mode 100644 src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.spec.ts create mode 100644 src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.ts diff --git a/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.html b/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.html index 6f56056781..f61c14d3ba 100644 --- a/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.html +++ b/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.html @@ -12,4 +12,9 @@ + + diff --git a/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.ts b/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.ts index 48957a6cbd..c7b9e1a333 100644 --- a/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.ts +++ b/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.ts @@ -7,13 +7,14 @@ import { RouterLink } from '@angular/router'; import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'; import { ItemMetadataRepresentationListElementComponent } from '../../../../shared/object-list/metadata-representation-list-element/item/item-metadata-representation-list-element.component'; +import { OrcidBadgeAndTooltipComponent } from '../../../../shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component'; import { TruncatableComponent } from '../../../../shared/truncatable/truncatable.component'; @Component({ selector: 'ds-person-item-metadata-list-element', templateUrl: './person-item-metadata-list-element.component.html', standalone: true, - imports: [NgIf, NgFor, TruncatableComponent, RouterLink, NgbTooltipModule], + imports: [NgIf, NgFor, TruncatableComponent, RouterLink, NgbTooltipModule, OrcidBadgeAndTooltipComponent], }) /** * The component for displaying an item of the type Person as a metadata field diff --git a/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.html b/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.html new file mode 100644 index 0000000000..fc34aee970 --- /dev/null +++ b/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.html @@ -0,0 +1,11 @@ +orcid-logo + + + {{ orcidTooltip }} + diff --git a/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.scss b/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.scss new file mode 100644 index 0000000000..6a1c259e18 --- /dev/null +++ b/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.scss @@ -0,0 +1,11 @@ +:host { + display: inline-block; +} + +.orcid-icon { + height: 1.2rem; + + &.not-authenticated { + filter: grayscale(100%); + } +} diff --git a/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.spec.ts b/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.spec.ts new file mode 100644 index 0000000000..dd47fd918b --- /dev/null +++ b/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.spec.ts @@ -0,0 +1,71 @@ +import { + NgClass, + NgIf, +} from '@angular/common'; +import { + ComponentFixture, + TestBed, +} from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; +import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateService } from '@ngx-translate/core'; + +import { MetadataValue } from '../../core/shared/metadata.models'; +import { OrcidBadgeAndTooltipComponent } from './orcid-badge-and-tooltip.component'; + +describe('OrcidBadgeAndTooltipComponent', () => { + let component: OrcidBadgeAndTooltipComponent; + let fixture: ComponentFixture; + let translateService: TranslateService; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ + OrcidBadgeAndTooltipComponent, + NgbTooltipModule, + NgClass, + NgIf, + ], + providers: [ + { provide: TranslateService, useValue: { instant: (key: string) => key } }, + ], + }).compileComponents(); + + fixture = TestBed.createComponent(OrcidBadgeAndTooltipComponent); + component = fixture.componentInstance; + translateService = TestBed.inject(TranslateService); + + component.orcid = { value: '0000-0002-1825-0097' } as MetadataValue; + component.authenticatedTimestamp = { value: '2023-10-01' } as MetadataValue; + + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should set orcidTooltip when authenticatedTimestamp is provided', () => { + component.ngOnInit(); + expect(component.orcidTooltip).toBe('person.orcid-tooltip.authenticated'); + }); + + it('should set orcidTooltip when authenticatedTimestamp is not provided', () => { + component.authenticatedTimestamp = null; + component.ngOnInit(); + expect(component.orcidTooltip).toBe('person.orcid-tooltip.not-authenticated'); + }); + + it('should display the ORCID icon', () => { + const badgeIcon = fixture.debugElement.query(By.css('img[data-test="orcidIcon"]')); + expect(badgeIcon).toBeTruthy(); + }); + + it('should display the ORCID icon in greyscale if there is no authenticated timestamp', () => { + component.authenticatedTimestamp = null; + fixture.detectChanges(); + const badgeIcon = fixture.debugElement.query(By.css('img[data-test="orcidIcon"]')); + expect(badgeIcon.nativeElement.classList).toContain('not-authenticated'); + }); + +}); diff --git a/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.ts b/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.ts new file mode 100644 index 0000000000..6e8ba7100f --- /dev/null +++ b/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.ts @@ -0,0 +1,65 @@ +import { + NgClass, + NgIf, +} from '@angular/common'; +import { + Component, + Input, + OnInit, +} from '@angular/core'; +import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateService } from '@ngx-translate/core'; + +import { MetadataValue } from '../../core/shared/metadata.models'; + +/** + * Component to display an ORCID badge with a tooltip. + * The tooltip text changes based on whether the ORCID is authenticated. + */ +@Component({ + selector: 'ds-orcid-badge-and-tooltip', + standalone: true, + imports: [ + NgIf, + NgbTooltipModule, + NgClass, + ], + templateUrl: './orcid-badge-and-tooltip.component.html', + styleUrl: './orcid-badge-and-tooltip.component.scss', +}) +export class OrcidBadgeAndTooltipComponent implements OnInit { + + /** + * The ORCID value to be displayed. + */ + @Input() orcid: MetadataValue; + + /** + * The timestamp indicating when the ORCID was authenticated. + */ + @Input() authenticatedTimestamp: MetadataValue; + + /** + * The tooltip text to be displayed. + */ + orcidTooltip: string; + + /** + * Constructor to inject the TranslateService. + * @param translateService - Service for translation. + */ + constructor( + private translateService: TranslateService, + ) { } + + /** + * Initializes the component. + * Sets the tooltip text based on the presence of the authenticated timestamp. + */ + ngOnInit() { + this.orcidTooltip = this.authenticatedTimestamp ? + this.translateService.instant('person.orcid-tooltip.authenticated', { orcid: this.orcid.value }) : + this.translateService.instant('person.orcid-tooltip.not-authenticated', { orcid: this.orcid.value }); + } + +} diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 8f20c657f9..7ae8985fbe 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -5980,6 +5980,10 @@ "person.orcid.registry.auth": "ORCID Authorizations", + "person.orcid-tooltip.authenticated": "{{orcid}}", + + "person.orcid-tooltip.not-authenticated": "{{orcid}} (unconfirmed)", + "home.recent-submissions.head": "Recent Submissions", "listable-notification-object.default-message": "This object couldn't be retrieved", From 99100371b8ff5fdcd7896a307ff4efa04c10289c Mon Sep 17 00:00:00 2001 From: Andrea Barbasso <´andrea.barbasso@4science.com´> Date: Mon, 23 Sep 2024 18:15:39 +0200 Subject: [PATCH 0448/1286] [CST-15078] add orcid icon with tooltip --- ...-item-metadata-list-element.component.html | 5 ++ ...on-item-metadata-list-element.component.ts | 3 +- .../orcid-badge-and-tooltip.component.html | 11 +++ .../orcid-badge-and-tooltip.component.scss | 11 +++ .../orcid-badge-and-tooltip.component.spec.ts | 71 +++++++++++++++++++ .../orcid-badge-and-tooltip.component.ts | 65 +++++++++++++++++ src/assets/i18n/en.json5 | 4 ++ 7 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.html create mode 100644 src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.scss create mode 100644 src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.spec.ts create mode 100644 src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.ts diff --git a/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.html b/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.html index 6f56056781..f61c14d3ba 100644 --- a/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.html +++ b/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.html @@ -12,4 +12,9 @@ + + diff --git a/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.ts b/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.ts index 48957a6cbd..c7b9e1a333 100644 --- a/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.ts +++ b/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.ts @@ -7,13 +7,14 @@ import { RouterLink } from '@angular/router'; import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'; import { ItemMetadataRepresentationListElementComponent } from '../../../../shared/object-list/metadata-representation-list-element/item/item-metadata-representation-list-element.component'; +import { OrcidBadgeAndTooltipComponent } from '../../../../shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component'; import { TruncatableComponent } from '../../../../shared/truncatable/truncatable.component'; @Component({ selector: 'ds-person-item-metadata-list-element', templateUrl: './person-item-metadata-list-element.component.html', standalone: true, - imports: [NgIf, NgFor, TruncatableComponent, RouterLink, NgbTooltipModule], + imports: [NgIf, NgFor, TruncatableComponent, RouterLink, NgbTooltipModule, OrcidBadgeAndTooltipComponent], }) /** * The component for displaying an item of the type Person as a metadata field diff --git a/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.html b/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.html new file mode 100644 index 0000000000..fc34aee970 --- /dev/null +++ b/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.html @@ -0,0 +1,11 @@ +orcid-logo + + + {{ orcidTooltip }} + diff --git a/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.scss b/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.scss new file mode 100644 index 0000000000..6a1c259e18 --- /dev/null +++ b/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.scss @@ -0,0 +1,11 @@ +:host { + display: inline-block; +} + +.orcid-icon { + height: 1.2rem; + + &.not-authenticated { + filter: grayscale(100%); + } +} diff --git a/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.spec.ts b/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.spec.ts new file mode 100644 index 0000000000..dd47fd918b --- /dev/null +++ b/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.spec.ts @@ -0,0 +1,71 @@ +import { + NgClass, + NgIf, +} from '@angular/common'; +import { + ComponentFixture, + TestBed, +} from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; +import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateService } from '@ngx-translate/core'; + +import { MetadataValue } from '../../core/shared/metadata.models'; +import { OrcidBadgeAndTooltipComponent } from './orcid-badge-and-tooltip.component'; + +describe('OrcidBadgeAndTooltipComponent', () => { + let component: OrcidBadgeAndTooltipComponent; + let fixture: ComponentFixture; + let translateService: TranslateService; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ + OrcidBadgeAndTooltipComponent, + NgbTooltipModule, + NgClass, + NgIf, + ], + providers: [ + { provide: TranslateService, useValue: { instant: (key: string) => key } }, + ], + }).compileComponents(); + + fixture = TestBed.createComponent(OrcidBadgeAndTooltipComponent); + component = fixture.componentInstance; + translateService = TestBed.inject(TranslateService); + + component.orcid = { value: '0000-0002-1825-0097' } as MetadataValue; + component.authenticatedTimestamp = { value: '2023-10-01' } as MetadataValue; + + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should set orcidTooltip when authenticatedTimestamp is provided', () => { + component.ngOnInit(); + expect(component.orcidTooltip).toBe('person.orcid-tooltip.authenticated'); + }); + + it('should set orcidTooltip when authenticatedTimestamp is not provided', () => { + component.authenticatedTimestamp = null; + component.ngOnInit(); + expect(component.orcidTooltip).toBe('person.orcid-tooltip.not-authenticated'); + }); + + it('should display the ORCID icon', () => { + const badgeIcon = fixture.debugElement.query(By.css('img[data-test="orcidIcon"]')); + expect(badgeIcon).toBeTruthy(); + }); + + it('should display the ORCID icon in greyscale if there is no authenticated timestamp', () => { + component.authenticatedTimestamp = null; + fixture.detectChanges(); + const badgeIcon = fixture.debugElement.query(By.css('img[data-test="orcidIcon"]')); + expect(badgeIcon.nativeElement.classList).toContain('not-authenticated'); + }); + +}); diff --git a/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.ts b/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.ts new file mode 100644 index 0000000000..6e8ba7100f --- /dev/null +++ b/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.ts @@ -0,0 +1,65 @@ +import { + NgClass, + NgIf, +} from '@angular/common'; +import { + Component, + Input, + OnInit, +} from '@angular/core'; +import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateService } from '@ngx-translate/core'; + +import { MetadataValue } from '../../core/shared/metadata.models'; + +/** + * Component to display an ORCID badge with a tooltip. + * The tooltip text changes based on whether the ORCID is authenticated. + */ +@Component({ + selector: 'ds-orcid-badge-and-tooltip', + standalone: true, + imports: [ + NgIf, + NgbTooltipModule, + NgClass, + ], + templateUrl: './orcid-badge-and-tooltip.component.html', + styleUrl: './orcid-badge-and-tooltip.component.scss', +}) +export class OrcidBadgeAndTooltipComponent implements OnInit { + + /** + * The ORCID value to be displayed. + */ + @Input() orcid: MetadataValue; + + /** + * The timestamp indicating when the ORCID was authenticated. + */ + @Input() authenticatedTimestamp: MetadataValue; + + /** + * The tooltip text to be displayed. + */ + orcidTooltip: string; + + /** + * Constructor to inject the TranslateService. + * @param translateService - Service for translation. + */ + constructor( + private translateService: TranslateService, + ) { } + + /** + * Initializes the component. + * Sets the tooltip text based on the presence of the authenticated timestamp. + */ + ngOnInit() { + this.orcidTooltip = this.authenticatedTimestamp ? + this.translateService.instant('person.orcid-tooltip.authenticated', { orcid: this.orcid.value }) : + this.translateService.instant('person.orcid-tooltip.not-authenticated', { orcid: this.orcid.value }); + } + +} diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index bf866950bc..c67fbaf3bc 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -5982,6 +5982,10 @@ "person.orcid.registry.auth": "ORCID Authorizations", + "person.orcid-tooltip.authenticated": "{{orcid}}", + + "person.orcid-tooltip.not-authenticated": "{{orcid}} (unconfirmed)", + "home.recent-submissions.head": "Recent Submissions", "listable-notification-object.default-message": "This object couldn't be retrieved", From cd51baa5f1ee5d8fa66e8ee94beb3168f93c5c01 Mon Sep 17 00:00:00 2001 From: Andrea Barbasso <´andrea.barbasso@4science.com´> Date: Mon, 23 Sep 2024 18:15:39 +0200 Subject: [PATCH 0449/1286] [CST-14904] add orcid icon with tooltip --- ...-item-metadata-list-element.component.html | 5 ++ .../orcid-badge-and-tooltip.component.html | 11 +++ .../orcid-badge-and-tooltip.component.scss | 11 +++ .../orcid-badge-and-tooltip.component.spec.ts | 71 +++++++++++++++++++ .../orcid-badge-and-tooltip.component.ts | 56 +++++++++++++++ src/app/shared/shared.module.ts | 2 + src/assets/i18n/en.json5 | 4 ++ 7 files changed, 160 insertions(+) create mode 100644 src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.html create mode 100644 src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.scss create mode 100644 src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.spec.ts create mode 100644 src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.ts diff --git a/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.html b/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.html index 6f56056781..f61c14d3ba 100644 --- a/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.html +++ b/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.html @@ -12,4 +12,9 @@ + + diff --git a/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.html b/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.html new file mode 100644 index 0000000000..fc34aee970 --- /dev/null +++ b/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.html @@ -0,0 +1,11 @@ +orcid-logo + + + {{ orcidTooltip }} + diff --git a/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.scss b/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.scss new file mode 100644 index 0000000000..6a1c259e18 --- /dev/null +++ b/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.scss @@ -0,0 +1,11 @@ +:host { + display: inline-block; +} + +.orcid-icon { + height: 1.2rem; + + &.not-authenticated { + filter: grayscale(100%); + } +} diff --git a/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.spec.ts b/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.spec.ts new file mode 100644 index 0000000000..adb3c91f94 --- /dev/null +++ b/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.spec.ts @@ -0,0 +1,71 @@ +import { + NgClass, + NgIf, +} from '@angular/common'; +import { + ComponentFixture, + TestBed, +} from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; +import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateService } from '@ngx-translate/core'; + +import { MetadataValue } from '../../core/shared/metadata.models'; +import { OrcidBadgeAndTooltipComponent } from './orcid-badge-and-tooltip.component'; + +describe('OrcidBadgeAndTooltipComponent', () => { + let component: OrcidBadgeAndTooltipComponent; + let fixture: ComponentFixture; + let translateService: TranslateService; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [OrcidBadgeAndTooltipComponent], + imports: [ + NgbTooltipModule, + NgClass, + NgIf, + ], + providers: [ + { provide: TranslateService, useValue: { instant: (key: string) => key } }, + ], + }).compileComponents(); + + fixture = TestBed.createComponent(OrcidBadgeAndTooltipComponent); + component = fixture.componentInstance; + translateService = TestBed.inject(TranslateService); + + component.orcid = { value: '0000-0002-1825-0097' } as MetadataValue; + component.authenticatedTimestamp = { value: '2023-10-01' } as MetadataValue; + + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should set orcidTooltip when authenticatedTimestamp is provided', () => { + component.ngOnInit(); + expect(component.orcidTooltip).toBe('person.orcid-tooltip.authenticated'); + }); + + it('should set orcidTooltip when authenticatedTimestamp is not provided', () => { + component.authenticatedTimestamp = null; + component.ngOnInit(); + expect(component.orcidTooltip).toBe('person.orcid-tooltip.not-authenticated'); + }); + + it('should display the ORCID icon', () => { + const badgeIcon = fixture.debugElement.query(By.css('img[data-test="orcidIcon"]')); + expect(badgeIcon).toBeTruthy(); + }); + + it('should display the ORCID icon in greyscale if there is no authenticated timestamp', () => { + component.authenticatedTimestamp = null; + fixture.detectChanges(); + const badgeIcon = fixture.debugElement.query(By.css('img[data-test="orcidIcon"]')); + expect(badgeIcon.nativeElement.classList).toContain('not-authenticated'); + }); + +}); diff --git a/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.ts b/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.ts new file mode 100644 index 0000000000..1939bad57f --- /dev/null +++ b/src/app/shared/orcid-badge-and-tooltip/orcid-badge-and-tooltip.component.ts @@ -0,0 +1,56 @@ + + +import { + Component, + Input, + OnInit, +} from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; + +import { MetadataValue } from '../../core/shared/metadata.models'; + +/** + * Component to display an ORCID badge with a tooltip. + * The tooltip text changes based on whether the ORCID is authenticated. + */ +@Component({ + selector: 'ds-orcid-badge-and-tooltip', + templateUrl: './orcid-badge-and-tooltip.component.html', + styleUrls: ['./orcid-badge-and-tooltip.component.scss'], +}) +export class OrcidBadgeAndTooltipComponent implements OnInit { + + /** + * The ORCID value to be displayed. + */ + @Input() orcid: MetadataValue; + + /** + * The timestamp indicating when the ORCID was authenticated. + */ + @Input() authenticatedTimestamp: MetadataValue; + + /** + * The tooltip text to be displayed. + */ + orcidTooltip: string; + + /** + * Constructor to inject the TranslateService. + * @param translateService - Service for translation. + */ + constructor( + private translateService: TranslateService, + ) { } + + /** + * Initializes the component. + * Sets the tooltip text based on the presence of the authenticated timestamp. + */ + ngOnInit() { + this.orcidTooltip = this.authenticatedTimestamp ? + this.translateService.instant('person.orcid-tooltip.authenticated', { orcid: this.orcid.value }) : + this.translateService.instant('person.orcid-tooltip.not-authenticated', { orcid: this.orcid.value }); + } + +} diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 9f05b1d370..d6b6e861ce 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -284,6 +284,7 @@ import { BitstreamListItemComponent } from './object-list/bitstream-list-item/bi import { NgxPaginationModule } from 'ngx-pagination'; import { ThemedLangSwitchComponent } from './lang-switch/themed-lang-switch.component'; import {ThemedUserMenuComponent} from './auth-nav-menu/user-menu/themed-user-menu.component'; +import { OrcidBadgeAndTooltipComponent } from './orcid-badge-and-tooltip/orcid-badge-and-tooltip.component'; const MODULES = [ CommonModule, @@ -404,6 +405,7 @@ const COMPONENTS = [ EpersonSearchBoxComponent, GroupSearchBoxComponent, ThemedItemPageTitleFieldComponent, + OrcidBadgeAndTooltipComponent, ]; const ENTRY_COMPONENTS = [ diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 0a1804fa5c..3f85e8b687 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -5248,6 +5248,10 @@ "person.orcid.registry.auth": "ORCID Authorizations", + "person.orcid-tooltip.authenticated": "{{orcid}}", + + "person.orcid-tooltip.not-authenticated": "{{orcid}} (unconfirmed)", + "home.recent-submissions.head": "Recent Submissions", "listable-notification-object.default-message": "This object couldn't be retrieved", From e45b6af26dc8faf25774951fe9e3309fda46b3c1 Mon Sep 17 00:00:00 2001 From: nwoodward Date: Tue, 24 Sep 2024 09:46:58 -0500 Subject: [PATCH 0450/1286] updates isbot dependency to newest version --- package.json | 2 +- server.ts | 2 +- yarn.lock | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 82822316aa..75c40857bc 100644 --- a/package.json +++ b/package.json @@ -106,7 +106,7 @@ "filesize": "^6.1.0", "http-proxy-middleware": "^1.0.5", "http-terminator": "^3.2.0", - "isbot": "^3.6.10", + "isbot": "^5.1.17", "js-cookie": "2.2.1", "js-yaml": "^4.1.0", "json5": "^2.2.3", diff --git a/server.ts b/server.ts index 22f3423287..032b79b8f2 100644 --- a/server.ts +++ b/server.ts @@ -27,7 +27,7 @@ import * as expressStaticGzip from 'express-static-gzip'; /* eslint-enable import/no-namespace */ import axios from 'axios'; import LRU from 'lru-cache'; -import isbot from 'isbot'; +import { isbot } from 'isbot'; import { createCertificate } from 'pem'; import { createServer } from 'https'; import { json } from 'body-parser'; diff --git a/yarn.lock b/yarn.lock index d923560e56..f42bb504fd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7282,10 +7282,10 @@ isbinaryfile@^4.0.8: resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.10.tgz#0c5b5e30c2557a2f06febd37b7322946aaee42b3" integrity sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw== -isbot@^3.6.10: - version "3.8.0" - resolved "https://registry.yarnpkg.com/isbot/-/isbot-3.8.0.tgz#b1f8e3d19aca0961b5ed27b62bb8bb0a275781e4" - integrity sha512-vne1mzQUTR+qsMLeCBL9+/tgnDXRyc2pygLGl/WsgA+EZKIiB5Ehu0CiVTHIIk30zhJ24uGz4M5Ppse37aR0Hg== +isbot@^5.1.17: + version "5.1.17" + resolved "https://registry.yarnpkg.com/isbot/-/isbot-5.1.17.tgz#ad7da5690a61bbb19056a069975c9a73182682a0" + integrity sha512-/wch8pRKZE+aoVhRX/hYPY1C7dMCeeMyhkQLNLNlYAbGQn9bkvMB8fOUXNnk5I0m4vDYbBJ9ciVtkr9zfBJ7qA== isexe@^2.0.0: version "2.0.0" From 35946dcf7cefdaafb70a2ee5ee02a2b53c7e8817 Mon Sep 17 00:00:00 2001 From: Alan Orth Date: Wed, 25 Sep 2024 08:13:21 +0300 Subject: [PATCH 0451/1286] Update isbot dependency Note that the minimum supported Node.js version is now v18, as v16 is now end of life. --- package.json | 2 +- server.ts | 2 +- yarn.lock | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 86959196d0..78f0cc9887 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,7 @@ "filesize": "^6.1.0", "http-proxy-middleware": "^1.0.5", "http-terminator": "^3.2.0", - "isbot": "^3.6.10", + "isbot": "^5.1.17", "js-cookie": "2.2.1", "js-yaml": "^4.1.0", "json5": "^2.2.3", diff --git a/server.ts b/server.ts index 93f3e86876..23d29723c6 100644 --- a/server.ts +++ b/server.ts @@ -28,7 +28,7 @@ import * as expressStaticGzip from 'express-static-gzip'; /* eslint-enable import/no-namespace */ import axios from 'axios'; import LRU from 'lru-cache'; -import isbot from 'isbot'; +import { isbot } from 'isbot'; import { createCertificate } from 'pem'; import { createServer } from 'https'; import { json } from 'body-parser'; diff --git a/yarn.lock b/yarn.lock index efc65983c6..2a4fd40b5a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7188,10 +7188,10 @@ isbinaryfile@^4.0.8: resolved "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz" integrity sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw== -isbot@^3.6.10: - version "3.6.10" - resolved "https://registry.yarnpkg.com/isbot/-/isbot-3.6.10.tgz#7b66334e81794f0461794debb567975cf08eaf2b" - integrity sha512-+I+2998oyP4oW9+OTQD8TS1r9P6wv10yejukj+Ksj3+UR5pUhsZN3f8W7ysq0p1qxpOVNbl5mCuv0bCaF8y5iQ== +isbot@^5.1.17: + version "5.1.17" + resolved "https://registry.yarnpkg.com/isbot/-/isbot-5.1.17.tgz#ad7da5690a61bbb19056a069975c9a73182682a0" + integrity sha512-/wch8pRKZE+aoVhRX/hYPY1C7dMCeeMyhkQLNLNlYAbGQn9bkvMB8fOUXNnk5I0m4vDYbBJ9ciVtkr9zfBJ7qA== isexe@^2.0.0: version "2.0.0" From 29c1b510733a6081fb5bfa09a5c8f7c0c25de300 Mon Sep 17 00:00:00 2001 From: Alan Orth Date: Wed, 25 Sep 2024 08:34:04 +0300 Subject: [PATCH 0452/1286] .github/workflows/build.yml: use Node.js v18 and v20 Node.js v16 LTS is end of life since October, 2023. See: https://nodejs.org/en/about/previous-releases --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 50b260b59e..f6ffa5e004 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -38,7 +38,7 @@ jobs: strategy: # Create a matrix of Node versions to test against (in parallel) matrix: - node-version: [16.x, 18.x] + node-version: [18.x, 20.x] # Do NOT exit immediately if one matrix job fails fail-fast: false # These are the actual CI steps to perform per job From c1fa52ee64e7c50f38c0e671aa13757bc7a4c024 Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Wed, 25 Sep 2024 09:50:33 +0200 Subject: [PATCH 0453/1286] 118220: Store messages with ID so clears can be targeted --- .../live-region/live-region.service.spec.ts | 34 +++++++++++++++- .../shared/live-region/live-region.service.ts | 39 ++++++++++++------- 2 files changed, 57 insertions(+), 16 deletions(-) diff --git a/src/app/shared/live-region/live-region.service.spec.ts b/src/app/shared/live-region/live-region.service.spec.ts index fe5e8b8d8c..858ef88313 100644 --- a/src/app/shared/live-region/live-region.service.spec.ts +++ b/src/app/shared/live-region/live-region.service.spec.ts @@ -1,12 +1,14 @@ import { LiveRegionService } from './live-region.service'; import { fakeAsync, tick, flush } from '@angular/core/testing'; +import { UUIDService } from '../../core/shared/uuid.service'; describe('liveRegionService', () => { let service: LiveRegionService; - beforeEach(() => { - service = new LiveRegionService(); + service = new LiveRegionService( + new UUIDService(), + ); }); describe('addMessage', () => { @@ -85,6 +87,34 @@ describe('liveRegionService', () => { expect(results[3]).toEqual([]); })); + it('should not pop messages added after clearing within timeOut period', fakeAsync(() => { + const results: string[][] = []; + + service.getMessages$().subscribe((messages) => { + results.push(messages); + }); + + expect(results.length).toEqual(1); + expect(results[0]).toEqual([]); + + service.addMessage('Message One'); + tick(10000); + service.clear(); + tick(15000); + service.addMessage('Message Two'); + + // Message Two should not be cleared after 5 more seconds + tick(5000); + + expect(results.length).toEqual(4); + expect(results[3]).toEqual(['Message Two']); + + // But should be cleared 30 seconds after it was added + tick(25000); + expect(results.length).toEqual(5); + expect(results[4]).toEqual([]); + })); + it('should respect configured timeOut', fakeAsync(() => { const results: string[][] = []; diff --git a/src/app/shared/live-region/live-region.service.ts b/src/app/shared/live-region/live-region.service.ts index 482d1ca1bb..d89d72a967 100644 --- a/src/app/shared/live-region/live-region.service.ts +++ b/src/app/shared/live-region/live-region.service.ts @@ -1,12 +1,18 @@ import { Injectable } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; import { environment } from '../../../environments/environment'; +import { UUIDService } from '../../core/shared/uuid.service'; @Injectable({ providedIn: 'root', }) export class LiveRegionService { + constructor( + protected uuidService: UUIDService, + ) { + } + /** * The duration after which the messages disappear in milliseconds * @protected @@ -14,10 +20,11 @@ export class LiveRegionService { protected messageTimeOutDurationMs: number = environment.liveRegion.messageTimeOutDurationMs; /** - * Array containing the messages that should be shown in the live region + * Array containing the messages that should be shown in the live region, + * together with a uuid, so they can be uniquely identified * @protected */ - protected messages: string[] = []; + protected messages: { message: string, uuid: string }[] = []; /** * BehaviorSubject emitting the array with messages every time the array updates @@ -34,27 +41,28 @@ export class LiveRegionService { /** * Returns a copy of the array with the current live region messages */ - getMessages() { - return [...this.messages]; + getMessages(): string[] { + return this.messages.map(messageObj => messageObj.message); } /** * Returns the BehaviorSubject emitting the array with messages every time the array updates */ - getMessages$() { + getMessages$(): BehaviorSubject { return this.messages$; } /** * Adds a message to the live-region messages array * @param message + * @return The uuid of the message */ - addMessage(message: string) { - this.messages.push(message); + addMessage(message: string): string { + const uuid = this.uuidService.generate(); + this.messages.push({ message, uuid }); + setTimeout(() => this.clearMessageByUUID(uuid), this.messageTimeOutDurationMs); this.emitCurrentMessages(); - - // Clear the message once the timeOut has passed - setTimeout(() => this.pop(), this.messageTimeOutDurationMs); + return uuid; } /** @@ -66,12 +74,15 @@ export class LiveRegionService { } /** - * Removes the longest living message from the array. + * Removes the message with the given UUID from the messages array + * @param uuid The uuid of the message to clear * @protected */ - protected pop() { - if (this.messages.length > 0) { - this.messages.shift(); + clearMessageByUUID(uuid: string) { + const index = this.messages.findIndex(messageObj => messageObj.uuid === uuid); + + if (index !== -1) { + this.messages.splice(index, 1); this.emitCurrentMessages(); } } From 8a5181a9a32df05fc52022244b34a525768fea7c Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Wed, 25 Sep 2024 14:55:37 +0200 Subject: [PATCH 0454/1286] documentation file --- .../rules/no-disabled-attribute-on-button.md | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 docs/lint/html/rules/no-disabled-attribute-on-button.md diff --git a/docs/lint/html/rules/no-disabled-attribute-on-button.md b/docs/lint/html/rules/no-disabled-attribute-on-button.md new file mode 100644 index 0000000000..d9d39ce82c --- /dev/null +++ b/docs/lint/html/rules/no-disabled-attribute-on-button.md @@ -0,0 +1,78 @@ +[DSpace ESLint plugins](../../../../lint/README.md) > [HTML rules](../index.md) > `dspace-angular-html/no-disabled-attribute-on-button` +_______ + +Buttons should use the `dsBtnDisabled` directive instead of the HTML `disabled` attribute. + This should be done to ensure that users with a screen reader are able to understand that the a button button is present, and that it is disabled. + The native html disabled attribute does not allow users to navigate to the button by keyboard, and thus they have no way of knowing that the button is present. + +_______ + +[Source code](../../../../lint/src/rules/html/no-disabled-attribute-on-button.ts) + +### Examples + + +#### Valid code + +##### should use [dsBtnDisabled] in HTML templates + +```html + +``` + +##### disabled attribute is still valid on non-button elements + +```html + +``` + +##### [disabled] attribute is still valid on non-button elements + +```html + +``` + +##### angular dynamic attributes that use disabled are still valid + +```html + +``` + + + + +#### Invalid code & automatic fixes + +##### should not use disabled attribute in HTML templates + +```html + +``` +Will produce the following error(s): +``` +Buttons should use the `dsBtnDisabled` directive instead of the `disabled` attribute. +``` + +Result of `yarn lint --fix`: +```html + +``` + + +##### should not use [disabled] attribute in HTML templates + +```html + +``` +Will produce the following error(s): +``` +Buttons should use the `dsBtnDisabled` directive instead of the `disabled` attribute. +``` + +Result of `yarn lint --fix`: +```html + +``` + + + From 1b17879d7ae74e45b6e383db81ca6a3eb5817928 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Wed, 25 Sep 2024 14:55:37 +0200 Subject: [PATCH 0455/1286] documentation file --- .../rules/no-disabled-attribute-on-button.md | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 docs/lint/html/rules/no-disabled-attribute-on-button.md diff --git a/docs/lint/html/rules/no-disabled-attribute-on-button.md b/docs/lint/html/rules/no-disabled-attribute-on-button.md new file mode 100644 index 0000000000..d9d39ce82c --- /dev/null +++ b/docs/lint/html/rules/no-disabled-attribute-on-button.md @@ -0,0 +1,78 @@ +[DSpace ESLint plugins](../../../../lint/README.md) > [HTML rules](../index.md) > `dspace-angular-html/no-disabled-attribute-on-button` +_______ + +Buttons should use the `dsBtnDisabled` directive instead of the HTML `disabled` attribute. + This should be done to ensure that users with a screen reader are able to understand that the a button button is present, and that it is disabled. + The native html disabled attribute does not allow users to navigate to the button by keyboard, and thus they have no way of knowing that the button is present. + +_______ + +[Source code](../../../../lint/src/rules/html/no-disabled-attribute-on-button.ts) + +### Examples + + +#### Valid code + +##### should use [dsBtnDisabled] in HTML templates + +```html + +``` + +##### disabled attribute is still valid on non-button elements + +```html + +``` + +##### [disabled] attribute is still valid on non-button elements + +```html + +``` + +##### angular dynamic attributes that use disabled are still valid + +```html + +``` + + + + +#### Invalid code & automatic fixes + +##### should not use disabled attribute in HTML templates + +```html + +``` +Will produce the following error(s): +``` +Buttons should use the `dsBtnDisabled` directive instead of the `disabled` attribute. +``` + +Result of `yarn lint --fix`: +```html + +``` + + +##### should not use [disabled] attribute in HTML templates + +```html + +``` +Will produce the following error(s): +``` +Buttons should use the `dsBtnDisabled` directive instead of the `disabled` attribute. +``` + +Result of `yarn lint --fix`: +```html + +``` + + + From aed97c9dccf5460897f5c24ea9473fa642468c0c Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Wed, 26 Jun 2024 14:46:13 +0200 Subject: [PATCH 0456/1286] added missing German translations (500 error) (cherry picked from commit 5f6b6ef9849e27eaf87e5b8b0f94ccde271d8043) --- src/assets/i18n/de.json5 | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/assets/i18n/de.json5 b/src/assets/i18n/de.json5 index 8efda0390e..d1ac01fe2a 100644 --- a/src/assets/i18n/de.json5 +++ b/src/assets/i18n/de.json5 @@ -9,8 +9,6 @@ // "401.unauthorized": "unauthorized", "401.unauthorized": "unautorisiert", - - // "403.help": "You don't have permission to access this page. You can use the button below to get back to the home page.", "403.help": "Sie sind nicht berechtigt, auf diese Seite zuzugreifen. Über den Button unten auf der Seite gelangen Sie zurück zur Startseite.", @@ -20,8 +18,6 @@ // "403.forbidden": "forbidden", "403.forbidden": "verboten", - - // "404.help": "We can't find the page you're looking for. The page may have been moved or deleted. You can use the button below to get back to the home page. ", "404.help": "Die Seite konnte nicht gefunden werden. Eventuell wurde sie verschoben oder gelöscht. Über den Button unten auf der Seite gelangen Sie zurück zur Startseite.", @@ -31,6 +27,16 @@ // "404.page-not-found": "page not found", "404.page-not-found": "Seite nicht gefunden", + // "500.page-internal-server-error": "Service unavailable", + "500.page-internal-server-error": "Dienst nicht verfügbar", + + // "500.help": "The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later.", + "500.help": "Der Dienst steht momentan nicht zur Verfügung. Bitte versuchen Sie es später noch einmal.", + + // "500.link.home-page": "Take me to the home page", + "500.link.home-page": "Zur Startseite", + + // "admin.access-control.epeople.breadcrumbs": "EPeople", "admin.access-control.epeople.breadcrumbs": "Personen suchen", From 48ec0cdc340ecf472688c6d606c3fb3643456663 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Tue, 9 Jul 2024 17:42:49 +0200 Subject: [PATCH 0457/1286] minor change: added missing periods in German translations (cherry picked from commit e26ab86dd33981ea4a9969b6043449619948a2b8) --- src/assets/i18n/de.json5 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assets/i18n/de.json5 b/src/assets/i18n/de.json5 index 8efda0390e..c154ae91c9 100644 --- a/src/assets/i18n/de.json5 +++ b/src/assets/i18n/de.json5 @@ -5143,10 +5143,10 @@ "submission.sections.general.deposit_error_notice": "Beim Einreichen des Items ist ein Fehler aufgetreten. Bitte versuchen Sie es später noch einmal.", // "submission.sections.general.deposit_success_notice": "Submission deposited successfully.", - "submission.sections.general.deposit_success_notice": "Veröffentlichung erfolgreich eingereicht", + "submission.sections.general.deposit_success_notice": "Veröffentlichung erfolgreich eingereicht.", // "submission.sections.general.discard_error_notice": "There was an issue when discarding the item, please try again later.", - "submission.sections.general.discard_error_notice": "Beim Verwerfen der Einreichung ist ein Fehler aufgetreten. Bitte versuchen Sie es später noch einmal", + "submission.sections.general.discard_error_notice": "Beim Verwerfen der Einreichung ist ein Fehler aufgetreten. Bitte versuchen Sie es später noch einmal.", // "submission.sections.general.discard_success_notice": "Submission discarded successfully.", "submission.sections.general.discard_success_notice": "Einreichung erfolgreich verworfen.", From 6b081ee470638d54ca856d6cd9219a715ddcd33c Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Tue, 9 Jul 2024 17:42:49 +0200 Subject: [PATCH 0458/1286] minor change: added missing periods in German translations (cherry picked from commit e26ab86dd33981ea4a9969b6043449619948a2b8) --- src/assets/i18n/de.json5 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assets/i18n/de.json5 b/src/assets/i18n/de.json5 index dac2eb4a52..e1ebb489cf 100644 --- a/src/assets/i18n/de.json5 +++ b/src/assets/i18n/de.json5 @@ -5560,10 +5560,10 @@ "submission.sections.general.deposit_error_notice": "Beim Einreichen des Items ist ein Fehler aufgetreten. Bitte versuchen Sie es später noch einmal.", // "submission.sections.general.deposit_success_notice": "Submission deposited successfully.", - "submission.sections.general.deposit_success_notice": "Veröffentlichung erfolgreich eingereicht", + "submission.sections.general.deposit_success_notice": "Veröffentlichung erfolgreich eingereicht.", // "submission.sections.general.discard_error_notice": "There was an issue when discarding the item, please try again later.", - "submission.sections.general.discard_error_notice": "Beim Verwerfen der Einreichung ist ein Fehler aufgetreten. Bitte versuchen Sie es später noch einmal", + "submission.sections.general.discard_error_notice": "Beim Verwerfen der Einreichung ist ein Fehler aufgetreten. Bitte versuchen Sie es später noch einmal.", // "submission.sections.general.discard_success_notice": "Submission discarded successfully.", "submission.sections.general.discard_success_notice": "Einreichung erfolgreich verworfen.", From edc738ae3964fada0c6628ce1732f047ae24a603 Mon Sep 17 00:00:00 2001 From: Julia Date: Mon, 23 Sep 2024 15:53:55 -0400 Subject: [PATCH 0459/1286] Update en.json5 - fixed typo for occurred (cherry picked from commit ed5ac47f886fb0e2ad7ef29c2152abcbe414cca1) --- src/assets/i18n/en.json5 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 0a1804fa5c..d00e16caa0 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1240,7 +1240,7 @@ "community.edit.notifications.unauthorized": "You do not have privileges to make this change", - "community.edit.notifications.error": "An error occured while editing the community", + "community.edit.notifications.error": "An error occurred while editing the community", "community.edit.return": "Back", @@ -1448,7 +1448,7 @@ "curation.form.submit.error.head": "Running the curation task failed", - "curation.form.submit.error.content": "An error occured when trying to start the curation task.", + "curation.form.submit.error.content": "An error occurred when trying to start the curation task.", "curation.form.submit.error.invalid-handle": "Couldn't determine the handle for this object", @@ -1700,7 +1700,7 @@ "forgot-email.form.error.head": "Error when trying to reset password", - "forgot-email.form.error.content": "An error occured when attempting to reset the password for the account associated with the following email address: {{ email }}", + "forgot-email.form.error.content": "An error occurred when attempting to reset the password for the account associated with the following email address: {{ email }}", "forgot-password.title": "Forgot Password", @@ -3518,7 +3518,7 @@ "register-page.registration.error.head": "Error when trying to register email", - "register-page.registration.error.content": "An error occured when registering the following email address: {{ email }}", + "register-page.registration.error.content": "An error occurred when registering the following email address: {{ email }}", "register-page.registration.error.recaptcha": "Error when trying to authenticate with recaptcha", From c2e9d5453aa1c74526b90a2f00e8e22e45a781c9 Mon Sep 17 00:00:00 2001 From: Julia Date: Mon, 23 Sep 2024 15:53:55 -0400 Subject: [PATCH 0460/1286] Update en.json5 - fixed typo for occurred (cherry picked from commit ed5ac47f886fb0e2ad7ef29c2152abcbe414cca1) --- src/assets/i18n/en.json5 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 8f20c657f9..17fbf33b4a 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1460,7 +1460,7 @@ "community.edit.notifications.unauthorized": "You do not have privileges to make this change", - "community.edit.notifications.error": "An error occured while editing the community", + "community.edit.notifications.error": "An error occurred while editing the community", "community.edit.return": "Back", @@ -1670,7 +1670,7 @@ "curation.form.submit.error.head": "Running the curation task failed", - "curation.form.submit.error.content": "An error occured when trying to start the curation task.", + "curation.form.submit.error.content": "An error occurred when trying to start the curation task.", "curation.form.submit.error.invalid-handle": "Couldn't determine the handle for this object", @@ -1932,7 +1932,7 @@ "forgot-email.form.error.head": "Error when trying to reset password", - "forgot-email.form.error.content": "An error occured when attempting to reset the password for the account associated with the following email address: {{ email }}", + "forgot-email.form.error.content": "An error occurred when attempting to reset the password for the account associated with the following email address: {{ email }}", "forgot-password.title": "Forgot Password", @@ -4108,7 +4108,7 @@ "register-page.registration.error.head": "Error when trying to register email", - "register-page.registration.error.content": "An error occured when registering the following email address: {{ email }}", + "register-page.registration.error.content": "An error occurred when registering the following email address: {{ email }}", "register-page.registration.error.recaptcha": "Error when trying to authenticate with recaptcha", From fe7d2a8a7e05bcdb3b63943261ab84cfdd9614d5 Mon Sep 17 00:00:00 2001 From: Elvi Nemiz Date: Sat, 29 Jun 2024 08:14:10 +0800 Subject: [PATCH 0461/1286] Fix to Mobile navbar hamburger menu for base (custom) theme https://github.com/DSpace/dspace-angular/pull/2444 only fixes the DSpace theme, not the base (and custom) theme. (cherry picked from commit a3b6aef66a81e93f537bf35647be97d14f5b1472) --- src/app/navbar/navbar.component.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/navbar/navbar.component.scss b/src/app/navbar/navbar.component.scss index b74408f0f5..bbf5feec15 100644 --- a/src/app/navbar/navbar.component.scss +++ b/src/app/navbar/navbar.component.scss @@ -10,7 +10,7 @@ /** Mobile menu styling **/ @media screen and (max-width: map-get($grid-breakpoints, md)-0.02) { .navbar { - width: 100%; + width: 100vw; background-color: var(--bs-white); position: absolute; overflow: hidden; From 0cff856bf5d4e3ad8087491973abf6516db776bc Mon Sep 17 00:00:00 2001 From: Elvi Nemiz Date: Sat, 29 Jun 2024 08:14:10 +0800 Subject: [PATCH 0462/1286] Fix to Mobile navbar hamburger menu for base (custom) theme https://github.com/DSpace/dspace-angular/pull/2444 only fixes the DSpace theme, not the base (and custom) theme. (cherry picked from commit a3b6aef66a81e93f537bf35647be97d14f5b1472) --- src/app/navbar/navbar.component.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/navbar/navbar.component.scss b/src/app/navbar/navbar.component.scss index b74408f0f5..bbf5feec15 100644 --- a/src/app/navbar/navbar.component.scss +++ b/src/app/navbar/navbar.component.scss @@ -10,7 +10,7 @@ /** Mobile menu styling **/ @media screen and (max-width: map-get($grid-breakpoints, md)-0.02) { .navbar { - width: 100%; + width: 100vw; background-color: var(--bs-white); position: absolute; overflow: hidden; From 751d689ff65b15fa4f8b2f898d43ecaa682e8085 Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Fri, 27 Sep 2024 10:02:26 +0200 Subject: [PATCH 0463/1286] 118220: Add additional TypeDocs --- src/app/shared/live-region/live-region.component.ts | 6 ++++++ src/app/shared/live-region/live-region.service.ts | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/app/shared/live-region/live-region.component.ts b/src/app/shared/live-region/live-region.component.ts index d7bd5eb806..8a25c4657c 100644 --- a/src/app/shared/live-region/live-region.component.ts +++ b/src/app/shared/live-region/live-region.component.ts @@ -2,6 +2,12 @@ import { Component, OnInit } from '@angular/core'; import { LiveRegionService } from './live-region.service'; import { Observable } from 'rxjs'; +/** + * The Live Region Component is an accessibility tool for screenreaders. When a change occurs on a page when the changed + * section is not in focus, a message should be displayed by this component so it can be announced by a screen reader. + * + * This component should not be used directly. Use the {@link LiveRegionService} to add messages. + */ @Component({ selector: `ds-live-region`, templateUrl: './live-region.component.html', diff --git a/src/app/shared/live-region/live-region.service.ts b/src/app/shared/live-region/live-region.service.ts index d89d72a967..72940c1a0e 100644 --- a/src/app/shared/live-region/live-region.service.ts +++ b/src/app/shared/live-region/live-region.service.ts @@ -3,6 +3,10 @@ import { BehaviorSubject } from 'rxjs'; import { environment } from '../../../environments/environment'; import { UUIDService } from '../../core/shared/uuid.service'; +/** + * The LiveRegionService is responsible for handling the messages that are shown by the {@link LiveRegionComponent}. + * Use this service to add or remove messages to the Live Region. + */ @Injectable({ providedIn: 'root', }) @@ -76,7 +80,6 @@ export class LiveRegionService { /** * Removes the message with the given UUID from the messages array * @param uuid The uuid of the message to clear - * @protected */ clearMessageByUUID(uuid: string) { const index = this.messages.findIndex(messageObj => messageObj.uuid === uuid); From 9565f9b9ee96b763ea22c39a0faf4e49cdab84ae Mon Sep 17 00:00:00 2001 From: andreaNeki Date: Fri, 27 Sep 2024 13:44:31 -0300 Subject: [PATCH 0464/1286] Adding the aria-label attribute to buttons --- .../vocabulary-treeview.component.html | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.html b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.html index 758d1426e0..6a4d9ea87d 100644 --- a/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.html +++ b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.html @@ -6,16 +6,20 @@ [attr.aria-label]="'vocabulary-treeview.search.form.search-placeholder' | translate" [placeholder]="'vocabulary-treeview.search.form.search-placeholder' | translate">
- - - -
@@ -91,13 +95,15 @@ - - From e54b1ce274febd27e6a3c47bfa14e8be82eb5d8e Mon Sep 17 00:00:00 2001 From: andreaNeki Date: Fri, 27 Sep 2024 14:01:44 -0300 Subject: [PATCH 0465/1286] Adding focus to the input after the reset button is clicked --- .../vocabulary-treeview.component.html | 2 +- .../vocabulary-treeview/vocabulary-treeview.component.ts | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.html b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.html index 6a4d9ea87d..782eb24be4 100644 --- a/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.html +++ b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.html @@ -2,7 +2,7 @@
-
diff --git a/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts index cd836a4a47..8ed1c769e5 100644 --- a/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts +++ b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts @@ -8,6 +8,7 @@ import { } from '@angular/common'; import { Component, + ElementRef, EventEmitter, Input, OnChanges, @@ -15,6 +16,7 @@ import { OnInit, Output, SimpleChanges, + ViewChild, } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'; @@ -70,6 +72,11 @@ export type VocabularyTreeItemType = FormFieldMetadataValueObject | VocabularyEn }) export class VocabularyTreeviewComponent implements OnDestroy, OnInit, OnChanges { + /** + * Implemented to manage focus on input + */ + @ViewChild('searchInput') searchInput: ElementRef; + /** * The {@link VocabularyOptions} object */ @@ -332,6 +339,7 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit, OnChanges this.storedNodeMap = new Map(); this.vocabularyTreeviewService.restoreNodes(); } + this.searchInput.nativeElement.focus(); } add() { From 3658ad1ec09ce6a314dad7e8c5339c2a18cff6e4 Mon Sep 17 00:00:00 2001 From: andreaNeki Date: Fri, 27 Sep 2024 15:08:53 -0300 Subject: [PATCH 0466/1286] =?UTF-8?q?Ensuring=20that=20the=20message=20?= =?UTF-8?q?=E2=80=9CThere=20were=20no=20items=20to=20show=E2=80=9D=20is=20?= =?UTF-8?q?announced=20to=20the=20screen=20reader=20when=20necessary?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vocabulary-treeview.component.html | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.html b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.html index 782eb24be4..f55f26aa68 100644 --- a/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.html +++ b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.html @@ -28,9 +28,11 @@
-

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

+
+

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

+
From 73d39abfe562a3ecd8b6e4ed20e8744a177ea1de Mon Sep 17 00:00:00 2001 From: andreaNeki Date: Fri, 27 Sep 2024 16:18:56 -0300 Subject: [PATCH 0467/1286] Trying to correct an error in the focus implementation --- .../vocabulary-treeview/vocabulary-treeview.component.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts index 8ed1c769e5..89d908ec7f 100644 --- a/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts +++ b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts @@ -75,7 +75,7 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit, OnChanges /** * Implemented to manage focus on input */ - @ViewChild('searchInput') searchInput: ElementRef; + @ViewChild('searchInput') searchInput!: ElementRef; /** * The {@link VocabularyOptions} object @@ -339,7 +339,9 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit, OnChanges this.storedNodeMap = new Map(); this.vocabularyTreeviewService.restoreNodes(); } - this.searchInput.nativeElement.focus(); + if (this.searchInput) { + this.searchInput.nativeElement.focus(); + } } add() { From cf54af2c22a8344d67573d7185401ade04cf5588 Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Tue, 3 Sep 2024 13:43:02 +0200 Subject: [PATCH 0468/1286] 117803: Refactor Item Edit Bitstreams page to use HTML Table elements --- .../item-bitstreams.component.html | 11 +- .../item-bitstreams.component.scss | 20 +- .../item-edit-bitstream-bundle.component.html | 109 +++++++-- .../item-edit-bitstream-bundle.component.scss | 20 ++ .../item-edit-bitstream-bundle.component.ts | 216 +++++++++++++++++- ...-drag-and-drop-bitstream-list.component.ts | 4 + src/assets/i18n/en.json5 | 2 + 7 files changed, 336 insertions(+), 46 deletions(-) create mode 100644 src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.scss diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html index 4cb9577fcb..70f6ca55e8 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html @@ -23,16 +23,7 @@
-
-
-
- - {{'item.edit.bitstreams.headers.name' | translate}} -
-
{{'item.edit.bitstreams.headers.description' | translate}}
-
{{'item.edit.bitstreams.headers.format' | translate}}
-
{{'item.edit.bitstreams.headers.actions' | translate}}
-
+
-
-
- -
- {{'item.edit.bitstreams.bundle.name' | translate:{ name: dsoNameService.getName(bundle) } }} -
-
-
-
- -
-
-
- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ {{'item.edit.bitstreams.headers.name' | translate}} + + {{'item.edit.bitstreams.headers.description' | translate}} + + {{'item.edit.bitstreams.headers.format' | translate}} + + {{'item.edit.bitstreams.headers.actions' | translate}} +
+ {{'item.edit.bitstreams.bundle.name' | translate:{ name: bundleName } }} + + +
+ {{ entry.name }} + + {{ entry.description }} + + {{ (entry.format | async)?.shortDescription }} + +
+
+ + + + + + +
+
+
+ +
+
+ diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.scss b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.scss new file mode 100644 index 0000000000..d344b1657a --- /dev/null +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.scss @@ -0,0 +1,20 @@ +.header-row { + color: var(--bs-table-dark-color); + background-color: var(--bs-table-dark-bg); + border-color: var(--bs-table-dark-border-color); +} + +.bundle-row { + color: var(--bs-table-head-color); + background-color: var(--bs-table-head-bg); + border-color: var(--bs-table-border-color); +} + +.row-element { + padding: 0.75em; + border-bottom: var(--bs-table-border-width) solid var(--bs-table-border-color); +} + +.bitstream-name { + font-weight: normal; +} diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts index 70f4b63217..ad009e7cb7 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts @@ -5,10 +5,65 @@ import { ResponsiveColumnSizes } from '../../../../shared/responsive-table-sizes import { ResponsiveTableSizes } from '../../../../shared/responsive-table-sizes/responsive-table-sizes'; import { getItemPageRoute } from '../../../item-page-routing-paths'; import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; +import { RemoteData } from 'src/app/core/data/remote-data'; +import { PaginatedList } from 'src/app/core/data/paginated-list.model'; +import { Bitstream } from 'src/app/core/shared/bitstream.model'; +import { Observable, BehaviorSubject, switchMap } from 'rxjs'; +import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model'; +import { FieldUpdates } from '../../../../core/data/object-updates/field-updates.model'; +import { PaginatedSearchOptions } from '../../../../shared/search/models/paginated-search-options.model'; +import { BundleDataService } from '../../../../core/data/bundle-data.service'; +import { followLink } from '../../../../shared/utils/follow-link-config.model'; +import { + getAllSucceededRemoteData, + paginatedListToArray, + getFirstSucceededRemoteDataPayload, getFirstSucceededRemoteData +} from '../../../../core/shared/operators'; +import { ObjectUpdatesService } from '../../../../core/data/object-updates/object-updates.service'; +import { BitstreamFormat } from '../../../../core/shared/bitstream-format.model'; +import { map } from 'rxjs/operators'; +import { getBitstreamDownloadRoute } from '../../../../app-routing-paths'; +import { FieldChangeType } from '../../../../core/data/object-updates/field-change-type.model'; +import { FieldUpdate } from '../../../../core/data/object-updates/field-update.model'; +import { PaginationService } from '../../../../core/pagination/pagination.service'; + +/** + * Interface storing all the information necessary to create a row in the bitstream edit table + */ +export interface BitstreamTableEntry { + /** + * The bitstream + */ + bitstream: Bitstream, + /** + * The uuid of the Bitstream + */ + id: string, + /** + * The name of the Bitstream + */ + name: string, + /** + * The name of the Bitstream with all whitespace removed + */ + nameStripped: string, + /** + * The description of the Bitstream + */ + description: string, + /** + * Observable emitting the Format of the Bitstream + */ + format: Observable, + /** + * The download url of the Bitstream + */ + downloadUrl: string, +} @Component({ selector: 'ds-item-edit-bitstream-bundle', - styleUrls: ['../item-bitstreams.component.scss'], + styleUrls: ['../item-bitstreams.component.scss', './item-edit-bitstream-bundle.component.scss'], templateUrl: './item-edit-bitstream-bundle.component.html', }) /** @@ -17,6 +72,7 @@ import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; * (which means it'll be added to the parents html without a wrapping ds-item-edit-bitstream-bundle element) */ export class ItemEditBitstreamBundleComponent implements OnInit { + protected readonly FieldChangeType = FieldChangeType; /** * The view on the bundle information and bitstreams @@ -56,9 +112,48 @@ export class ItemEditBitstreamBundleComponent implements OnInit { */ itemPageRoute: string; + /** + * The name of the bundle + */ + bundleName: string; + + /** + * The bitstreams to show in the table + */ + bitstreamsRD$: Observable>>; + + /** + * The data to show in the table + */ + tableEntries$: Observable; + + /** + * The initial page options to use for fetching the bitstreams + */ + paginationOptions: PaginationComponentOptions; + + /** + * The current page options + */ + currentPaginationOptions$: BehaviorSubject; + + /** + * The self url of the bundle, also used when retrieving fieldUpdates + */ + bundleUrl: string; + + /** + * The updates to the current bitstreams + */ + updates$: Observable; + + constructor( protected viewContainerRef: ViewContainerRef, public dsoNameService: DSONameService, + protected bundleService: BundleDataService, + protected objectUpdatesService: ObjectUpdatesService, + protected paginationService: PaginationService, ) { } @@ -66,5 +161,124 @@ export class ItemEditBitstreamBundleComponent implements OnInit { this.bundleNameColumn = this.columnSizes.combineColumns(0, 2); this.viewContainerRef.createEmbeddedView(this.bundleView); this.itemPageRoute = getItemPageRoute(this.item); + this.bundleName = this.dsoNameService.getName(this.bundle); + this.bundleUrl = this.bundle.self; + + this.initializePagination(); + this.initializeBitstreams(); + + // this.bitstreamsRD = this. + } + + protected initializePagination() { + this.paginationOptions = Object.assign(new PaginationComponentOptions(),{ + id: this.bundleName, // This might behave unexpectedly if the item contains two bundles with the same name + currentPage: 1, + pageSize: 10 + }); + + this.currentPaginationOptions$ = new BehaviorSubject(this.paginationOptions); + + this.paginationService.getCurrentPagination(this.paginationOptions.id, this.paginationOptions) + .subscribe((pagination) => { + this.currentPaginationOptions$.next(pagination); + }); + } + + protected initializeBitstreams() { + this.bitstreamsRD$ = this.currentPaginationOptions$.pipe( + switchMap((page: PaginationComponentOptions) => { + const paginatedOptions = new PaginatedSearchOptions({ pagination: Object.assign({}, page) }); + return this.bundleService.getBitstreams(this.bundle.id, paginatedOptions, followLink('format')); + }), + ); + + this.bitstreamsRD$.pipe( + getFirstSucceededRemoteData(), + paginatedListToArray(), + ).subscribe((bitstreams) => { + this.objectUpdatesService.initialize(this.bundleUrl, bitstreams, new Date()); + }); + + this.updates$ = this.bitstreamsRD$.pipe( + getAllSucceededRemoteData(), + paginatedListToArray(), + switchMap((bitstreams) => this.objectUpdatesService.getFieldUpdatesExclusive(this.bundleUrl, bitstreams)) + ); + + this.tableEntries$ = this.bitstreamsRD$.pipe( + getAllSucceededRemoteData(), + paginatedListToArray(), + map((bitstreams) => { + return bitstreams.map((bitstream) => { + const name = this.dsoNameService.getName(bitstream); + + return { + bitstream: bitstream, + id: bitstream.uuid, + name: name, + nameStripped: this.stripWhiteSpace(name), + description: bitstream.firstMetadataValue('dc.description'), + format: bitstream.format.pipe(getFirstSucceededRemoteDataPayload()), + downloadUrl: getBitstreamDownloadRoute(bitstream), + }; + }); + }), + ); + } + + /** + * Check if a user should be allowed to remove this field + */ + canRemove(fieldUpdate: FieldUpdate): boolean { + return fieldUpdate.changeType !== FieldChangeType.REMOVE; + } + + /** + * Check if a user should be allowed to cancel the update to this field + */ + canUndo(fieldUpdate: FieldUpdate): boolean { + return fieldUpdate.changeType >= 0; + } + + /** + * Sends a new remove update for this field to the object updates service + */ + remove(bitstream: Bitstream): void { + this.objectUpdatesService.saveRemoveFieldUpdate(this.bundleUrl, bitstream); + } + + /** + * Cancels the current update for this field in the object updates service + */ + undo(bitstream: Bitstream): void { + this.objectUpdatesService.removeSingleFieldUpdate(this.bundleUrl, bitstream.uuid); + } + + getRowClass(update: FieldUpdate): string { + switch (update.changeType) { + case FieldChangeType.UPDATE: + return 'table-warning'; + case FieldChangeType.ADD: + return 'table-success'; + case FieldChangeType.REMOVE: + return 'table-danger'; + default: + return 'bg-white'; + } + } + + /** + * Returns a string equal to the input string with all whitespace removed. + * @param str + */ + // Whitespace is stripped from the Bitstream names for accessibility reasons. + // To make it clear which headers are relevant for a specific field in the table, the 'headers' attribute is used to + // refer to specific headers. The Bitstream's name is used as header ID for the row containing information regarding + // that bitstream. As the 'headers' attribute contains a space-separated string of header IDs, the Bitstream's header + // ID can not contain strings itself. + stripWhiteSpace(str: string): string { + // '/\s+/g' matches all occurrences of any amount of whitespace characters + return str.replace(/\s+/g, ''); } } diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.ts index 2c81a4e2cb..d5bb9eceea 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.ts @@ -24,6 +24,10 @@ import { PaginationComponentOptions } from '../../../../../shared/pagination/pag * bitstreams within the paginated list. To drag and drop a bitstream between two pages, drag the row on top of the * page number you want the bitstream to end up at. Doing so will add the bitstream to the top of that page. */ +// NOTE: +// This component was used by the item-edit-bitstream-bundle.component, but this is no longer the case. It is left here +// as a reference for the drag-and-drop functionality. This component (and the abstract version it extends) should be +// removed once this reference is no longer useful. export class PaginatedDragAndDropBitstreamListComponent extends AbstractPaginatedDragAndDropListComponent implements OnInit { /** * The bundle to display bitstreams for diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 6c91bae4c1..4d5ef9ee1b 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1934,6 +1934,8 @@ "item.edit.bitstreams.bundle.name": "BUNDLE: {{ name }}", + "item.edit.bitstreams.bundle.table.aria-label": "Bitstreams in the {{ bundle }} Bundle", + "item.edit.bitstreams.discard-button": "Discard", "item.edit.bitstreams.edit.buttons.download": "Download", From a11bfc80ad5b087aab9c6e283a08f0db2f87d5ed Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Tue, 3 Sep 2024 14:24:31 +0200 Subject: [PATCH 0469/1286] 117803: Hide table headers for subsequent bundle tables --- .../item-bitstreams/item-bitstreams.component.html | 3 ++- .../item-edit-bitstream-bundle.component.html | 14 +++++++++----- .../item-edit-bitstream-bundle.component.ts | 5 +++++ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html index 70f6ca55e8..f22dbe6a0e 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html @@ -24,10 +24,11 @@
-
diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html index c11035e305..a95a7921a4 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html @@ -10,7 +10,7 @@ - + - - - - diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.scss b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.scss index d344b1657a..725d329936 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.scss +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.scss @@ -18,3 +18,12 @@ .bitstream-name { font-weight: normal; } + +.pagination-control-container { + display: flex; +} + +.pagination-control { + padding: 0 0.1rem; + vertical-align: center; +} diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts index ae6bc0876c..2a84c00c02 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts @@ -26,6 +26,8 @@ import { getBitstreamDownloadRoute } from '../../../../app-routing-paths'; import { FieldChangeType } from '../../../../core/data/object-updates/field-change-type.model'; import { FieldUpdate } from '../../../../core/data/object-updates/field-update.model'; import { PaginationService } from '../../../../core/pagination/pagination.service'; +import { SortDirection } from '../../../../core/cache/models/sort-options.model'; +import { PaginationComponent } from '../../../../shared/pagination/pagination.component'; /** * Interface storing all the information necessary to create a row in the bitstream edit table @@ -79,6 +81,8 @@ export class ItemEditBitstreamBundleComponent implements OnInit { */ @ViewChild('bundleView', {static: true}) bundleView; + @ViewChild(PaginationComponent) paginationComponent: PaginationComponent; + /** * The bundle to display bitstreams for */ @@ -142,6 +146,16 @@ export class ItemEditBitstreamBundleComponent implements OnInit { */ currentPaginationOptions$: BehaviorSubject; + /** + * The available page size options + */ + pageSizeOptions: number[]; + + /** + * The currently selected page size + */ + pageSize$: BehaviorSubject; + /** * The self url of the bundle, also used when retrieving fieldUpdates */ @@ -182,11 +196,15 @@ export class ItemEditBitstreamBundleComponent implements OnInit { pageSize: 10 }); + this.pageSizeOptions = this.paginationOptions.pageSizeOptions; + this.currentPaginationOptions$ = new BehaviorSubject(this.paginationOptions); + this.pageSize$ = new BehaviorSubject(this.paginationOptions.pageSize); this.paginationService.getCurrentPagination(this.paginationOptions.id, this.paginationOptions) .subscribe((pagination) => { this.currentPaginationOptions$.next(pagination); + this.pageSize$.next(pagination.pageSize); }); } @@ -286,4 +304,9 @@ export class ItemEditBitstreamBundleComponent implements OnInit { // '/\s+/g' matches all occurrences of any amount of whitespace characters return str.replace(/\s+/g, ''); } + + public doPageSizeChange(pageSize: number) { + this.paginationComponent.doPageSizeChange(pageSize); + } + } From d85124c121db1ef88f3015cfdc333bfe1b8c9ce3 Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Wed, 4 Sep 2024 14:32:29 +0200 Subject: [PATCH 0471/1286] 117803: Fix deleted bitstreams not being removed from list --- .../item-edit-bitstream-bundle.component.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts index 2a84c00c02..6ef15397b0 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts @@ -26,8 +26,8 @@ import { getBitstreamDownloadRoute } from '../../../../app-routing-paths'; import { FieldChangeType } from '../../../../core/data/object-updates/field-change-type.model'; import { FieldUpdate } from '../../../../core/data/object-updates/field-update.model'; import { PaginationService } from '../../../../core/pagination/pagination.service'; -import { SortDirection } from '../../../../core/cache/models/sort-options.model'; import { PaginationComponent } from '../../../../shared/pagination/pagination.component'; +import { RequestService } from '../../../../core/data/request.service'; /** * Interface storing all the information necessary to create a row in the bitstream edit table @@ -173,6 +173,7 @@ export class ItemEditBitstreamBundleComponent implements OnInit { protected bundleService: BundleDataService, protected objectUpdatesService: ObjectUpdatesService, protected paginationService: PaginationService, + protected requestService: RequestService, ) { } @@ -212,7 +213,14 @@ export class ItemEditBitstreamBundleComponent implements OnInit { this.bitstreamsRD$ = this.currentPaginationOptions$.pipe( switchMap((page: PaginationComponentOptions) => { const paginatedOptions = new PaginatedSearchOptions({ pagination: Object.assign({}, page) }); - return this.bundleService.getBitstreams(this.bundle.id, paginatedOptions, followLink('format')); + return this.bundleService.getBitstreamsEndpoint(this.bundle.id, paginatedOptions).pipe( + switchMap((href) => this.requestService.hasByHref$(href)), + switchMap(() => this.bundleService.getBitstreams( + this.bundle.id, + paginatedOptions, + followLink('format') + )) + ); }), ); From 374a9ae14eb036c1bf91eec2891aa722722545ed Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Wed, 4 Sep 2024 15:46:04 +0200 Subject: [PATCH 0472/1286] 117803: Add item-bitstream service --- .../item-bitstreams.component.ts | 82 ++------- .../item-bitstreams.service.ts | 158 ++++++++++++++++++ .../item-edit-bitstream-bundle.component.ts | 41 +---- 3 files changed, 176 insertions(+), 105 deletions(-) create mode 100644 src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.ts diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts index ee53bd919c..9f27cf11b3 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts @@ -8,23 +8,19 @@ import { ActivatedRoute, Router } from '@angular/router'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; import { BitstreamDataService } from '../../../core/data/bitstream-data.service'; -import { hasValue, isNotEmpty } from '../../../shared/empty.util'; +import { hasValue } from '../../../shared/empty.util'; import { ObjectCacheService } from '../../../core/cache/object-cache.service'; import { RequestService } from '../../../core/data/request.service'; import { getFirstSucceededRemoteData, getRemoteDataPayload } from '../../../core/shared/operators'; import { RemoteData } from '../../../core/data/remote-data'; import { PaginatedList } from '../../../core/data/paginated-list.model'; import { Bundle } from '../../../core/shared/bundle.model'; -import { Bitstream } from '../../../core/shared/bitstream.model'; import { BundleDataService } from '../../../core/data/bundle-data.service'; import { PaginatedSearchOptions } from '../../../shared/search/models/paginated-search-options.model'; -import { ResponsiveColumnSizes } from '../../../shared/responsive-table-sizes/responsive-column-sizes'; import { ResponsiveTableSizes } from '../../../shared/responsive-table-sizes/responsive-table-sizes'; import { NoContent } from '../../../core/shared/NoContent.model'; import { Operation } from 'fast-json-patch'; -import { FieldUpdate } from '../../../core/data/object-updates/field-update.model'; -import { FieldUpdates } from '../../../core/data/object-updates/field-updates.model'; -import { FieldChangeType } from '../../../core/data/object-updates/field-change-type.model'; +import { ItemBitstreamsService } from './item-bitstreams.service'; @Component({ selector: 'ds-item-bitstreams', @@ -41,28 +37,10 @@ export class ItemBitstreamsComponent extends AbstractItemUpdateComponent impleme */ bundles$: Observable; - /** - * The page options to use for fetching the bundles - */ - bundlesOptions = { - id: 'bundles-pagination-options', - currentPage: 1, - pageSize: 9999 - } as any; - /** * The bootstrap sizes used for the columns within this table */ - columnSizes = new ResponsiveTableSizes([ - // Name column - new ResponsiveColumnSizes(2, 2, 3, 4, 4), - // Description column - new ResponsiveColumnSizes(2, 3, 3, 3, 3), - // Format column - new ResponsiveColumnSizes(2, 2, 2, 2, 2), - // Actions column - new ResponsiveColumnSizes(6, 5, 4, 3, 3) - ]); + columnSizes: ResponsiveTableSizes; /** * Are we currently submitting the changes? @@ -88,16 +66,21 @@ export class ItemBitstreamsComponent extends AbstractItemUpdateComponent impleme public requestService: RequestService, public cdRef: ChangeDetectorRef, public bundleService: BundleDataService, - public zone: NgZone + public zone: NgZone, + public itemBitstreamsService: ItemBitstreamsService, ) { super(itemService, objectUpdatesService, router, notificationsService, translateService, route); + + this.columnSizes = this.itemBitstreamsService.getColumnSizes(); } /** * Actions to perform after the item has been initialized */ postItemInit(): void { - this.bundles$ = this.itemService.getBundles(this.item.id, new PaginatedSearchOptions({pagination: this.bundlesOptions})).pipe( + const bundlesOptions = this.itemBitstreamsService.getInitialBundlesPaginationOptions(); + + this. bundles$ = this.itemService.getBundles(this.item.id, new PaginatedSearchOptions({pagination: bundlesOptions})).pipe( getFirstSucceededRemoteData(), getRemoteDataPayload(), map((bundlePage: PaginatedList) => bundlePage.page) @@ -119,30 +102,12 @@ export class ItemBitstreamsComponent extends AbstractItemUpdateComponent impleme */ submit() { this.submitting = true; - const bundlesOnce$ = this.bundles$.pipe(take(1)); - // Fetch all removed bitstreams from the object update service - const removedBitstreams$ = bundlesOnce$.pipe( - switchMap((bundles: Bundle[]) => observableZip( - ...bundles.map((bundle: Bundle) => this.objectUpdatesService.getFieldUpdates(bundle.self, [], true)) - )), - map((fieldUpdates: FieldUpdates[]) => ([] as FieldUpdate[]).concat( - ...fieldUpdates.map((updates: FieldUpdates) => Object.values(updates).filter((fieldUpdate: FieldUpdate) => fieldUpdate.changeType === FieldChangeType.REMOVE)) - )), - map((fieldUpdates: FieldUpdate[]) => fieldUpdates.map((fieldUpdate: FieldUpdate) => fieldUpdate.field)) - ); - - // Send out delete requests for all deleted bitstreams - const removedResponses$: Observable> = removedBitstreams$.pipe( - take(1), - switchMap((removedBitstreams: Bitstream[]) => { - return this.bitstreamService.removeMultiple(removedBitstreams); - }) - ); + const removedResponses$ = this.itemBitstreamsService.removeMarkedBitstreams(this.bundles$); // Perform the setup actions from above in order and display notifications removedResponses$.subscribe((responses: RemoteData) => { - this.displayNotifications('item.edit.bitstreams.notifications.remove', [responses]); + this.itemBitstreamsService.displayNotifications('item.edit.bitstreams.notifications.remove', [responses]); this.submitting = false; }); } @@ -164,7 +129,7 @@ export class ItemBitstreamsComponent extends AbstractItemUpdateComponent impleme } as Operation; this.bundleService.patch(bundle, [moveOperation]).pipe(take(1)).subscribe((response: RemoteData) => { this.zone.run(() => { - this.displayNotifications('item.edit.bitstreams.notifications.move', [response]); + this.itemBitstreamsService.displayNotifications('item.edit.bitstreams.notifications.move', [response]); // Remove all cached requests from this bundle and call the event's callback when the requests are cleared this.requestService.removeByHrefSubstring(bundle.self).pipe( filter((isCached) => isCached), @@ -176,27 +141,6 @@ export class ItemBitstreamsComponent extends AbstractItemUpdateComponent impleme }); } - /** - * Display notifications - * - Error notification for each failed response with their message - * - Success notification in case there's at least one successful response - * @param key The i18n key for the notification messages - * @param responses The returned responses to display notifications for - */ - displayNotifications(key: string, responses: RemoteData[]) { - if (isNotEmpty(responses)) { - const failedResponses = responses.filter((response: RemoteData) => hasValue(response) && response.hasFailed); - const successfulResponses = responses.filter((response: RemoteData) => hasValue(response) && response.hasSucceeded); - - failedResponses.forEach((response: RemoteData) => { - this.notificationsService.error(this.translateService.instant(`${key}.failed.title`), response.errorMessage); - }); - if (successfulResponses.length > 0) { - this.notificationsService.success(this.translateService.instant(`${key}.saved.title`), this.translateService.instant(`${key}.saved.content`)); - } - } - } - /** * Request the object updates service to discard all current changes to this item * Shows a notification to remind the user that they can undo this diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.ts new file mode 100644 index 0000000000..487df77b28 --- /dev/null +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.ts @@ -0,0 +1,158 @@ +import { Injectable } from '@angular/core'; +import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; +import { ResponsiveTableSizes } from '../../../shared/responsive-table-sizes/responsive-table-sizes'; +import { ResponsiveColumnSizes } from '../../../shared/responsive-table-sizes/responsive-column-sizes'; +import { RemoteData } from '../../../core/data/remote-data'; +import { isNotEmpty, hasValue } from '../../../shared/empty.util'; +import { Bundle } from '../../../core/shared/bundle.model'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { TranslateService } from '@ngx-translate/core'; +import { Observable, zip as observableZip } from 'rxjs'; +import { NoContent } from '../../../core/shared/NoContent.model'; +import { take, switchMap, map } from 'rxjs/operators'; +import { FieldUpdates } from '../../../core/data/object-updates/field-updates.model'; +import { FieldUpdate } from '../../../core/data/object-updates/field-update.model'; +import { FieldChangeType } from '../../../core/data/object-updates/field-change-type.model'; +import { Bitstream } from '../../../core/shared/bitstream.model'; +import { ObjectUpdatesService } from '../../../core/data/object-updates/object-updates.service'; +import { BitstreamDataService } from '../../../core/data/bitstream-data.service'; +import { BitstreamTableEntry } from './item-edit-bitstream-bundle/item-edit-bitstream-bundle.component'; +import { getFirstSucceededRemoteDataPayload } from '../../../core/shared/operators'; +import { getBitstreamDownloadRoute } from '../../../app-routing-paths'; +import { DSONameService } from '../../../core/breadcrumbs/dso-name.service'; + +@Injectable( + { providedIn: 'root' }, +) +export class ItemBitstreamsService { + + constructor( + protected notificationsService: NotificationsService, + protected translateService: TranslateService, + protected objectUpdatesService: ObjectUpdatesService, + protected bitstreamService: BitstreamDataService, + protected dsoNameService: DSONameService, + ) { + } + + /** + * Returns the pagination options to use when fetching the bundles + */ + getInitialBundlesPaginationOptions(): PaginationComponentOptions { + return Object.assign(new PaginationComponentOptions(), { + id: 'bundles-pagination-options', + currentPage: 1, + pageSize: 9999 + }); + } + + getInitialBitstreamsPaginationOptions(bundleName: string): PaginationComponentOptions { + return Object.assign(new PaginationComponentOptions(),{ + id: bundleName, // This might behave unexpectedly if the item contains two bundles with the same name + currentPage: 1, + pageSize: 10 + }); + } + + /** + * Returns the {@link ResponsiveTableSizes} for use in the columns of the edit bitstreams table + */ + getColumnSizes(): ResponsiveTableSizes { + return new ResponsiveTableSizes([ + // Name column + new ResponsiveColumnSizes(2, 2, 3, 4, 4), + // Description column + new ResponsiveColumnSizes(2, 3, 3, 3, 3), + // Format column + new ResponsiveColumnSizes(2, 2, 2, 2, 2), + // Actions column + new ResponsiveColumnSizes(6, 5, 4, 3, 3) + ]); + } + + /** + * Display notifications + * - Error notification for each failed response with their message + * - Success notification in case there's at least one successful response + * @param key The i18n key for the notification messages + * @param responses The returned responses to display notifications for + */ + displayNotifications(key: string, responses: RemoteData[]) { + if (isNotEmpty(responses)) { + const failedResponses = responses.filter((response: RemoteData) => hasValue(response) && response.hasFailed); + const successfulResponses = responses.filter((response: RemoteData) => hasValue(response) && response.hasSucceeded); + + failedResponses.forEach((response: RemoteData) => { + this.notificationsService.error(this.translateService.instant(`${key}.failed.title`), response.errorMessage); + }); + if (successfulResponses.length > 0) { + this.notificationsService.success(this.translateService.instant(`${key}.saved.title`), this.translateService.instant(`${key}.saved.content`)); + } + } + } + + /** + * Removes the bitstreams marked for deletion from the Bundles emitted by the provided observable. + * @param bundles$ + */ + removeMarkedBitstreams(bundles$: Observable): Observable> { + const bundlesOnce$ = bundles$.pipe(take(1)); + + // Fetch all removed bitstreams from the object update service + const removedBitstreams$ = bundlesOnce$.pipe( + switchMap((bundles: Bundle[]) => observableZip( + ...bundles.map((bundle: Bundle) => this.objectUpdatesService.getFieldUpdates(bundle.self, [], true)) + )), + map((fieldUpdates: FieldUpdates[]) => ([] as FieldUpdate[]).concat( + ...fieldUpdates.map((updates: FieldUpdates) => Object.values(updates).filter((fieldUpdate: FieldUpdate) => fieldUpdate.changeType === FieldChangeType.REMOVE)) + )), + map((fieldUpdates: FieldUpdate[]) => fieldUpdates.map((fieldUpdate: FieldUpdate) => fieldUpdate.field)) + ); + + // Send out delete requests for all deleted bitstreams + return removedBitstreams$.pipe( + take(1), + switchMap((removedBitstreams: Bitstream[]) => { + return this.bitstreamService.removeMultiple(removedBitstreams); + }) + ); + } + + mapBitstreamsToTableEntries(bitstreams: Bitstream[]): BitstreamTableEntry[] { + return bitstreams.map((bitstream) => { + const name = this.dsoNameService.getName(bitstream); + + return { + bitstream: bitstream, + id: bitstream.uuid, + name: name, + nameStripped: this.nameToHeader(name), + description: bitstream.firstMetadataValue('dc.description'), + format: bitstream.format.pipe(getFirstSucceededRemoteDataPayload()), + downloadUrl: getBitstreamDownloadRoute(bitstream), + }; + }); + } + + /** + * Returns a string appropriate to be used as header ID + * @param name + */ + nameToHeader(name: string): string { + // Whitespace is stripped from the Bitstream names for accessibility reasons. + // To make it clear which headers are relevant for a specific field in the table, the 'headers' attribute is used to + // refer to specific headers. The Bitstream's name is used as header ID for the row containing information regarding + // that bitstream. As the 'headers' attribute contains a space-separated string of header IDs, the Bitstream's header + // ID can not contain strings itself. + return this.stripWhiteSpace(name); + } + + /** + * Returns a string equal to the input string with all whitespace removed. + * @param str + */ + stripWhiteSpace(str: string): string { + // '/\s+/g' matches all occurrences of any amount of whitespace characters + return str.replace(/\s+/g, ''); + } +} diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts index 6ef15397b0..9c62fe06e7 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts @@ -17,17 +17,17 @@ import { followLink } from '../../../../shared/utils/follow-link-config.model'; import { getAllSucceededRemoteData, paginatedListToArray, - getFirstSucceededRemoteDataPayload, getFirstSucceededRemoteData + getFirstSucceededRemoteData } from '../../../../core/shared/operators'; import { ObjectUpdatesService } from '../../../../core/data/object-updates/object-updates.service'; import { BitstreamFormat } from '../../../../core/shared/bitstream-format.model'; import { map } from 'rxjs/operators'; -import { getBitstreamDownloadRoute } from '../../../../app-routing-paths'; import { FieldChangeType } from '../../../../core/data/object-updates/field-change-type.model'; import { FieldUpdate } from '../../../../core/data/object-updates/field-update.model'; import { PaginationService } from '../../../../core/pagination/pagination.service'; import { PaginationComponent } from '../../../../shared/pagination/pagination.component'; import { RequestService } from '../../../../core/data/request.service'; +import { ItemBitstreamsService } from '../item-bitstreams.service'; /** * Interface storing all the information necessary to create a row in the bitstream edit table @@ -174,6 +174,7 @@ export class ItemEditBitstreamBundleComponent implements OnInit { protected objectUpdatesService: ObjectUpdatesService, protected paginationService: PaginationService, protected requestService: RequestService, + protected itemBitstreamsService: ItemBitstreamsService, ) { } @@ -191,11 +192,7 @@ export class ItemEditBitstreamBundleComponent implements OnInit { } protected initializePagination() { - this.paginationOptions = Object.assign(new PaginationComponentOptions(),{ - id: this.bundleName, // This might behave unexpectedly if the item contains two bundles with the same name - currentPage: 1, - pageSize: 10 - }); + this.paginationOptions = this.itemBitstreamsService.getInitialBitstreamsPaginationOptions(this.bundleName); this.pageSizeOptions = this.paginationOptions.pageSizeOptions; @@ -240,21 +237,7 @@ export class ItemEditBitstreamBundleComponent implements OnInit { this.tableEntries$ = this.bitstreamsRD$.pipe( getAllSucceededRemoteData(), paginatedListToArray(), - map((bitstreams) => { - return bitstreams.map((bitstream) => { - const name = this.dsoNameService.getName(bitstream); - - return { - bitstream: bitstream, - id: bitstream.uuid, - name: name, - nameStripped: this.stripWhiteSpace(name), - description: bitstream.firstMetadataValue('dc.description'), - format: bitstream.format.pipe(getFirstSucceededRemoteDataPayload()), - downloadUrl: getBitstreamDownloadRoute(bitstream), - }; - }); - }), + map((bitstreams) => this.itemBitstreamsService.mapBitstreamsToTableEntries(bitstreams)), ); } @@ -299,20 +282,6 @@ export class ItemEditBitstreamBundleComponent implements OnInit { } } - /** - * Returns a string equal to the input string with all whitespace removed. - * @param str - */ - // Whitespace is stripped from the Bitstream names for accessibility reasons. - // To make it clear which headers are relevant for a specific field in the table, the 'headers' attribute is used to - // refer to specific headers. The Bitstream's name is used as header ID for the row containing information regarding - // that bitstream. As the 'headers' attribute contains a space-separated string of header IDs, the Bitstream's header - // ID can not contain strings itself. - stripWhiteSpace(str: string): string { - // '/\s+/g' matches all occurrences of any amount of whitespace characters - return str.replace(/\s+/g, ''); - } - public doPageSizeChange(pageSize: number) { this.paginationComponent.doPageSizeChange(pageSize); } From 3f4bf7ce0fdf73494bcb28045ef6d7cb8a4634dd Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Wed, 4 Sep 2024 16:32:30 +0200 Subject: [PATCH 0473/1286] 117803: Fix existing tests --- ...em-edit-bitstream-bundle.component.spec.ts | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.spec.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.spec.ts index c26f99eb8f..1502ad2311 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.spec.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.spec.ts @@ -6,6 +6,15 @@ import { Item } from '../../../../core/shared/item.model'; import { Bundle } from '../../../../core/shared/bundle.model'; import { ResponsiveTableSizes } from '../../../../shared/responsive-table-sizes/responsive-table-sizes'; import { ResponsiveColumnSizes } from '../../../../shared/responsive-table-sizes/responsive-column-sizes'; +import { BundleDataService } from '../../../../core/data/bundle-data.service'; +import { of as observableOf } from 'rxjs'; +import { ObjectUpdatesService } from '../../../../core/data/object-updates/object-updates.service'; +import { PaginationServiceStub } from '../../../../shared/testing/pagination-service.stub'; +import { RequestService } from '../../../../core/data/request.service'; +import { getMockRequestService } from '../../../../shared/mocks/request.service.mock'; +import { ItemBitstreamsService } from '../item-bitstreams.service'; +import { PaginationService } from '../../../../core/pagination/pagination.service'; +import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model'; describe('ItemEditBitstreamBundleComponent', () => { let comp: ItemEditBitstreamBundleComponent; @@ -31,10 +40,37 @@ describe('ItemEditBitstreamBundleComponent', () => { } }); + const restEndpoint = 'fake-rest-endpoint'; + const bundleService = jasmine.createSpyObj('bundleService', { + getBitstreamsEndpoint: observableOf(restEndpoint), + getBitstreams: null, + }); + + const objectUpdatesService = { + initialize: () => { + // do nothing + }, + }; + + const itemBitstreamsService = jasmine.createSpyObj('itemBitstreamsService', { + getInitialBitstreamsPaginationOptions: Object.assign(new PaginationComponentOptions(), { + id: 'bundles-pagination-options', + currentPage: 1, + pageSize: 9999 + }), + }); + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot()], declarations: [ItemEditBitstreamBundleComponent], + providers: [ + { provide: BundleDataService, useValue: bundleService }, + { provide: ObjectUpdatesService, useValue: objectUpdatesService }, + { provide: PaginationService, useValue: new PaginationServiceStub() }, + { provide: RequestService, useValue: getMockRequestService() }, + { provide: ItemBitstreamsService, useValue: itemBitstreamsService }, + ], schemas: [ NO_ERRORS_SCHEMA ] From d8b426d7458da47320447a85e3c2fb4c7028f20c Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Thu, 5 Sep 2024 10:52:02 +0200 Subject: [PATCH 0474/1286] 117803: Add ItemBitsreamsService tests --- .../object-updates.service.stub.ts | 28 ++++ .../item-bitstreams.service.spec.ts | 129 ++++++++++++++++++ 2 files changed, 157 insertions(+) create mode 100644 src/app/core/data/object-updates/object-updates.service.stub.ts create mode 100644 src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.spec.ts diff --git a/src/app/core/data/object-updates/object-updates.service.stub.ts b/src/app/core/data/object-updates/object-updates.service.stub.ts new file mode 100644 index 0000000000..c41728a338 --- /dev/null +++ b/src/app/core/data/object-updates/object-updates.service.stub.ts @@ -0,0 +1,28 @@ +export class ObjectUpdatesServiceStub { + + initialize = jasmine.createSpy('initialize'); + saveFieldUpdate = jasmine.createSpy('saveFieldUpdate'); + getObjectEntry = jasmine.createSpy('getObjectEntry'); + getFieldState = jasmine.createSpy('getFieldState'); + getFieldUpdates = jasmine.createSpy('getFieldUpdates'); + getFieldUpdatesExclusive = jasmine.createSpy('getFieldUpdatesExclusive'); + isValid = jasmine.createSpy('isValid'); + isValidPage = jasmine.createSpy('isValidPage'); + saveAddFieldUpdate = jasmine.createSpy('saveAddFieldUpdate'); + saveRemoveFieldUpdate = jasmine.createSpy('saveRemoveFieldUpdate'); + saveChangeFieldUpdate = jasmine.createSpy('saveChangeFieldUpdate'); + isSelectedVirtualMetadata = jasmine.createSpy('isSelectedVirtualMetadata'); + setSelectedVirtualMetadata = jasmine.createSpy('setSelectedVirtualMetadata'); + setEditableFieldUpdate = jasmine.createSpy('setEditableFieldUpdate'); + setValidFieldUpdate = jasmine.createSpy('setValidFieldUpdate'); + discardFieldUpdates = jasmine.createSpy('discardFieldUpdates'); + discardAllFieldUpdates = jasmine.createSpy('discardAllFieldUpdates'); + reinstateFieldUpdates = jasmine.createSpy('reinstateFieldUpdates'); + removeSingleFieldUpdate = jasmine.createSpy('removeSingleFieldUpdate'); + getUpdateFields = jasmine.createSpy('getUpdateFields'); + hasUpdates = jasmine.createSpy('hasUpdates'); + isReinstatable = jasmine.createSpy('isReinstatable'); + getLastModified = jasmine.createSpy('getLastModified'); + createPatch = jasmine.createSpy('getPatch'); + +} diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.spec.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.spec.ts new file mode 100644 index 0000000000..89ecfb518f --- /dev/null +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.spec.ts @@ -0,0 +1,129 @@ +import { ItemBitstreamsService } from './item-bitstreams.service'; +import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub'; +import { getMockTranslateService } from '../../../shared/mocks/translate.service.mock'; +import { ObjectUpdatesServiceStub } from '../../../core/data/object-updates/object-updates.service.stub'; +import { BitstreamDataServiceStub } from '../../../shared/testing/bitstream-data-service.stub'; +import { DSONameServiceMock } from '../../../shared/mocks/dso-name.service.mock'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { ObjectUpdatesService } from '../../../core/data/object-updates/object-updates.service'; +import { TranslateService } from '@ngx-translate/core'; +import { BitstreamDataService } from '../../../core/data/bitstream-data.service'; +import { DSONameService } from '../../../core/breadcrumbs/dso-name.service'; +import { Bitstream } from '../../../core/shared/bitstream.model'; +import { BitstreamFormat } from '../../../core/shared/bitstream-format.model'; +import { + createSuccessfulRemoteDataObject$, + createFailedRemoteDataObject, + createSuccessfulRemoteDataObject +} from '../../../shared/remote-data.utils'; + +describe('ItemBitstreamsService', () => { + let service: ItemBitstreamsService; + let notificationsService: NotificationsService; + let translateService: TranslateService; + let objectUpdatesService: ObjectUpdatesService; + let bitstreamDataService: BitstreamDataService; + let dsoNameService: DSONameService; + + beforeEach(() => { + notificationsService = new NotificationsServiceStub() as any; + translateService = getMockTranslateService(); + objectUpdatesService = new ObjectUpdatesServiceStub() as any; + bitstreamDataService = new BitstreamDataServiceStub() as any; + dsoNameService = new DSONameServiceMock() as any; + + service = new ItemBitstreamsService( + notificationsService, + translateService, + objectUpdatesService, + bitstreamDataService, + dsoNameService, + ); + }); + + describe('displayNotifications', () => { + it('should display an error notification if a response failed', () => { + const responses = [ + createFailedRemoteDataObject(), + ]; + + const key = 'some.key'; + + service.displayNotifications(key, responses); + + expect(notificationsService.success).not.toHaveBeenCalled(); + expect(notificationsService.error).toHaveBeenCalled(); + expect(translateService.instant).toHaveBeenCalledWith('some.key.failed.title'); + }); + + it('should display a success notification if a response succeeded', () => { + const responses = [ + createSuccessfulRemoteDataObject(undefined), + ]; + + const key = 'some.key'; + + service.displayNotifications(key, responses); + + expect(notificationsService.success).toHaveBeenCalled(); + expect(notificationsService.error).not.toHaveBeenCalled(); + expect(translateService.instant).toHaveBeenCalledWith('some.key.saved.title'); + }); + + it('should display both notifications if some failed and some succeeded', () => { + const responses = [ + createFailedRemoteDataObject(), + createSuccessfulRemoteDataObject(undefined), + ]; + + const key = 'some.key'; + + service.displayNotifications(key, responses); + + expect(notificationsService.success).toHaveBeenCalled(); + expect(notificationsService.error).toHaveBeenCalled(); + expect(translateService.instant).toHaveBeenCalledWith('some.key.saved.title'); + expect(translateService.instant).toHaveBeenCalledWith('some.key.saved.title'); + }); + }); + + describe('mapBitstreamsToTableEntries', () => { + it('should correctly map a Bitstream to a BitstreamTableEntry', () => { + const format: BitstreamFormat = new BitstreamFormat(); + + const bitstream: Bitstream = Object.assign(new Bitstream(), { + uuid: 'testUUID', + format: createSuccessfulRemoteDataObject$(format), + }); + + spyOn(dsoNameService, 'getName').and.returnValue('Test Name'); + spyOn(bitstream, 'firstMetadataValue').and.returnValue('description'); + + const tableEntry = service.mapBitstreamsToTableEntries([bitstream])[0]; + + expect(tableEntry.name).toEqual('Test Name'); + expect(tableEntry.nameStripped).toEqual('TestName'); + expect(tableEntry.bitstream).toBe(bitstream); + expect(tableEntry.id).toEqual('testUUID'); + expect(tableEntry.description).toEqual('description'); + expect(tableEntry.downloadUrl).toEqual('/bitstreams/testUUID/download'); + }); + }); + + describe('nameToHeader', () => { + it('should correctly transform a string to an appropriate header ID', () => { + const stringA = 'Test String'; + const stringAResult = 'TestString'; + expect(service.nameToHeader(stringA)).toEqual(stringAResult); + + const stringB = 'Test String Two'; + const stringBResult = 'TestStringTwo'; + expect(service.nameToHeader(stringB)).toEqual(stringBResult); + + const stringC = 'Test String Three'; + const stringCResult = 'TestStringThree'; + expect(service.nameToHeader(stringC)).toEqual(stringCResult); + }); + }); + +}); From cc5b841a65ee396a2622ca3eceb1f2d9bbce07c7 Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Tue, 10 Sep 2024 13:36:27 +0200 Subject: [PATCH 0475/1286] 117803: Only visually hide header rows --- .../item-edit-bitstream-bundle.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html index 6a505b9274..2eb1a151b7 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html @@ -10,7 +10,7 @@
{{'item.edit.bitstreams.headers.name' | translate}} @@ -45,16 +45,20 @@
+ {{ entry.name }} + {{ entry.description }} + {{ (entry.format | async)?.shortDescription }} + - + +
+ +
+ + + +
+
+
- + - + @@ -31,7 +31,7 @@ (versionsHistoryChange)="getAllVersions($event)" > - + (cdkDragStarted)="dragStart(entry.name)" (cdkDragEnded)="dragEnd(entry.name)">
{{'item.edit.bitstreams.headers.name' | translate}} From 8481604b1eb63acdc152fc9b7061bb9cd464294e Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Tue, 10 Sep 2024 14:14:58 +0200 Subject: [PATCH 0476/1286] 117803: Fix table & pagination margin --- .../item-bitstreams/item-bitstreams.component.scss | 4 ++++ .../item-edit-bitstream-bundle.component.scss | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.scss b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.scss index 480bf56cc7..662c999461 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.scss +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.scss @@ -42,3 +42,7 @@ .table-border { border: 1px solid #dee2e6; } + +:host ::ng-deep .pagination { + padding-top: 0.5rem; +} diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.scss b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.scss index 725d329936..ae4eac8d52 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.scss +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.scss @@ -27,3 +27,7 @@ padding: 0 0.1rem; vertical-align: center; } + +.table { + margin-bottom: 0; +} From 79f3a3116e2e358d5d7b778324d15c4977c7d55f Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Tue, 10 Sep 2024 14:35:05 +0200 Subject: [PATCH 0477/1286] 117803: Set header border to background color --- .../item-edit-bitstream-bundle.component.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.scss b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.scss index ae4eac8d52..7088c3978e 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.scss +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.scss @@ -1,7 +1,7 @@ .header-row { color: var(--bs-table-dark-color); background-color: var(--bs-table-dark-bg); - border-color: var(--bs-table-dark-border-color); + border-color: var(--bs-table-dark-bg); } .bundle-row { From 6a8095d456167a139d320c4ad5c3a3d8a20a365e Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Tue, 10 Sep 2024 15:00:18 +0200 Subject: [PATCH 0478/1286] 117803: Change pagination settings styling --- .../item-edit-bitstream-bundle.component.html | 4 ++-- .../item-edit-bitstream-bundle.component.scss | 9 --------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html index 2eb1a151b7..f434bf0f8f 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html @@ -41,8 +41,8 @@ title="{{'item.edit.bitstreams.bundle.edit.buttons.upload' | translate}}"> -
- diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.scss b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.scss index 7088c3978e..bbd4e1e75c 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.scss +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.scss @@ -19,15 +19,6 @@ font-weight: normal; } -.pagination-control-container { - display: flex; -} - -.pagination-control { - padding: 0 0.1rem; - vertical-align: center; -} - .table { margin-bottom: 0; } From a230eee76d931a5b55046587c0fe06fcdd383a90 Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Tue, 10 Sep 2024 16:06:44 +0200 Subject: [PATCH 0479/1286] 117803: Add negative top-margin to subsequent tables --- .../item-bitstreams/item-bitstreams.component.html | 2 +- .../item-edit-bitstream-bundle.component.html | 4 ++-- .../item-edit-bitstream-bundle.component.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html index f22dbe6a0e..3527f2f5b8 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html @@ -28,7 +28,7 @@ [bundle]="bundle" [item]="item" [columnSizes]="columnSizes" - [hideHeader]="!isFirst" + [isFirstTable]="isFirst" (dropObject)="dropBitstream(bundle, $event)">
diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html index f434bf0f8f..3d6ee4fa47 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html @@ -8,9 +8,9 @@ [collectionSize]="bitstreamsList.totalElements"> - - + - + - + - + - +
{{'item.edit.bitstreams.headers.name' | translate}} diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts index 9c62fe06e7..0974da3f8c 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts @@ -99,9 +99,9 @@ export class ItemEditBitstreamBundleComponent implements OnInit { @Input() columnSizes: ResponsiveTableSizes; /** - * Whether to hide the table headers + * Whether this is the first in a series of bundle tables */ - @Input() hideHeader = false; + @Input() isFirstTable = false; /** * Send an event when the user drops an object on the pagination From be99cc5c23763240869697798b95608e4ff1e319 Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Wed, 11 Sep 2024 10:09:03 +0200 Subject: [PATCH 0480/1286] 118219: Allow dragging of table rows --- .../item-bitstreams/item-bitstreams.component.scss | 7 ------- .../item-edit-bitstream-bundle.component.html | 7 +++++-- .../item-edit-bitstream-bundle.component.ts | 5 +++++ 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.scss b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.scss index 662c999461..0ee56fe67e 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.scss +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.scss @@ -1,7 +1,4 @@ - - .drag-handle { - visibility: hidden; &:hover { cursor: move; } @@ -11,10 +8,6 @@ cursor: move; } -:host ::ng-deep .bitstream-row:hover .drag-handle, :host ::ng-deep .bitstream-row-drag-handle:focus .drag-handle { - visibility: visible !important; -} - .cdk-drag-preview { margin-left: 0; box-sizing: border-box; diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html index 3d6ee4fa47..b79518a763 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html @@ -27,7 +27,7 @@
{{'item.edit.bitstreams.bundle.name' | translate:{ name: bundleName } }} @@ -65,10 +65,13 @@
+
+ +
{{ entry.name }}
) { + console.log('dropEvent:', event); + } + } From eadbcdbe14108b6c47f9e623e8b99c10d03ff5bd Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Wed, 11 Sep 2024 16:25:42 +0200 Subject: [PATCH 0481/1286] 118219: Store result of drag & dropping bitstream --- .../item-bitstreams.component.ts | 15 +++-- .../item-edit-bitstream-bundle.component.ts | 60 ++++++++++++++++--- 2 files changed, 62 insertions(+), 13 deletions(-) diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts index 9f27cf11b3..e7c846b5da 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts @@ -1,6 +1,6 @@ import { ChangeDetectorRef, Component, NgZone, OnDestroy } from '@angular/core'; import { AbstractItemUpdateComponent } from '../abstract-item-update/abstract-item-update.component'; -import { filter, map, switchMap, take } from 'rxjs/operators'; +import { map, switchMap, take } from 'rxjs/operators'; import { Observable, Subscription, zip as observableZip } from 'rxjs'; import { ItemDataService } from '../../../core/data/item-data.service'; import { ObjectUpdatesService } from '../../../core/data/object-updates/object-updates.service'; @@ -11,7 +11,11 @@ import { BitstreamDataService } from '../../../core/data/bitstream-data.service' import { hasValue } from '../../../shared/empty.util'; import { ObjectCacheService } from '../../../core/cache/object-cache.service'; import { RequestService } from '../../../core/data/request.service'; -import { getFirstSucceededRemoteData, getRemoteDataPayload } from '../../../core/shared/operators'; +import { + getFirstSucceededRemoteData, + getRemoteDataPayload, + getFirstCompletedRemoteData +} from '../../../core/shared/operators'; import { RemoteData } from '../../../core/data/remote-data'; import { PaginatedList } from '../../../core/data/paginated-list.model'; import { Bundle } from '../../../core/shared/bundle.model'; @@ -127,12 +131,13 @@ export class ItemBitstreamsComponent extends AbstractItemUpdateComponent impleme from: `/_links/bitstreams/${event.fromIndex}/href`, path: `/_links/bitstreams/${event.toIndex}/href` } as Operation; - this.bundleService.patch(bundle, [moveOperation]).pipe(take(1)).subscribe((response: RemoteData) => { + this.bundleService.patch(bundle, [moveOperation]).pipe( + getFirstCompletedRemoteData(), + ).subscribe((response: RemoteData) => { this.zone.run(() => { this.itemBitstreamsService.displayNotifications('item.edit.bitstreams.notifications.move', [response]); // Remove all cached requests from this bundle and call the event's callback when the requests are cleared - this.requestService.removeByHrefSubstring(bundle.self).pipe( - filter((isCached) => isCached), + this.requestService.setStaleByHrefSubstring(bundle.self).pipe( take(1) ).subscribe(() => event.finish()); }); diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts index c0c4e30231..0293a1daea 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts @@ -28,7 +28,8 @@ import { PaginationService } from '../../../../core/pagination/pagination.servic import { PaginationComponent } from '../../../../shared/pagination/pagination.component'; import { RequestService } from '../../../../core/data/request.service'; import { ItemBitstreamsService } from '../item-bitstreams.service'; -import { CdkDragDrop } from '@angular/cdk/drag-drop'; +import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop'; +import { hasValue } from '../../../../shared/empty.util'; /** * Interface storing all the information necessary to create a row in the bitstream edit table @@ -135,7 +136,7 @@ export class ItemEditBitstreamBundleComponent implements OnInit { /** * The data to show in the table */ - tableEntries$: Observable; + tableEntries$: BehaviorSubject = new BehaviorSubject(null); /** * The initial page options to use for fetching the bitstreams @@ -165,7 +166,7 @@ export class ItemEditBitstreamBundleComponent implements OnInit { /** * The updates to the current bitstreams */ - updates$: Observable; + updates$: BehaviorSubject = new BehaviorSubject(null); constructor( @@ -229,17 +230,17 @@ export class ItemEditBitstreamBundleComponent implements OnInit { this.objectUpdatesService.initialize(this.bundleUrl, bitstreams, new Date()); }); - this.updates$ = this.bitstreamsRD$.pipe( + this.bitstreamsRD$.pipe( getAllSucceededRemoteData(), paginatedListToArray(), switchMap((bitstreams) => this.objectUpdatesService.getFieldUpdatesExclusive(this.bundleUrl, bitstreams)) - ); + ).subscribe((updates) => this.updates$.next(updates)); - this.tableEntries$ = this.bitstreamsRD$.pipe( + this.bitstreamsRD$.pipe( getAllSucceededRemoteData(), paginatedListToArray(), map((bitstreams) => this.itemBitstreamsService.mapBitstreamsToTableEntries(bitstreams)), - ); + ).subscribe((tableEntries) => this.tableEntries$.next(tableEntries)); } /** @@ -288,7 +289,50 @@ export class ItemEditBitstreamBundleComponent implements OnInit { } drop(event: CdkDragDrop) { - console.log('dropEvent:', event); + const dragIndex = event.previousIndex; + let dropIndex = event.currentIndex; + const dragPage = this.currentPaginationOptions$.value.currentPage - 1; + let dropPage = this.currentPaginationOptions$.value.currentPage - 1; + + // Check if the user is hovering over any of the pagination's pages at the time of dropping the object + const droppedOnElement = document.elementFromPoint(event.dropPoint.x, event.dropPoint.y); + if (hasValue(droppedOnElement) && hasValue(droppedOnElement.textContent) && droppedOnElement.classList.contains('page-link')) { + // The user is hovering over a page, fetch the page's number from the element + const droppedPage = Number(droppedOnElement.textContent); + if (hasValue(droppedPage) && !Number.isNaN(droppedPage)) { + dropPage = droppedPage - 1; + dropIndex = 0; + } + } + + const isNewPage = dragPage !== dropPage; + // Move the object in the custom order array if the drop happened within the same page + // This allows us to instantly display a change in the order, instead of waiting for the REST API's response first + if (!isNewPage && dragIndex !== dropIndex) { + const currentEntries = [...this.tableEntries$.value]; + moveItemInArray(currentEntries, dragIndex, dropIndex); + this.tableEntries$.next(currentEntries); + } + + const pageSize = this.currentPaginationOptions$.value.pageSize; + const redirectPage = dropPage + 1; + const fromIndex = (dragPage * pageSize) + dragIndex; + const toIndex = (dropPage * pageSize) + dropIndex; + // Send out a drop event (and navigate to the new page) when the "from" and "to" indexes are different from each other + if (fromIndex !== toIndex) { + // if (isNewPage) { + // this.loading$.next(true); + // } + this.dropObject.emit(Object.assign({ + fromIndex, + toIndex, + finish: () => { + if (isNewPage) { + this.paginationComponent.doPageChange(redirectPage); + } + } + })); + } } } From 6a2c7d09d69e6275d5e29d06a2672ce9b79e52fb Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Thu, 12 Sep 2024 10:01:55 +0200 Subject: [PATCH 0482/1286] 118219: Add dragging tooltip explaining how to drag to other page --- .../item-edit-bitstream-bundle.component.html | 7 +++-- .../item-edit-bitstream-bundle.component.ts | 30 ++++++++++++++++++- src/assets/i18n/en.json5 | 2 ++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html index b79518a763..0338055df5 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html @@ -27,7 +27,9 @@
{{'item.edit.bitstreams.bundle.name' | translate:{ name: bundleName } }} @@ -65,7 +67,8 @@
diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts index 0293a1daea..bd99fc1a09 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts @@ -21,7 +21,7 @@ import { } from '../../../../core/shared/operators'; import { ObjectUpdatesService } from '../../../../core/data/object-updates/object-updates.service'; import { BitstreamFormat } from '../../../../core/shared/bitstream-format.model'; -import { map } from 'rxjs/operators'; +import { map, take, filter } from 'rxjs/operators'; import { FieldChangeType } from '../../../../core/data/object-updates/field-change-type.model'; import { FieldUpdate } from '../../../../core/data/object-updates/field-update.model'; import { PaginationService } from '../../../../core/pagination/pagination.service'; @@ -83,8 +83,16 @@ export class ItemEditBitstreamBundleComponent implements OnInit { */ @ViewChild('bundleView', {static: true}) bundleView; + /** + * The view on the pagination component + */ @ViewChild(PaginationComponent) paginationComponent: PaginationComponent; + /** + * The view on the drag tooltip + */ + @ViewChild('dragTooltip') dragTooltip; + /** * The bundle to display bitstreams for */ @@ -158,6 +166,11 @@ export class ItemEditBitstreamBundleComponent implements OnInit { */ pageSize$: BehaviorSubject; + /** + * Whether the table has multiple pages + */ + hasMultiplePages = false; + /** * The self url of the bundle, also used when retrieving fieldUpdates */ @@ -288,6 +301,21 @@ export class ItemEditBitstreamBundleComponent implements OnInit { this.paginationComponent.doPageSizeChange(pageSize); } + dragStart() { + // Only open the drag tooltip when there are multiple pages + this.paginationComponent.shouldShowBottomPager.pipe( + take(1), + filter((hasMultiplePages) => hasMultiplePages), + ).subscribe(() => { + this.dragTooltip.open(); + }); + } + + dragEnd() { + this.dragTooltip.close(); + } + + drop(event: CdkDragDrop) { const dragIndex = event.previousIndex; let dropIndex = event.currentIndex; diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 4d5ef9ee1b..f2dbf9b2d1 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1936,6 +1936,8 @@ "item.edit.bitstreams.bundle.table.aria-label": "Bitstreams in the {{ bundle }} Bundle", + "item.edit.bitstreams.bundle.tooltip": "You can move a bitstream to a different page by dropping it on the page number.", + "item.edit.bitstreams.discard-button": "Discard", "item.edit.bitstreams.edit.buttons.download": "Download", From 8a16597b6958f99f949a413028ee2d5dee2905dc Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Thu, 12 Sep 2024 10:33:21 +0200 Subject: [PATCH 0483/1286] 118219: Fix tests --- .../item-bitstreams.component.spec.ts | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.spec.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.spec.ts index 10e1812131..6ce7394473 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.spec.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.spec.ts @@ -18,7 +18,6 @@ import { ObjectValuesPipe } from '../../../shared/utils/object-values-pipe'; import { VarDirective } from '../../../shared/utils/var.directive'; import { BundleDataService } from '../../../core/data/bundle-data.service'; import { Bundle } from '../../../core/shared/bundle.model'; -import { RestResponse } from '../../../core/cache/response.models'; import { SearchConfigurationService } from '../../../core/shared/search/search-configuration.service'; import { RouterStub } from '../../../shared/testing/router.stub'; import { getMockRequestService } from '../../../shared/mocks/request.service.mock'; @@ -145,7 +144,7 @@ describe('ItemBitstreamsComponent', () => { url: url }); bundleService = jasmine.createSpyObj('bundleService', { - patch: observableOf(new RestResponse(true, 200, 'OK')) + patch: createSuccessfulRemoteDataObject$({}), }); TestBed.configureTestingModule({ @@ -191,20 +190,6 @@ describe('ItemBitstreamsComponent', () => { }); }); - describe('when dropBitstream is called', () => { - const event = { - fromIndex: 0, - toIndex: 50, - // eslint-disable-next-line no-empty,@typescript-eslint/no-empty-function - finish: () => { - } - }; - - beforeEach(() => { - comp.dropBitstream(bundle, event); - }); - }); - describe('when dropBitstream is called', () => { beforeEach((done) => { comp.dropBitstream(bundle, { From a207fb51e9159c0076bb8a76cd5a73944a11655b Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Thu, 12 Sep 2024 10:38:38 +0200 Subject: [PATCH 0484/1286] 118219: Remove unused paginated-drag-and-drop components --- .../edit-item-page/edit-item-page.module.ts | 4 - ...rag-and-drop-bitstream-list.component.html | 33 --- ...-and-drop-bitstream-list.component.spec.ts | 150 ----------- ...-drag-and-drop-bitstream-list.component.ts | 80 ------ ...-edit-bitstream-drag-handle.component.html | 5 - ...em-edit-bitstream-drag-handle.component.ts | 26 -- ...nated-drag-and-drop-list.component.spec.ts | 136 ---------- ...-paginated-drag-and-drop-list.component.ts | 239 ------------------ 8 files changed, 673 deletions(-) delete mode 100644 src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.html delete mode 100644 src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.spec.ts delete mode 100644 src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.ts delete mode 100644 src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-drag-handle/item-edit-bitstream-drag-handle.component.html delete mode 100644 src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-drag-handle/item-edit-bitstream-drag-handle.component.ts delete mode 100644 src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.spec.ts delete mode 100644 src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.ts diff --git a/src/app/item-page/edit-item-page/edit-item-page.module.ts b/src/app/item-page/edit-item-page/edit-item-page.module.ts index 0a75394ddd..4ae5ebe666 100644 --- a/src/app/item-page/edit-item-page/edit-item-page.module.ts +++ b/src/app/item-page/edit-item-page/edit-item-page.module.ts @@ -26,8 +26,6 @@ import { ItemMoveComponent } from './item-move/item-move.component'; import { ItemEditBitstreamBundleComponent } from './item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component'; import { BundleDataService } from '../../core/data/bundle-data.service'; import { DragDropModule } from '@angular/cdk/drag-drop'; -import { ItemEditBitstreamDragHandleComponent } from './item-bitstreams/item-edit-bitstream-drag-handle/item-edit-bitstream-drag-handle.component'; -import { PaginatedDragAndDropBitstreamListComponent } from './item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component'; import { VirtualMetadataComponent } from './virtual-metadata/virtual-metadata.component'; import { ItemVersionHistoryComponent } from './item-version-history/item-version-history.component'; import { ItemAuthorizationsComponent } from './item-authorizations/item-authorizations.component'; @@ -82,12 +80,10 @@ import { ItemVersionHistoryComponent, ItemEditBitstreamComponent, ItemEditBitstreamBundleComponent, - PaginatedDragAndDropBitstreamListComponent, EditRelationshipComponent, EditRelationshipListComponent, ItemCollectionMapperComponent, ItemMoveComponent, - ItemEditBitstreamDragHandleComponent, VirtualMetadataComponent, ItemAuthorizationsComponent, IdentifierDataComponent, diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.html b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.html deleted file mode 100644 index f54aa73597..0000000000 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.html +++ /dev/null @@ -1,33 +0,0 @@ - - -
- -
- -
- -
-
-
-
-
-
- -
diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.spec.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.spec.ts deleted file mode 100644 index 7317eb93be..0000000000 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.spec.ts +++ /dev/null @@ -1,150 +0,0 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; -import { NO_ERRORS_SCHEMA } from '@angular/core'; -import { Bundle } from '../../../../../core/shared/bundle.model'; -import { TranslateModule } from '@ngx-translate/core'; -import { PaginatedDragAndDropBitstreamListComponent } from './paginated-drag-and-drop-bitstream-list.component'; -import { VarDirective } from '../../../../../shared/utils/var.directive'; -import { ObjectValuesPipe } from '../../../../../shared/utils/object-values-pipe'; -import { ObjectUpdatesService } from '../../../../../core/data/object-updates/object-updates.service'; -import { BundleDataService } from '../../../../../core/data/bundle-data.service'; -import { Bitstream } from '../../../../../core/shared/bitstream.model'; -import { BitstreamFormat } from '../../../../../core/shared/bitstream-format.model'; -import { of as observableOf } from 'rxjs'; -import { take } from 'rxjs/operators'; -import { ResponsiveTableSizes } from '../../../../../shared/responsive-table-sizes/responsive-table-sizes'; -import { ResponsiveColumnSizes } from '../../../../../shared/responsive-table-sizes/responsive-column-sizes'; -import { createSuccessfulRemoteDataObject$ } from '../../../../../shared/remote-data.utils'; -import { createPaginatedList } from '../../../../../shared/testing/utils.test'; -import { RequestService } from '../../../../../core/data/request.service'; -import { PaginationService } from '../../../../../core/pagination/pagination.service'; -import { PaginationServiceStub } from '../../../../../shared/testing/pagination-service.stub'; - -describe('PaginatedDragAndDropBitstreamListComponent', () => { - let comp: PaginatedDragAndDropBitstreamListComponent; - let fixture: ComponentFixture; - let objectUpdatesService: ObjectUpdatesService; - let bundleService: BundleDataService; - let objectValuesPipe: ObjectValuesPipe; - let requestService: RequestService; - let paginationService; - - const columnSizes = new ResponsiveTableSizes([ - new ResponsiveColumnSizes(2, 2, 3, 4, 4), - new ResponsiveColumnSizes(2, 3, 3, 3, 3), - new ResponsiveColumnSizes(2, 2, 2, 2, 2), - new ResponsiveColumnSizes(6, 5, 4, 3, 3) - ]); - - const bundle = Object.assign(new Bundle(), { - id: 'bundle-1', - uuid: 'bundle-1', - _links: { - self: { href: 'bundle-1-selflink' } - } - }); - const date = new Date(); - const format = Object.assign(new BitstreamFormat(), { - shortDescription: 'PDF' - }); - const bitstream1 = Object.assign(new Bitstream(), { - uuid: 'bitstreamUUID1', - name: 'Fake Bitstream 1', - bundleName: 'ORIGINAL', - description: 'Description', - format: createSuccessfulRemoteDataObject$(format) - }); - const fieldUpdate1 = { - field: bitstream1, - changeType: undefined - }; - const bitstream2 = Object.assign(new Bitstream(), { - uuid: 'bitstreamUUID2', - name: 'Fake Bitstream 2', - bundleName: 'ORIGINAL', - description: 'Description', - format: createSuccessfulRemoteDataObject$(format) - }); - const fieldUpdate2 = { - field: bitstream2, - changeType: undefined - }; - - beforeEach(waitForAsync(() => { - objectUpdatesService = jasmine.createSpyObj('objectUpdatesService', - { - getFieldUpdates: observableOf({ - [bitstream1.uuid]: fieldUpdate1, - [bitstream2.uuid]: fieldUpdate2, - }), - getFieldUpdatesExclusive: observableOf({ - [bitstream1.uuid]: fieldUpdate1, - [bitstream2.uuid]: fieldUpdate2, - }), - getFieldUpdatesByCustomOrder: observableOf({ - [bitstream1.uuid]: fieldUpdate1, - [bitstream2.uuid]: fieldUpdate2, - }), - saveMoveFieldUpdate: {}, - saveRemoveFieldUpdate: {}, - removeSingleFieldUpdate: {}, - saveAddFieldUpdate: {}, - discardFieldUpdates: {}, - reinstateFieldUpdates: observableOf(true), - initialize: {}, - getUpdatedFields: observableOf([bitstream1, bitstream2]), - getLastModified: observableOf(date), - hasUpdates: observableOf(true), - isReinstatable: observableOf(false), - isValidPage: observableOf(true), - initializeWithCustomOrder: {}, - addPageToCustomOrder: {} - } - ); - - bundleService = jasmine.createSpyObj('bundleService', { - getBitstreams: createSuccessfulRemoteDataObject$(createPaginatedList([bitstream1, bitstream2])), - getBitstreamsEndpoint: observableOf('') - }); - - objectValuesPipe = new ObjectValuesPipe(); - - requestService = jasmine.createSpyObj('requestService', { - hasByHref$: observableOf(true) - }); - - paginationService = new PaginationServiceStub(); - - TestBed.configureTestingModule({ - imports: [TranslateModule.forRoot()], - declarations: [PaginatedDragAndDropBitstreamListComponent, VarDirective], - providers: [ - { provide: ObjectUpdatesService, useValue: objectUpdatesService }, - { provide: BundleDataService, useValue: bundleService }, - { provide: ObjectValuesPipe, useValue: objectValuesPipe }, - { provide: RequestService, useValue: requestService }, - { provide: PaginationService, useValue: paginationService } - ], schemas: [ - NO_ERRORS_SCHEMA - ] - }).compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(PaginatedDragAndDropBitstreamListComponent); - comp = fixture.componentInstance; - comp.bundle = bundle; - comp.columnSizes = columnSizes; - fixture.detectChanges(); - }); - - it('should initialize the objectsRD$', (done) => { - comp.objectsRD$.pipe(take(1)).subscribe((objects) => { - expect(objects.payload.page).toEqual([bitstream1, bitstream2]); - done(); - }); - }); - - it('should initialize the URL', () => { - expect(comp.url).toEqual(bundle.self); - }); -}); diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.ts deleted file mode 100644 index d5bb9eceea..0000000000 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { AbstractPaginatedDragAndDropListComponent } from '../../../../../shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component'; -import { Component, ElementRef, Input, OnInit } from '@angular/core'; -import { Bundle } from '../../../../../core/shared/bundle.model'; -import { Bitstream } from '../../../../../core/shared/bitstream.model'; -import { ObjectUpdatesService } from '../../../../../core/data/object-updates/object-updates.service'; -import { BundleDataService } from '../../../../../core/data/bundle-data.service'; -import { switchMap } from 'rxjs/operators'; -import { PaginatedSearchOptions } from '../../../../../shared/search/models/paginated-search-options.model'; -import { ResponsiveTableSizes } from '../../../../../shared/responsive-table-sizes/responsive-table-sizes'; -import { followLink } from '../../../../../shared/utils/follow-link-config.model'; -import { ObjectValuesPipe } from '../../../../../shared/utils/object-values-pipe'; -import { RequestService } from '../../../../../core/data/request.service'; -import { PaginationService } from '../../../../../core/pagination/pagination.service'; -import { PaginationComponentOptions } from '../../../../../shared/pagination/pagination-component-options.model'; - -@Component({ - selector: 'ds-paginated-drag-and-drop-bitstream-list', - styleUrls: ['../../item-bitstreams.component.scss'], - templateUrl: './paginated-drag-and-drop-bitstream-list.component.html', -}) -/** - * A component listing edit-bitstream rows for each bitstream within the given bundle. - * This component makes use of the AbstractPaginatedDragAndDropListComponent, allowing for users to drag and drop - * bitstreams within the paginated list. To drag and drop a bitstream between two pages, drag the row on top of the - * page number you want the bitstream to end up at. Doing so will add the bitstream to the top of that page. - */ -// NOTE: -// This component was used by the item-edit-bitstream-bundle.component, but this is no longer the case. It is left here -// as a reference for the drag-and-drop functionality. This component (and the abstract version it extends) should be -// removed once this reference is no longer useful. -export class PaginatedDragAndDropBitstreamListComponent extends AbstractPaginatedDragAndDropListComponent implements OnInit { - /** - * The bundle to display bitstreams for - */ - @Input() bundle: Bundle; - - /** - * The bootstrap sizes used for the columns within this table - */ - @Input() columnSizes: ResponsiveTableSizes; - - constructor(protected objectUpdatesService: ObjectUpdatesService, - protected elRef: ElementRef, - protected objectValuesPipe: ObjectValuesPipe, - protected bundleService: BundleDataService, - protected paginationService: PaginationService, - protected requestService: RequestService) { - super(objectUpdatesService, elRef, objectValuesPipe, paginationService); - } - - ngOnInit() { - super.ngOnInit(); - } - - /** - * Initialize the bitstreams observable depending on currentPage$ - */ - initializeObjectsRD(): void { - this.objectsRD$ = this.currentPage$.pipe( - switchMap((page: PaginationComponentOptions) => { - const paginatedOptions = new PaginatedSearchOptions({pagination: Object.assign({}, page)}); - return this.bundleService.getBitstreamsEndpoint(this.bundle.id, paginatedOptions).pipe( - switchMap((href) => this.requestService.hasByHref$(href)), - switchMap(() => this.bundleService.getBitstreams( - this.bundle.id, - paginatedOptions, - followLink('format') - )) - ); - }) - ); - } - - /** - * Initialize the URL used for the field-update store, in this case the bundle's self-link - */ - initializeURL(): void { - this.url = this.bundle.self; - } -} diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-drag-handle/item-edit-bitstream-drag-handle.component.html b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-drag-handle/item-edit-bitstream-drag-handle.component.html deleted file mode 100644 index 1bce8667ee..0000000000 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-drag-handle/item-edit-bitstream-drag-handle.component.html +++ /dev/null @@ -1,5 +0,0 @@ - -
- -
-
diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-drag-handle/item-edit-bitstream-drag-handle.component.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-drag-handle/item-edit-bitstream-drag-handle.component.ts deleted file mode 100644 index e5cb9ba403..0000000000 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-drag-handle/item-edit-bitstream-drag-handle.component.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Component, OnInit, ViewChild, ViewContainerRef } from '@angular/core'; - -@Component({ - selector: 'ds-item-edit-bitstream-drag-handle', - styleUrls: ['../item-bitstreams.component.scss'], - templateUrl: './item-edit-bitstream-drag-handle.component.html', -}) -/** - * Component displaying a drag handle for the item-edit-bitstream page - * Creates an embedded view of the contents - * (which means it'll be added to the parents html without a wrapping ds-item-edit-bitstream-drag-handle element) - */ -export class ItemEditBitstreamDragHandleComponent implements OnInit { - /** - * The view on the drag-handle - */ - @ViewChild('handleView', {static: true}) handleView; - - constructor(private viewContainerRef: ViewContainerRef) { - } - - ngOnInit(): void { - this.viewContainerRef.createEmbeddedView(this.handleView); - } - -} diff --git a/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.spec.ts b/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.spec.ts deleted file mode 100644 index bac6b89583..0000000000 --- a/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.spec.ts +++ /dev/null @@ -1,136 +0,0 @@ -import { AbstractPaginatedDragAndDropListComponent } from './abstract-paginated-drag-and-drop-list.component'; -import { DSpaceObject } from '../../core/shared/dspace-object.model'; -import { ObjectUpdatesService } from '../../core/data/object-updates/object-updates.service'; -import { Component, ElementRef } from '@angular/core'; -import { BehaviorSubject, Observable, of as observableOf } from 'rxjs'; -import { PaginatedList } from '../../core/data/paginated-list.model'; -import { RemoteData } from '../../core/data/remote-data'; -import { take } from 'rxjs/operators'; -import { PaginationComponent } from '../pagination/pagination.component'; -import { createSuccessfulRemoteDataObject } from '../remote-data.utils'; -import { createPaginatedList } from '../testing/utils.test'; -import { ObjectValuesPipe } from '../utils/object-values-pipe'; -import { PaginationService } from '../../core/pagination/pagination.service'; -import { PaginationServiceStub } from '../testing/pagination-service.stub'; -import { FieldUpdates } from '../../core/data/object-updates/field-updates.model'; - -@Component({ - selector: 'ds-mock-paginated-drag-drop-abstract', - template: '' -}) -class MockAbstractPaginatedDragAndDropListComponent extends AbstractPaginatedDragAndDropListComponent { - - constructor(protected objectUpdatesService: ObjectUpdatesService, - protected elRef: ElementRef, - protected objectValuesPipe: ObjectValuesPipe, - protected mockUrl: string, - protected paginationService: PaginationService, - protected mockObjectsRD$: Observable>>) { - super(objectUpdatesService, elRef, objectValuesPipe, paginationService); - } - - initializeObjectsRD(): void { - this.objectsRD$ = this.mockObjectsRD$; - } - - initializeURL(): void { - this.url = this.mockUrl; - } -} - -describe('AbstractPaginatedDragAndDropListComponent', () => { - let component: MockAbstractPaginatedDragAndDropListComponent; - let objectUpdatesService: ObjectUpdatesService; - let elRef: ElementRef; - let objectValuesPipe: ObjectValuesPipe; - - const url = 'mock-abstract-paginated-drag-and-drop-list-component'; - - - const object1 = Object.assign(new DSpaceObject(), { uuid: 'object-1' }); - const object2 = Object.assign(new DSpaceObject(), { uuid: 'object-2' }); - const objectsRD = createSuccessfulRemoteDataObject(createPaginatedList([object1, object2])); - let objectsRD$: BehaviorSubject>>; - let paginationService; - - const updates = { - [object1.uuid]: { field: object1, changeType: undefined }, - [object2.uuid]: { field: object2, changeType: undefined } - } as FieldUpdates; - - let paginationComponent: PaginationComponent; - - beforeEach(() => { - objectUpdatesService = jasmine.createSpyObj('objectUpdatesService', { - initialize: {}, - getFieldUpdatesExclusive: observableOf(updates) - }); - elRef = { - nativeElement: jasmine.createSpyObj('nativeElement', { - querySelector: {} - }) - }; - objectValuesPipe = new ObjectValuesPipe(); - paginationComponent = jasmine.createSpyObj('paginationComponent', { - doPageChange: {} - }); - paginationService = new PaginationServiceStub(); - objectsRD$ = new BehaviorSubject(objectsRD); - component = new MockAbstractPaginatedDragAndDropListComponent(objectUpdatesService, elRef, objectValuesPipe, url, paginationService, objectsRD$); - component.paginationComponent = paginationComponent; - component.ngOnInit(); - }); - - it('should call initialize to initialize the objects in the store', () => { - expect(objectUpdatesService.initialize).toHaveBeenCalled(); - }); - - it('should initialize the updates correctly', (done) => { - component.updates$.pipe(take(1)).subscribe((fieldUpdates) => { - expect(fieldUpdates).toEqual(updates); - done(); - }); - }); - - describe('drop', () => { - const event = { - previousIndex: 0, - currentIndex: 1, - item: { element: { nativeElement: { id: object1.uuid } } } - } as any; - - describe('when the user is hovering over a new page', () => { - const hoverPage = 3; - const hoverElement = { textContent: '' + hoverPage }; - - beforeEach(() => { - elRef.nativeElement.querySelector.and.returnValue(hoverElement); - spyOn(component.dropObject, 'emit'); - component.drop(event); - }); - - it('should send out a dropObject event with the expected processed paginated indexes', () => { - expect(component.dropObject.emit).toHaveBeenCalledWith(Object.assign({ - fromIndex: ((component.currentPage$.value.currentPage - 1) * component.pageSize) + event.previousIndex, - toIndex: ((hoverPage - 1) * component.pageSize), - finish: jasmine.anything() - })); - }); - }); - - describe('when the user is not hovering over a new page', () => { - beforeEach(() => { - spyOn(component.dropObject, 'emit'); - component.drop(event); - }); - - it('should send out a dropObject event with the expected properties', () => { - expect(component.dropObject.emit).toHaveBeenCalledWith(Object.assign({ - fromIndex: event.previousIndex, - toIndex: event.currentIndex, - finish: jasmine.anything() - })); - }); - }); - }); -}); diff --git a/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.ts b/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.ts deleted file mode 100644 index 8dba47566f..0000000000 --- a/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.ts +++ /dev/null @@ -1,239 +0,0 @@ -import { BehaviorSubject, Observable, Subscription } from 'rxjs'; -import { RemoteData } from '../../core/data/remote-data'; -import { PaginatedList } from '../../core/data/paginated-list.model'; -import { PaginationComponentOptions } from '../pagination/pagination-component-options.model'; -import { ObjectUpdatesService } from '../../core/data/object-updates/object-updates.service'; -import { distinctUntilChanged, map, switchMap } from 'rxjs/operators'; -import { hasValue } from '../empty.util'; -import { - paginatedListToArray, - getFirstSucceededRemoteData, - getAllSucceededRemoteData -} from '../../core/shared/operators'; -import { DSpaceObject } from '../../core/shared/dspace-object.model'; -import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop'; -import { Component, ElementRef, EventEmitter, OnDestroy, Output, ViewChild } from '@angular/core'; -import { PaginationComponent } from '../pagination/pagination.component'; -import { ObjectValuesPipe } from '../utils/object-values-pipe'; -import { compareArraysUsing } from '../../item-page/simple/item-types/shared/item-relationships-utils'; -import { PaginationService } from '../../core/pagination/pagination.service'; -import { FieldUpdate } from '../../core/data/object-updates/field-update.model'; -import { FieldUpdates } from '../../core/data/object-updates/field-updates.model'; - -/** - * Operator used for comparing {@link FieldUpdate}s by their field's UUID - */ -export const compareArraysUsingFieldUuids = () => - compareArraysUsing((fieldUpdate: FieldUpdate) => (hasValue(fieldUpdate) && hasValue(fieldUpdate.field)) ? fieldUpdate.field.uuid : undefined); - -/** - * An abstract component containing general methods and logic to be able to drag and drop objects within a paginated - * list. This implementation supports being able to drag and drop objects between pages. - * Dragging an object on top of a page number will automatically detect the page it's being dropped on and send a - * dropObject event to the parent component containing detailed information about the indexes the object was dropped from - * and to. - * - * To extend this component, it is important to make sure to: - * - Initialize objectsRD$ within the initializeObjectsRD() method - * - Initialize a unique URL for this component/page within the initializeURL() method - * - Add (cdkDropListDropped)="drop($event)" to the cdkDropList element in your template - * - Add (pageChange)="switchPage($event)" to the ds-pagination element in your template - * - Use the updates$ observable for building your list of cdkDrag elements in your template - * - * An example component extending from this abstract component: PaginatedDragAndDropBitstreamListComponent - */ -@Component({ - selector: 'ds-paginated-drag-drop-abstract', - template: '' -}) -export abstract class AbstractPaginatedDragAndDropListComponent implements OnDestroy { - /** - * A view on the child pagination component - */ - @ViewChild(PaginationComponent) paginationComponent: PaginationComponent; - - /** - * Send an event when the user drops an object on the pagination - * The event contains details about the index the object came from and is dropped to (across the entirety of the list, - * not just within a single page) - */ - @Output() dropObject: EventEmitter = new EventEmitter(); - - /** - * The URL to use for accessing the object updates from this list - */ - url: string; - - /** - * The objects to retrieve data for and transform into field updates - */ - objectsRD$: Observable>>; - - /** - * The updates to the current list - */ - updates$: Observable; - - /** - * A list of object UUIDs - * This is the order the objects will be displayed in - */ - customOrder: string[]; - - /** - * The amount of objects to display per page - */ - pageSize = 10; - - /** - * The page options to use for fetching the objects - * Start at page 1 and always use the set page size - */ - options = Object.assign(new PaginationComponentOptions(),{ - id: 'dad', - currentPage: 1, - pageSize: this.pageSize - }); - - /** - * The current page being displayed - */ - currentPage$ = new BehaviorSubject(this.options); - - /** - * Whether or not we should display a loading animation - * This is used to display a loading page when the user drops a bitstream onto a new page. The loading animation - * should stop once the bitstream has moved to the new page and the new page's response has loaded and contains the - * dropped object on top (see this.stopLoadingWhenFirstIs below) - */ - loading$: BehaviorSubject = new BehaviorSubject(false); - - /** - * List of subscriptions - */ - subs: Subscription[] = []; - - protected constructor(protected objectUpdatesService: ObjectUpdatesService, - protected elRef: ElementRef, - protected objectValuesPipe: ObjectValuesPipe, - protected paginationService: PaginationService - ) { - } - - /** - * Initialize the observables - */ - ngOnInit() { - this.initializeObjectsRD(); - this.initializeURL(); - this.initializeUpdates(); - this.initializePagination(); - } - - /** - * Overwrite this method to define how the list of objects is initialized and updated - */ - abstract initializeObjectsRD(): void; - - /** - * Overwrite this method to define how the URL is set - */ - abstract initializeURL(): void; - - /** - * Initialize the current pagination retrieval from the paginationService and push to the currentPage$ - */ - initializePagination() { - this.paginationService.getCurrentPagination(this.options.id, this.options).subscribe((currentPagination) => { - this.currentPage$.next(currentPagination); - }); - } - - /** - * Initialize the field-updates in the store - */ - initializeUpdates(): void { - this.objectsRD$.pipe( - getFirstSucceededRemoteData(), - paginatedListToArray(), - ).subscribe((objects: T[]) => { - this.objectUpdatesService.initialize(this.url, objects, new Date()); - }); - this.updates$ = this.objectsRD$.pipe( - getAllSucceededRemoteData(), - paginatedListToArray(), - switchMap((objects: T[]) => this.objectUpdatesService.getFieldUpdatesExclusive(this.url, objects)) - ); - this.subs.push( - this.updates$.pipe( - map((fieldUpdates) => this.objectValuesPipe.transform(fieldUpdates)), - distinctUntilChanged(compareArraysUsingFieldUuids()) - ).subscribe((updateValues) => { - this.customOrder = updateValues.map((fieldUpdate) => fieldUpdate.field.uuid); - // We received new values, stop displaying a loading indicator if it's present - this.loading$.next(false); - }), - // Disable the pagination when objects are loading - this.loading$.subscribe((loading) => this.options.disabled = loading) - ); - } - - /** - * An object was moved, send updates to the dropObject EventEmitter - * When the object is dropped on a page within the pagination of this component, the object moves to the top of that - * page and the pagination automatically loads and switches the view to that page (this is done by calling the event's - * finish() method after sending patch requests to the REST API) - * @param event - */ - drop(event: CdkDragDrop) { - const dragIndex = event.previousIndex; - let dropIndex = event.currentIndex; - const dragPage = this.currentPage$.value.currentPage - 1; - let dropPage = this.currentPage$.value.currentPage - 1; - - // Check if the user is hovering over any of the pagination's pages at the time of dropping the object - const droppedOnElement = this.elRef.nativeElement.querySelector('.page-item:hover'); - if (hasValue(droppedOnElement) && hasValue(droppedOnElement.textContent)) { - // The user is hovering over a page, fetch the page's number from the element - const droppedPage = Number(droppedOnElement.textContent); - if (hasValue(droppedPage) && !Number.isNaN(droppedPage)) { - dropPage = droppedPage - 1; - dropIndex = 0; - } - } - - const isNewPage = dragPage !== dropPage; - // Move the object in the custom order array if the drop happened within the same page - // This allows us to instantly display a change in the order, instead of waiting for the REST API's response first - if (!isNewPage && dragIndex !== dropIndex) { - moveItemInArray(this.customOrder, dragIndex, dropIndex); - } - - const redirectPage = dropPage + 1; - const fromIndex = (dragPage * this.pageSize) + dragIndex; - const toIndex = (dropPage * this.pageSize) + dropIndex; - // Send out a drop event (and navigate to the new page) when the "from" and "to" indexes are different from each other - if (fromIndex !== toIndex) { - if (isNewPage) { - this.loading$.next(true); - } - this.dropObject.emit(Object.assign({ - fromIndex, - toIndex, - finish: () => { - if (isNewPage) { - this.paginationComponent.doPageChange(redirectPage); - } - } - })); - } - } - - /** - * unsub all subscriptions - */ - ngOnDestroy(): void { - this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe()); - this.paginationService.clearPagination(this.options.id); - } -} From 8fb4772b6c6308d2ba9e358e2858244105064c7f Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Tue, 1 Oct 2024 13:12:10 +0200 Subject: [PATCH 0485/1286] Always sanitize HTML in dsMarkdown even if markdown disabled Instead of setting innerHTML directly to value, sanitize the value, even if not passing to renderMarkdown/Mathjax --- .../shared/utils/markdown.directive.spec.ts | 58 +++++++++++++++++-- src/app/shared/utils/markdown.directive.ts | 2 +- 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/src/app/shared/utils/markdown.directive.spec.ts b/src/app/shared/utils/markdown.directive.spec.ts index 79e795be87..b984543c40 100644 --- a/src/app/shared/utils/markdown.directive.spec.ts +++ b/src/app/shared/utils/markdown.directive.spec.ts @@ -8,21 +8,20 @@ import { } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; +import { environment } from '../../../environments/environment.test'; import { MathService } from '../../core/shared/math.service'; import { MockMathService } from '../../core/shared/math.service.spec'; import { MarkdownDirective } from './markdown.directive'; @Component({ - template: `
`, + template: `
`, standalone: true, imports: [ MarkdownDirective ], }) class TestComponent {} describe('MarkdownDirective', () => { - let component: TestComponent; let fixture: ComponentFixture; - let divEl: DebugElement; beforeEach(async () => { await TestBed.configureTestingModule({ @@ -32,12 +31,61 @@ describe('MarkdownDirective', () => { }).compileComponents(); spyOn(MarkdownDirective.prototype, 'render'); fixture = TestBed.createComponent(TestComponent); - component = fixture.componentInstance; - divEl = fixture.debugElement.query(By.css('div')); }); it('should call render method', () => { fixture.detectChanges(); expect(MarkdownDirective.prototype.render).toHaveBeenCalled(); }); + +}); + +describe('MarkdownDirective sanitization with markdown disabled', () => { + let fixture: ComponentFixture; + let divEl: DebugElement; + // Disable markdown + environment.markdown.enabled = false; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + providers: [ + { provide: MathService, useClass: MockMathService }, + ], + }).compileComponents(); + fixture = TestBed.createComponent(TestComponent); + divEl = fixture.debugElement.query(By.css('div')); + + }); + + it('should sanitize the script element out of innerHTML (markdown disabled)',() => { + fixture.detectChanges(); + divEl = fixture.debugElement.query(By.css('div')); + expect(divEl.nativeElement.innerHTML).toEqual('test'); + }); + +}); + +describe('MarkdownDirective sanitization with markdown enabled', () => { + let fixture: ComponentFixture; + let divEl: DebugElement; + // Enable markdown + environment.markdown.enabled = true; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + providers: [ + { provide: MathService, useClass: MockMathService }, + ], + }).compileComponents(); + fixture = TestBed.createComponent(TestComponent); + divEl = fixture.debugElement.query(By.css('div')); + + }); + + it('should sanitize the script element out of innerHTML (markdown enabled)',() => { + fixture.detectChanges(); + divEl = fixture.debugElement.query(By.css('div')); + expect(divEl.nativeElement.innerHTML).toEqual('test'); + }); + }); diff --git a/src/app/shared/utils/markdown.directive.ts b/src/app/shared/utils/markdown.directive.ts index 0540e25cc5..de13acb303 100644 --- a/src/app/shared/utils/markdown.directive.ts +++ b/src/app/shared/utils/markdown.directive.ts @@ -55,7 +55,7 @@ export class MarkdownDirective implements OnInit, OnDestroy { async render(value: string, forcePreview = false): Promise { if (isEmpty(value) || (!environment.markdown.enabled && !forcePreview)) { - this.el.innerHTML = value; + this.el.innerHTML = this.sanitizer.sanitize(SecurityContext.HTML, value); return; } else { if (environment.markdown.mathjax) { From 85f1ba21769a6fe2df07c6840fc63e5a0862ea7d Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Tue, 1 Oct 2024 13:12:10 +0200 Subject: [PATCH 0486/1286] Always sanitize HTML in dsMarkdown even if markdown disabled Instead of setting innerHTML directly to value, sanitize the value, even if not passing to renderMarkdown/Mathjax (cherry picked from commit 8fb4772b6c6308d2ba9e358e2858244105064c7f) --- .../shared/utils/markdown.directive.spec.ts | 58 +++++++++++++++++-- src/app/shared/utils/markdown.directive.ts | 2 +- 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/src/app/shared/utils/markdown.directive.spec.ts b/src/app/shared/utils/markdown.directive.spec.ts index 79e795be87..b984543c40 100644 --- a/src/app/shared/utils/markdown.directive.spec.ts +++ b/src/app/shared/utils/markdown.directive.spec.ts @@ -8,21 +8,20 @@ import { } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; +import { environment } from '../../../environments/environment.test'; import { MathService } from '../../core/shared/math.service'; import { MockMathService } from '../../core/shared/math.service.spec'; import { MarkdownDirective } from './markdown.directive'; @Component({ - template: `
`, + template: `
`, standalone: true, imports: [ MarkdownDirective ], }) class TestComponent {} describe('MarkdownDirective', () => { - let component: TestComponent; let fixture: ComponentFixture; - let divEl: DebugElement; beforeEach(async () => { await TestBed.configureTestingModule({ @@ -32,12 +31,61 @@ describe('MarkdownDirective', () => { }).compileComponents(); spyOn(MarkdownDirective.prototype, 'render'); fixture = TestBed.createComponent(TestComponent); - component = fixture.componentInstance; - divEl = fixture.debugElement.query(By.css('div')); }); it('should call render method', () => { fixture.detectChanges(); expect(MarkdownDirective.prototype.render).toHaveBeenCalled(); }); + +}); + +describe('MarkdownDirective sanitization with markdown disabled', () => { + let fixture: ComponentFixture; + let divEl: DebugElement; + // Disable markdown + environment.markdown.enabled = false; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + providers: [ + { provide: MathService, useClass: MockMathService }, + ], + }).compileComponents(); + fixture = TestBed.createComponent(TestComponent); + divEl = fixture.debugElement.query(By.css('div')); + + }); + + it('should sanitize the script element out of innerHTML (markdown disabled)',() => { + fixture.detectChanges(); + divEl = fixture.debugElement.query(By.css('div')); + expect(divEl.nativeElement.innerHTML).toEqual('test'); + }); + +}); + +describe('MarkdownDirective sanitization with markdown enabled', () => { + let fixture: ComponentFixture; + let divEl: DebugElement; + // Enable markdown + environment.markdown.enabled = true; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + providers: [ + { provide: MathService, useClass: MockMathService }, + ], + }).compileComponents(); + fixture = TestBed.createComponent(TestComponent); + divEl = fixture.debugElement.query(By.css('div')); + + }); + + it('should sanitize the script element out of innerHTML (markdown enabled)',() => { + fixture.detectChanges(); + divEl = fixture.debugElement.query(By.css('div')); + expect(divEl.nativeElement.innerHTML).toEqual('test'); + }); + }); diff --git a/src/app/shared/utils/markdown.directive.ts b/src/app/shared/utils/markdown.directive.ts index 0540e25cc5..de13acb303 100644 --- a/src/app/shared/utils/markdown.directive.ts +++ b/src/app/shared/utils/markdown.directive.ts @@ -55,7 +55,7 @@ export class MarkdownDirective implements OnInit, OnDestroy { async render(value: string, forcePreview = false): Promise { if (isEmpty(value) || (!environment.markdown.enabled && !forcePreview)) { - this.el.innerHTML = value; + this.el.innerHTML = this.sanitizer.sanitize(SecurityContext.HTML, value); return; } else { if (environment.markdown.mathjax) { From f975e1da897b34df0621ecd78ee11d4fc58460b4 Mon Sep 17 00:00:00 2001 From: andreaNeki Date: Tue, 1 Oct 2024 14:34:43 -0300 Subject: [PATCH 0487/1286] Edit item - making page content more responsive and accessible --- .../item-status/item-status.component.html | 16 ++++++++-------- .../item-status/item-status.component.scss | 3 +++ .../item-status/item-status.component.ts | 1 + 3 files changed, 12 insertions(+), 8 deletions(-) create mode 100644 src/app/item-page/edit-item-page/item-status/item-status.component.scss diff --git a/src/app/item-page/edit-item-page/item-status/item-status.component.html b/src/app/item-page/edit-item-page/item-status/item-status.component.html index faad0e679b..30212c4a4c 100644 --- a/src/app/item-page/edit-item-page/item-status/item-status.component.html +++ b/src/app/item-page/edit-item-page/item-status/item-status.component.html @@ -1,28 +1,28 @@

{{'item.edit.tabs.status.description' | translate}}

-
-
+
+
{{'item.edit.tabs.status.labels.' + statusKey | translate}}:
-
+
{{statusData[statusKey]}}
-
+
-
+
{{identifier.identifierType.toLocaleUpperCase()}}
-
{{identifier.value}} +
{{identifier.value}} ({{"item.edit.identifiers.doi.status."+identifier.identifierStatus|translate}})
-
+
{{'item.edit.tabs.status.labels.itemPage' | translate}}:
-
+ diff --git a/src/app/item-page/edit-item-page/item-status/item-status.component.scss b/src/app/item-page/edit-item-page/item-status/item-status.component.scss new file mode 100644 index 0000000000..349416cd20 --- /dev/null +++ b/src/app/item-page/edit-item-page/item-status/item-status.component.scss @@ -0,0 +1,3 @@ +.status-label { + font-weight: 700; +} diff --git a/src/app/item-page/edit-item-page/item-status/item-status.component.ts b/src/app/item-page/edit-item-page/item-status/item-status.component.ts index 1bb17dc77c..0ad500b56f 100644 --- a/src/app/item-page/edit-item-page/item-status/item-status.component.ts +++ b/src/app/item-page/edit-item-page/item-status/item-status.component.ts @@ -60,6 +60,7 @@ import { ItemOperation } from '../item-operation/itemOperation.model'; @Component({ selector: 'ds-base-item-status', + styleUrls: ['item-status.component.scss'], templateUrl: './item-status.component.html', changeDetection: ChangeDetectionStrategy.Default, animations: [ From fec4aa6df1bd6c5ea1ca9eeb10e4bc643a16d39e Mon Sep 17 00:00:00 2001 From: DanGastardelli <55243638+DanGastardelli@users.noreply.github.com> Date: Tue, 1 Oct 2024 17:15:53 -0300 Subject: [PATCH 0488/1286] Changing the bitstream title in the submission form to use the view component title, avoiding disappearance with changes to the form --- .../sections/upload/file/section-upload-file.component.html | 3 +-- .../upload/file/view/section-upload-file-view.component.html | 5 +++-- .../upload/file/view/section-upload-file-view.component.ts | 4 +++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/app/submission/sections/upload/file/section-upload-file.component.html b/src/app/submission/sections/upload/file/section-upload-file.component.html index da83e3f9a0..4698fdf68a 100644 --- a/src/app/submission/sections/upload/file/section-upload-file.component.html +++ b/src/app/submission/sections/upload/file/section-upload-file.component.html @@ -18,7 +18,7 @@
-

{{fileName}} ({{fileData?.sizeBytes | dsFileSize}})

+
@@ -43,7 +43,6 @@
-
diff --git a/src/app/submission/sections/upload/file/view/section-upload-file-view.component.html b/src/app/submission/sections/upload/file/view/section-upload-file-view.component.html index cc12b5dea6..dc72fbdad0 100644 --- a/src/app/submission/sections/upload/file/view/section-upload-file-view.component.html +++ b/src/app/submission/sections/upload/file/view/section-upload-file-view.component.html @@ -2,9 +2,10 @@ -
+

{{entry.value}} -

+ ({{fileData?.sizeBytes | dsFileSize}}) +
diff --git a/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts b/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts index 0630a28a76..7ab21fb85b 100644 --- a/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts +++ b/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts @@ -18,6 +18,7 @@ import { WorkspaceitemSectionUploadFileObject } from '../../../../../core/submis import { isNotEmpty } from '../../../../../shared/empty.util'; import { TruncatePipe } from '../../../../../shared/utils/truncate.pipe'; import { SubmissionSectionUploadAccessConditionsComponent } from '../../accessConditions/submission-section-upload-access-conditions.component'; +import { FileSizePipe } from "../../../../../shared/utils/file-size-pipe"; /** * This component allow to show bitstream's metadata @@ -31,7 +32,8 @@ import { SubmissionSectionUploadAccessConditionsComponent } from '../../accessCo TruncatePipe, NgIf, NgForOf, - ], + FileSizePipe +], standalone: true, }) export class SubmissionSectionUploadFileViewComponent implements OnInit { From 876d94e124cf11477a5548f11f095bc129c4b313 Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Wed, 2 Oct 2024 09:23:26 +0200 Subject: [PATCH 0489/1286] 115284: Add tests for isRepeatable --- .../edit-relationship-list.component.spec.ts | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.spec.ts b/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.spec.ts index 312f2936ac..69a2340fd5 100644 --- a/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.spec.ts +++ b/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.spec.ts @@ -78,7 +78,7 @@ describe('EditRelationshipListComponent', () => { fixture.detectChanges(); }; - function init(leftType: string, rightType: string): void { + function init(leftType: string, rightType: string, leftMaxCardinality?: number, rightMaxCardinality?: number): void { entityTypeLeft = Object.assign(new ItemType(), { id: leftType, uuid: leftType, @@ -98,6 +98,8 @@ describe('EditRelationshipListComponent', () => { rightType: createSuccessfulRemoteDataObject$(entityTypeRight), leftwardType: `is${rightType}Of${leftType}`, rightwardType: `is${leftType}Of${rightType}`, + leftMaxCardinality: leftMaxCardinality, + rightMaxCardinality: rightMaxCardinality, }); paginationOptions = Object.assign(new PaginationComponentOptions(), { @@ -367,4 +369,31 @@ describe('EditRelationshipListComponent', () => { })); }); }); + + describe('Is repeatable relationship', () => { + beforeEach(waitForAsync(() => { + currentItemIsLeftItem$ = new BehaviorSubject(true); + })); + describe('when max cardinality is 1', () => { + beforeEach(waitForAsync(() => init('Publication', 'OrgUnit', 1, undefined))); + it('should return false', () => { + const result = (comp as any).isRepeatable(); + expect(result).toBeFalse(); + }); + }); + describe('when max cardinality is 2', () => { + beforeEach(waitForAsync(() => init('Publication', 'OrgUnit', 2, undefined))); + it('should return true', () => { + const result = (comp as any).isRepeatable(); + expect(result).toBeTrue(); + }); + }); + describe('when max cardinality is undefined', () => { + beforeEach(waitForAsync(() => init('Publication', 'OrgUnit', undefined, undefined))); + it('should return true', () => { + const result = (comp as any).isRepeatable(); + expect(result).toBeTrue(); + }); + }); + }); }); From 161daffcc08e3c9ebcc209ba3115111243d2e6ae Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Wed, 2 Oct 2024 09:23:26 +0200 Subject: [PATCH 0490/1286] 115284: Add tests for isRepeatable --- .../edit-relationship-list.component.spec.ts | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.spec.ts b/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.spec.ts index 48415000be..4784e8fc5c 100644 --- a/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.spec.ts +++ b/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.spec.ts @@ -110,7 +110,7 @@ describe('EditRelationshipListComponent', () => { }, }; - function init(leftType: string, rightType: string): void { + function init(leftType: string, rightType: string, leftMaxCardinality?: number, rightMaxCardinality?: number): void { entityTypeLeft = Object.assign(new ItemType(), { id: leftType, uuid: leftType, @@ -130,6 +130,8 @@ describe('EditRelationshipListComponent', () => { rightType: createSuccessfulRemoteDataObject$(entityTypeRight), leftwardType: `is${rightType}Of${leftType}`, rightwardType: `is${leftType}Of${rightType}`, + leftMaxCardinality: leftMaxCardinality, + rightMaxCardinality: rightMaxCardinality, }); paginationOptions = Object.assign(new PaginationComponentOptions(), { @@ -402,4 +404,31 @@ describe('EditRelationshipListComponent', () => { })); }); }); + + describe('Is repeatable relationship', () => { + beforeEach(waitForAsync(() => { + currentItemIsLeftItem$ = new BehaviorSubject(true); + })); + describe('when max cardinality is 1', () => { + beforeEach(waitForAsync(() => init('Publication', 'OrgUnit', 1, undefined))); + it('should return false', () => { + const result = (comp as any).isRepeatable(); + expect(result).toBeFalse(); + }); + }); + describe('when max cardinality is 2', () => { + beforeEach(waitForAsync(() => init('Publication', 'OrgUnit', 2, undefined))); + it('should return true', () => { + const result = (comp as any).isRepeatable(); + expect(result).toBeTrue(); + }); + }); + describe('when max cardinality is undefined', () => { + beforeEach(waitForAsync(() => init('Publication', 'OrgUnit', undefined, undefined))); + it('should return true', () => { + const result = (comp as any).isRepeatable(); + expect(result).toBeTrue(); + }); + }); + }); }); From df24a63a464c3f88adedf982cdf540241414a86a Mon Sep 17 00:00:00 2001 From: DanGastardelli <55243638+DanGastardelli@users.noreply.github.com> Date: Wed, 2 Oct 2024 08:38:42 -0300 Subject: [PATCH 0491/1286] Adjusting spacing and good rules --- .../upload/file/view/section-upload-file-view.component.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts b/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts index 7ab21fb85b..378753a1e6 100644 --- a/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts +++ b/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts @@ -18,7 +18,7 @@ import { WorkspaceitemSectionUploadFileObject } from '../../../../../core/submis import { isNotEmpty } from '../../../../../shared/empty.util'; import { TruncatePipe } from '../../../../../shared/utils/truncate.pipe'; import { SubmissionSectionUploadAccessConditionsComponent } from '../../accessConditions/submission-section-upload-access-conditions.component'; -import { FileSizePipe } from "../../../../../shared/utils/file-size-pipe"; +import { FileSizePipe } from '../../../../../shared/utils/file-size-pipe'; /** * This component allow to show bitstream's metadata @@ -32,8 +32,8 @@ import { FileSizePipe } from "../../../../../shared/utils/file-size-pipe"; TruncatePipe, NgIf, NgForOf, - FileSizePipe -], + FileSizePipe, + ], standalone: true, }) export class SubmissionSectionUploadFileViewComponent implements OnInit { From 4aed1b60563b3486da9f5c98cd4ee15451553b73 Mon Sep 17 00:00:00 2001 From: andreaNeki Date: Wed, 2 Oct 2024 08:45:52 -0300 Subject: [PATCH 0492/1286] Adjusting bold text on labels --- .../item-operation/item-operation.component.html | 2 +- .../edit-item-page/item-status/item-status.component.html | 8 ++++---- .../edit-item-page/item-status/item-status.component.scss | 3 --- .../edit-item-page/item-status/item-status.component.ts | 1 - 4 files changed, 5 insertions(+), 9 deletions(-) delete mode 100644 src/app/item-page/edit-item-page/item-status/item-status.component.scss diff --git a/src/app/item-page/edit-item-page/item-operation/item-operation.component.html b/src/app/item-page/edit-item-page/item-operation/item-operation.component.html index deb8e15d29..0977876a19 100644 --- a/src/app/item-page/edit-item-page/item-operation/item-operation.component.html +++ b/src/app/item-page/edit-item-page/item-operation/item-operation.component.html @@ -1,5 +1,5 @@
- + {{'item.edit.tabs.status.buttons.' + operation.operationKey + '.label' | translate}}
diff --git a/src/app/item-page/edit-item-page/item-status/item-status.component.html b/src/app/item-page/edit-item-page/item-status/item-status.component.html index 30212c4a4c..7d6e2e9559 100644 --- a/src/app/item-page/edit-item-page/item-status/item-status.component.html +++ b/src/app/item-page/edit-item-page/item-status/item-status.component.html @@ -1,7 +1,7 @@

{{'item.edit.tabs.status.description' | translate}}

-
+
{{'item.edit.tabs.status.labels.' + statusKey | translate}}:
@@ -11,15 +11,15 @@
-
+
{{identifier.identifierType.toLocaleUpperCase()}}
-
{{identifier.value}} +
{{identifier.value}} ({{"item.edit.identifiers.doi.status."+identifier.identifierStatus|translate}})
-
+
{{'item.edit.tabs.status.labels.itemPage' | translate}}:
diff --git a/src/app/item-page/edit-item-page/item-status/item-status.component.scss b/src/app/item-page/edit-item-page/item-status/item-status.component.scss deleted file mode 100644 index 349416cd20..0000000000 --- a/src/app/item-page/edit-item-page/item-status/item-status.component.scss +++ /dev/null @@ -1,3 +0,0 @@ -.status-label { - font-weight: 700; -} diff --git a/src/app/item-page/edit-item-page/item-status/item-status.component.ts b/src/app/item-page/edit-item-page/item-status/item-status.component.ts index 0ad500b56f..1bb17dc77c 100644 --- a/src/app/item-page/edit-item-page/item-status/item-status.component.ts +++ b/src/app/item-page/edit-item-page/item-status/item-status.component.ts @@ -60,7 +60,6 @@ import { ItemOperation } from '../item-operation/itemOperation.model'; @Component({ selector: 'ds-base-item-status', - styleUrls: ['item-status.component.scss'], templateUrl: './item-status.component.html', changeDetection: ChangeDetectionStrategy.Default, animations: [ From 762bc8ce8c5a87a1dc7ba9763916addaabe06398 Mon Sep 17 00:00:00 2001 From: DanGastardelli <55243638+DanGastardelli@users.noreply.github.com> Date: Wed, 2 Oct 2024 08:46:37 -0300 Subject: [PATCH 0493/1286] Adjusting spacing --- .../upload/file/view/section-upload-file-view.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts b/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts index 378753a1e6..7b8e870400 100644 --- a/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts +++ b/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts @@ -54,13 +54,13 @@ export class SubmissionSectionUploadFileViewComponent implements OnInit { * The bitstream's title key * @type {string} */ - public fileTitleKey = 'Title'; + public fileTitleKey: string = 'Title'; /** * The bitstream's description key * @type {string} */ - public fileDescrKey = 'Description'; + public fileDescrKey: string = 'Description'; public fileFormat!: string; From 62006c00cacf7e74661d6cc3dd4b5a53f47aeb72 Mon Sep 17 00:00:00 2001 From: DanGastardelli <55243638+DanGastardelli@users.noreply.github.com> Date: Wed, 2 Oct 2024 09:01:56 -0300 Subject: [PATCH 0494/1286] Fix last commit --- .../upload/file/view/section-upload-file-view.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts b/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts index 7b8e870400..378753a1e6 100644 --- a/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts +++ b/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts @@ -54,13 +54,13 @@ export class SubmissionSectionUploadFileViewComponent implements OnInit { * The bitstream's title key * @type {string} */ - public fileTitleKey: string = 'Title'; + public fileTitleKey = 'Title'; /** * The bitstream's description key * @type {string} */ - public fileDescrKey: string = 'Description'; + public fileDescrKey = 'Description'; public fileFormat!: string; From eeaac8965b8b82e8d21f712350781c3e7f627157 Mon Sep 17 00:00:00 2001 From: DanGastardelli <55243638+DanGastardelli@users.noreply.github.com> Date: Wed, 2 Oct 2024 09:10:48 -0300 Subject: [PATCH 0495/1286] Import order adjustment --- .../upload/file/view/section-upload-file-view.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts b/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts index 378753a1e6..20e86a492d 100644 --- a/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts +++ b/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts @@ -17,8 +17,8 @@ import { Metadata } from '../../../../../core/shared/metadata.utils'; import { WorkspaceitemSectionUploadFileObject } from '../../../../../core/submission/models/workspaceitem-section-upload-file.model'; import { isNotEmpty } from '../../../../../shared/empty.util'; import { TruncatePipe } from '../../../../../shared/utils/truncate.pipe'; -import { SubmissionSectionUploadAccessConditionsComponent } from '../../accessConditions/submission-section-upload-access-conditions.component'; import { FileSizePipe } from '../../../../../shared/utils/file-size-pipe'; +import { SubmissionSectionUploadAccessConditionsComponent } from '../../accessConditions/submission-section-upload-access-conditions.component'; /** * This component allow to show bitstream's metadata From 2643a459b6a1213b4edb16f245732ba0a1b32bcb Mon Sep 17 00:00:00 2001 From: DanGastardelli <55243638+DanGastardelli@users.noreply.github.com> Date: Wed, 2 Oct 2024 09:24:46 -0300 Subject: [PATCH 0496/1286] Import order adjustment --- .../upload/file/view/section-upload-file-view.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts b/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts index 20e86a492d..f065fc9e19 100644 --- a/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts +++ b/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts @@ -16,8 +16,8 @@ import { import { Metadata } from '../../../../../core/shared/metadata.utils'; import { WorkspaceitemSectionUploadFileObject } from '../../../../../core/submission/models/workspaceitem-section-upload-file.model'; import { isNotEmpty } from '../../../../../shared/empty.util'; -import { TruncatePipe } from '../../../../../shared/utils/truncate.pipe'; import { FileSizePipe } from '../../../../../shared/utils/file-size-pipe'; +import { TruncatePipe } from '../../../../../shared/utils/truncate.pipe'; import { SubmissionSectionUploadAccessConditionsComponent } from '../../accessConditions/submission-section-upload-access-conditions.component'; /** From 01d09810ba045affc083fdf0398930231a80d51a Mon Sep 17 00:00:00 2001 From: root Date: Wed, 26 Jun 2024 08:29:32 -0300 Subject: [PATCH 0497/1286] Resolution of issue #1190 - Improving the accessibility of the status page using the item-operation component (cherry picked from commit e06b67fd73358ac52e2e71fa96d708520de33f3e) --- .../item-operation/item-operation.component.html | 4 ++-- .../item-operation/item-operation.component.scss | 9 +++++++++ .../item-operation/item-operation.component.ts | 1 + 3 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 src/app/item-page/edit-item-page/item-operation/item-operation.component.scss diff --git a/src/app/item-page/edit-item-page/item-operation/item-operation.component.html b/src/app/item-page/edit-item-page/item-operation/item-operation.component.html index 85c6a2cca1..e282017315 100644 --- a/src/app/item-page/edit-item-page/item-operation/item-operation.component.html +++ b/src/app/item-page/edit-item-page/item-operation/item-operation.component.html @@ -1,9 +1,9 @@ -
+
{{'item.edit.tabs.status.buttons.' + operation.operationKey + '.label' | translate}}
-
+
diff --git a/src/styles/_global-styles.scss b/src/styles/_global-styles.scss index 765b50ae86..b3120c08cd 100644 --- a/src/styles/_global-styles.scss +++ b/src/styles/_global-styles.scss @@ -466,3 +466,11 @@ ngb-accordion { .mt-ncs { margin-top: calc(var(--ds-content-spacing) * -1); } .mb-ncs { margin-bottom: calc(var(--ds-content-spacing) * -1); } .my-ncs { margin-top: calc(var(--ds-content-spacing) * -1); margin-bottom: calc(var(--ds-content-spacing) * -1); } + + +.link-contrast { + // Rules for accessibility to meet minimum contrast and have an identifiable link between other texts + color: darken($link-color, 5%); + // We use underline to discern link from text as we can't make color lighter on a white bg + text-decoration: underline; +} From 69f618e8566445b800b83bcc4604bd2e59a98b28 Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Tue, 23 Jul 2024 17:13:20 +0200 Subject: [PATCH 0513/1286] [CST-15592] improve tests, add attributes for testing, fix wrong references --- cypress/e2e/admin-add-new-modals.cy.ts | 6 ++-- cypress/e2e/admin-edit-modals.cy.ts | 6 ++-- cypress/e2e/admin-export-modals.cy.ts | 4 +-- cypress/e2e/admin-search-page.cy.ts | 3 ++ cypress/e2e/admin-workflow-page.cy.ts | 3 ++ cypress/e2e/bulk-access.cy.ts | 7 +++++ cypress/e2e/health-page.cy.ts | 31 +++++++++++++++---- .../health-page/health-page.component.html | 4 +-- .../onclick-menu-item.component.html | 3 +- 9 files changed, 50 insertions(+), 17 deletions(-) diff --git a/cypress/e2e/admin-add-new-modals.cy.ts b/cypress/e2e/admin-add-new-modals.cy.ts index 6e2e8e6970..565ae154f1 100644 --- a/cypress/e2e/admin-add-new-modals.cy.ts +++ b/cypress/e2e/admin-add-new-modals.cy.ts @@ -14,7 +14,7 @@ describe('Admin Add New Modals', () => { // Click on entry of menu cy.get('#admin-menu-section-new-title').click(); - cy.get('a[title="menu.section.new_community"]').click(); + cy.get('a[data-test="menu.section.new_community"]').click(); // Analyze for accessibility testA11y('ds-create-community-parent-selector'); @@ -27,7 +27,7 @@ describe('Admin Add New Modals', () => { // Click on entry of menu cy.get('#admin-menu-section-new-title').click(); - cy.get('a[title="menu.section.new_collection"]').click(); + cy.get('a[data-test="menu.section.new_collection"]').click(); // Analyze for accessibility testA11y('ds-create-collection-parent-selector'); @@ -40,7 +40,7 @@ describe('Admin Add New Modals', () => { // Click on entry of menu cy.get('#admin-menu-section-new-title').click(); - cy.get('a[title="menu.section.new_item"]').click(); + cy.get('a[data-test="menu.section.new_item"]').click(); // Analyze for accessibility testA11y('ds-create-item-parent-selector'); diff --git a/cypress/e2e/admin-edit-modals.cy.ts b/cypress/e2e/admin-edit-modals.cy.ts index 256a6d89cb..e96d6ce898 100644 --- a/cypress/e2e/admin-edit-modals.cy.ts +++ b/cypress/e2e/admin-edit-modals.cy.ts @@ -14,7 +14,7 @@ describe('Admin Edit Modals', () => { // Click on entry of menu cy.get('#admin-menu-section-edit-title').click(); - cy.get('a[title="menu.section.edit_community"]').click(); + cy.get('a[data-test="menu.section.edit_community"]').click(); // Analyze for accessibility testA11y('ds-edit-community-selector'); @@ -27,7 +27,7 @@ describe('Admin Edit Modals', () => { // Click on entry of menu cy.get('#admin-menu-section-edit-title').click(); - cy.get('a[title="menu.section.edit_collection"]').click(); + cy.get('a[data-test="menu.section.edit_collection"]').click(); // Analyze for accessibility testA11y('ds-edit-collection-selector'); @@ -40,7 +40,7 @@ describe('Admin Edit Modals', () => { // Click on entry of menu cy.get('#admin-menu-section-edit-title').click(); - cy.get('a[title="menu.section.edit_item"]').click(); + cy.get('a[data-test="menu.section.edit_item"]').click(); // Analyze for accessibility testA11y('ds-edit-item-selector'); diff --git a/cypress/e2e/admin-export-modals.cy.ts b/cypress/e2e/admin-export-modals.cy.ts index b611bb8fd5..9f69764d19 100644 --- a/cypress/e2e/admin-export-modals.cy.ts +++ b/cypress/e2e/admin-export-modals.cy.ts @@ -14,7 +14,7 @@ describe('Admin Export Modals', () => { // Click on entry of menu cy.get('#admin-menu-section-export-title').click(); - cy.get('a[title="menu.section.export_metadata"]').click(); + cy.get('a[data-test="menu.section.export_metadata"]').click(); // Analyze for accessibility testA11y('ds-export-metadata-selector'); @@ -27,7 +27,7 @@ describe('Admin Export Modals', () => { // Click on entry of menu cy.get('#admin-menu-section-export-title').click(); - cy.get('a[title="menu.section.export_batch"]').click(); + cy.get('a[data-test="menu.section.export_batch"]').click(); // Analyze for accessibility testA11y('ds-export-batch-selector'); diff --git a/cypress/e2e/admin-search-page.cy.ts b/cypress/e2e/admin-search-page.cy.ts index 2e1d13aa13..4fbf8939fe 100644 --- a/cypress/e2e/admin-search-page.cy.ts +++ b/cypress/e2e/admin-search-page.cy.ts @@ -12,6 +12,9 @@ describe('Admin Search Page', () => { cy.get('ds-admin-search-page').should('be.visible'); // At least one search result should be displayed cy.get('[data-test="list-object"]').should('be.visible'); + // Click each filter toggle to open *every* filter + // (As we want to scan filter section for accessibility issues as well) + cy.get('[data-test="filter-toggle"]').click({ multiple: true }); // Analyze for accessibility issues testA11y('ds-admin-search-page'); }); diff --git a/cypress/e2e/admin-workflow-page.cy.ts b/cypress/e2e/admin-workflow-page.cy.ts index cd2275f584..c3c235e346 100644 --- a/cypress/e2e/admin-workflow-page.cy.ts +++ b/cypress/e2e/admin-workflow-page.cy.ts @@ -12,6 +12,9 @@ describe('Admin Workflow Page', () => { cy.get('ds-admin-workflow-page').should('be.visible'); // At least one search result should be displayed cy.get('[data-test="list-object"]').should('be.visible'); + // Click each filter toggle to open *every* filter + // (As we want to scan filter section for accessibility issues as well) + cy.get('[data-test="filter-toggle"]').click({ multiple: true }); // Analyze for accessibility issues testA11y('ds-admin-workflow-page'); }); diff --git a/cypress/e2e/bulk-access.cy.ts b/cypress/e2e/bulk-access.cy.ts index 4d199f53f9..87033e13e4 100644 --- a/cypress/e2e/bulk-access.cy.ts +++ b/cypress/e2e/bulk-access.cy.ts @@ -11,6 +11,11 @@ describe('Bulk Access', () => { it('should pass accessibility tests', () => { // Page must first be visible cy.get('ds-bulk-access').should('be.visible'); + // At least one search result should be displayed + cy.get('[data-test="list-object"]').should('be.visible'); + // Click each filter toggle to open *every* filter + // (As we want to scan filter section for accessibility issues as well) + cy.get('[data-test="filter-toggle"]').click({ multiple: true }); // Analyze for accessibility issues testA11y('ds-bulk-access', { rules: { @@ -18,6 +23,8 @@ describe('Bulk Access', () => { // Seem to require updating ng-bootstrap and https://github.com/DSpace/dspace-angular/issues/2216 'aria-required-children': { enabled: false }, 'nested-interactive': { enabled: false }, + // Card titles fail this test currently + 'heading-order': { enabled: false }, }, } as Options); }); diff --git a/cypress/e2e/health-page.cy.ts b/cypress/e2e/health-page.cy.ts index 91c68638ea..79ebf4bc04 100644 --- a/cypress/e2e/health-page.cy.ts +++ b/cypress/e2e/health-page.cy.ts @@ -1,13 +1,14 @@ import { testA11y } from 'cypress/support/utils'; import { Options } from 'cypress-axe'; -describe('Health Page', () => { - beforeEach(() => { - // Must login as an Admin to see the page - cy.visit('/health'); - cy.loginViaForm(Cypress.env('DSPACE_TEST_ADMIN_USER'), Cypress.env('DSPACE_TEST_ADMIN_PASSWORD')); - }); +beforeEach(() => { + // Must login as an Admin to see the page + cy.visit('/health'); + cy.loginViaForm(Cypress.env('DSPACE_TEST_ADMIN_USER'), Cypress.env('DSPACE_TEST_ADMIN_PASSWORD')); +}); + +describe('Health Page > Status Tab', () => { it('should pass accessibility tests', () => { // Page must first be visible cy.get('ds-health-page').should('be.visible'); @@ -22,3 +23,21 @@ describe('Health Page', () => { } as Options); }); }); + +describe('Health Page > Info Tab', () => { + it('should pass accessibility tests', () => { + // Page must first be visible + cy.get('ds-health-page').should('be.visible'); + cy.get('a[data-test="health-page.info-tab"]').click(); + + // Analyze for accessibility issues + testA11y('ds-health-page', { + rules: { + // All panels are accordians & fail "aria-required-children" and "nested-interactive". + // Seem to require updating ng-bootstrap and https://github.com/DSpace/dspace-angular/issues/2216 + 'aria-required-children': { enabled: false }, + 'nested-interactive': { enabled: false }, + }, + } as Options); + }); +}); diff --git a/src/app/health-page/health-page.component.html b/src/app/health-page/health-page.component.html index d8cba1d46d..797ca0bc6e 100644 --- a/src/app/health-page/health-page.component.html +++ b/src/app/health-page/health-page.component.html @@ -3,7 +3,7 @@
diff --git a/src/styles/_global-styles.scss b/src/styles/_global-styles.scss index 765b50ae86..b3120c08cd 100644 --- a/src/styles/_global-styles.scss +++ b/src/styles/_global-styles.scss @@ -466,3 +466,11 @@ ngb-accordion { .mt-ncs { margin-top: calc(var(--ds-content-spacing) * -1); } .mb-ncs { margin-bottom: calc(var(--ds-content-spacing) * -1); } .my-ncs { margin-top: calc(var(--ds-content-spacing) * -1); margin-bottom: calc(var(--ds-content-spacing) * -1); } + + +.link-contrast { + // Rules for accessibility to meet minimum contrast and have an identifiable link between other texts + color: darken($link-color, 5%); + // We use underline to discern link from text as we can't make color lighter on a white bg + text-decoration: underline; +} From 75981cf46e5f10d3186b45c363b86f2749c6a0d9 Mon Sep 17 00:00:00 2001 From: FrancescoMolinaro Date: Tue, 23 Jul 2024 17:13:20 +0200 Subject: [PATCH 0528/1286] [CST-15592] improve tests, add attributes for testing, fix wrong references (cherry picked from commit 69f618e8566445b800b83bcc4604bd2e59a98b28) --- cypress/e2e/admin-add-new-modals.cy.ts | 6 ++-- cypress/e2e/admin-edit-modals.cy.ts | 6 ++-- cypress/e2e/admin-export-modals.cy.ts | 4 +-- cypress/e2e/admin-search-page.cy.ts | 3 ++ cypress/e2e/admin-workflow-page.cy.ts | 3 ++ cypress/e2e/bulk-access.cy.ts | 7 +++++ cypress/e2e/health-page.cy.ts | 31 +++++++++++++++---- .../health-page/health-page.component.html | 4 +-- .../onclick-menu-item.component.html | 3 +- 9 files changed, 50 insertions(+), 17 deletions(-) diff --git a/cypress/e2e/admin-add-new-modals.cy.ts b/cypress/e2e/admin-add-new-modals.cy.ts index 6e2e8e6970..565ae154f1 100644 --- a/cypress/e2e/admin-add-new-modals.cy.ts +++ b/cypress/e2e/admin-add-new-modals.cy.ts @@ -14,7 +14,7 @@ describe('Admin Add New Modals', () => { // Click on entry of menu cy.get('#admin-menu-section-new-title').click(); - cy.get('a[title="menu.section.new_community"]').click(); + cy.get('a[data-test="menu.section.new_community"]').click(); // Analyze for accessibility testA11y('ds-create-community-parent-selector'); @@ -27,7 +27,7 @@ describe('Admin Add New Modals', () => { // Click on entry of menu cy.get('#admin-menu-section-new-title').click(); - cy.get('a[title="menu.section.new_collection"]').click(); + cy.get('a[data-test="menu.section.new_collection"]').click(); // Analyze for accessibility testA11y('ds-create-collection-parent-selector'); @@ -40,7 +40,7 @@ describe('Admin Add New Modals', () => { // Click on entry of menu cy.get('#admin-menu-section-new-title').click(); - cy.get('a[title="menu.section.new_item"]').click(); + cy.get('a[data-test="menu.section.new_item"]').click(); // Analyze for accessibility testA11y('ds-create-item-parent-selector'); diff --git a/cypress/e2e/admin-edit-modals.cy.ts b/cypress/e2e/admin-edit-modals.cy.ts index 256a6d89cb..e96d6ce898 100644 --- a/cypress/e2e/admin-edit-modals.cy.ts +++ b/cypress/e2e/admin-edit-modals.cy.ts @@ -14,7 +14,7 @@ describe('Admin Edit Modals', () => { // Click on entry of menu cy.get('#admin-menu-section-edit-title').click(); - cy.get('a[title="menu.section.edit_community"]').click(); + cy.get('a[data-test="menu.section.edit_community"]').click(); // Analyze for accessibility testA11y('ds-edit-community-selector'); @@ -27,7 +27,7 @@ describe('Admin Edit Modals', () => { // Click on entry of menu cy.get('#admin-menu-section-edit-title').click(); - cy.get('a[title="menu.section.edit_collection"]').click(); + cy.get('a[data-test="menu.section.edit_collection"]').click(); // Analyze for accessibility testA11y('ds-edit-collection-selector'); @@ -40,7 +40,7 @@ describe('Admin Edit Modals', () => { // Click on entry of menu cy.get('#admin-menu-section-edit-title').click(); - cy.get('a[title="menu.section.edit_item"]').click(); + cy.get('a[data-test="menu.section.edit_item"]').click(); // Analyze for accessibility testA11y('ds-edit-item-selector'); diff --git a/cypress/e2e/admin-export-modals.cy.ts b/cypress/e2e/admin-export-modals.cy.ts index b611bb8fd5..9f69764d19 100644 --- a/cypress/e2e/admin-export-modals.cy.ts +++ b/cypress/e2e/admin-export-modals.cy.ts @@ -14,7 +14,7 @@ describe('Admin Export Modals', () => { // Click on entry of menu cy.get('#admin-menu-section-export-title').click(); - cy.get('a[title="menu.section.export_metadata"]').click(); + cy.get('a[data-test="menu.section.export_metadata"]').click(); // Analyze for accessibility testA11y('ds-export-metadata-selector'); @@ -27,7 +27,7 @@ describe('Admin Export Modals', () => { // Click on entry of menu cy.get('#admin-menu-section-export-title').click(); - cy.get('a[title="menu.section.export_batch"]').click(); + cy.get('a[data-test="menu.section.export_batch"]').click(); // Analyze for accessibility testA11y('ds-export-batch-selector'); diff --git a/cypress/e2e/admin-search-page.cy.ts b/cypress/e2e/admin-search-page.cy.ts index 2e1d13aa13..4fbf8939fe 100644 --- a/cypress/e2e/admin-search-page.cy.ts +++ b/cypress/e2e/admin-search-page.cy.ts @@ -12,6 +12,9 @@ describe('Admin Search Page', () => { cy.get('ds-admin-search-page').should('be.visible'); // At least one search result should be displayed cy.get('[data-test="list-object"]').should('be.visible'); + // Click each filter toggle to open *every* filter + // (As we want to scan filter section for accessibility issues as well) + cy.get('[data-test="filter-toggle"]').click({ multiple: true }); // Analyze for accessibility issues testA11y('ds-admin-search-page'); }); diff --git a/cypress/e2e/admin-workflow-page.cy.ts b/cypress/e2e/admin-workflow-page.cy.ts index cd2275f584..c3c235e346 100644 --- a/cypress/e2e/admin-workflow-page.cy.ts +++ b/cypress/e2e/admin-workflow-page.cy.ts @@ -12,6 +12,9 @@ describe('Admin Workflow Page', () => { cy.get('ds-admin-workflow-page').should('be.visible'); // At least one search result should be displayed cy.get('[data-test="list-object"]').should('be.visible'); + // Click each filter toggle to open *every* filter + // (As we want to scan filter section for accessibility issues as well) + cy.get('[data-test="filter-toggle"]').click({ multiple: true }); // Analyze for accessibility issues testA11y('ds-admin-workflow-page'); }); diff --git a/cypress/e2e/bulk-access.cy.ts b/cypress/e2e/bulk-access.cy.ts index 4d199f53f9..87033e13e4 100644 --- a/cypress/e2e/bulk-access.cy.ts +++ b/cypress/e2e/bulk-access.cy.ts @@ -11,6 +11,11 @@ describe('Bulk Access', () => { it('should pass accessibility tests', () => { // Page must first be visible cy.get('ds-bulk-access').should('be.visible'); + // At least one search result should be displayed + cy.get('[data-test="list-object"]').should('be.visible'); + // Click each filter toggle to open *every* filter + // (As we want to scan filter section for accessibility issues as well) + cy.get('[data-test="filter-toggle"]').click({ multiple: true }); // Analyze for accessibility issues testA11y('ds-bulk-access', { rules: { @@ -18,6 +23,8 @@ describe('Bulk Access', () => { // Seem to require updating ng-bootstrap and https://github.com/DSpace/dspace-angular/issues/2216 'aria-required-children': { enabled: false }, 'nested-interactive': { enabled: false }, + // Card titles fail this test currently + 'heading-order': { enabled: false }, }, } as Options); }); diff --git a/cypress/e2e/health-page.cy.ts b/cypress/e2e/health-page.cy.ts index 91c68638ea..79ebf4bc04 100644 --- a/cypress/e2e/health-page.cy.ts +++ b/cypress/e2e/health-page.cy.ts @@ -1,13 +1,14 @@ import { testA11y } from 'cypress/support/utils'; import { Options } from 'cypress-axe'; -describe('Health Page', () => { - beforeEach(() => { - // Must login as an Admin to see the page - cy.visit('/health'); - cy.loginViaForm(Cypress.env('DSPACE_TEST_ADMIN_USER'), Cypress.env('DSPACE_TEST_ADMIN_PASSWORD')); - }); +beforeEach(() => { + // Must login as an Admin to see the page + cy.visit('/health'); + cy.loginViaForm(Cypress.env('DSPACE_TEST_ADMIN_USER'), Cypress.env('DSPACE_TEST_ADMIN_PASSWORD')); +}); + +describe('Health Page > Status Tab', () => { it('should pass accessibility tests', () => { // Page must first be visible cy.get('ds-health-page').should('be.visible'); @@ -22,3 +23,21 @@ describe('Health Page', () => { } as Options); }); }); + +describe('Health Page > Info Tab', () => { + it('should pass accessibility tests', () => { + // Page must first be visible + cy.get('ds-health-page').should('be.visible'); + cy.get('a[data-test="health-page.info-tab"]').click(); + + // Analyze for accessibility issues + testA11y('ds-health-page', { + rules: { + // All panels are accordians & fail "aria-required-children" and "nested-interactive". + // Seem to require updating ng-bootstrap and https://github.com/DSpace/dspace-angular/issues/2216 + 'aria-required-children': { enabled: false }, + 'nested-interactive': { enabled: false }, + }, + } as Options); + }); +}); diff --git a/src/app/health-page/health-page.component.html b/src/app/health-page/health-page.component.html index d8cba1d46d..797ca0bc6e 100644 --- a/src/app/health-page/health-page.component.html +++ b/src/app/health-page/health-page.component.html @@ -3,7 +3,7 @@
-
* {{ "item.version.history.selected" | translate }}
+
* {{"item.version.history.selected" | translate}}
From 5619d6bc4c7c259a9b72c2f37710c3bf3932d117 Mon Sep 17 00:00:00 2001 From: Andrea Barbasso <´andrea.barbasso@4science.com´> Date: Mon, 15 Apr 2024 09:43:38 +0200 Subject: [PATCH 0584/1286] [DURACOM-248] set function call result in a class attribute (cherry picked from commit 87cff6c90792553b2170e6a9326fdabdd478456c) --- src/app/item-page/versions/item-versions.component.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/item-page/versions/item-versions.component.html b/src/app/item-page/versions/item-versions.component.html index 745f835492..6184b42aa8 100644 --- a/src/app/item-page/versions/item-versions.component.html +++ b/src/app/item-page/versions/item-versions.component.html @@ -15,7 +15,7 @@
{{ "item.version.history.table.version" | translate }}{{ "item.version.history.table.editor" | translate }}{{ "item.version.history.table.editor" | translate }} {{ "item.version.history.table.date" | translate }} {{ "item.version.history.table.summary" | translate }}
+ {{ versionDTO.version.submitterName }} From 704cc06f1647c29fadb0ba12f93fde5d190d8a7f Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Fri, 11 Oct 2024 09:59:10 +0200 Subject: [PATCH 0585/1286] 118944: Fix hasDraftVersion$ not working for embedded payloads with no content --- src/app/core/data/version-history-data.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/core/data/version-history-data.service.ts b/src/app/core/data/version-history-data.service.ts index 8229083535..8ecfde0686 100644 --- a/src/app/core/data/version-history-data.service.ts +++ b/src/app/core/data/version-history-data.service.ts @@ -171,7 +171,7 @@ export class VersionHistoryDataService extends IdentifiableDataService) => { - if (versionRD.hasSucceeded && !versionRD.hasNoContent) { + if (versionRD.hasSucceeded && !versionRD.hasNoContent && hasValue(versionRD.payload)) { return versionRD.payload.versionhistory.pipe( getFirstCompletedRemoteData(), map((versionHistoryRD: RemoteData) => { From 680d6c94166266d6195f13b92e3be916917ae8c0 Mon Sep 17 00:00:00 2001 From: milanmajchrak Date: Fri, 11 Oct 2024 13:37:24 +0200 Subject: [PATCH 0586/1286] Fixed small cs localization mistakes --- src/assets/i18n/cs.json5 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assets/i18n/cs.json5 b/src/assets/i18n/cs.json5 index 09dd023e8d..466e3475bf 100644 --- a/src/assets/i18n/cs.json5 +++ b/src/assets/i18n/cs.json5 @@ -2939,7 +2939,7 @@ "error.top-level-communities": "Chyba při načítání komunit nejvyšší úrovně", // "error.validation.license.notgranted": "You must grant this license to complete your submission. If you are unable to grant this license at this time you may save your work and return later or remove the submission.", - "error.validation.license.notgranted": "Bez udělení licence nelze záznam dokončit. Pokud v tuto chvíli nemůžete licenci udělit, uložte svou práci a vraťte se k příspěveku později nebo jej smažte.", + "error.validation.license.notgranted": "Bez udělení licence nelze záznam dokončit. Pokud v tuto chvíli nemůžete licenci udělit, uložte svou práci a vraťte se k příspěvku později nebo jej smažte.", // "error.validation.pattern": "This input is restricted by the current pattern: {{ pattern }}.", "error.validation.pattern": "Toto zadání je omezeno aktuálním vzorcem: {{ pattern }}.", @@ -4934,7 +4934,7 @@ "iiif.page.doi": "Trvalý odkaz: ", // "iiif.page.issue": "Issue: ", - "iiif.page.issue": "Číslo:", + "iiif.page.issue": "Číslo: ", // "iiif.page.description": "Description: ", "iiif.page.description": "Popis: ", From b709ee03000086cd52f5de9bc67d5619a64df29d Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Fri, 11 Oct 2024 14:59:34 +0200 Subject: [PATCH 0587/1286] 118944: Embed the accessStatus link on collection, browse, recent item submissions & the item page related items & delete tab when enabled --- .../collection-page.component.ts | 4 +-- .../breadcrumbs/item-breadcrumb.resolver.ts | 4 +-- src/app/core/browse/browse.service.spec.ts | 12 -------- src/app/core/browse/browse.service.ts | 19 ++++++++----- .../data/relationship-data.service.spec.ts | 4 ++- .../core/data/relationship-data.service.ts | 4 ++- .../recent-item-list.component.ts | 3 ++ .../abstract-item-update.component.ts | 4 +-- .../item-delete/item-delete.component.ts | 4 +-- .../edit-relationship-list.component.spec.ts | 5 ++-- .../edit-relationship-list.component.ts | 2 +- src/app/item-page/item.resolver.ts | 27 +++++++++++------- ...ynamic-form-control-container.component.ts | 2 +- src/app/shared/utils/relation-query.utils.ts | 28 +++++++++++-------- 14 files changed, 67 insertions(+), 55 deletions(-) diff --git a/src/app/collection-page/collection-page.component.ts b/src/app/collection-page/collection-page.component.ts index 16704cef52..e74db09f24 100644 --- a/src/app/collection-page/collection-page.component.ts +++ b/src/app/collection-page/collection-page.component.ts @@ -28,7 +28,7 @@ import { AuthorizationDataService } from '../core/data/feature-authorization/aut import { FeatureID } from '../core/data/feature-authorization/feature-id'; import { getCollectionPageRoute } from './collection-page-routing-paths'; import { redirectOn4xx } from '../core/shared/authorized.operators'; -import { BROWSE_LINKS_TO_FOLLOW } from '../core/browse/browse.service'; +import { getBrowseLinksToFollow } from '../core/browse/browse.service'; import { DSONameService } from '../core/breadcrumbs/dso-name.service'; import { APP_CONFIG, AppConfig } from '../../../src/config/app-config.interface'; @@ -115,7 +115,7 @@ export class CollectionPageComponent implements OnInit { pagination: currentPagination, sort: currentSort, dsoTypes: [DSpaceObjectType.ITEM] - }), null, true, true, ...BROWSE_LINKS_TO_FOLLOW) + }), null, true, true, ...getBrowseLinksToFollow()) .pipe(toDSpaceObjectListRD()) as Observable>>; }), startWith(undefined) // Make sure switching pages shows loading component diff --git a/src/app/core/breadcrumbs/item-breadcrumb.resolver.ts b/src/app/core/breadcrumbs/item-breadcrumb.resolver.ts index 3005b6f09a..f396fd08dd 100644 --- a/src/app/core/breadcrumbs/item-breadcrumb.resolver.ts +++ b/src/app/core/breadcrumbs/item-breadcrumb.resolver.ts @@ -4,7 +4,7 @@ import { ItemDataService } from '../data/item-data.service'; import { Item } from '../shared/item.model'; import { DSOBreadcrumbResolver } from './dso-breadcrumb.resolver'; import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; -import { ITEM_PAGE_LINKS_TO_FOLLOW } from '../../item-page/item.resolver'; +import { getItemPageLinksToFollow } from '../../item-page/item.resolver'; /** * The class that resolves the BreadcrumbConfig object for an Item @@ -23,6 +23,6 @@ export class ItemBreadcrumbResolver extends DSOBreadcrumbResolver { * Requesting them as embeds will limit the number of requests */ get followLinks(): FollowLinkConfig[] { - return ITEM_PAGE_LINKS_TO_FOLLOW; + return getItemPageLinksToFollow(); } } diff --git a/src/app/core/browse/browse.service.spec.ts b/src/app/core/browse/browse.service.spec.ts index 9f166e3d19..f7027fc91e 100644 --- a/src/app/core/browse/browse.service.spec.ts +++ b/src/app/core/browse/browse.service.spec.ts @@ -1,10 +1,8 @@ import { cold, getTestScheduler, hot } from 'jasmine-marbles'; import { of as observableOf } from 'rxjs'; import { TestScheduler } from 'rxjs/testing'; -import { getMockRemoteDataBuildService } from '../../shared/mocks/remote-data-build.service.mock'; import { getMockRequestService } from '../../shared/mocks/request.service.mock'; import { HALEndpointServiceStub } from '../../shared/testing/hal-endpoint-service.stub'; -import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { RequestService } from '../data/request.service'; import { BrowseEntrySearchOptions } from './browse-entry-search-options.model'; import { BrowseService } from './browse.service'; @@ -20,7 +18,6 @@ describe('BrowseService', () => { let scheduler: TestScheduler; let service: BrowseService; let requestService: RequestService; - let rdbService: RemoteDataBuildService; const browsesEndpointURL = 'https://rest.api/browses'; const halService: any = new HALEndpointServiceStub(browsesEndpointURL); @@ -118,7 +115,6 @@ describe('BrowseService', () => { halService, browseDefinitionDataService, hrefOnlyDataService, - rdbService ); } @@ -130,11 +126,9 @@ describe('BrowseService', () => { beforeEach(() => { requestService = getMockRequestService(getRequestEntry$(true)); - rdbService = getMockRemoteDataBuildService(); service = initTestService(); spyOn(halService, 'getEndpoint').and .returnValue(hot('--a-', { a: browsesEndpointURL })); - spyOn(rdbService, 'buildList').and.callThrough(); }); it('should call BrowseDefinitionDataService to create the RemoteData Observable', () => { @@ -151,9 +145,7 @@ describe('BrowseService', () => { beforeEach(() => { requestService = getMockRequestService(getRequestEntry$(true)); - rdbService = getMockRemoteDataBuildService(); service = initTestService(); - spyOn(rdbService, 'buildList').and.callThrough(); }); describe('when getBrowseEntriesFor is called with a valid browse definition id', () => { @@ -204,7 +196,6 @@ describe('BrowseService', () => { describe('if getBrowseDefinitions fires', () => { beforeEach(() => { requestService = getMockRequestService(getRequestEntry$(true)); - rdbService = getMockRemoteDataBuildService(); service = initTestService(); spyOn(service, 'getBrowseDefinitions').and .returnValue(hot('--a-', { @@ -259,7 +250,6 @@ describe('BrowseService', () => { describe('if getBrowseDefinitions doesn\'t fire', () => { it('should return undefined', () => { requestService = getMockRequestService(getRequestEntry$(true)); - rdbService = getMockRemoteDataBuildService(); service = initTestService(); spyOn(service, 'getBrowseDefinitions').and .returnValue(hot('----')); @@ -277,9 +267,7 @@ describe('BrowseService', () => { describe('getFirstItemFor', () => { beforeEach(() => { requestService = getMockRequestService(); - rdbService = getMockRemoteDataBuildService(); service = initTestService(); - spyOn(rdbService, 'buildList').and.callThrough(); }); describe('when getFirstItemFor is called with a valid browse definition id', () => { diff --git a/src/app/core/browse/browse.service.ts b/src/app/core/browse/browse.service.ts index b210b34949..2d8dd4b80f 100644 --- a/src/app/core/browse/browse.service.ts +++ b/src/app/core/browse/browse.service.ts @@ -2,7 +2,6 @@ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { distinctUntilChanged, map, startWith } from 'rxjs/operators'; import { hasValue, hasValueOperator, isEmpty, isNotEmpty } from '../../shared/empty.util'; -import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { PaginatedList } from '../data/paginated-list.model'; import { RemoteData } from '../data/remote-data'; import { RequestService } from '../data/request.service'; @@ -24,11 +23,18 @@ import { HrefOnlyDataService } from '../data/href-only-data.service'; import { followLink, FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; import { BrowseDefinitionDataService } from './browse-definition-data.service'; import { SortDirection } from '../cache/models/sort-options.model'; +import { environment } from '../../../environments/environment'; -export const BROWSE_LINKS_TO_FOLLOW: FollowLinkConfig[] = [ - followLink('thumbnail') -]; +export function getBrowseLinksToFollow(): FollowLinkConfig[] { + const followLinks = [ + followLink('thumbnail'), + ]; + if (environment.item.showAccessStatuses) { + followLinks.push(followLink('accessStatus')); + } + return followLinks; +} /** * The service handling all browse requests @@ -55,7 +61,6 @@ export class BrowseService { protected halService: HALEndpointService, private browseDefinitionDataService: BrowseDefinitionDataService, private hrefOnlyDataService: HrefOnlyDataService, - private rdb: RemoteDataBuildService, ) { } @@ -105,7 +110,7 @@ export class BrowseService { }) ); if (options.fetchThumbnail ) { - return this.hrefOnlyDataService.findListByHref(href$, {}, null, null, ...BROWSE_LINKS_TO_FOLLOW); + return this.hrefOnlyDataService.findListByHref(href$, {}, null, null, ...getBrowseLinksToFollow()); } return this.hrefOnlyDataService.findListByHref(href$); } @@ -153,7 +158,7 @@ export class BrowseService { }), ); if (options.fetchThumbnail) { - return this.hrefOnlyDataService.findListByHref(href$, {}, null, null, ...BROWSE_LINKS_TO_FOLLOW); + return this.hrefOnlyDataService.findListByHref(href$, {}, null, null, ...getBrowseLinksToFollow()); } return this.hrefOnlyDataService.findListByHref(href$); } diff --git a/src/app/core/data/relationship-data.service.spec.ts b/src/app/core/data/relationship-data.service.spec.ts index 4432d5213a..fd24c0665b 100644 --- a/src/app/core/data/relationship-data.service.spec.ts +++ b/src/app/core/data/relationship-data.service.spec.ts @@ -23,6 +23,7 @@ import { FindListOptions } from './find-list-options.model'; import { testSearchDataImplementation } from './base/search-data.spec'; import { MetadataValue } from '../shared/metadata.models'; import { MetadataRepresentationType } from '../shared/metadata-representation/metadata-representation.model'; +import { environment } from '../../../environments/environment.test'; describe('RelationshipDataService', () => { let service: RelationshipDataService; @@ -137,6 +138,7 @@ describe('RelationshipDataService', () => { itemService, null, jasmine.createSpy('paginatedRelationsToItems').and.returnValue((v) => v), + environment, ); } @@ -152,7 +154,7 @@ describe('RelationshipDataService', () => { }); describe('composition', () => { - const initService = () => new RelationshipDataService(null, null, null, null, null, null, null); + const initService = () => new RelationshipDataService(null, null, null, null, null, null, null, environment); testSearchDataImplementation(initService); }); diff --git a/src/app/core/data/relationship-data.service.ts b/src/app/core/data/relationship-data.service.ts index 46a51a2d01..7620f8ab75 100644 --- a/src/app/core/data/relationship-data.service.ts +++ b/src/app/core/data/relationship-data.service.ts @@ -51,6 +51,7 @@ import { MetadataRepresentation } from '../shared/metadata-representation/metada import { MetadatumRepresentation } from '../shared/metadata-representation/metadatum/metadatum-representation.model'; import { ItemMetadataRepresentation } from '../shared/metadata-representation/item/item-metadata-representation.model'; import { DSpaceObject } from '../shared/dspace-object.model'; +import { APP_CONFIG, AppConfig } from '../../../config/app-config.interface'; const relationshipListsStateSelector = (state: AppState) => state.relationshipLists; @@ -92,6 +93,7 @@ export class RelationshipDataService extends IdentifiableDataService, @Inject(PAGINATED_RELATIONS_TO_ITEMS_OPERATOR) private paginatedRelationsToItems: (thisId: string) => (source: Observable>>) => Observable>>, + @Inject(APP_CONFIG) private appConfig: AppConfig, ) { super('relationships', requestService, rdbService, objectCache, halService, 15 * 60 * 1000); @@ -264,7 +266,7 @@ export class RelationshipDataService extends IdentifiableDataService>> { - let linksToFollow: FollowLinkConfig[] = itemLinksToFollow(options.fetchThumbnail); + let linksToFollow: FollowLinkConfig[] = itemLinksToFollow(options.fetchThumbnail, this.appConfig.item.showAccessStatuses); linksToFollow.push(followLink('relationshipType')); return this.getItemRelationshipsByLabel(item, label, options, true, true, ...linksToFollow).pipe(this.paginatedRelationsToItems(item.uuid)); diff --git a/src/app/home-page/recent-item-list/recent-item-list.component.ts b/src/app/home-page/recent-item-list/recent-item-list.component.ts index 9a8535d970..da7d8141e3 100644 --- a/src/app/home-page/recent-item-list/recent-item-list.component.ts +++ b/src/app/home-page/recent-item-list/recent-item-list.component.ts @@ -64,6 +64,9 @@ export class RecentItemListComponent implements OnInit { if (this.appConfig.browseBy.showThumbnails) { linksToFollow.push(followLink('thumbnail')); } + if (this.appConfig.item.showAccessStatuses) { + linksToFollow.push(followLink('accessStatus')); + } this.itemRD$ = this.searchService.search( new PaginatedSearchOptions({ diff --git a/src/app/item-page/edit-item-page/abstract-item-update/abstract-item-update.component.ts b/src/app/item-page/edit-item-page/abstract-item-update/abstract-item-update.component.ts index 80002f614b..3a07632346 100644 --- a/src/app/item-page/edit-item-page/abstract-item-update/abstract-item-update.component.ts +++ b/src/app/item-page/edit-item-page/abstract-item-update/abstract-item-update.component.ts @@ -13,7 +13,7 @@ import { environment } from '../../../../environments/environment'; import { getItemPageRoute } from '../../item-page-routing-paths'; import { getAllSucceededRemoteData } from '../../../core/shared/operators'; import { hasValue } from '../../../shared/empty.util'; -import { ITEM_PAGE_LINKS_TO_FOLLOW } from '../../item.resolver'; +import { getItemPageLinksToFollow } from '../../item.resolver'; import { FieldUpdate } from '../../../core/data/object-updates/field-update.model'; import { FieldUpdates } from '../../../core/data/object-updates/field-updates.model'; @@ -72,7 +72,7 @@ export class AbstractItemUpdateComponent extends AbstractTrackableComponent impl this.item = rd.payload; }), switchMap((rd: RemoteData) => { - return this.itemService.findByHref(rd.payload._links.self.href, true, true, ...ITEM_PAGE_LINKS_TO_FOLLOW); + return this.itemService.findByHref(rd.payload._links.self.href, true, true, ...getItemPageLinksToFollow()); }), getAllSucceededRemoteData() ).subscribe((rd: RemoteData) => { diff --git a/src/app/item-page/edit-item-page/item-delete/item-delete.component.ts b/src/app/item-page/edit-item-page/item-delete/item-delete.component.ts index 9012ebe7d7..8b26b71fef 100644 --- a/src/app/item-page/edit-item-page/item-delete/item-delete.component.ts +++ b/src/app/item-page/edit-item-page/item-delete/item-delete.component.ts @@ -236,8 +236,8 @@ export class ItemDeleteComponent this.linkService.resolveLinks( relationship, followLink('relationshipType'), - followLink('leftItem'), - followLink('rightItem'), + followLink('leftItem', undefined, followLink('accessStatus')), + followLink('rightItem', undefined, followLink('accessStatus')), ); return relationship.relationshipType.pipe( getFirstSucceededRemoteData(), diff --git a/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.spec.ts b/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.spec.ts index 4cd663f0fb..29851c9e93 100644 --- a/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.spec.ts +++ b/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.spec.ts @@ -32,6 +32,7 @@ import { ConfigurationProperty } from '../../../../core/shared/configuration-pro import { Router } from '@angular/router'; import { RouterMock } from '../../../../shared/mocks/router.mock'; import { APP_CONFIG } from '../../../../../config/app-config.interface'; +import { environment } from '../../../../../environments/environment.test'; let comp: EditRelationshipListComponent; let fixture: ComponentFixture; @@ -202,11 +203,11 @@ describe('EditRelationshipListComponent', () => { })) }); - const environmentUseThumbs = { + const environmentUseThumbs = Object.assign({}, environment, { browseBy: { showThumbnails: true } - }; + }); TestBed.configureTestingModule({ imports: [SharedModule, TranslateModule.forRoot()], diff --git a/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.ts b/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.ts index b8542f5806..b27e57f773 100644 --- a/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.ts +++ b/src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.ts @@ -493,7 +493,7 @@ export class EditRelationshipListComponent implements OnInit, OnDestroy { ); // this adds thumbnail images when required by configuration - let linksToFollow: FollowLinkConfig[] = itemLinksToFollow(this.fetchThumbnail); + let linksToFollow: FollowLinkConfig[] = itemLinksToFollow(this.fetchThumbnail, this.appConfig.item.showAccessStatuses); this.subs.push( observableCombineLatest([ diff --git a/src/app/item-page/item.resolver.ts b/src/app/item-page/item.resolver.ts index ca6a6c5958..ffeef57ecb 100644 --- a/src/app/item-page/item.resolver.ts +++ b/src/app/item-page/item.resolver.ts @@ -8,20 +8,27 @@ import { followLink, FollowLinkConfig } from '../shared/utils/follow-link-config import { getFirstCompletedRemoteData } from '../core/shared/operators'; import { Store } from '@ngrx/store'; import { ResolvedAction } from '../core/resolving/resolver.actions'; +import { environment } from '../../environments/environment'; /** * The self links defined in this list are expected to be requested somewhere in the near future * Requesting them as embeds will limit the number of requests */ -export const ITEM_PAGE_LINKS_TO_FOLLOW: FollowLinkConfig[] = [ - followLink('owningCollection', {}, - followLink('parentCommunity', {}, - followLink('parentCommunity')) - ), - followLink('relationships'), - followLink('version', {}, followLink('versionhistory')), - followLink('thumbnail') -]; +export function getItemPageLinksToFollow(): FollowLinkConfig[] { + const followLinks: FollowLinkConfig[] = [ + followLink('owningCollection', {}, + followLink('parentCommunity', {}, + followLink('parentCommunity')) + ), + followLink('relationships'), + followLink('version', {}, followLink('versionhistory')), + followLink('thumbnail'), + ]; + if (environment.item.showAccessStatuses) { + followLinks.push(followLink('accessStatus')); + } + return followLinks; +} /** * This class represents a resolver that requests a specific item before the route is activated @@ -46,7 +53,7 @@ export class ItemResolver implements Resolve> { const itemRD$ = this.itemService.findById(route.params.id, true, false, - ...ITEM_PAGE_LINKS_TO_FOLLOW + ...getItemPageLinksToFollow(), ).pipe( getFirstCompletedRemoteData(), ); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts index ff5a119b6f..a04c10bf3a 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts @@ -328,7 +328,7 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo const relationship$ = this.relationshipService.findById(this.value.virtualValue, true, true, - ... itemLinksToFollow(this.fetchThumbnail)).pipe( + ... itemLinksToFollow(this.fetchThumbnail, this.appConfig.item.showAccessStatuses)).pipe( getAllSucceededRemoteData(), getRemoteDataPayload()); this.relationshipValue$ = observableCombineLatest([this.item$.pipe(take(1)), relationship$]).pipe( diff --git a/src/app/shared/utils/relation-query.utils.ts b/src/app/shared/utils/relation-query.utils.ts index 62a69075fc..635ae946da 100644 --- a/src/app/shared/utils/relation-query.utils.ts +++ b/src/app/shared/utils/relation-query.utils.ts @@ -1,5 +1,6 @@ import { followLink, FollowLinkConfig } from './follow-link-config.model'; import { Relationship } from '../../core/shared/item-relationships/relationship.model'; +import { Item } from '../../core/shared/item.model'; /** * Get the query for looking up items by relation type @@ -21,19 +22,22 @@ export function getFilterByRelation(relationType: string, itemUUID: string): str } /** - * Creates links to follow for the leftItem and rightItem. Links will include - * @param showThumbnail thumbnail image configuration - * @returns followLink array + * Creates links to follow for the leftItem and rightItem. Optionally additional links for `thumbnail` & `accessStatus` + * can be embedded as well. + * + * @param showThumbnail Whether the `thumbnail` needs to be embedded on the {@link Item} + * @param showAccessStatus Whether the `accessStatus` needs to be embedded on the {@link Item} */ -export function itemLinksToFollow(showThumbnail: boolean): FollowLinkConfig[] { - let linksToFollow: FollowLinkConfig[]; +export function itemLinksToFollow(showThumbnail: boolean, showAccessStatus: boolean): FollowLinkConfig[] { + const conditionalLinksToFollow: FollowLinkConfig[] = []; if (showThumbnail) { - linksToFollow = [ - followLink('leftItem',{}, followLink('thumbnail')), - followLink('rightItem',{}, followLink('thumbnail')) - ]; - } else { - linksToFollow = [followLink('leftItem'), followLink('rightItem')]; + conditionalLinksToFollow.push(followLink('thumbnail')); } - return linksToFollow; + if (showAccessStatus) { + conditionalLinksToFollow.push(followLink('accessStatus')); + } + return [ + followLink('leftItem', undefined, ...conditionalLinksToFollow), + followLink('rightItem', undefined, ...conditionalLinksToFollow), + ]; } From 4de3c58e06daef1753645691782857b5b0c8cee2 Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Thu, 10 Oct 2024 22:12:10 +0200 Subject: [PATCH 0588/1286] 119207: Reinitialize the BrowseByComponent's objectInjector when startsWithOptions don't exist yet OnInit --- .../browse-by/browse-by.component.spec.ts | 2 ++ .../shared/browse-by/browse-by.component.ts | 30 ++++++++++++------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/app/shared/browse-by/browse-by.component.spec.ts b/src/app/shared/browse-by/browse-by.component.spec.ts index 9317a68007..260e27c8cb 100644 --- a/src/app/shared/browse-by/browse-by.component.spec.ts +++ b/src/app/shared/browse-by/browse-by.component.spec.ts @@ -142,6 +142,8 @@ describe('BrowseByComponent', () => { { provide: RouteService, useValue: routeServiceStub}, { provide: SelectableListService, useValue: {} }, { provide: HostWindowService, useValue: new HostWindowServiceStub(800) }, + { provide: 'startsWithOptions', useValue: [] }, + { provide: 'paginationId', useValue: 'bbm' }, ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); diff --git a/src/app/shared/browse-by/browse-by.component.ts b/src/app/shared/browse-by/browse-by.component.ts index 0dc20033f8..0e4c8cdca9 100644 --- a/src/app/shared/browse-by/browse-by.component.ts +++ b/src/app/shared/browse-by/browse-by.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Injector, Input, OnDestroy, OnInit, Output } from '@angular/core'; +import { Component, EventEmitter, Injector, Input, OnDestroy, OnInit, Output, SimpleChanges, OnChanges } from '@angular/core'; import { RemoteData } from '../../core/data/remote-data'; import { PaginatedList } from '../../core/data/paginated-list.model'; import { PaginationComponentOptions } from '../pagination/pagination-component-options.model'; @@ -26,7 +26,7 @@ import { TranslateService } from '@ngx-translate/core'; /** * Component to display a browse-by page for any ListableObject */ -export class BrowseByComponent implements OnInit, OnDestroy { +export class BrowseByComponent implements OnInit, OnDestroy, OnChanges { /** * ViewMode that should be passed to {@link ListableObjectComponentLoaderComponent}. @@ -182,14 +182,7 @@ export class BrowseByComponent implements OnInit, OnDestroy { } ngOnInit(): void { - this.objectInjector = Injector.create({ - providers: [ - { provide: 'startsWithOptions', useFactory: () => (this.startsWithOptions), deps:[] }, - { provide: 'paginationId', useFactory: () => (this.paginationConfig?.id), deps:[] } - ], - parent: this.injector - }); - + this.generateInjector(); const startsWith$ = this.routeService.getQueryParameterValue('startsWith'); const value$ = this.routeService.getQueryParameterValue('value'); @@ -199,9 +192,26 @@ export class BrowseByComponent implements OnInit, OnDestroy { this.sub = this.routeService.getQueryParameterValue(this.paginationConfig.id + '.return').subscribe(this.previousPage$); } + ngOnChanges(changes: SimpleChanges): void { + if (changes.startsWithOptions || changes.paginationId) { + this.generateInjector(); + } + } + ngOnDestroy(): void { if (this.sub) { this.sub.unsubscribe(); } } + + generateInjector(): void { + this.objectInjector = Injector.create({ + providers: [ + { provide: 'startsWithOptions', useFactory: () => (this.startsWithOptions), deps:[] }, + { provide: 'paginationId', useFactory: () => (this.paginationConfig?.id), deps:[] } + ], + parent: this.injector + }); + } + } From 0657517915cd1d81c542a31737e9dc2428ea0018 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 11 Oct 2024 20:14:58 +0000 Subject: [PATCH 0589/1286] Bump body-parser from 1.20.2 to 1.20.3 Bumps [body-parser](https://github.com/expressjs/body-parser) from 1.20.2 to 1.20.3. - [Release notes](https://github.com/expressjs/body-parser/releases) - [Changelog](https://github.com/expressjs/body-parser/blob/master/HISTORY.md) - [Commits](https://github.com/expressjs/body-parser/compare/1.20.2...1.20.3) --- updated-dependencies: - dependency-name: body-parser dependency-type: indirect ... Signed-off-by: dependabot[bot] --- yarn.lock | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/yarn.lock b/yarn.lock index 368a89a5f0..3888a2384e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3946,7 +3946,7 @@ bluebird@^3.7.2: resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== -body-parser@1.20.3: +body-parser@1.20.3, body-parser@^1.19.0: version "1.20.3" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6" integrity sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g== @@ -3964,24 +3964,6 @@ body-parser@1.20.3: type-is "~1.6.18" unpipe "1.0.0" -body-parser@^1.19.0: - version "1.20.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" - integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== - dependencies: - bytes "3.1.2" - content-type "~1.0.5" - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - http-errors "2.0.0" - iconv-lite "0.4.24" - on-finished "2.4.1" - qs "6.11.0" - raw-body "2.5.2" - type-is "~1.6.18" - unpipe "1.0.0" - bonjour-service@^1.0.11: version "1.2.1" resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.2.1.tgz#eb41b3085183df3321da1264719fbada12478d02" @@ -5603,11 +5585,9 @@ eslint-plugin-deprecation@^1.4.1: "eslint-plugin-dspace-angular-html@link:./lint/dist/src/rules/html": version "0.0.0" - uid "" "eslint-plugin-dspace-angular-ts@link:./lint/dist/src/rules/ts": version "0.0.0" - uid "" eslint-plugin-import-newlines@^1.3.1: version "1.4.0" @@ -9727,13 +9707,6 @@ qjobs@^1.2.0: resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071" integrity sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg== -qs@6.11.0: - version "6.11.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" - integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== - dependencies: - side-channel "^1.0.4" - qs@6.13.0: version "6.13.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906" From f9fa58606051bf8641e326e1a647d3143efe373f Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Mon, 14 Oct 2024 12:08:33 -0500 Subject: [PATCH 0590/1286] Create dependabot.yml Add configs for version dependency updates --- .github/dependabot.yml | 47 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..bc91ec15f7 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,47 @@ +# Enable Dependabot NPM updates for all dependencies on a weekly basis +version: 2 +updates: + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "weekly" + # Allow up to 10 open PRs for dependencies + open-pull-requests-limit: 10 +# Group together Angular package upgrades +groups: + # Group together all minor/patch version updates for Angular in a single PR + angular: + applies-to: version-updates + patterns: + - "@angular*" + update-types: + - "minor" + - "patch" + # Group together all security updates for Angular. Only accept minor/patch types. + angular-security: + applies-to: security-updates + patterns: + - "@angular*" + update-types: + - "minor" + - "patch" + # Group together all minor/patch version updates for NgRx in a single PR + ngrx: + applies-to: version-updates + patterns: + - "@ngrx*" + update-types: + - "minor" + - "patch" + # Group together all security updates for NgRx. Only accept minor/patch types. + ngrx-security: + applies-to: security-updates + patterns: + - "@ngrx*" + update-types: + - "minor" + - "patch" +ignore: + # Ignore all major version updates for all dependencies. We'll only automate minor/patch updates. + - dependency-name: "*" + update-types: ["version-update:semver-major"] From 0d36bcec2e79945bccca4e4463be1466f208b711 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Mon, 14 Oct 2024 12:22:53 -0500 Subject: [PATCH 0591/1286] Fix yaml alignment --- .github/dependabot.yml | 76 +++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index bc91ec15f7..e8ce97d1ae 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -7,41 +7,41 @@ updates: interval: "weekly" # Allow up to 10 open PRs for dependencies open-pull-requests-limit: 10 -# Group together Angular package upgrades -groups: - # Group together all minor/patch version updates for Angular in a single PR - angular: - applies-to: version-updates - patterns: - - "@angular*" - update-types: - - "minor" - - "patch" - # Group together all security updates for Angular. Only accept minor/patch types. - angular-security: - applies-to: security-updates - patterns: - - "@angular*" - update-types: - - "minor" - - "patch" - # Group together all minor/patch version updates for NgRx in a single PR - ngrx: - applies-to: version-updates - patterns: - - "@ngrx*" - update-types: - - "minor" - - "patch" - # Group together all security updates for NgRx. Only accept minor/patch types. - ngrx-security: - applies-to: security-updates - patterns: - - "@ngrx*" - update-types: - - "minor" - - "patch" -ignore: - # Ignore all major version updates for all dependencies. We'll only automate minor/patch updates. - - dependency-name: "*" - update-types: ["version-update:semver-major"] + # Group together Angular package upgrades + groups: + # Group together all minor/patch version updates for Angular in a single PR + angular: + applies-to: version-updates + patterns: + - "@angular*" + update-types: + - "minor" + - "patch" + # Group together all security updates for Angular. Only accept minor/patch types. + angular-security: + applies-to: security-updates + patterns: + - "@angular*" + update-types: + - "minor" + - "patch" + # Group together all minor/patch version updates for NgRx in a single PR + ngrx: + applies-to: version-updates + patterns: + - "@ngrx*" + update-types: + - "minor" + - "patch" + # Group together all security updates for NgRx. Only accept minor/patch types. + ngrx-security: + applies-to: security-updates + patterns: + - "@ngrx*" + update-types: + - "minor" + - "patch" + ignore: + # Ignore all major version updates for all dependencies. We'll only automate minor/patch updates. + - dependency-name: "*" + update-types: ["version-update:semver-major"] From 2cf36824730d78f3b1d2d3a02d1f025068f4090d Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Mon, 14 Oct 2024 15:52:50 -0500 Subject: [PATCH 0592/1286] Enable dependabot on 7.x and 8.x maintenance branches. --- .github/dependabot.yml | 100 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index e8ce97d1ae..f9e32a0190 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,8 +1,108 @@ # Enable Dependabot NPM updates for all dependencies on a weekly basis version: 2 updates: + ############### + ## Main branch + ############### - package-ecosystem: "npm" directory: "/" + target-branch: main + schedule: + interval: "weekly" + # Allow up to 10 open PRs for dependencies + open-pull-requests-limit: 10 + # Group together Angular package upgrades + groups: + # Group together all minor/patch version updates for Angular in a single PR + angular: + applies-to: version-updates + patterns: + - "@angular*" + update-types: + - "minor" + - "patch" + # Group together all security updates for Angular. Only accept minor/patch types. + angular-security: + applies-to: security-updates + patterns: + - "@angular*" + update-types: + - "minor" + - "patch" + # Group together all minor/patch version updates for NgRx in a single PR + ngrx: + applies-to: version-updates + patterns: + - "@ngrx*" + update-types: + - "minor" + - "patch" + # Group together all security updates for NgRx. Only accept minor/patch types. + ngrx-security: + applies-to: security-updates + patterns: + - "@ngrx*" + update-types: + - "minor" + - "patch" + ignore: + # Ignore all major version updates for all dependencies. We'll only automate minor/patch updates. + - dependency-name: "*" + update-types: ["version-update:semver-major"] + ##################### + ## dspace-8_x branch + ##################### + - package-ecosystem: "npm" + directory: "/" + target-branch: dspace-8_x + schedule: + interval: "weekly" + # Allow up to 10 open PRs for dependencies + open-pull-requests-limit: 10 + # Group together Angular package upgrades + groups: + # Group together all patch version updates for Angular in a single PR + angular: + applies-to: version-updates + patterns: + - "@angular*" + update-types: + - "minor" + - "patch" + # Group together all security updates for Angular. Only accept minor/patch types. + angular-security: + applies-to: security-updates + patterns: + - "@angular*" + update-types: + - "minor" + - "patch" + # Group together all minor/patch version updates for NgRx in a single PR + ngrx: + applies-to: version-updates + patterns: + - "@ngrx*" + update-types: + - "minor" + - "patch" + # Group together all security updates for NgRx. Only accept minor/patch types. + ngrx-security: + applies-to: security-updates + patterns: + - "@ngrx*" + update-types: + - "minor" + - "patch" + ignore: + # Ignore all major version updates for all dependencies. We'll only automate minor/patch updates. + - dependency-name: "*" + update-types: ["version-update:semver-major"] + ##################### + ## dspace-7_x branch + ##################### + - package-ecosystem: "npm" + directory: "/" + target-branch: dspace-7_x schedule: interval: "weekly" # Allow up to 10 open PRs for dependencies From aee7f0f89932e612ece5ee28c51e5c20050df79c Mon Sep 17 00:00:00 2001 From: Mohamed Ali <66433220+mohamedali654321@users.noreply.github.com> Date: Wed, 26 Jun 2024 00:51:14 -0700 Subject: [PATCH 0593/1286] Update Arabic Translation Update Arabic Translation Update ar.json5 translation (cherry picked from commit f5f40c3dc75563bbd67ef98307e58ef33c8b2789) --- src/assets/i18n/ar.json5 | 11229 ++++++++++++++++++++++++++++++------- 1 file changed, 9246 insertions(+), 1983 deletions(-) diff --git a/src/assets/i18n/ar.json5 b/src/assets/i18n/ar.json5 index 6d97effb4c..cf7f7b05bd 100644 --- a/src/assets/i18n/ar.json5 +++ b/src/assets/i18n/ar.json5 @@ -1,3383 +1,10646 @@ { - "401.help": "غير مصرح لك بالوصول إلى هذه الصفحة. ", + + // "401.help": "You're not authorized to access this page. You can use the button below to get back to the home page.", + "401.help": "غير مصرح لك بالوصول إلى هذه الصفحة. يمكنك استخدام الزر أدناه للعودة إلى الصفحة الرئيسية.", + + // "401.link.home-page": "Take me to the home page", "401.link.home-page": "اذهب إلى الصفحة الرئيسية", - "401.unauthorized": "بدون كمية كافية", - "403.help": "ليس لديك إمكانية الوصول إلى هذه الصفحة. ", + + // "401.unauthorized": "Unauthorized", + "401.unauthorized": "بدون تصريح", + + // "403.help": "You don't have permission to access this page. You can use the button below to get back to the home page.", + "403.help": "ليس لديك صلاحية الوصول إلى هذه الصفحة. يمكنك استخدام الزر أدناه للعودة إلى الصفحة الرئيسية.", + + // "403.link.home-page": "Take me to the home page", "403.link.home-page": "اذهب إلى الصفحة الرئيسية", + + // "403.forbidden": "Forbidden", "403.forbidden": "ممنوع", - "500.page-internal-server-error": "الخدمة غير دائمة", - "500.help": "خادم غير قادر على الرد على سؤالك بسبب توقف التوفير أو وجود مشاكل في السعة. ", + + // "500.page-internal-server-error": "Service unavailable", + "500.page-internal-server-error": "الخدمة غير متاحة", + + // "500.help": "The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later.", + "500.help": "الخادم غير قادر مؤقتًا على تلبية طلبك بسبب توقف الصيانة أو وجود مشاكل في السعة. يرجى إعادة المحاولة في وقت لاحق.", + + // "500.link.home-page": "Take me to the home page", "500.link.home-page": "اذهب إلى الصفحة الرئيسية", - "404.help": "يمكنك العثور على الصفحة التي تبحث عنها. ", + + // "404.help": "We can't find the page you're looking for. The page may have been moved or deleted. You can use the button below to get back to the home page. ", + "404.help": "تعذر العثور على الصفحة التي تبحث عنها. ربما تمت إزالتها أو حذفها. يمكنك استخدام الزر أدناه للعودة إلى الصفحة الرئيسية. ", + + // "404.link.home-page": "Take me to the home page", "404.link.home-page": "اذهب إلى الصفحة الرئيسية", - "404.page-not-found": "لم يتم العثور عليها على الصفحة", - "error-page.description.401": "بدون كمية كافية", + + // "404.page-not-found": "Page not found", + "404.page-not-found": "لم يتم العثور على الصفحة", + + // "error-page.description.401": "Unauthorized", + "error-page.description.401": "بدون تصريح", + + // "error-page.description.403": "Forbidden", "error-page.description.403": "ممنوع", - "error-page.description.500": "الخدمة غير دائمة", - "error-page.description.404": "لم يتم العثور عليها على الصفحة", - "error-page.orcid.generic-error": "حدث خطأ أثناء تسجيل الدخول عبر أوركيد. ", + + // "error-page.description.500": "Service unavailable", + "error-page.description.500": "الخدمة غير متاحة", + + // "error-page.description.404": "Page not found", + "error-page.description.404": "لم يتم العثور على الصفحة", + + // "error-page.orcid.generic-error": "An error occurred during login via ORCID. Make sure you have shared your ORCID account email address with DSpace. If the error persists, contact the administrator", + "error-page.orcid.generic-error": "حدث خطأ أثناء تسجيل الدخول عبر أوركيد. يرجى التأكد من أنك قمت بمشاركة عنوان البريد الإلكتروني الخاص بحساب أوركيد الخاص بك مع دي سبيس. إذا استمر الخطأ، فاتصل بالمسؤول", + + // "access-status.embargo.listelement.badge": "Embargo", "access-status.embargo.listelement.badge": "حظر", + + // "access-status.metadata.only.listelement.badge": "Metadata only", "access-status.metadata.only.listelement.badge": "ميتاداتا فقط", + + // "access-status.open.access.listelement.badge": "Open Access", "access-status.open.access.listelement.badge": "وصول حر", + + // "access-status.restricted.listelement.badge": "Restricted", "access-status.restricted.listelement.badge": "مقيد", + + // "access-status.unknown.listelement.badge": "Unknown", "access-status.unknown.listelement.badge": "غير معروف", - "admin.curation-tasks.breadcrumbs": "واجبات النظام", - "admin.curation-tasks.title": "واجبات النظام", - "admin.curation-tasks.header": "واجبات النظام", - "admin.registries.bitstream-formats.breadcrumbs": "قم بالتسجيل", + + // "admin.curation-tasks.breadcrumbs": "System curation tasks", + "admin.curation-tasks.breadcrumbs": "مهام أكرتة النظام", + + // "admin.curation-tasks.title": "System curation tasks", + "admin.curation-tasks.title": "مهام أكرتة النظام", + + // "admin.curation-tasks.header": "System curation tasks", + "admin.curation-tasks.header": "مهام أكرتة النظام", + + // "admin.registries.bitstream-formats.breadcrumbs": "Format registry", + "admin.registries.bitstream-formats.breadcrumbs": "سجل التنسيق", + + // "admin.registries.bitstream-formats.create.breadcrumbs": "Bitstream format", "admin.registries.bitstream-formats.create.breadcrumbs": "تنسيق تدفق البت", - "admin.registries.bitstream-formats.create.failure.content": "حدث خطأ أثناء إنشاء تدفق البت الجديد.", + + // "admin.registries.bitstream-formats.create.failure.content": "An error occurred while creating the new bitstream format.", + "admin.registries.bitstream-formats.create.failure.content": "حدث خطأ أثناء إنشاء تنسيق تدفق البت الجديد.", + + // "admin.registries.bitstream-formats.create.failure.head": "Failure", "admin.registries.bitstream-formats.create.failure.head": "فشل", - "admin.registries.bitstream-formats.create.head": "إنشاء تدفق بت", - "admin.registries.bitstream-formats.create.new": "تمت إضافة تدفق بت جديد", - "admin.registries.bitstream-formats.create.success.content": "تم إنشاء تدفق البت الجديد الفعال.", + + // "admin.registries.bitstream-formats.create.head": "Create bitstream format", + "admin.registries.bitstream-formats.create.head": "إنشاء تنسيق تدفق بت", + + // "admin.registries.bitstream-formats.create.new": "Add a new bitstream format", + "admin.registries.bitstream-formats.create.new": "إضافة تنسيق تدفق بت جديد", + + // "admin.registries.bitstream-formats.create.success.content": "The new bitstream format was successfully created.", + "admin.registries.bitstream-formats.create.success.content": "تم إنشاء تنسيق تدفق البت الجديد بنجاح.", + + // "admin.registries.bitstream-formats.create.success.head": "Success", "admin.registries.bitstream-formats.create.success.head": "نجاح", - "admin.registries.bitstream-formats.delete.failure.amount": "فشل في إزالة {{ amount }} تنسيقًا", + + // "admin.registries.bitstream-formats.delete.failure.amount": "Failed to remove {{ amount }} format(s)", + "admin.registries.bitstream-formats.delete.failure.amount": "فشل إزالة {{ amount }} تنسيقًا", + + // "admin.registries.bitstream-formats.delete.failure.head": "Failure", "admin.registries.bitstream-formats.delete.failure.head": "فشل", - "admin.registries.bitstream-formats.delete.success.amount": "بعد إزالة {{ amount }} فعالة", + + // "admin.registries.bitstream-formats.delete.success.amount": "Successfully removed {{ amount }} format(s)", + "admin.registries.bitstream-formats.delete.success.amount": "تمت إزالة {{ amount }} تنسيقًا بنجاح", + + // "admin.registries.bitstream-formats.delete.success.head": "Success", "admin.registries.bitstream-formats.delete.success.head": "نجاح", - "admin.registries.bitstream-formats.description": "مطلوب قائمة تدفق المعلومات الأساسية حول ما هو مطلوب ومستوى دعمها.", + + // "admin.registries.bitstream-formats.description": "This list of bitstream formats provides information about known formats and their support level.", + "admin.registries.bitstream-formats.description": "توفر قائمة تنسيقات تدفق البت معلومات حول التنسيقات المعروفة ومستوى دعمها.", + + // "admin.registries.bitstream-formats.edit.breadcrumbs": "Bitstream format", "admin.registries.bitstream-formats.edit.breadcrumbs": "تنسيق تدفق البت", + + // "admin.registries.bitstream-formats.edit.description.hint": "", "admin.registries.bitstream-formats.edit.description.hint": "", + + // "admin.registries.bitstream-formats.edit.description.label": "Description", "admin.registries.bitstream-formats.edit.description.label": "الوصف", - "admin.registries.bitstream-formats.edit.extensions.hint": "الامتدادات هي امتدادات الملفات التي تستخدم لتعريف الملفات المرفوعة الأصلية. ", + + // "admin.registries.bitstream-formats.edit.extensions.hint": "Extensions are file extensions that are used to automatically identify the format of uploaded files. You can enter several extensions for each format.", + "admin.registries.bitstream-formats.edit.extensions.hint": "الامتدادات هي امتدادات الملفات التي تستخدم لتعريف تنسيق الملفات المرفوعة تلقائيًا. يمكنك إدخال عدة امتدادات لكل تنسيق.", + + // "admin.registries.bitstream-formats.edit.extensions.label": "File extensions", "admin.registries.bitstream-formats.edit.extensions.label": "امتدادات الملفات", - "admin.registries.bitstream-formats.edit.extensions.placeholder": "قم بتوسعة ملف بدون النقطة", - "admin.registries.bitstream-formats.edit.failure.content": "حدث خطأ أثناء تحرير تدفق البت.", + + // "admin.registries.bitstream-formats.edit.extensions.placeholder": "Enter a file extension without the dot", + "admin.registries.bitstream-formats.edit.extensions.placeholder": "قم بإدخال امتداد ملف بدون النقطة", + + // "admin.registries.bitstream-formats.edit.failure.content": "An error occurred while editing the bitstream format.", + "admin.registries.bitstream-formats.edit.failure.content": "حدث خطأ أثناء تحرير تنسيق تدفق البت.", + + // "admin.registries.bitstream-formats.edit.failure.head": "Failure", "admin.registries.bitstream-formats.edit.failure.head": "فشل", - "admin.registries.bitstream-formats.edit.head": "تدفق البت: {{ format }}", - "admin.registries.bitstream-formats.edit.internal.hint": "لاغراض إدارية خالية من المستخدم، لأغراض إدارية.", + + // "admin.registries.bitstream-formats.edit.head": "Bitstream format: {{ format }}", + "admin.registries.bitstream-formats.edit.head": "تنسيق تدفق البت: {{ format }}", + + // "admin.registries.bitstream-formats.edit.internal.hint": "Formats marked as internal are hidden from the user, and used for administrative purposes.", + "admin.registries.bitstream-formats.edit.internal.hint": "التنسيقات الداخلية مخفية من المستخدم، وتستخدم لأغراض إدارية.", + + // "admin.registries.bitstream-formats.edit.internal.label": "Internal", "admin.registries.bitstream-formats.edit.internal.label": "داخلي", - "admin.registries.bitstream-formats.edit.mimetype.hint": "نوع الميمات المرغوبة لذلك، لا يجب أن يكون فريدًا.", - "admin.registries.bitstream-formats.edit.mimetype.label": "نوع الميم", - "admin.registries.bitstream-formats.edit.shortDescription.hint": "اسم فريد لهذا الغرض، (مثال: ميكروسوفت وورد إكس بي أو ميكروسوفت وورد 200)", + + // "admin.registries.bitstream-formats.edit.mimetype.hint": "The MIME type associated with this format, does not have to be unique.", + "admin.registries.bitstream-formats.edit.mimetype.hint": "نوع المايم المرتبط بهذا التنسيق، لا يجب أن يكون فريدًا.", + + // "admin.registries.bitstream-formats.edit.mimetype.label": "MIME Type", + "admin.registries.bitstream-formats.edit.mimetype.label": "نوع المايم", + + // "admin.registries.bitstream-formats.edit.shortDescription.hint": "A unique name for this format, (e.g. Microsoft Word XP or Microsoft Word 2000)", + "admin.registries.bitstream-formats.edit.shortDescription.hint": "اسم فريد لهذا التنسيق، (مثال: ميكروسوفت وورد إكس بي أو ميكروسوفت وورد 200)", + + // "admin.registries.bitstream-formats.edit.shortDescription.label": "Name", "admin.registries.bitstream-formats.edit.shortDescription.label": "الاسم", - "admin.registries.bitstream-formats.edit.success.content": "تم تحرير الجذر التدفق الفعال.", + + // "admin.registries.bitstream-formats.edit.success.content": "The bitstream format was successfully edited.", + "admin.registries.bitstream-formats.edit.success.content": "تم تحرير تنسيق تدفق البت بنجاح.", + + // "admin.registries.bitstream-formats.edit.success.head": "Success", "admin.registries.bitstream-formats.edit.success.head": "نجاح", - "admin.registries.bitstream-formats.edit.supportLevel.hint": "مستوى الدعم الذي تعهد به مؤسستك لهذا الغرض.", + + // "admin.registries.bitstream-formats.edit.supportLevel.hint": "The level of support your institution pledges for this format.", + "admin.registries.bitstream-formats.edit.supportLevel.hint": "مستوى الدعم التي تتعهد به مؤسستك لهذا التنسيق.", + + // "admin.registries.bitstream-formats.edit.supportLevel.label": "Support level", "admin.registries.bitstream-formats.edit.supportLevel.label": "مستوى الدعم", - "admin.registries.bitstream-formats.head": "سجل تدفق البت", + + // "admin.registries.bitstream-formats.head": "Bitstream Format Registry", + "admin.registries.bitstream-formats.head": "سجل تنسيق تدفق البت", + + // "admin.registries.bitstream-formats.no-items": "No bitstream formats to show.", "admin.registries.bitstream-formats.no-items": "لا توجد تنسيقات لتدفق البت.", - "admin.registries.bitstream-formats.table.delete": "حذف", + + // "admin.registries.bitstream-formats.table.delete": "Delete selected", + "admin.registries.bitstream-formats.table.delete": "حذف المحدد", + + // "admin.registries.bitstream-formats.table.deselect-all": "Deselect all", "admin.registries.bitstream-formats.table.deselect-all": "إلغاء تحديد الكل", + + // "admin.registries.bitstream-formats.table.internal": "internal", "admin.registries.bitstream-formats.table.internal": "داخلي", - "admin.registries.bitstream-formats.table.mimetype": "نوع الميم", + + // "admin.registries.bitstream-formats.table.mimetype": "MIME Type", + "admin.registries.bitstream-formats.table.mimetype": "نوع المايم", + + // "admin.registries.bitstream-formats.table.name": "Name", "admin.registries.bitstream-formats.table.name": "الاسم", - "admin.registries.bitstream-formats.table.selected": "تنسيقات تدفقات البتات الأولية", + + // "admin.registries.bitstream-formats.table.selected": "Selected bitstream formats", + "admin.registries.bitstream-formats.table.selected": "تنسيقات تدفقات البت المحددة", + + // "admin.registries.bitstream-formats.table.id": "ID", "admin.registries.bitstream-formats.table.id": "المعرّف", + + // "admin.registries.bitstream-formats.table.return": "Back", "admin.registries.bitstream-formats.table.return": "رجوع", + + // "admin.registries.bitstream-formats.table.supportLevel.KNOWN": "Known", "admin.registries.bitstream-formats.table.supportLevel.KNOWN": "معروف", + + // "admin.registries.bitstream-formats.table.supportLevel.SUPPORTED": "Supported", "admin.registries.bitstream-formats.table.supportLevel.SUPPORTED": "مدعوم", + + // "admin.registries.bitstream-formats.table.supportLevel.UNKNOWN": "Unknown", "admin.registries.bitstream-formats.table.supportLevel.UNKNOWN": "غير معروف", + + // "admin.registries.bitstream-formats.table.supportLevel.head": "Support Level", "admin.registries.bitstream-formats.table.supportLevel.head": "مستوى الدعم", - "admin.registries.bitstream-formats.title": "سجل تدفق البت", + + // "admin.registries.bitstream-formats.title": "Bitstream Format Registry", + "admin.registries.bitstream-formats.title": "سجل تنسيق تدفق البت", + + // "admin.registries.bitstream-formats.select": "Select", "admin.registries.bitstream-formats.select": "تحديد", - "admin.registries.bitstream-formats.deselect": "قم بإلغاء التحديد", - "admin.registries.metadata.breadcrumbs": "سجل المذكرات", - "admin.registries.metadata.description": "تدعو إلى تسجيل النداءات بقائمة شاملة لتغطية النداءات المتاحة في المستودع. ", - "admin.registries.metadata.form.create": "إنشاء مخطط ميتاماتا", + + // "admin.registries.bitstream-formats.deselect": "Deselect", + "admin.registries.bitstream-formats.deselect": "إلغاء تحديد", + + // "admin.registries.metadata.breadcrumbs": "Metadata registry", + "admin.registries.metadata.breadcrumbs": "سجل الميتاداتا", + + // "admin.registries.metadata.description": "The metadata registry maintains a list of all metadata fields available in the repository. These fields may be divided amongst multiple schemas. However, DSpace requires the qualified Dublin Core schema.", + "admin.registries.metadata.description": "يحتفظ سجل الميتاداتا بقائمة بجميع حقول الميتاداتا المتاحة في المستودع. يمكن تقسيم تلك الحقول بين عدة تخطيطات، يتطلب دي سبيس مخطط دبلن كور المؤهل.", + + // "admin.registries.metadata.form.create": "Create metadata schema", + "admin.registries.metadata.form.create": "إنشاء مخطط ميتاداتا", + + // "admin.registries.metadata.form.edit": "Edit metadata schema", "admin.registries.metadata.form.edit": "تحرير مخطط الميتاداتا", + + // "admin.registries.metadata.form.name": "Name", "admin.registries.metadata.form.name": "الاسم", - "admin.registries.metadata.form.namespace": "اسم بعيد", - "admin.registries.metadata.head": "سجل المذكرات", - "admin.registries.metadata.schemas.no-items": "لا يوجد مخططات ميتاداتا للعرض.", + + // "admin.registries.metadata.form.namespace": "Namespace", + "admin.registries.metadata.form.namespace": "مسافة الاسم", + + // "admin.registries.metadata.head": "Metadata Registry", + "admin.registries.metadata.head": "سجل الميتاداتا", + + // "admin.registries.metadata.schemas.no-items": "No metadata schemas to show.", + "admin.registries.metadata.schemas.no-items": "لا توجد مخططات ميتاداتا للعرض.", + + // "admin.registries.metadata.schemas.select": "Select", "admin.registries.metadata.schemas.select": "تحديد", - "admin.registries.metadata.schemas.deselect": "قم بإلغاء التحديد", - "admin.registries.metadata.schemas.table.delete": "حذف", - "admin.registries.metadata.schemas.table.selected": "التصنيفات المحددة", + + // "admin.registries.metadata.schemas.deselect": "Deselect", + "admin.registries.metadata.schemas.deselect": "إلغاء تحديد", + + // "admin.registries.metadata.schemas.table.delete": "Delete selected", + "admin.registries.metadata.schemas.table.delete": "حذف المحدد", + + // "admin.registries.metadata.schemas.table.selected": "Selected schemas", + "admin.registries.metadata.schemas.table.selected": "المخططات المحددة", + + // "admin.registries.metadata.schemas.table.id": "ID", "admin.registries.metadata.schemas.table.id": "المعرّف", + + // "admin.registries.metadata.schemas.table.name": "Name", "admin.registries.metadata.schemas.table.name": "الاسم", - "admin.registries.metadata.schemas.table.namespace": "اسم بعيد", - "admin.registries.metadata.title": "سجل المذكرات", + + // "admin.registries.metadata.schemas.table.namespace": "Namespace", + "admin.registries.metadata.schemas.table.namespace": "مسافة الاسم", + + // "admin.registries.metadata.title": "Metadata Registry", + "admin.registries.metadata.title": "سجل الميتاداتا", + + // "admin.registries.schema.breadcrumbs": "Metadata schema", "admin.registries.schema.breadcrumbs": "مخطط الميتاداتا", - "admin.registries.schema.description": "هذا هو مخطط الميتاداتا لـ \"{{namespace}}\".", + + // "admin.registries.schema.description": "This is the metadata schema for \"{{namespace}}\".", + "admin.registries.schema.description": "هذا هو مخطط الميتاداتا لـ \"{{namespace}}\".", + + // "admin.registries.schema.fields.select": "Select", "admin.registries.schema.fields.select": "تحديد", - "admin.registries.schema.fields.deselect": "قم بإلغاء التحديد", - "admin.registries.schema.fields.head": "يغطي مخطط الميتاداتا", - "admin.registries.schema.fields.no-items": "لا توجد مشكلة ميتاداتا للعرض.", - "admin.registries.schema.fields.table.delete": "حذف", - "admin.registries.schema.fields.table.field": "بحث متقدم", - "admin.registries.schema.fields.table.selected": "تكفير الميتاداتا المحددة", + + // "admin.registries.schema.fields.deselect": "Deselect", + "admin.registries.schema.fields.deselect": "إلغاء تحديد", + + // "admin.registries.schema.fields.head": "Schema metadata fields", + "admin.registries.schema.fields.head": "حقول مخطط الميتاداتا", + + // "admin.registries.schema.fields.no-items": "No metadata fields to show.", + "admin.registries.schema.fields.no-items": "لا توجد حقول ميتاداتا للعرض.", + + // "admin.registries.schema.fields.table.delete": "Delete selected", + "admin.registries.schema.fields.table.delete": "حذف المحدد", + + // "admin.registries.schema.fields.table.field": "Field", + "admin.registries.schema.fields.table.field": "حقل", + + // "admin.registries.schema.fields.table.selected": "Selected metadata fields", + "admin.registries.schema.fields.table.selected": "حقول الميتاداتا المحددة", + + // "admin.registries.schema.fields.table.id": "ID", "admin.registries.schema.fields.table.id": "المعرّف", - "admin.registries.schema.fields.table.scopenote": "لاحظ النطاق", - "admin.registries.schema.form.create": "إنشاء بحث ميتا", - "admin.registries.schema.form.edit": "تحرير البحث ميتا", + + // "admin.registries.schema.fields.table.scopenote": "Scope Note", + "admin.registries.schema.fields.table.scopenote": "ملاحظة النطاق", + + // "admin.registries.schema.form.create": "Create metadata field", + "admin.registries.schema.form.create": "إنشاء حقل ميتاداتا", + + // "admin.registries.schema.form.edit": "Edit metadata field", + "admin.registries.schema.form.edit": "تحرير حقل ميتاداتا", + + // "admin.registries.schema.form.element": "Element", "admin.registries.schema.form.element": "عنصر", + + // "admin.registries.schema.form.qualifier": "Qualifier", "admin.registries.schema.form.qualifier": "مؤهل", - "admin.registries.schema.form.scopenote": "لاحظ النطاق", + + // "admin.registries.schema.form.scopenote": "Scope Note", + "admin.registries.schema.form.scopenote": "ملاحظة النطاق", + + // "admin.registries.schema.head": "Metadata Schema", "admin.registries.schema.head": "مخطط الميتاداتا", - "admin.registries.schema.notification.created": "تم إنشاء مخطط الميتاداتا \"{{prefix}}\"", - "admin.registries.schema.notification.deleted.failure": "فشل الحذف {{amount}} مخططات ميتا", - "admin.registries.schema.notification.deleted.success": "تم الحذف {{amount}} مخططات ميتا فعالة", - "admin.registries.schema.notification.edited": "تم فعالية تحرير مخطط الميتاداتا \"{{prefix}}\"", + + // "admin.registries.schema.notification.created": "Successfully created metadata schema \"{{prefix}}\"", + "admin.registries.schema.notification.created": "تم بنجاح إنشاء مخطط الميتاداتا \"{{prefix}}\"", + + // "admin.registries.schema.notification.deleted.failure": "Failed to delete {{amount}} metadata schemas", + "admin.registries.schema.notification.deleted.failure": "فشل حذف {{amount}} مخطط ميتاداتا", + + // "admin.registries.schema.notification.deleted.success": "Successfully deleted {{amount}} metadata schemas", + "admin.registries.schema.notification.deleted.success": "تم حذف {{amount}} مخطط ميتاداتا بنجاح", + + // "admin.registries.schema.notification.edited": "Successfully edited metadata schema \"{{prefix}}\"", + "admin.registries.schema.notification.edited": "تم بنجاح تحرير مخطط الميتاداتا \"{{prefix}}\"", + + // "admin.registries.schema.notification.failure": "Error", "admin.registries.schema.notification.failure": "خطأ", - "admin.registries.schema.notification.field.created": "تم إنشاء البحث العلمي \"{{field}}\"", - "admin.registries.schema.notification.field.deleted.failure": "فشل الحذف {{amount}} بحث ميتا", - "admin.registries.schema.notification.field.deleted.success": "تم الحذف {{amount}} بحثت عن نتائج ميتا فعالة", - "admin.registries.schema.notification.field.edited": "تم البحث الفعال عن البحث في الميتاداتا \"{{field}}\"", + + // "admin.registries.schema.notification.field.created": "Successfully created metadata field \"{{field}}\"", + "admin.registries.schema.notification.field.created": "تم بنجاح إنشاء حقل الميتاداتا \"{{field}}\"", + + // "admin.registries.schema.notification.field.deleted.failure": "Failed to delete {{amount}} metadata fields", + "admin.registries.schema.notification.field.deleted.failure": "فشل حذف {{amount}} حقل ميتاداتا", + + // "admin.registries.schema.notification.field.deleted.success": "Successfully deleted {{amount}} metadata fields", + "admin.registries.schema.notification.field.deleted.success": "تم حذف {{amount}} حقل ميتاداتا بنجاح", + + // "admin.registries.schema.notification.field.edited": "Successfully edited metadata field \"{{field}}\"", + "admin.registries.schema.notification.field.edited": "تم بنجاح تحرير حقل الميتاداتا \"{{field}}\"", + + // "admin.registries.schema.notification.success": "Success", "admin.registries.schema.notification.success": "نجاح", + + // "admin.registries.schema.return": "Back", "admin.registries.schema.return": "رجوع", + + // "admin.registries.schema.title": "Metadata Schema Registry", "admin.registries.schema.title": "سجل مخطط الميتاداتا", + + // "admin.access-control.bulk-access.breadcrumbs": "Bulk Access Management", "admin.access-control.bulk-access.breadcrumbs": "إدارة الوصول بالجملة", + + // "administrativeBulkAccess.search.results.head": "Search Results", "administrativeBulkAccess.search.results.head": "نتائج البحث", + + // "admin.access-control.bulk-access": "Bulk Access Management", "admin.access-control.bulk-access": "إدارة الوصول بالجملة", + + // "admin.access-control.bulk-access.title": "Bulk Access Management", "admin.access-control.bulk-access.title": "إدارة الوصول بالجملة", - "admin.access-control.bulk-access-browse.header": "الخطوة الأولى: قم بإنشاء الكائنات الحية", + + // "admin.access-control.bulk-access-browse.header": "Step 1: Select Objects", + "admin.access-control.bulk-access-browse.header": "الخطوة الأولى: قم بتحديد الكائنات", + + // "admin.access-control.bulk-access-browse.search.header": "Search", "admin.access-control.bulk-access-browse.search.header": "بحث", - "admin.access-control.bulk-access-browse.selected.header": "التحديد الفعلي({{number}})", - "admin.access-control.bulk-access-settings.header": "الثانية: المراد بإجرائها", - "admin.access-control.epeople.actions.delete": "حذف الالكترونيات الشخصية", + + // "admin.access-control.bulk-access-browse.selected.header": "Current selection({{number}})", + "admin.access-control.bulk-access-browse.selected.header": "التحديد الحالي({{number}})", + + // "admin.access-control.bulk-access-settings.header": "Step 2: Operation to Perform", + "admin.access-control.bulk-access-settings.header": "الخطوة الثانية: العملية المراد إجراؤها", + + // "admin.access-control.epeople.actions.delete": "Delete EPerson", + "admin.access-control.epeople.actions.delete": "حذف شخص إلكتروني", + + // "admin.access-control.epeople.actions.impersonate": "Impersonate EPerson", "admin.access-control.epeople.actions.impersonate": "التصرف كشخص إلكتروني", + + // "admin.access-control.epeople.actions.reset": "Reset password", "admin.access-control.epeople.actions.reset": "إعادة تعيين كلمة المرور", - "admin.access-control.epeople.actions.stop-impersonating": "ضبط التصرف كشخص إلكتروني", - "admin.access-control.epeople.breadcrumbs": "يأتي إليكين", - "admin.access-control.epeople.title": "يأتي إليكين", - "admin.access-control.epeople.edit.breadcrumbs": "شخصي إلكتروني جديد", - "admin.access-control.epeople.edit.title": "شخصي إلكتروني جديد", - "admin.access-control.epeople.add.breadcrumbs": "إضافة خاصة إلكترونيات", - "admin.access-control.epeople.add.title": "إضافة خاصة إلكترونيات", - "admin.access-control.epeople.head": "يأتي إليكين", + + // "admin.access-control.epeople.actions.stop-impersonating": "Stop impersonating EPerson", + "admin.access-control.epeople.actions.stop-impersonating": "التوقف عن التصرف كشخص إلكتروني", + + // "admin.access-control.epeople.breadcrumbs": "EPeople", + "admin.access-control.epeople.breadcrumbs": "أشخاص إلكترونيين", + + // "admin.access-control.epeople.title": "EPeople", + "admin.access-control.epeople.title": "أشخاص إلكترونيين", + + // "admin.access-control.epeople.edit.breadcrumbs": "New EPerson", + "admin.access-control.epeople.edit.breadcrumbs": "شخص إلكتروني جديد", + + // "admin.access-control.epeople.edit.title": "New EPerson", + "admin.access-control.epeople.edit.title": "شخص إلكتروني جديد", + + // "admin.access-control.epeople.add.breadcrumbs": "Add EPerson", + "admin.access-control.epeople.add.breadcrumbs": "إضافة شخص إلكتروني", + + // "admin.access-control.epeople.add.title": "Add EPerson", + "admin.access-control.epeople.add.title": "إضافة شخص إلكتروني", + + // "admin.access-control.epeople.head": "EPeople", + "admin.access-control.epeople.head": "أشخاص إلكترونيين", + + // "admin.access-control.epeople.search.head": "Search", "admin.access-control.epeople.search.head": "بحث", - "admin.access-control.epeople.button.see-all": "مراجعة الكل", - "admin.access-control.epeople.search.scope.metadata": "ميداداتا", + + // "admin.access-control.epeople.button.see-all": "Browse All", + "admin.access-control.epeople.button.see-all": "استعراض الكل", + + // "admin.access-control.epeople.search.scope.metadata": "Metadata", + "admin.access-control.epeople.search.scope.metadata": "الميتاداتا", + + // "admin.access-control.epeople.search.scope.email": "Email (exact)", "admin.access-control.epeople.search.scope.email": "البريد الإلكتروني (بالضبط)", + + // "admin.access-control.epeople.search.button": "Search", "admin.access-control.epeople.search.button": "بحث", - "admin.access-control.epeople.search.placeholder": "بحث الناس...", - "admin.access-control.epeople.button.add": "إضافة خاصة إلكترونيات", + + // "admin.access-control.epeople.search.placeholder": "Search people...", + "admin.access-control.epeople.search.placeholder": "بحث الأشخاص...", + + // "admin.access-control.epeople.button.add": "Add EPerson", + "admin.access-control.epeople.button.add": "إضافة شخص إلكتروني", + + // "admin.access-control.epeople.table.id": "ID", "admin.access-control.epeople.table.id": "المعرّف", + + // "admin.access-control.epeople.table.name": "Name", "admin.access-control.epeople.table.name": "الاسم", + + // "admin.access-control.epeople.table.email": "Email (exact)", "admin.access-control.epeople.table.email": "البريد الإلكتروني (بالضبط)", + + // "admin.access-control.epeople.table.edit": "Edit", "admin.access-control.epeople.table.edit": "تحرير", + + // "admin.access-control.epeople.table.edit.buttons.edit": "Edit \"{{name}}\"", "admin.access-control.epeople.table.edit.buttons.edit": "تحرير \"{{name}}\"", - "admin.access-control.epeople.table.edit.buttons.edit-disabled": "غير مصرح لك لتحرير هذه المجموعة", + + // "admin.access-control.epeople.table.edit.buttons.edit-disabled": "You are not authorized to edit this group", + "admin.access-control.epeople.table.edit.buttons.edit-disabled": "غير مصرح لك بتحرير هذه المجموعة", + + // "admin.access-control.epeople.table.edit.buttons.remove": "Delete \"{{name}}\"", "admin.access-control.epeople.table.edit.buttons.remove": "حذف \"{{name}}\"", - "admin.access-control.epeople.no-items": "لا يوجد رجل إلكترونين للعرض.", + + // "admin.access-control.epeople.no-items": "No EPeople to show.", + "admin.access-control.epeople.no-items": "لا يوجد أشخاص إلكترونيين للعرض.", + + // "admin.access-control.epeople.form.create": "Create EPerson", "admin.access-control.epeople.form.create": "إنشاء شخص إلكتروني", - "admin.access-control.epeople.form.edit": "تحرير الكمبيوتر الشخصي", + + // "admin.access-control.epeople.form.edit": "Edit EPerson", + "admin.access-control.epeople.form.edit": "تحرير شخص إلكتروني", + + // "admin.access-control.epeople.form.firstName": "First name", "admin.access-control.epeople.form.firstName": "الاسم الأول", + + // "admin.access-control.epeople.form.lastName": "Last name", "admin.access-control.epeople.form.lastName": "اسم العائلة", + + // "admin.access-control.epeople.form.email": "Email", "admin.access-control.epeople.form.email": "البريد الإلكتروني", - "admin.access-control.epeople.form.emailHint": "يجب أن يكون عنوان بريد الإلكتروني صالح", - "admin.access-control.epeople.form.canLogIn": "يمكننا تسجيل الدخول", - "admin.access-control.epeople.form.requireCertificate": "أنا", + + // "admin.access-control.epeople.form.emailHint": "Must be a valid email address", + "admin.access-control.epeople.form.emailHint": "يجب أن يكون عنوان بريد إلكتروني صالح", + + // "admin.access-control.epeople.form.canLogIn": "Can log in", + "admin.access-control.epeople.form.canLogIn": "يمكنه تسجيل الدخول", + + // "admin.access-control.epeople.form.requireCertificate": "Requires certificate", + "admin.access-control.epeople.form.requireCertificate": "يتطلب شهادة", + + // "admin.access-control.epeople.form.return": "Back", "admin.access-control.epeople.form.return": "رجوع", + + // "admin.access-control.epeople.form.notification.created.success": "Successfully created EPerson \"{{name}}\"", "admin.access-control.epeople.form.notification.created.success": "تم إنشاء الشخص الإلكتروني \"{{name}}\"", + + // "admin.access-control.epeople.form.notification.created.failure": "Failed to create EPerson \"{{name}}\"", "admin.access-control.epeople.form.notification.created.failure": "فشل إنشاء الشخص الإلكتروني \"{{name}}\"", - "admin.access-control.epeople.form.notification.created.failure.emailInUse": "فشل إنشاء الشخص الإلكتروني \"{{name}}\"، البريد الإلكتروني \"{{email}}\"تعمل بالفعل.", - "admin.access-control.epeople.form.notification.edited.failure.emailInUse": "فشل في تحرير الشخص الإلكتروني \"{{name}}\"، البريد الإلكتروني \"{{email}}\"تعمل بالفعل.", + + // "admin.access-control.epeople.form.notification.created.failure.emailInUse": "Failed to create EPerson \"{{name}}\", email \"{{email}}\" already in use.", + "admin.access-control.epeople.form.notification.created.failure.emailInUse": "فشل إنشاء الشخص الإلكتروني \"{{name}}\", البريد الإلكتروني \"{{email}}\" قيد الاستخدام بالفعل.", + + // "admin.access-control.epeople.form.notification.edited.failure.emailInUse": "Failed to edit EPerson \"{{name}}\", email \"{{email}}\" already in use.", + "admin.access-control.epeople.form.notification.edited.failure.emailInUse": "فشل تحرير الشخص الإلكتروني \"{{name}}\", البريد الإلكتروني \"{{email}}\" قيد الاستخدام بالفعل.", + + // "admin.access-control.epeople.form.notification.edited.success": "Successfully edited EPerson \"{{name}}\"", "admin.access-control.epeople.form.notification.edited.success": "تم تحرير الشخص الإلكتروني \"{{name}}\"بنجاح", - "admin.access-control.epeople.form.notification.edited.failure": "فشل في تحرير الشخص الإلكتروني \"{{name}}\"", + + // "admin.access-control.epeople.form.notification.edited.failure": "Failed to edit EPerson \"{{name}}\"", + "admin.access-control.epeople.form.notification.edited.failure": "فشل تحرير الشخص الإلكتروني \"{{name}}\"", + + // "admin.access-control.epeople.form.notification.deleted.success": "Successfully deleted EPerson \"{{name}}\"", "admin.access-control.epeople.form.notification.deleted.success": "تم حذف الشخص الإلكتروني \"{{name}}\"بنجاح", - "admin.access-control.epeople.form.notification.deleted.failure": "فشل في حذف الهاتف الإلكتروني \"{{name}}\"", + + // "admin.access-control.epeople.form.notification.deleted.failure": "Failed to delete EPerson \"{{name}}\"", + "admin.access-control.epeople.form.notification.deleted.failure": "فشل حذف الشخص الإلكتروني \"{{name}}\"", + + // "admin.access-control.epeople.form.groupsEPersonIsMemberOf": "Member of these groups:", "admin.access-control.epeople.form.groupsEPersonIsMemberOf": "عضو في هذه المجموعات:", + + // "admin.access-control.epeople.form.table.id": "ID", "admin.access-control.epeople.form.table.id": "المعرّف", + + // "admin.access-control.epeople.form.table.name": "Name", "admin.access-control.epeople.form.table.name": "الاسم", - "admin.access-control.epeople.form.table.collectionOrCommunity": "الحاوية/المجتمع", + + // "admin.access-control.epeople.form.table.collectionOrCommunity": "Collection/Community", + "admin.access-control.epeople.form.table.collectionOrCommunity": "حاوية/مجتمع", + + // "admin.access-control.epeople.form.memberOfNoGroups": "This EPerson is not a member of any groups", "admin.access-control.epeople.form.memberOfNoGroups": "هذا الشخص الإلكتروني ليس عضواً في أي مجموعة", - "admin.access-control.epeople.form.goToGroups": "إضافة إلى مجموعات", - "admin.access-control.epeople.notification.deleted.failure": "حدث خطأ عند محاولة حذف الشخص الإلكتروني بالمعرف \"{{id}}\" بالرمز: \"{{statusCode}}\" والرسالة: \"{{restResponse.errorMessage}}\"", - "admin.access-control.epeople.notification.deleted.success": "تم حذف البريد الإلكتروني الخاص بالشخص: \"{{name}}\"بنجاح", - "admin.access-control.groups.title": "مجموعات", - "admin.access-control.groups.breadcrumbs": "مجموعات", - "admin.access-control.groups.singleGroup.breadcrumbs": "تحرير المجموعة", - "admin.access-control.groups.title.singleGroup": "تحرير المجموعة", + + // "admin.access-control.epeople.form.goToGroups": "Add to groups", + "admin.access-control.epeople.form.goToGroups": "أضف إلى مجموعات", + + // "admin.access-control.epeople.notification.deleted.failure": "Error occurred when trying to delete EPerson with id \"{{id}}\" with code: \"{{statusCode}}\" and message: \"{{restResponse.errorMessage}}\"", + "admin.access-control.epeople.notification.deleted.failure": "حدث خطأ عند محاولة حذف شخص إلكتروني بالمعرف \"{{id}}\" بالرمز: \"{{statusCode}}\" والرسالة: \"{{restResponse.errorMessage}}\"", + + // "admin.access-control.epeople.notification.deleted.success": "Successfully deleted EPerson: \"{{name}}\"", + "admin.access-control.epeople.notification.deleted.success": "تم حذف الشخص الإلكتروني: \"{{name}}\"بنجاح", + + // "admin.access-control.groups.title": "Groups", + "admin.access-control.groups.title": "المجموعات", + + // "admin.access-control.groups.breadcrumbs": "Groups", + "admin.access-control.groups.breadcrumbs": "المجموعات", + + // "admin.access-control.groups.singleGroup.breadcrumbs": "Edit Group", + "admin.access-control.groups.singleGroup.breadcrumbs": "تحرير مجموعة", + + // "admin.access-control.groups.title.singleGroup": "Edit Group", + "admin.access-control.groups.title.singleGroup": "تحرير مجموعة", + + // "admin.access-control.groups.title.addGroup": "New Group", "admin.access-control.groups.title.addGroup": "مجموعة جديدة", + + // "admin.access-control.groups.addGroup.breadcrumbs": "New Group", "admin.access-control.groups.addGroup.breadcrumbs": "مجموعة جديدة", - "admin.access-control.groups.head": "مجموعات", + + // "admin.access-control.groups.head": "Groups", + "admin.access-control.groups.head": "المجموعات", + + // "admin.access-control.groups.button.add": "Add group", "admin.access-control.groups.button.add": "إضافة مجموعة", - "admin.access-control.groups.search.head": "بحثت المجموعات", - "admin.access-control.groups.button.see-all": "مراجعة الكل", + + // "admin.access-control.groups.search.head": "Search groups", + "admin.access-control.groups.search.head": "بحث المجموعات", + + // "admin.access-control.groups.button.see-all": "Browse all", + "admin.access-control.groups.button.see-all": "استعراض الكل", + + // "admin.access-control.groups.search.button": "Search", "admin.access-control.groups.search.button": "بحث", - "admin.access-control.groups.search.placeholder": "بحث في المجموعات...", + + // "admin.access-control.groups.search.placeholder": "Search groups...", + "admin.access-control.groups.search.placeholder": "بحث المجموعات...", + + // "admin.access-control.groups.table.id": "ID", "admin.access-control.groups.table.id": "المعرّف", + + // "admin.access-control.groups.table.name": "Name", "admin.access-control.groups.table.name": "الاسم", - "admin.access-control.groups.table.collectionOrCommunity": "الحاوية/المجتمع", + + // "admin.access-control.groups.table.collectionOrCommunity": "Collection/Community", + "admin.access-control.groups.table.collectionOrCommunity": "حاوية/مجتمع", + + // "admin.access-control.groups.table.members": "Members", "admin.access-control.groups.table.members": "الأعضاء", + + // "admin.access-control.groups.table.edit": "Edit", "admin.access-control.groups.table.edit": "تحرير", + + // "admin.access-control.groups.table.edit.buttons.edit": "Edit \"{{name}}\"", "admin.access-control.groups.table.edit.buttons.edit": "تحرير \"{{name}}\"", + + // "admin.access-control.groups.table.edit.buttons.remove": "Delete \"{{name}}\"", "admin.access-control.groups.table.edit.buttons.remove": "حذف \"{{name}}\"", - "admin.access-control.groups.no-items": "لم يتم العثور على أي مجموعات دي فيينا أو كمعرفي فريد", + + // "admin.access-control.groups.no-items": "No groups found with this in their name or this as UUID", + "admin.access-control.groups.no-items": "لم يتم العثور على أي مجموعات بهذا في اسمها أو كمعرف عمومي فريد", + + // "admin.access-control.groups.notification.deleted.success": "Successfully deleted group \"{{name}}\"", "admin.access-control.groups.notification.deleted.success": "تم حذف المجموعة \"{{name}}\"بنجاح", - "admin.access-control.groups.notification.deleted.failure.title": "فشل في حذف المجموعة \"{{name}}\"", + + // "admin.access-control.groups.notification.deleted.failure.title": "Failed to delete group \"{{name}}\"", + "admin.access-control.groups.notification.deleted.failure.title": "فشل حذف المجموعة \"{{name}}\"", + + // "admin.access-control.groups.notification.deleted.failure.content": "Cause: \"{{cause}}\"", "admin.access-control.groups.notification.deleted.failure.content": "السبب: \"{{cause}}\"", - "admin.access-control.groups.form.alert.permanent": "هذه المجموعة حقوق، حقوق لا يمكن تحريرها أو حذفها. ", - "admin.access-control.groups.form.alert.workflowGroup": "لا يمكن تعديل هذه المجموعة أو حذفها بشكل واضح مع دقة عملية التقديم وسير العمل في \"{{name}}\" {{comcol}}. \"تعيين الضبط\" في صفحة التحرير {{comcol}}. ", + + // "admin.access-control.groups.form.alert.permanent": "This group is permanent, so it can't be edited or deleted. You can still add and remove group members using this page.", + "admin.access-control.groups.form.alert.permanent": "هذه المجموعة دائمة، لذا لا يمكن تحريرها أو حذفها. لكن لايزال بإمكانك إضافة وإزالة أعضاء المجموعة باستخدام هذه الصفحة..", + + // "admin.access-control.groups.form.alert.workflowGroup": "This group can’t be modified or deleted because it corresponds to a role in the submission and workflow process in the \"{{name}}\" {{comcol}}. You can delete it from the \"assign roles\" tab on the edit {{comcol}} page. You can still add and remove group members using this page.", + "admin.access-control.groups.form.alert.workflowGroup": "لا يمكن تعديل هذه المجموعة أو حذفها لأنها تتوافق مع دور في عملية التقديم وسير العمل في \"{{name}}\" {{comcol}}. يمكنك حذفها من تبويب \"تعيين الأدوار\" في صفحة تحرير {{comcol}}. لا يزال بإمكانك إضافة وإزالة أعضاء المجموعة باستخدام هذه الصفحة.", + + // "admin.access-control.groups.form.head.create": "Create group", "admin.access-control.groups.form.head.create": "إنشاء مجموعة", - "admin.access-control.groups.form.head.edit": "تحرير المجموعة", + + // "admin.access-control.groups.form.head.edit": "Edit group", + "admin.access-control.groups.form.head.edit": "تحرير مجموعة", + + // "admin.access-control.groups.form.groupName": "Group name", "admin.access-control.groups.form.groupName": "اسم المجموعة", + + // "admin.access-control.groups.form.groupCommunity": "Community or Collection", "admin.access-control.groups.form.groupCommunity": "مجتمع أو حاوية", + + // "admin.access-control.groups.form.groupDescription": "Description", "admin.access-control.groups.form.groupDescription": "الوصف", + + // "admin.access-control.groups.form.notification.created.success": "Successfully created Group \"{{name}}\"", "admin.access-control.groups.form.notification.created.success": "تم إنشاء المجموعة \"{{name}}\"بنجاح", + + // "admin.access-control.groups.form.notification.created.failure": "Failed to create Group \"{{name}}\"", "admin.access-control.groups.form.notification.created.failure": "فشل إنشاء المجموعة \"{{name}}\"", - "admin.access-control.groups.form.notification.created.failure.groupNameInUse": "فشل في إنشاء المجموعة بالاسم: \"{{name}}\"، يرجى مراعاة أن الاسم ليس قيد التنفيذ.", + + // "admin.access-control.groups.form.notification.created.failure.groupNameInUse": "Failed to create Group with name: \"{{name}}\", make sure the name is not already in use.", + "admin.access-control.groups.form.notification.created.failure.groupNameInUse": "فشل إنشاء المجموعة بالاسم: \"{{name}}\"، يرجى التأكد أن الاسم ليس قيد الاستخدام بالفعل.", + + // "admin.access-control.groups.form.notification.edited.failure": "Failed to edit Group \"{{name}}\"", "admin.access-control.groups.form.notification.edited.failure": "فشل تحرير المجموعة \"{{name}}\"", - "admin.access-control.groups.form.notification.edited.failure.groupNameInUse": "الاسم \"{{name}}\"تعمل بالفعل!", + + // "admin.access-control.groups.form.notification.edited.failure.groupNameInUse": "Name \"{{name}}\" already in use!", + "admin.access-control.groups.form.notification.edited.failure.groupNameInUse": "الاسم \"{{name}}\" قيد الاستخدام بالفعل!", + + // "admin.access-control.groups.form.notification.edited.success": "Successfully edited Group \"{{name}}\"", "admin.access-control.groups.form.notification.edited.success": "تم تحرير المجموعة \"{{name}}\"بنجاح", + + // "admin.access-control.groups.form.actions.delete": "Delete Group", "admin.access-control.groups.form.actions.delete": "حذف المجموعة", + + // "admin.access-control.groups.form.delete-group.modal.header": "Delete Group \"{{ dsoName }}\"", "admin.access-control.groups.form.delete-group.modal.header": "حذف المجموعة \"{{ dsoName }}\"", + + // "admin.access-control.groups.form.delete-group.modal.info": "Are you sure you want to delete Group \"{{ dsoName }}\"", "admin.access-control.groups.form.delete-group.modal.info": "هل أنت متأكد من أنك ترغب في حذف المجموعة \"{{ dsoName }}\"", + + // "admin.access-control.groups.form.delete-group.modal.cancel": "Cancel", "admin.access-control.groups.form.delete-group.modal.cancel": "إلغاء", + + // "admin.access-control.groups.form.delete-group.modal.confirm": "Delete", "admin.access-control.groups.form.delete-group.modal.confirm": "حذف", + + // "admin.access-control.groups.form.notification.deleted.success": "Successfully deleted group \"{{ name }}\"", "admin.access-control.groups.form.notification.deleted.success": "تم حذف المجموعة \"{{ name }}\"بنجاح", - "admin.access-control.groups.form.notification.deleted.failure.title": "فشل في حذف المجموعة \"{{ name }}\"", + + // "admin.access-control.groups.form.notification.deleted.failure.title": "Failed to delete group \"{{ name }}\"", + "admin.access-control.groups.form.notification.deleted.failure.title": "فشل حذف المجموعة \"{{ name }}\"", + + // "admin.access-control.groups.form.notification.deleted.failure.content": "Cause: \"{{ cause }}\"", "admin.access-control.groups.form.notification.deleted.failure.content": "السبب: \"{{ cause }}\"", - "admin.access-control.groups.form.members-list.head": "يأتي إليكين", - "admin.access-control.groups.form.members-list.search.head": "إضافة المزيد من الإلكترونيات", - "admin.access-control.groups.form.members-list.button.see-all": "مراجعة الكل", - "admin.access-control.groups.form.members-list.headMembers": "الأعضاء الحالية", + + // "admin.access-control.groups.form.members-list.head": "EPeople", + "admin.access-control.groups.form.members-list.head": "أشخاص إلكترونيين", + + // "admin.access-control.groups.form.members-list.search.head": "Add EPeople", + "admin.access-control.groups.form.members-list.search.head": "إضافة أشخاص إلكترونيين", + + // "admin.access-control.groups.form.members-list.button.see-all": "Browse All", + "admin.access-control.groups.form.members-list.button.see-all": "استعراض الكل", + + // "admin.access-control.groups.form.members-list.headMembers": "Current Members", + "admin.access-control.groups.form.members-list.headMembers": "الأعضاء الحاليين", + + // "admin.access-control.groups.form.members-list.search.button": "Search", "admin.access-control.groups.form.members-list.search.button": "بحث", + + // "admin.access-control.groups.form.members-list.table.id": "ID", "admin.access-control.groups.form.members-list.table.id": "المعرّف", + + // "admin.access-control.groups.form.members-list.table.name": "Name", "admin.access-control.groups.form.members-list.table.name": "الاسم", - "admin.access-control.groups.form.members-list.table.identity": "هوية", + + // "admin.access-control.groups.form.members-list.table.identity": "Identity", + "admin.access-control.groups.form.members-list.table.identity": "الهوية", + + // "admin.access-control.groups.form.members-list.table.email": "Email", "admin.access-control.groups.form.members-list.table.email": "البريد الإلكتروني", + + // "admin.access-control.groups.form.members-list.table.netid": "NetID", "admin.access-control.groups.form.members-list.table.netid": "NetID", + + // "admin.access-control.groups.form.members-list.table.edit": "Remove / Add", "admin.access-control.groups.form.members-list.table.edit": "إزالة / إضافة", - "admin.access-control.groups.form.members-list.table.edit.buttons.remove": "حذف العضو باسم \"{{name}}\"", - "admin.access-control.groups.form.members-list.notification.success.addMember": "أكمل إضافة العضو: \"{{name}}\"بنجاح", - "admin.access-control.groups.form.members-list.notification.failure.addMember": "فشل في إضافة الموضوع: \"{{name}}\"", + + // "admin.access-control.groups.form.members-list.table.edit.buttons.remove": "Remove member with name \"{{name}}\"", + "admin.access-control.groups.form.members-list.table.edit.buttons.remove": "حذف عضو باسم \"{{name}}\"", + + // "admin.access-control.groups.form.members-list.notification.success.addMember": "Successfully added member: \"{{name}}\"", + "admin.access-control.groups.form.members-list.notification.success.addMember": "تمت إضافة العضو: \"{{name}}\"بنجاح", + + // "admin.access-control.groups.form.members-list.notification.failure.addMember": "Failed to add member: \"{{name}}\"", + "admin.access-control.groups.form.members-list.notification.failure.addMember": "فشل إضافة العضو: \"{{name}}\"", + + // "admin.access-control.groups.form.members-list.notification.success.deleteMember": "Successfully deleted member: \"{{name}}\"", "admin.access-control.groups.form.members-list.notification.success.deleteMember": "تم حذف العضو: \"{{name}}\"بنجاح", - "admin.access-control.groups.form.members-list.notification.failure.deleteMember": "فشل في حذف العضو: \"{{name}}\"", + + // "admin.access-control.groups.form.members-list.notification.failure.deleteMember": "Failed to delete member: \"{{name}}\"", + "admin.access-control.groups.form.members-list.notification.failure.deleteMember": "فشل حذف العضو: \"{{name}}\"", + + // "admin.access-control.groups.form.members-list.table.edit.buttons.add": "Add member with name \"{{name}}\"", "admin.access-control.groups.form.members-list.table.edit.buttons.add": "إضافة عضو باسم \"{{name}}\"", - "admin.access-control.groups.form.members-list.notification.failure.noActiveGroup": "لا توجد مجموعة حاليًا، سيتم تقديم الاسم الجديد.", + + // "admin.access-control.groups.form.members-list.notification.failure.noActiveGroup": "No current active group, submit a name first.", + "admin.access-control.groups.form.members-list.notification.failure.noActiveGroup": "لا توجد مجموعة نشطة حالياً، قم بتقديم الاسم أولاً.", + + // "admin.access-control.groups.form.members-list.no-members-yet": "No members in group yet, search and add.", "admin.access-control.groups.form.members-list.no-members-yet": "لا يوجد أعضاء في المجموعة حتى الآن، قم بالبحث والإضافة.", - "admin.access-control.groups.form.members-list.no-items": "لم يتم العثور على أي شخص إلكترونين في هذا البحث", + + // "admin.access-control.groups.form.members-list.no-items": "No EPeople found in that search", + "admin.access-control.groups.form.members-list.no-items": "لم يتم العثور على أي أشخاص إلكترونيين في هذا البحث", + + // "admin.access-control.groups.form.subgroups-list.notification.failure": "Something went wrong: \"{{cause}}\"", "admin.access-control.groups.form.subgroups-list.notification.failure": "هناك خطأ ما: \"{{cause}}\"", - "admin.access-control.groups.form.subgroups-list.head": "مجموعات", + + // "admin.access-control.groups.form.subgroups-list.head": "Groups", + "admin.access-control.groups.form.subgroups-list.head": "المجموعات", + + // "admin.access-control.groups.form.subgroups-list.search.head": "Add Subgroup", "admin.access-control.groups.form.subgroups-list.search.head": "إضافة مجموعة فرعية", - "admin.access-control.groups.form.subgroups-list.button.see-all": "مراجعة الكل", - "admin.access-control.groups.form.subgroups-list.headSubgroups": "المجموعات الشكلية", + + // "admin.access-control.groups.form.subgroups-list.button.see-all": "Browse All", + "admin.access-control.groups.form.subgroups-list.button.see-all": "استعراض الكل", + + // "admin.access-control.groups.form.subgroups-list.headSubgroups": "Current Subgroups", + "admin.access-control.groups.form.subgroups-list.headSubgroups": "المجموعات الفرعية الحالية", + + // "admin.access-control.groups.form.subgroups-list.search.button": "Search", "admin.access-control.groups.form.subgroups-list.search.button": "بحث", + + // "admin.access-control.groups.form.subgroups-list.table.id": "ID", "admin.access-control.groups.form.subgroups-list.table.id": "المعرّف", + + // "admin.access-control.groups.form.subgroups-list.table.name": "Name", "admin.access-control.groups.form.subgroups-list.table.name": "الاسم", - "admin.access-control.groups.form.subgroups-list.table.collectionOrCommunity": "ابدأ/المجتمع", + + // "admin.access-control.groups.form.subgroups-list.table.collectionOrCommunity": "Collection/Community", + "admin.access-control.groups.form.subgroups-list.table.collectionOrCommunity": "الحاوية/المجتمع", + + // "admin.access-control.groups.form.subgroups-list.table.edit": "Remove / Add", "admin.access-control.groups.form.subgroups-list.table.edit": "إزالة / إضافة", - "admin.access-control.groups.form.subgroups-list.table.edit.buttons.remove": "إزالة المجموعة الفرعية باسم \"{{name}}\"", + + // "admin.access-control.groups.form.subgroups-list.table.edit.buttons.remove": "Remove subgroup with name \"{{name}}\"", + "admin.access-control.groups.form.subgroups-list.table.edit.buttons.remove": "إزالة مجموعة فرعية باسم \"{{name}}\"", + + // "admin.access-control.groups.form.subgroups-list.table.edit.buttons.add": "Add subgroup with name \"{{name}}\"", "admin.access-control.groups.form.subgroups-list.table.edit.buttons.add": "إضافة مجموعة فرعية باسم \"{{name}}\"", - "admin.access-control.groups.form.subgroups-list.notification.success.addSubgroup": "متابعة إضافة المجموعة: \"{{name}}\"بنجاح", - "admin.access-control.groups.form.subgroups-list.notification.failure.addSubgroup": "فشل في إضافة المجموعة الفرعية: \"{{name}}\"", - "admin.access-control.groups.form.subgroups-list.notification.success.deleteSubgroup": "تم حذف المجموعة اليدوية: \"{{name}}\"بنجاح", - "admin.access-control.groups.form.subgroups-list.notification.failure.deleteSubgroup": "فشل حذف المجموعة المصنوعة: \"{{name}}\"", - "admin.access-control.groups.form.subgroups-list.notification.failure.noActiveGroup": "لا توجد مجموعة حاليًا، سيتم تقديم الاسم الجديد.", - "admin.access-control.groups.form.subgroups-list.notification.failure.subgroupToAddIsActiveGroup": "هذه هي المجموعة الحالية، لا يمكن الاتصال بها.", - "admin.access-control.groups.form.subgroups-list.no-items": "لم يتم العثور على مجموعات بهذا الاسم في دارفور أو بكمعرفي فريد", - "admin.access-control.groups.form.subgroups-list.no-subgroups-yet": "لا يوجد مجموعات فرعية في المجموعة حتى الآن.", + + // "admin.access-control.groups.form.subgroups-list.notification.success.addSubgroup": "Successfully added subgroup: \"{{name}}\"", + "admin.access-control.groups.form.subgroups-list.notification.success.addSubgroup": "تمت إضافة المجموعة الفرعية: \"{{name}}\"بنجاح", + + // "admin.access-control.groups.form.subgroups-list.notification.failure.addSubgroup": "Failed to add subgroup: \"{{name}}\"", + "admin.access-control.groups.form.subgroups-list.notification.failure.addSubgroup": "فشل إضافة مجموعة فرعية: \"{{name}}\"", + + // "admin.access-control.groups.form.subgroups-list.notification.success.deleteSubgroup": "Successfully deleted subgroup: \"{{name}}\"", + "admin.access-control.groups.form.subgroups-list.notification.success.deleteSubgroup": "تم حذف المجموعة الفرعية: \"{{name}}\"بنجاح", + + // "admin.access-control.groups.form.subgroups-list.notification.failure.deleteSubgroup": "Failed to delete subgroup: \"{{name}}\"", + "admin.access-control.groups.form.subgroups-list.notification.failure.deleteSubgroup": "فشل حذف المجموعة الفرعية: \"{{name}}\"", + + // "admin.access-control.groups.form.subgroups-list.notification.failure.noActiveGroup": "No current active group, submit a name first.", + "admin.access-control.groups.form.subgroups-list.notification.failure.noActiveGroup": "لا توجد مجموعة نشطة حالياً، قم بتقديم الاسم أولاً.", + + // "admin.access-control.groups.form.subgroups-list.notification.failure.subgroupToAddIsActiveGroup": "This is the current group, can't be added.", + "admin.access-control.groups.form.subgroups-list.notification.failure.subgroupToAddIsActiveGroup": "هذه هي المجموعة الحالية، لا يمكن إضافتها.", + + // "admin.access-control.groups.form.subgroups-list.no-items": "No groups found with this in their name or this as UUID", + "admin.access-control.groups.form.subgroups-list.no-items": "لم يتم العثور على مجموعات بهذا في اسمها أو بهذا كمعرف عمومي فريد", + + // "admin.access-control.groups.form.subgroups-list.no-subgroups-yet": "No subgroups in group yet.", + "admin.access-control.groups.form.subgroups-list.no-subgroups-yet": "لا توجد مجموعات فرعية في المجموعة حتى الآن.", + + // "admin.access-control.groups.form.return": "Back", "admin.access-control.groups.form.return": "رجوع", + + // "admin.quality-assurance.breadcrumbs": "Quality Assurance", "admin.quality-assurance.breadcrumbs": "ضمان الجودة", - "admin.notifications.event.breadcrumbs": "آلات ضمان الجودة", - "admin.notifications.event.page.title": "آلات ضمان الجودة", + + // "admin.notifications.event.breadcrumbs": "Quality Assurance Suggestions", + "admin.notifications.event.breadcrumbs": "مقترحات ضمان الجودة", + + // "admin.notifications.event.page.title": "Quality Assurance Suggestions", + "admin.notifications.event.page.title": "مقترحات ضمان الجودة", + + // "admin.quality-assurance.page.title": "Quality Assurance", "admin.quality-assurance.page.title": "ضمان الجودة", + + // "admin.notifications.source.breadcrumbs": "Quality Assurance", "admin.notifications.source.breadcrumbs": "مصدر ضمان الجودة", - "admin.access-control.groups.form.tooltip.editGroupPage": "في هذه الصفحة، يمكنك تعديل مجموعة الخصائص وأعضائها. ", - "admin.access-control.groups.form.tooltip.editGroup.addEpeople": "وتفكر شخصياً في هذه المجموعة أو تأسيسها، قم بالنقر على زر 'استعراض الكل' أو قم باستخدام شريط البحث أدناه للبحث عن المستخدمين (استخدم القائمة المسدلة الموجودة على يسار شريط البحث ما إذا كنت تريد البحث حسب الميتاداتا أو حسب البريد الإلكتروني). ", - "admin.access-control.groups.form.tooltip.editGroup.addSubgroups": "وبعد مجموعة فرعية إلى هذه المجموعة أو التغطية منها، قم بالنقر على زر 'استعراض الكل' أو قم باستخدام شريط البحث أدناه للبحث عن المجموعات. ", - "admin.reports.collections.title": "تقرير تصفية المجموعة", - "admin.reports.collections.breadcrumbs": "تقرير تصفية المجموعة", - "admin.reports.collections.head": "تقرير تصفية المجموعة", - "admin.reports.button.show-collections": "عرض المجموعات", - "admin.reports.collections.collections-report": "تقرير التحصيل", - "admin.reports.collections.item-results": "نتائج البند", - "admin.reports.collections.community": "مجتمع", - "admin.reports.collections.collection": "مجموعة", - "admin.reports.collections.nb_items": "ملحوظة. ", - "admin.reports.collections.match_all_selected_filters": "مطابقة جميع المرشحات المحددة", - "admin.reports.items.breadcrumbs": "تقرير استعلام بيانات التعريف", - "admin.reports.items.head": "تقرير استعلام بيانات التعريف", - "admin.reports.items.run": "تشغيل استعلام العنصر", - "admin.reports.items.section.collectionSelector": "محدد المجموعة", - "admin.reports.items.section.metadataFieldQueries": "استعلامات حقل بيانات التعريف", - "admin.reports.items.predefinedQueries": "الاستعلامات المحددة مسبقًا", - "admin.reports.items.section.limitPaginateQueries": "استعلامات الحد/الصفحات", - "admin.reports.items.limit": "حد/", - "admin.reports.items.offset": "عوض", - "admin.reports.items.wholeRepo": "المستودع كله", - "admin.reports.items.anyField": "أي مجال", - "admin.reports.items.predicate.exists": "موجود", - "admin.reports.items.predicate.doesNotExist": "غير موجود", - "admin.reports.items.predicate.equals": "يساوي", - "admin.reports.items.predicate.doesNotEqual": "لا يساوي", - "admin.reports.items.predicate.like": "يحب", - "admin.reports.items.predicate.notLike": "لا يشبه", - "admin.reports.items.predicate.contains": "يتضمن", - "admin.reports.items.predicate.doesNotContain": "لا يحتوي", - "admin.reports.items.predicate.matches": "اعواد الكبريت", - "admin.reports.items.predicate.doesNotMatch": "غير متطابق", - "admin.reports.items.preset.new": "استعلام جديد", - "admin.reports.items.preset.hasNoTitle": "لا يوجد لديه عنوان", - "admin.reports.items.preset.hasNoIdentifierUri": "لا يوجد لديه dc.identifier.uri", - "admin.reports.items.preset.hasCompoundSubject": "لديه موضوع مركب", - "admin.reports.items.preset.hasCompoundAuthor": "يحتوي على مركب dc.contributor.author", - "admin.reports.items.preset.hasCompoundCreator": "لديه مجمع DC.creator", - "admin.reports.items.preset.hasUrlInDescription": "لديه عنوان URL في dc.description", - "admin.reports.items.preset.hasFullTextInProvenance": "يحتوي على النص الكامل في dc.description.provenance", - "admin.reports.items.preset.hasNonFullTextInProvenance": "يحتوي على نص غير كامل في dc.description.provenance", - "admin.reports.items.preset.hasEmptyMetadata": "تحتوي على بيانات وصفية فارغة", - "admin.reports.items.preset.hasUnbreakingDataInDescription": "يحتوي على بيانات وصفية غير منقطعة في الوصف", - "admin.reports.items.preset.hasXmlEntityInMetadata": "يحتوي على كيان XML في بيانات التعريف", - "admin.reports.items.preset.hasNonAsciiCharInMetadata": "يحتوي على حرف غير ascii في البيانات الوصفية", - "admin.reports.items.number": "لا.", + + // "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": "في هذه الصفحة، يمكنك تعديل خصائص المجموعة وأعضائها. في القسم العلوي، يمكنك تحرير اسم المجموعة ووصفها، ما لم تكن هذه مجموعة إدارية لحاوية أو مجتمع، وفي هذه الحالة يتم إنشاء اسم المجموعة ووصفها تلقائياً ولا يمكن تحريرهما. في الأقسام التالية، يمكنك تعديل عضوية المجموعة. انظر [الويكي](https://wiki.lyrasis.org/display/DSDOC7x/Create+or+manage+a+user+group) للمزيد من التفاصيل.", + + // "admin.access-control.groups.form.tooltip.editGroup.addEpeople": "To add or remove an EPerson to/from this group, either click the 'Browse All' button or use the search bar below to search for users (use the dropdown to the left of the search bar to choose whether to search by metadata or by email). 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.", + "admin.access-control.groups.form.tooltip.editGroup.addEpeople": "لإضافة شخص إلكتروني إلى هذه المجموعة أو إزالته منها، قم بالنقر على زر 'استعراض الكل' أو قم باستخدام شريط البحث أدناه للبحث عن المستخدمين (استخدم القائمة المنسدلة الموجودة على يسار شريط البحث لاختيار ما إذا كنت تريد البحث حسب الميتاداتا أو حسب البريد الإلكتروني). ثم قم بالنقر على أيقونة زائد لكل مستخدم ترغب في إضافته في القائمة أدناه، أو أيقونة سلة المهملات لكل مستخدم ترغب في إزالته. قد تحتوي القائمة أدناه على عدة صفحات: استخدم عناصر التحكم في الصفحة الموجودة أسفل القائمة للانتقال إلى الصفحات التالية.", + + // "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.access-control.groups.form.tooltip.editGroup.addSubgroups": "لإضافة مجموعة فرعية إلى هذه المجموعة أو إزالتها منها، قم بالنقر على زر 'استعراض الكل' أو قم باستخدام شريط البحث أدناه للبحث عن المجموعات. ثم قم بالنقر على أيقونة زائد لكل مجموعة ترغب في إضافتها في القائمة أدناه، أو أيقونة سلة المهملات لكل مجموعة ترغب في إزالتها. قد تحتوي القائمة أدناه على عدة صفحات: استخدم عناصر التحكم في الصفحة الموجودة أسفل القائمة للانتقال إلى الصفحات التالية.", + + // "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.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.offset": "Offset", + // TODO New key - Add a translation + "admin.reports.items.offset": "Offset", + + // "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": "مجموعة", + + // "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": "عنوان", - "admin.reports.commons.filters": "المرشحات", - "admin.reports.commons.additional-data": "بيانات إضافية للعودة", - "admin.reports.commons.previous-page": "الصفحة السابقة", - "admin.reports.commons.next-page": "الصفحة التالية", - "admin.reports.commons.page": "صفحة", - "admin.reports.commons.of": "ل", - "admin.reports.commons.export": "تصدير لتحديث بيانات التعريف", - "admin.reports.commons.filters.deselect_all": "قم بإلغاء تحديد جميع المرشحات", - "admin.reports.commons.filters.select_all": "حدد كافة المرشحات", - "admin.reports.commons.filters.matches_all": "يطابق جميع المرشحات المحددة", - "admin.reports.commons.filters.property": "عوامل تصفية خصائص العنصر", - "admin.reports.commons.filters.property.is_item": "هل البند - صحيح دائمًا", - "admin.reports.commons.filters.property.is_withdrawn": "العناصر المسحوبة", - "admin.reports.commons.filters.property.is_not_withdrawn": "العناصر المتوفرة - لم يتم سحبها", - "admin.reports.commons.filters.property.is_discoverable": "العناصر القابلة للاكتشاف - ليست خاصة", - "admin.reports.commons.filters.property.is_not_discoverable": "غير قابل للاكتشاف - عنصر خاص", - "admin.reports.commons.filters.bitstream": "مرشحات تيار البت الأساسية", - "admin.reports.commons.filters.bitstream.has_multiple_originals": "يحتوي العنصر على تدفقات بت أصلية متعددة", - "admin.reports.commons.filters.bitstream.has_no_originals": "لا يحتوي العنصر على تدفقات بت أصلية", - "admin.reports.commons.filters.bitstream.has_one_original": "يحتوي العنصر على تدفق بت أصلي واحد", - "admin.reports.commons.filters.bitstream_mime": "عوامل تصفية Bitstream حسب نوع MIME", - "admin.reports.commons.filters.bitstream_mime.has_doc_original": "يحتوي العنصر على Doc Original Bitstream (PDF، Office، Text، HTML، XML، إلخ)", - "admin.reports.commons.filters.bitstream_mime.has_image_original": "يحتوي العنصر على تدفق بت للصورة الأصلية", - "admin.reports.commons.filters.bitstream_mime.has_unsupp_type": "يحتوي على أنواع Bitstream أخرى (ليست Doc أو Image)", - "admin.reports.commons.filters.bitstream_mime.has_mixed_original": "يحتوي العنصر على أنواع متعددة من تدفقات البت الأصلية (Doc، Image، Other)", - "admin.reports.commons.filters.bitstream_mime.has_pdf_original": "يحتوي العنصر على تدفق بت أصلي بتنسيق PDF", - "admin.reports.commons.filters.bitstream_mime.has_jpg_original": "يحتوي العنصر على JPG Original Bitstream", - "admin.reports.commons.filters.bitstream_mime.has_small_pdf": "يحتوي على ملف PDF صغير بشكل غير عادي", - "admin.reports.commons.filters.bitstream_mime.has_large_pdf": "يحتوي على ملف PDF كبير الحجم بشكل غير عادي", - "admin.reports.commons.filters.bitstream_mime.has_doc_without_text": "يحتوي على تدفق بت للمستند بدون عنصر TEXT", - "admin.reports.commons.filters.mime": "عوامل تصفية نوع MIME المدعومة", - "admin.reports.commons.filters.mime.has_only_supp_image_type": "يتم دعم تدفقات البت لصورة العنصر", - "admin.reports.commons.filters.mime.has_unsupp_image_type": "يحتوي العنصر على Image Bitstream غير مدعوم", - "admin.reports.commons.filters.mime.has_only_supp_doc_type": "يتم دعم تدفقات بت مستند العنصر", - "admin.reports.commons.filters.mime.has_unsupp_doc_type": "يحتوي العنصر على تدفق بت للمستند غير مدعوم", - "admin.reports.commons.filters.bundle": "مرشحات حزمة Bitstream", - "admin.reports.commons.filters.bundle.has_unsupported_bundle": "يحتوي على تدفق بت في حزمة غير مدعومة", - "admin.reports.commons.filters.bundle.has_small_thumbnail": "لديه صورة مصغرة صغيرة بشكل غير عادي", - "admin.reports.commons.filters.bundle.has_original_without_thumbnail": "يحتوي على تدفق بت أصلي بدون صورة مصغرة", - "admin.reports.commons.filters.bundle.has_invalid_thumbnail_name": "يحتوي على اسم صورة مصغرة غير صالح (بافتراض صورة مصغرة واحدة لكل نسخة أصلية)", - "admin.reports.commons.filters.bundle.has_non_generated_thumb": "تحتوي على صورة مصغرة لم يتم إنشاؤها", - "admin.reports.commons.filters.bundle.no_license": "ليس لديه ترخيص", - "admin.reports.commons.filters.bundle.has_license_documentation": "لديه وثائق في حزمة الترخيص", - "admin.reports.commons.filters.permission": "مرشحات الأذونات", - "admin.reports.commons.filters.permission.has_restricted_original": "يحتوي العنصر على تدفق بت أصلي مقيد", - "admin.reports.commons.filters.permission.has_restricted_original.tooltip": "يحتوي العنصر على تدفق بت أصلي واحد على الأقل لا يمكن للمستخدم المجهول الوصول إليه", - "admin.reports.commons.filters.permission.has_restricted_thumbnail": "يحتوي العنصر على صورة مصغرة مقيدة", - "admin.reports.commons.filters.permission.has_restricted_thumbnail.tooltip": "يحتوي العنصر على صورة مصغرة واحدة على الأقل لا يمكن للمستخدم المجهول الوصول إليها", - "admin.reports.commons.filters.permission.has_restricted_metadata": "يحتوي العنصر على بيانات وصفية مقيدة", - "admin.reports.commons.filters.permission.has_restricted_metadata.tooltip": "يحتوي العنصر على بيانات تعريف لا يمكن للمستخدم المجهول الوصول إليها", + + // "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.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.search.collection.edit": "Edit", "admin.search.collection.edit": "تحرير", + + // "admin.search.community.edit": "Edit", "admin.search.community.edit": "تحرير", + + // "admin.search.item.delete": "Delete", "admin.search.item.delete": "حذف", + + // "admin.search.item.edit": "Edit", "admin.search.item.edit": "تحرير", - "admin.search.item.make-private": "اجعله غير للاكتشاف", - "admin.search.item.make-public": "اجعله للاكتشاف", + + // "admin.search.item.make-private": "Make non-discoverable", + "admin.search.item.make-private": "اجعله غير قابل للاكتشاف", + + // "admin.search.item.make-public": "Make discoverable", + "admin.search.item.make-public": "اجعله قابل للاكتشاف", + + // "admin.search.item.move": "Move", "admin.search.item.move": "نقل", + + // "admin.search.item.reinstate": "Reinstate", "admin.search.item.reinstate": "إعادة تعيين", - "admin.search.item.withdraw": "يسحب", + + // "admin.search.item.withdraw": "Withdraw", + "admin.search.item.withdraw": "سحب", + + // "admin.search.title": "Administrative Search", "admin.search.title": "بحث إداري", + + // "administrativeView.search.results.head": "Administrative Search", "administrativeView.search.results.head": "بحث إداري", + + // "admin.workflow.breadcrumbs": "Administer Workflow", "admin.workflow.breadcrumbs": "أدر سير العمل", + + // "admin.workflow.title": "Administer Workflow", "admin.workflow.title": "أدر سير العمل", + + // "admin.workflow.item.workflow": "Workflow", "admin.workflow.item.workflow": "سير العمل", + + // "admin.workflow.item.workspace": "Workspace", "admin.workflow.item.workspace": "مساحة العمل", + + // "admin.workflow.item.delete": "Delete", "admin.workflow.item.delete": "حذف", - "admin.workflow.item.send-back": "إعادة الإرسال", - "admin.workflow.item.policies": "تماما", - "admin.workflow.item.supervision": "شاهد", - "admin.metadata-import.breadcrumbs": "قم باستيراد الميتاداتا", + + // "admin.workflow.item.send-back": "Send back", + "admin.workflow.item.send-back": "إعادة إرسال", + + // "admin.workflow.item.policies": "Policies", + "admin.workflow.item.policies": "السياسات", + + // "admin.workflow.item.supervision": "Supervision", + "admin.workflow.item.supervision": "الإشراف", + + // "admin.metadata-import.breadcrumbs": "Import Metadata", + "admin.metadata-import.breadcrumbs": "استيراد الميتاداتا", + + // "admin.batch-import.breadcrumbs": "Import Batch", "admin.batch-import.breadcrumbs": "استيراد الدفعة", - "admin.metadata-import.title": "قم باستيراد الميتاداتا", + + // "admin.metadata-import.title": "Import Metadata", + "admin.metadata-import.title": "استيراد الميتاداتا", + + // "admin.batch-import.title": "Import Batch", "admin.batch-import.title": "استيراد الدفعة", - "admin.metadata-import.page.header": "قم باستيراد الميتاداتا", + + // "admin.metadata-import.page.header": "Import Metadata", + "admin.metadata-import.page.header": "استيراد الميتاداتا", + + // "admin.batch-import.page.header": "Import Batch", "admin.batch-import.page.header": "استيراد الدفعة", - "admin.metadata-import.page.help": "يمكنك أن تحتوي أو تستعرض ملفات CSV التي تحتوي على عمليات ميتة بالدفع على الملفات من هنا", - "admin.batch-import.page.help": "حدد المراد الاستيراد منها. ", - "admin.batch-import.page.toggle.help": "من خلال إجراء الاستيراد إما عن طريق تحميل الملف أو عبر عنوان URL، استخدم المزيد لتعيين مصدر الإدخال", - "admin.metadata-import.page.dropMsg": "قم بإسقاط ملف CSV للميتاداتا للاستيراده", + + // "admin.metadata-import.page.help": "You can drop or browse CSV files that contain batch metadata operations on files here", + "admin.metadata-import.page.help": "يمكنك إفلات أو استعراض ملفات CSV التي تحتوي على عمليات ميتاداتا بالدفعة على الملفات من هنا", + + // "admin.batch-import.page.help": "Select the Collection to import into. Then, drop or browse to a Simple Archive Format (SAF) zip file that includes the Items to import", + "admin.batch-import.page.help": "حدد الحاوية المراد الاستيراد إليها. بعد ذلك، قم بإسقاط أو تصفح ملف مضغوط بتنسيق أرشيف بسيط (SAF) يتضمن المواد المراد استيرادها", + + // "admin.batch-import.page.toggle.help": "It is possible to perform import either with file upload or via URL, use above toggle to set the input source", + "admin.batch-import.page.toggle.help": "من الممكن إجراء الاستيراد إما عن طريق تحميل الملف أو عبر عنوان URL، استخدم التبديل أعلاه لتعيين مصدر الإدخال", + + // "admin.metadata-import.page.dropMsg": "Drop a metadata CSV to import", + "admin.metadata-import.page.dropMsg": "قم بإسقاط ملف CSV للميتاداتا لاستيراده", + + // "admin.batch-import.page.dropMsg": "Drop a batch ZIP to import", "admin.batch-import.page.dropMsg": "قم بإسقاط ZIP الدفعة المراد استيرادها", - "admin.metadata-import.page.dropMsgReplace": "قم بالمسح لاستبدال ملف CSV للميتاداتا المراد استيراده", - "admin.batch-import.page.dropMsgReplace": "قم بالمسح لاستبدال ZIP الدفعة المراد استيرادها", + + // "admin.metadata-import.page.dropMsgReplace": "Drop to replace the metadata CSV to import", + "admin.metadata-import.page.dropMsgReplace": "قم بالإسقاط لاستبدال ملف CSV للميتاداتا المراد استيراده", + + // "admin.batch-import.page.dropMsgReplace": "Drop to replace the batch ZIP to import", + "admin.batch-import.page.dropMsgReplace": "قم بالإسقاط لاستبدال ZIP الدفعة المراد استيرادها", + + // "admin.metadata-import.page.button.return": "Back", "admin.metadata-import.page.button.return": "رجوع", + + // "admin.metadata-import.page.button.proceed": "Proceed", "admin.metadata-import.page.button.proceed": "متابعة", - "admin.metadata-import.page.button.select-collection": "حدد", - "admin.metadata-import.page.error.addFile": "حدد ملف الجديد!", - "admin.metadata-import.page.error.addFileUrl": "أدخل عنوان URL للملف الجديد!", - "admin.batch-import.page.error.addFile": "حدد ملف ZIP الجديد!", + + // "admin.metadata-import.page.button.select-collection": "Select Collection", + "admin.metadata-import.page.button.select-collection": "حدد الحاوية", + + // "admin.metadata-import.page.error.addFile": "Select file first!", + "admin.metadata-import.page.error.addFile": "حدد ملف أولاً!", + + // "admin.metadata-import.page.error.addFileUrl": "Insert file URL first!", + "admin.metadata-import.page.error.addFileUrl": "أدخل عنوان URL للملف أولاً!", + + // "admin.batch-import.page.error.addFile": "Select ZIP file first!", + "admin.batch-import.page.error.addFile": "حدد ملف ZIP أولاً!", + + // "admin.metadata-import.page.toggle.upload": "Upload", "admin.metadata-import.page.toggle.upload": "تحميل", + + // "admin.metadata-import.page.toggle.url": "URL", "admin.metadata-import.page.toggle.url": "عنوان URL", - "admin.metadata-import.page.urlMsg": "قم بالضغط على عنوان url لملف ZIP الخاص بالدفعة للاستيراده", + + // "admin.metadata-import.page.urlMsg": "Insert the batch ZIP url to import", + "admin.metadata-import.page.urlMsg": "قم بإدخال عنوان url لملف ZIP الخاص بالدفعة لاستيراده", + + // "admin.metadata-import.page.validateOnly": "Validate Only", "admin.metadata-import.page.validateOnly": "التحقق فقط", - "admin.metadata-import.page.validateOnly.hint": "عند التحديد، سيتم التحقق من صحة ملف CSV الذي تم تحميله. ", + + // "admin.metadata-import.page.validateOnly.hint": "When selected, the uploaded CSV will be validated. You will receive a report of detected changes, but no changes will be saved.", + "admin.metadata-import.page.validateOnly.hint": "عند التحديد، سيتم التحقق من صحة ملف CSV الذي تم تحميله. ستتلقى تقريراً بالتغييرات التي تم اكتشافها، ولكن لن يتم حفظ أي تغييرات.", + + // "advanced-workflow-action.rating.form.rating.label": "Rating", "advanced-workflow-action.rating.form.rating.label": "التقييم", + + // "advanced-workflow-action.rating.form.rating.error": "You must rate the item", "advanced-workflow-action.rating.form.rating.error": "يجب عليك تقييم هذه المادة", + + // "advanced-workflow-action.rating.form.review.label": "Review", "advanced-workflow-action.rating.form.review.label": "مراجعة", - "advanced-workflow-action.rating.form.review.error": "يجب عليك تفصيل تفاصيل لتقديم هذا التقييم", - "advanced-workflow-action.rating.description": "برجاء تحديد التقييم أدناه", - "advanced-workflow-action.rating.description-requiredDescription": "يرجى تحديد التقييم التفصيلي للمراجعة", - "advanced-workflow-action.select-reviewer.description-single": "يرجى اختيار مرشح واحد أدناه للمقدمة", - "advanced-workflow-action.select-reviewer.description-multiple": "يرجى اختيار مرشح واحد أو أكثر أدناه قبل التقديم", - "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.head": "يأتي إليكين", - "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.search.head": "إضافة المزيد من الإلكترونيات", - "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.button.see-all": "مراجعة الكل", - "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.headMembers": "الأعضاء الحالية", + + // "advanced-workflow-action.rating.form.review.error": "You must enter a review to submit this rating", + "advanced-workflow-action.rating.form.review.error": "يجب عليك إدخال مراجعة لتقديم هذا التقييم", + + // "advanced-workflow-action.rating.description": "Please select a rating below", + "advanced-workflow-action.rating.description": "يرجى تحديد التقييم أدناه", + + // "advanced-workflow-action.rating.description-requiredDescription": "Please select a rating below and also add a review", + "advanced-workflow-action.rating.description-requiredDescription": "يرجى تحديد التقييم أدناه وإضافة مراجعة", + + // "advanced-workflow-action.select-reviewer.description-single": "Please select a single reviewer below before submitting", + "advanced-workflow-action.select-reviewer.description-single": "يرجى اختيار مراجع واحد أدناه قبل التقديم", + + // "advanced-workflow-action.select-reviewer.description-multiple": "Please select one or more reviewers below before submitting", + "advanced-workflow-action.select-reviewer.description-multiple": "يرجى اختيار مراجع واحد أو أكثر أدناه قبل التقديم", + + // "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.head": "EPeople", + "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.head": "أشخاص إلكترونيين", + + // "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.search.head": "Add EPeople", + "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.search.head": "إضافة أشخاص إلكترونيين", + + // "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.button.see-all": "Browse All", + "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.button.see-all": "استعراض الكل", + + // "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.headMembers": "Current Members", + "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.headMembers": "الأعضاء الحاليين", + + // "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.search.button": "Search", "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.search.button": "بحث", + + // "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.table.id": "ID", "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.table.id": "المعرّف", + + // "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.table.name": "Name", "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.table.name": "الاسم", - "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.table.identity": "هوية", + + // "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.table.identity": "Identity", + "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.table.identity": "الهوية", + + // "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.table.email": "Email", "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.table.email": "البريد الإلكتروني", + + // "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.table.netid": "NetID", "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.table.netid": "NetID", + + // "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.table.edit": "Remove / Add", "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.table.edit": "إزالة / إضافة", + + // "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.table.edit.buttons.remove": "Remove member with name \"{{name}}\"", "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.table.edit.buttons.remove": "إزالة عضو باسم \"{{name}}\"", - "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.notification.success.addMember": "أكمل إضافة العضو: \"{{name}}\"بنجاح", - "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.notification.failure.addMember": "فشل في إضافة الموضوع: \"{{name}}\"", + + // "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.notification.success.addMember": "Successfully added member: \"{{name}}\"", + "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.notification.success.addMember": "تمت إضافة العضو: \"{{name}}\"بنجاح", + + // "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.notification.failure.addMember": "Failed to add member: \"{{name}}\"", + "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.notification.failure.addMember": "فشل إضافة العضو: \"{{name}}\"", + + // "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.notification.success.deleteMember": "Successfully deleted member: \"{{name}}\"", "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.notification.success.deleteMember": "تم حذف العضو: \"{{name}}\"بنجاح", - "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.notification.failure.deleteMember": "فشل في حذف العضو: \"{{name}}\"", + + // "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.notification.failure.deleteMember": "Failed to delete member: \"{{name}}\"", + "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.notification.failure.deleteMember": "فشل حذف العضو: \"{{name}}\"", + + // "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.table.edit.buttons.add": "Add member with name \"{{name}}\"", "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.table.edit.buttons.add": "إضافة عضو باسم \"{{name}}\"", - "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.notification.failure.noActiveGroup": "لا توجد مجموعة حاليًا، سيتم تقديم الاسم الجديد.", + + // "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.notification.failure.noActiveGroup": "No current active group, submit a name first.", + "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.notification.failure.noActiveGroup": "لا توجد مجموعة نشطة حالياً، قم بتقديم الاسم أولاً.", + + // "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.no-members-yet": "No members in group yet, search and add.", "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.no-members-yet": "لا يوجد أعضاء في المجموعة حتى الآن، قم بالبحث والإضافة.", - "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.no-items": "لم يتم العثور على أي شخص إلكترونين في هذا البحث", - "advanced-workflow-action.select-reviewer.no-reviewer-selected.error": "لم يتم تحديد أي زائر.", - "admin.batch-import.page.validateOnly.hint": "عند التحديد، سيتم التحقق من صحة الملف الموجود الذي تم تحميله. ", + + // "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.no-items": "No EPeople found in that search", + "advanced-workflow-action-select-reviewer.groups.form.reviewers-list.no-items": "لم يتم العثور على أي أشخاص إلكترونيين في هذا البحث", + + // "advanced-workflow-action.select-reviewer.no-reviewer-selected.error": "No reviewer selected.", + "advanced-workflow-action.select-reviewer.no-reviewer-selected.error": "لم يتم تحديد أي مراجع.", + + // "admin.batch-import.page.validateOnly.hint": "When selected, the uploaded ZIP will be validated. You will receive a report of detected changes, but no changes will be saved.", + "admin.batch-import.page.validateOnly.hint": "عند التحديد، سيتم التحقق من صحة الملف المضغوط الذي تم تحميله. ستتلقى تقريراً بالتغييرات التي تم اكتشافها، ولكن لن يتم حفظ أي تغييرات.", + + // "admin.batch-import.page.remove": "remove", "admin.batch-import.page.remove": "إزالة", - "auth.errors.invalid-user": "عنوان البريد الإلكتروني أو كلمة مرور غير صالحة.", - "auth.messages.expired": "لقد تعلمت. ", - "auth.messages.token-refresh-failed": "فشل تحديث الرمز المميز لجلستك. ", + + // "auth.errors.invalid-user": "Invalid email address or password.", + "auth.errors.invalid-user": "عنوان البريد الإلكتروني أو كلمة المرور غير صالحة.", + + // "auth.messages.expired": "Your session has expired. Please log in again.", + "auth.messages.expired": "لقد انتهت جلستك. يرجى تسجيل الدخول مرة أخرى.", + + // "auth.messages.token-refresh-failed": "Refreshing your session token failed. Please log in again.", + "auth.messages.token-refresh-failed": "فشل تحديث الرمز المميز لجلستك. يرجى تسجيل الدخول مرة أخرى.", + + // "bitstream.download.page": "Now downloading {{bitstream}}...", "bitstream.download.page": "جاري الآن تنزيل {{bitstream}}...", + + // "bitstream.download.page.back": "Back", "bitstream.download.page.back": "رجوع", - "bitstream.edit.authorizations.link": "تحرير سياسة تدفق البت", - "bitstream.edit.authorizations.title": "تحرير سياسة تدفق البت", + + // "bitstream.edit.authorizations.link": "Edit bitstream's Policies", + "bitstream.edit.authorizations.link": "تحرير سياسات تدفق البت", + + // "bitstream.edit.authorizations.title": "Edit bitstream's Policies", + "bitstream.edit.authorizations.title": "تحرير سياسات تدفق البت", + + // "bitstream.edit.return": "Back", "bitstream.edit.return": "رجوع", + + // "bitstream.edit.bitstream": "Bitstream: ", "bitstream.edit.bitstream": "تدفق البت: ", - "bitstream.edit.form.description.hint": "اختياريًا، قم بتقديم وصف مختصر للملف، على سبيل المثال \"المقال الرئيسي\"أو\"قراءات بيانات الخبرة\".", + + // "bitstream.edit.form.description.hint": "Optionally, provide a brief description of the file, for example \"Main article\" or \"Experiment data readings\".", + "bitstream.edit.form.description.hint": "اختيارياً، قم بتقديم وصف مختصر للملف، على سبيل المثال \"المقال الرئيسي\" أو \"قراءات بيانات التجربة\".", + + // "bitstream.edit.form.description.label": "Description", "bitstream.edit.form.description.label": "الوصف", - "bitstream.edit.form.embargo.hint": "أول يوم يسمح له بالوصول. لا يمكن تعديل هذا التاريخ في هذا النموذج. لتعيين تاريخ حظر تدفق بت، قم بالذهاب إلى كتلة المادة، كوك بالنقر على ...تصاريح، إنشاء أو تحرير أبو يقرأ الخاصة بتدفق البت، وتعيين تاريخ الميلاد حسب الطلب.", - "bitstream.edit.form.embargo.label": "الحظر حتى تاريخ المحدد", - "bitstream.edit.form.fileName.hint": "تغيير اسم الملف لتدفق البت. ", + + // "bitstream.edit.form.embargo.hint": "The first day from which access is allowed. This date cannot be modified on this form. To set an embargo date for a bitstream, go to the Item Status tab, click Authorizations..., create or edit the bitstream's READ policy, and set the Start Date as desired.", + "bitstream.edit.form.embargo.hint": "أول يوم يسمح منه الوصول. لا يمكن تعديل هذا التاريخ في هذا النموذج. لتعيين تاريخ حظر لتدفق بت، قم بالذهاب إلى تبويب حالة المادة، وقم بالنقر على تصاريح...، إنشاء أو تحرير سياسة READ الخاصة بتدفق البت، وتعيين تاريخ البدء حسب الرغبة.", + + // "bitstream.edit.form.embargo.label": "Embargo until specific date", + "bitstream.edit.form.embargo.label": "حظر حتى تاريخ محدد", + + // "bitstream.edit.form.fileName.hint": "Change the filename for the bitstream. Note that this will change the display bitstream URL, but old links will still resolve as long as the sequence ID does not change.", + "bitstream.edit.form.fileName.hint": "تغيير اسم الملف لتدفق البت. لاحظ أن هذا سيؤدي إلى تغيير عنوان URL لدفق البت المعروض، لكن الروابط القديمة ستظل تحل طالما لم يتغير معرف التسلسل.", + + // "bitstream.edit.form.fileName.label": "Filename", "bitstream.edit.form.fileName.label": "اسم الملف", - "bitstream.edit.form.newFormat.label": "وصفه محدده جديده", + + // "bitstream.edit.form.newFormat.label": "Describe new format", + "bitstream.edit.form.newFormat.label": "وصف التنسيق الجديد", + + // "bitstream.edit.form.newFormat.hint": "The application you used to create the file, and the version number (for example, \"ACMESoft SuperApp version 1.5\").", "bitstream.edit.form.newFormat.hint": "التطبيق الذي قمت باستخدامه لإنشاء الملف، ورقم الإصدار (على سبيل المثال: \"ACMESoft SuperApp الإصدار 1.5\").", - "bitstream.edit.form.primaryBitstream.label": "التدفق الرئيسي للبيت", - "bitstream.edit.form.selectedFormat.hint": "إذا لم يكن متاحًا في المستقبل، يجب أن يطلب \"التنسيق غير موجود في المستند\" مسبقًا مسموح لها \"وصف التنسيق الجديد\".", - "bitstream.edit.form.selectedFormat.label": "البحث عن أداة", - "bitstream.edit.form.selectedFormat.unknown": "في حالة عدم وجودها في القائمة", - "bitstream.edit.notifications.error.format.title": "لقد حدث خطأ أثناء حفظ تدفق البت", - "bitstream.edit.notifications.error.primaryBitstream.title": "حدث خطأ أثناء حفظ التدفق الأساسي", - "bitstream.edit.form.iiifLabel.label": "ملصق التسمية IIIF", - "bitstream.edit.form.iiifLabel.hint": "تسمية قماش لهذه الصورة. ", + + // "bitstream.edit.form.primaryBitstream.label": "Primary File", + "bitstream.edit.form.primaryBitstream.label": "تدفق البت الرئيسي", + + // "bitstream.edit.form.selectedFormat.hint": "If the format is not in the above list, select \"format not in list\" above and describe it under \"Describe new format\".", + "bitstream.edit.form.selectedFormat.hint": "إذا لم يكن التنسيق موجوداً في القائمة أعلاه، قم بتحديد \"التنسيق غير موجود في القائمة\" أعلاه وقم بوصفه أدنى \"وصف تنسيق جديد\".", + + // "bitstream.edit.form.selectedFormat.label": "Selected Format", + "bitstream.edit.form.selectedFormat.label": "التنسيق المحدد", + + // "bitstream.edit.form.selectedFormat.unknown": "Format not in list", + "bitstream.edit.form.selectedFormat.unknown": "التنسيق غير موجود في القائمة", + + // "bitstream.edit.notifications.error.format.title": "An error occurred saving the bitstream's format", + "bitstream.edit.notifications.error.format.title": "لقد حدث خطأ أثناء حفظ تنسيق تدفق البت", + + // "bitstream.edit.notifications.error.primaryBitstream.title": "An error occurred saving the primary bitstream", + "bitstream.edit.notifications.error.primaryBitstream.title": "حدث خطأ أثناء حفظ تدفق البت الرئيسي", + + // "bitstream.edit.form.iiifLabel.label": "IIIF Label", + "bitstream.edit.form.iiifLabel.label": "ملصق تسمية IIIF", + + // "bitstream.edit.form.iiifLabel.hint": "Canvas label for this image. If not provided default label will be used.", + "bitstream.edit.form.iiifLabel.hint": "تسمية Canvas لهذه الصورة. إذا لم يتم توفير التسمية الافتراضية سيتم استخدامها.", + + // "bitstream.edit.form.iiifToc.label": "IIIF Table of Contents", "bitstream.edit.form.iiifToc.label": "جدول محتويات IIIF", - "bitstream.edit.form.iiifToc.hint": "إن إضافة نص هنا تجعل هذا بداية لنطاق محتويات جديد.", - "bitstream.edit.form.iiifWidth.label": "عرض قماش IIIF", - "bitstream.edit.form.iiifWidth.hint": "يجب أن يتطابق عرض القماش مع عرض الصورة.", - "bitstream.edit.form.iiifHeight.label": "ارتفاع قماش IIIF", - "bitstream.edit.form.iiifHeight.hint": "يجب أن يتطابق ارتفاع القماش مع ارتفاع الصورة.", - "bitstream.edit.notifications.saved.content": "تم حفظ التغييرات التي أحبها على تدفق هذا.", + + // "bitstream.edit.form.iiifToc.hint": "Adding text here makes this the start of a new table of contents range.", + "bitstream.edit.form.iiifToc.hint": "إن إضافة نص هنا تجعل هذا بداية لنطاق جدول محتويات جديد.", + + // "bitstream.edit.form.iiifWidth.label": "IIIF Canvas Width", + "bitstream.edit.form.iiifWidth.label": "عرض IIIF Canvas", + + // "bitstream.edit.form.iiifWidth.hint": "The canvas width should usually match the image width.", + "bitstream.edit.form.iiifWidth.hint": "يجب أن يتطابق عرض Canvas عادةً مع عرض الصورة.", + + // "bitstream.edit.form.iiifHeight.label": "IIIF Canvas Height", + "bitstream.edit.form.iiifHeight.label": "ارتفاع Canvas IIIF", + + // "bitstream.edit.form.iiifHeight.hint": "The canvas height should usually match the image height.", + "bitstream.edit.form.iiifHeight.hint": "يجب أن يتطابق ارتفاع Canvas عادةً مع ارتفاع الصورة.", + + // "bitstream.edit.notifications.saved.content": "Your changes to this bitstream were saved.", + "bitstream.edit.notifications.saved.content": "تم حفظ التغييرات التي أجريتها على تدفق البت هذا.", + + // "bitstream.edit.notifications.saved.title": "Bitstream saved", "bitstream.edit.notifications.saved.title": "تم حفظ تدفق البت", + + // "bitstream.edit.title": "Edit bitstream", "bitstream.edit.title": "تحرير تدفق البت", - "bitstream-request-a-copy.alert.canDownload1": "لقد بالفعل حق الوصول إلى هذا الملف. ", + + // "bitstream-request-a-copy.alert.canDownload1": "You already have access to this file. If you want to download the file, click ", + "bitstream-request-a-copy.alert.canDownload1": "لديك بالفعل حق الوصول إلى هذا الملف. إذا كنت تريد تنزيل الملف، انقر ", + + // "bitstream-request-a-copy.alert.canDownload2": "here", "bitstream-request-a-copy.alert.canDownload2": "هنا", - "bitstream-request-a-copy.header": "نسخة الطلب من الملف", - "bitstream-request-a-copy.intro": "يرجى إعادة المعلومات التالية لطلب النسخة التالية: ", - "bitstream-request-a-copy.intro.bitstream.one": "جاري الطلب الملف التالي: ", + + // "bitstream-request-a-copy.header": "Request a copy of the file", + "bitstream-request-a-copy.header": "طلب نسخة من الملف", + + // "bitstream-request-a-copy.intro": "Enter the following information to request a copy for the following item: ", + "bitstream-request-a-copy.intro": "قم بإدخال المعلومات التالية لطلب نسخة للمادة التالية: ", + + // "bitstream-request-a-copy.intro.bitstream.one": "Requesting the following file: ", + "bitstream-request-a-copy.intro.bitstream.one": "جاري طلب الملف التالي: ", + + // "bitstream-request-a-copy.intro.bitstream.all": "Requesting all files. ", "bitstream-request-a-copy.intro.bitstream.all": "طلب كل الملفات. ", + + // "bitstream-request-a-copy.name.label": "Name *", "bitstream-request-a-copy.name.label": "الاسم *", + + // "bitstream-request-a-copy.name.error": "The name is required", "bitstream-request-a-copy.name.error": "الاسم مطلوب", - "bitstream-request-a-copy.email.label": "عنوان بريدك الإلكتروني *", - "bitstream-request-a-copy.email.hint": "يتم استخدام عنوان البريد الإلكتروني هذا الملف.", - "bitstream-request-a-copy.email.error": "يرجى الاتصال بعنوان بريد إلكتروني صالح.", + + // "bitstream-request-a-copy.email.label": "Your email address *", + "bitstream-request-a-copy.email.label": "عنوان بريدك الإلكتروني *", + + // "bitstream-request-a-copy.email.hint": "This email address is used for sending the file.", + "bitstream-request-a-copy.email.hint": "يتم استخدام عنوان هذا البريد الإلكتروني لإرسال الملف.", + + // "bitstream-request-a-copy.email.error": "Please enter a valid email address.", + "bitstream-request-a-copy.email.error": "يرجى إدخال عنوان بريد إلكتروني صالح.", + + // "bitstream-request-a-copy.allfiles.label": "Files", "bitstream-request-a-copy.allfiles.label": "ملفات", + + // "bitstream-request-a-copy.files-all-false.label": "Only the requested file", "bitstream-request-a-copy.files-all-false.label": "الملف المطلوب فقط", - "bitstream-request-a-copy.files-all-true.label": "كل الملفات (لهذه المادة) في الوصول المحدود", + + // "bitstream-request-a-copy.files-all-true.label": "All files (of this item) in restricted access", + "bitstream-request-a-copy.files-all-true.label": "كل الملفات (لهذه المادة) في الوصول المقيد", + + // "bitstream-request-a-copy.message.label": "Message", "bitstream-request-a-copy.message.label": "رسالة", + + // "bitstream-request-a-copy.return": "Back", "bitstream-request-a-copy.return": "رجوع", - "bitstream-request-a-copy.submit": "نسخة الطلب", - "bitstream-request-a-copy.submit.success": "تم تقديم طلب فعال.", + + // "bitstream-request-a-copy.submit": "Request copy", + "bitstream-request-a-copy.submit": "طلب نسخة", + + // "bitstream-request-a-copy.submit.success": "The item request was submitted successfully.", + "bitstream-request-a-copy.submit.success": "تم تقديم طلب المادة بنجاح.", + + // "bitstream-request-a-copy.submit.error": "Something went wrong with submitting the item request.", "bitstream-request-a-copy.submit.error": "حدث خطأ ما أثناء تقديم طلب المادة.", - "browse.back.all-results": "جميع النتائج حدثت", + + // "browse.back.all-results": "All browse results", + "browse.back.all-results": "جميع نتائج الاستعراض", + + // "browse.comcol.by.author": "By Author", "browse.comcol.by.author": "حسب المؤلف", + + // "browse.comcol.by.dateissued": "By Issue Date", "browse.comcol.by.dateissued": "حسب تاريخ الإصدار", + + // "browse.comcol.by.subject": "By Subject", "browse.comcol.by.subject": "حسب الموضوع", + + // "browse.comcol.by.srsc": "By Subject Category", "browse.comcol.by.srsc": "حسب فئة الموضوع", - "browse.comcol.by.nsi": "حسب فرس العلوم النرويجي", - "browse.comcol.by.title": "عنوان حسب الطلب", + + // "browse.comcol.by.nsi": "By Norwegian Science Index", + "browse.comcol.by.nsi": "حسب فهرس العلوم النرويجي", + + // "browse.comcol.by.title": "By Title", + "browse.comcol.by.title": "حسب العنوان", + + // "browse.comcol.head": "Browse", "browse.comcol.head": "استعراض", - "browse.empty": "لا يوجد شيء للعرض.", + + // "browse.empty": "No items to show.", + "browse.empty": "لا توجد مواد للعرض.", + + // "browse.metadata.author": "Author", "browse.metadata.author": "المؤلف", + + // "browse.metadata.dateissued": "Issue Date", "browse.metadata.dateissued": "تاريخ الإصدار", + + // "browse.metadata.subject": "Subject", "browse.metadata.subject": "الموضوع", - "browse.metadata.title": "عنوان العنوان", + + // "browse.metadata.title": "Title", + "browse.metadata.title": "العنوان", + + // "browse.metadata.srsc": "Subject Category", "browse.metadata.srsc": "فئة الموضوع", - "browse.metadata.author.breadcrumbs": "مراجعة حسب المؤلف", - "browse.metadata.dateissued.breadcrumbs": "تاريخ المراجعة حسب التاريخ", - "browse.metadata.subject.breadcrumbs": "مراجعة حسب الموضوع", - "browse.metadata.srsc.breadcrumbs": "مراجعة حسب فئة الموضوع", - "browse.metadata.nsi.breadcrumbs": "مراجعة حسب هرس العلوم النرويجي", - "browse.metadata.title.breadcrumbs": "قم باستعراض العنوان حسب الطلب", + + // "browse.metadata.author.breadcrumbs": "Browse by Author", + "browse.metadata.author.breadcrumbs": "استعراض حسب المؤلف", + + // "browse.metadata.dateissued.breadcrumbs": "Browse by Date", + "browse.metadata.dateissued.breadcrumbs": "استعراض حسب التاريخ", + + // "browse.metadata.subject.breadcrumbs": "Browse by Subject", + "browse.metadata.subject.breadcrumbs": "استعراض حسب الموضوع", + + // "browse.metadata.srsc.breadcrumbs": "Browse by Subject Category", + "browse.metadata.srsc.breadcrumbs": "استعراض حسب فئة الموضوع", + + // "browse.metadata.nsi.breadcrumbs": "Browse by Norwegian Science Index", + "browse.metadata.nsi.breadcrumbs": "استعراض حسب فهرس العلوم النرويجي", + + // "browse.metadata.title.breadcrumbs": "Browse by Title", + "browse.metadata.title.breadcrumbs": "استعراض حسب العنوان", + + // "pagination.next.button": "Next", "pagination.next.button": "التالي", - "pagination.previous.button": "السابقة", - "pagination.next.button.disabled.tooltip": "لا تقرأ من الصفحات من النتائج", - "browse.startsWith": "، يبدأ بـ {{ startsWith }}", + + // "pagination.previous.button": "Previous", + "pagination.previous.button": "السابق", + + // "pagination.next.button.disabled.tooltip": "No more pages of results", + "pagination.next.button.disabled.tooltip": "لا مزيد من الصفحات من النتائج", + + // "browse.startsWith": ", starting with {{ startsWith }}", + "browse.startsWith": ", يبدأ بـ {{ startsWith }}", + + // "browse.startsWith.choose_start": "(Choose start)", "browse.startsWith.choose_start": "(اختر الشهر)", + + // "browse.startsWith.choose_year": "(Choose year)", "browse.startsWith.choose_year": "(اختر السنة)", + + // "browse.startsWith.choose_year.label": "Choose the issue year", "browse.startsWith.choose_year.label": "اختر سنة الإصدار", - "browse.startsWith.jump": "تهذيب النتيجة حسب السنة أو الشهر", + + // "browse.startsWith.jump": "Filter results by year or month", + "browse.startsWith.jump": "تنقيح النتائج حسب السنة أو الشهر", + + // "browse.startsWith.months.april": "April", "browse.startsWith.months.april": "أبريل", + + // "browse.startsWith.months.august": "August", "browse.startsWith.months.august": "أغسطس", + + // "browse.startsWith.months.december": "December", "browse.startsWith.months.december": "ديسمبر", + + // "browse.startsWith.months.february": "February", "browse.startsWith.months.february": "فبراير", + + // "browse.startsWith.months.january": "January", "browse.startsWith.months.january": "يناير", + + // "browse.startsWith.months.july": "July", "browse.startsWith.months.july": "يوليو", + + // "browse.startsWith.months.june": "June", "browse.startsWith.months.june": "يونيو", + + // "browse.startsWith.months.march": "March", "browse.startsWith.months.march": "مارس", + + // "browse.startsWith.months.may": "May", "browse.startsWith.months.may": "مايو", + + // "browse.startsWith.months.none": "(Choose month)", "browse.startsWith.months.none": "(اختر الشهر)", - "browse.startsWith.months.none.label": "تاريخ إنشاء الإصدار", + + // "browse.startsWith.months.none.label": "Choose the issue month", + "browse.startsWith.months.none.label": "اختر تاريخ الإصدار", + + // "browse.startsWith.months.november": "November", "browse.startsWith.months.november": "نوفمبر", + + // "browse.startsWith.months.october": "October", "browse.startsWith.months.october": "أكتوبر", + + // "browse.startsWith.months.september": "September", "browse.startsWith.months.september": "سبتمبر", + + // "browse.startsWith.submit": "Browse", "browse.startsWith.submit": "استعراض", - "browse.startsWith.type_date": "تأهيل النتائج حسب التاريخ", - "browse.startsWith.type_date.label": "أو قم بكتابة تاريخ (السنة - الشهر) والنقر على زر المراجعة.", - "browse.startsWith.type_text": "تسهيل البحث عن طريق كتابة الرواية الأولى", + + // "browse.startsWith.type_date": "Filter results by date", + "browse.startsWith.type_date": "تنقيح النتائج حسب التاريخ", + + // "browse.startsWith.type_date.label": "Or type in a date (year-month) and click on the Browse button", + "browse.startsWith.type_date.label": "أو قم بكتابة تاريخ (السنة - الشهر) والنقر على زر استعراض.", + + // "browse.startsWith.type_text": "Filter results by typing the first few letters", + "browse.startsWith.type_text": "تنقيح النتائج عن طريق كتابة الأحرف الأولى", + + // "browse.startsWith.input": "Filter", "browse.startsWith.input": "منقح", + + // "browse.taxonomy.button": "Browse", "browse.taxonomy.button": "استعراض", - "browse.title": "مراجعة حسب الطلب {{ field }}{{ startsWith }} {{ value }}", - "browse.title.page": "مراجعة حسب الطلب {{ field }} {{ value }}", + + // "browse.title": "Browsing by {{ field }}{{ startsWith }} {{ value }}", + "browse.title": "استعراض حسب {{ field }}{{ startsWith }} {{ value }}", + + // "browse.title.page": "Browsing by {{ field }} {{ value }}", + "browse.title.page": "استعراض حسب {{ field }} {{ value }}", + + // "search.browse.item-back": "Back to Results", "search.browse.item-back": "العودة إلى النتائج", - "chips.remove": "إزالة الجانب", + + // "chips.remove": "Remove chip", + "chips.remove": "إزالة الشريحة", + + // "claimed-approved-search-result-list-element.title": "Approved", "claimed-approved-search-result-list-element.title": "مقبول", - "claimed-declined-search-result-list-element.title": "تم الرفض وتمت إعادة إنتاجه إلى مقدم الطلب", - "claimed-declined-task-search-result-list-element.title": "تم الرفض، وتمت إعادة العمل إلى سير عمل مدير المراجعة", - "collection.browse.logo": "تمت القراءة للحصول على شعار للصورة", + + // "claimed-declined-search-result-list-element.title": "Rejected, sent back to submitter", + "claimed-declined-search-result-list-element.title": "تم الرفض، وتمت الإعادة إلى مقدم الطلب", + + // "claimed-declined-task-search-result-list-element.title": "Declined, sent back to Review Manager's workflow", + "claimed-declined-task-search-result-list-element.title": "تم الرفض، وتمت الإعادة إلى سير عمل مدير المراجعة", + + // "collection.browse.logo": "Browse for a collection logo", + "collection.browse.logo": "استعراض للحصول على شعار للحاوية", + + // "collection.create.head": "Create a Collection", "collection.create.head": "إنشاء حاوية", - "collection.create.notifications.success": "تم إنشاء فعال", - "collection.create.sub-head": "إنشاء خانة تمكين {{ parent }}", + + // "collection.create.notifications.success": "Successfully created the Collection", + "collection.create.notifications.success": "تم إنشاء الحاوية بنجاح", + + // "collection.create.sub-head": "Create a Collection for Community {{ parent }}", + "collection.create.sub-head": "إنشاء حاوية للمجتمع {{ parent }}", + + // "collection.curate.header": "Curate Collection: {{collection}}", "collection.curate.header": "أكرتة الحاوية: {{collection}}", + + // "collection.delete.cancel": "Cancel", "collection.delete.cancel": "إلغاء", - "collection.delete.confirm": "بالتأكيد", - "collection.delete.processing": "غاري الحذف", - "collection.delete.head": "تأكد من الحذف", - "collection.delete.notification.fail": "عذرا حف", - "collection.delete.notification.success": "تم الحذف الفعال", - "collection.delete.text": "هل أنت متأكد من أنك تريد حذف الهاتف \"{{ dso }}\"", - "collection.edit.delete": "حذف هذه الصورة", - "collection.edit.head": "تحرير", - "collection.edit.breadcrumbs": "تحرير", + + // "collection.delete.confirm": "Confirm", + "collection.delete.confirm": "تأكيد", + + // "collection.delete.processing": "Deleting", + "collection.delete.processing": "جاري الحذف", + + // "collection.delete.head": "Delete Collection", + "collection.delete.head": "حذف الحاوية", + + // "collection.delete.notification.fail": "Collection could not be deleted", + "collection.delete.notification.fail": "تعذر حف الحاوية", + + // "collection.delete.notification.success": "Successfully deleted collection", + "collection.delete.notification.success": "تم حذف الحاوية بنجاح", + + // "collection.delete.text": "Are you sure you want to delete collection \"{{ dso }}\"", + "collection.delete.text": "هل أنت متأكد من أنك تريد حذف الحاوية \"{{ dso }}\"", + + // "collection.edit.delete": "Delete this collection", + "collection.edit.delete": "حذف هذه الحاوية", + + // "collection.edit.head": "Edit Collection", + "collection.edit.head": "تحرير الحاوية", + + // "collection.edit.breadcrumbs": "Edit Collection", + "collection.edit.breadcrumbs": "تحرير الحاوية", + + // "collection.edit.tabs.mapper.head": "Item Mapper", "collection.edit.tabs.mapper.head": "مخطط المادة", - "collection.edit.tabs.item-mapper.title": "فتح المادة", + + // "collection.edit.tabs.item-mapper.title": "Collection Edit - Item Mapper", + "collection.edit.tabs.item-mapper.title": "تحرير الحاوية - مخطط المادة", + + // "collection.edit.item-mapper.cancel": "Cancel", "collection.edit.item-mapper.cancel": "إلغاء", - "collection.edit.item-mapper.collection": "التام: \"{{name}}\"", + + // "collection.edit.item-mapper.collection": "Collection: \"{{name}}\"", + "collection.edit.item-mapper.collection": "الحاوية: \"{{name}}\"", + + // "collection.edit.item-mapper.confirm": "Map selected items", "collection.edit.item-mapper.confirm": "تخطيط المواد المحددة", - "collection.edit.item-mapper.description": "هذه هي أداة المادة والتي بدأت لمديري في تخطيط المنتجات من كعكة صغيرة أخرى إلى هذه الثلاجة. ", - "collection.edit.item-mapper.head": "الخامة الأخرى - تخطيط مواد من توفيق", - "collection.edit.item-mapper.no-search": "يرجى الاتصال باستعلام للبحث", - "collection.edit.item-mapper.notifications.map.error.content": "حدثت أثناء التخطيط {{amount}} مادة.", + + // "collection.edit.item-mapper.description": "This is the item mapper tool that allows collection administrators to map items from other collections into this collection. You can search for items from other collections and map them, or browse the list of currently mapped items.", + "collection.edit.item-mapper.description": "هذه هي أداة مخطط المادة والتي تتيح لمديري الحاوية بتخطيط مواد من حاويات أخرى إلى هذه الحاوية. يمكنك البحث عن مواد من حاويات أخرى وتخطيطها، أو استعراض قائمة بالمواد المخططة حاليًا.", + + // "collection.edit.item-mapper.head": "Item Mapper - Map Items from Other Collections", + "collection.edit.item-mapper.head": "مخطط المادة - تخطيط مواد من حاويات أخرى", + + // "collection.edit.item-mapper.no-search": "Please enter a query to search", + "collection.edit.item-mapper.no-search": "يرجى إدخال استعلام للبحث", + + // "collection.edit.item-mapper.notifications.map.error.content": "Errors occurred for mapping of {{amount}} items.", + "collection.edit.item-mapper.notifications.map.error.content": "حدثت أخطاء أثناء تخطيط {{amount}} مادة.", + + // "collection.edit.item-mapper.notifications.map.error.head": "Mapping errors", "collection.edit.item-mapper.notifications.map.error.head": "أخطاء التخطيط", - "collection.edit.item-mapper.notifications.map.success.content": "تم التخطيط {{amount}} مادة فعالة.", + + // "collection.edit.item-mapper.notifications.map.success.content": "Successfully mapped {{amount}} items.", + "collection.edit.item-mapper.notifications.map.success.content": "تم تخطيط {{amount}} مادة بنجاح.", + + // "collection.edit.item-mapper.notifications.map.success.head": "Mapping completed", "collection.edit.item-mapper.notifications.map.success.head": "اكتمل التخطيط", - "collection.edit.item-mapper.notifications.unmap.error.content": "حدث خطأ أثناء إزالة التخطيطات {{amount}} مادة.", + + // "collection.edit.item-mapper.notifications.unmap.error.content": "Errors occurred for removing the mappings of {{amount}} items.", + "collection.edit.item-mapper.notifications.unmap.error.content": "حدثت أخطأ أثناء إزالة تخطيطات {{amount}} مادة.", + + // "collection.edit.item-mapper.notifications.unmap.error.head": "Remove mapping errors", "collection.edit.item-mapper.notifications.unmap.error.head": "أخطاء إزالة التخطيط", - "collection.edit.item-mapper.notifications.unmap.success.content": "بعد إزالة {{amount}} تخطيط فعّال.", + + // "collection.edit.item-mapper.notifications.unmap.success.content": "Successfully removed the mappings of {{amount}} items.", + "collection.edit.item-mapper.notifications.unmap.success.content": "تمت إزالة {{amount}} تخطيط مادة بنجاح.", + + // "collection.edit.item-mapper.notifications.unmap.success.head": "Remove mapping completed", "collection.edit.item-mapper.notifications.unmap.success.head": "اكتملت إزالة التخطيط", - "collection.edit.item-mapper.remove": "إزالة التخطيطات المحددة", - "collection.edit.item-mapper.search-form.placeholder": "المواد المدروسة...", - "collection.edit.item-mapper.tabs.browse": "فحص المواد الجيدة", + + // "collection.edit.item-mapper.remove": "Remove selected item mappings", + "collection.edit.item-mapper.remove": "إزالة تخطيطات المادة المحددة", + + // "collection.edit.item-mapper.search-form.placeholder": "Search items...", + "collection.edit.item-mapper.search-form.placeholder": "بحث المواد...", + + // "collection.edit.item-mapper.tabs.browse": "Browse mapped items", + "collection.edit.item-mapper.tabs.browse": "استعراض المواد المخططة", + + // "collection.edit.item-mapper.tabs.map": "Map new items", "collection.edit.item-mapper.tabs.map": "تخطيط مواد جديدة", + + // "collection.edit.logo.delete.title": "Delete logo", "collection.edit.logo.delete.title": "حذف الشعار", - "collection.edit.logo.delete-undo.title": "السماء عن الحذف", - "collection.edit.logo.label": "شعار تجاري", - "collection.edit.logo.notifications.add.error": "فشل تحميل شعار التعليمات. ", - "collection.edit.logo.notifications.add.success": "تم تحميل فيتامين فعال.", + + // "collection.edit.logo.delete-undo.title": "Undo delete", + "collection.edit.logo.delete-undo.title": "التراجع عن الحذف", + + // "collection.edit.logo.label": "Collection logo", + "collection.edit.logo.label": "شعار الحاوية", + + // "collection.edit.logo.notifications.add.error": "Uploading Collection logo failed. Please verify the content before retrying.", + "collection.edit.logo.notifications.add.error": "فشل تحميل شعار الحاوية. يرجى التحقق من المحتوى قبل إعادة المحاولة.", + + // "collection.edit.logo.notifications.add.success": "Upload Collection logo successful.", + "collection.edit.logo.notifications.add.success": "تم تحميل شعار الحاوية بنجاح.", + + // "collection.edit.logo.notifications.delete.success.title": "Logo deleted", "collection.edit.logo.notifications.delete.success.title": "تم حذف الشعار", - "collection.edit.logo.notifications.delete.success.content": "تم حذف الشعار الفعال", + + // "collection.edit.logo.notifications.delete.success.content": "Successfully deleted the collection's logo", + "collection.edit.logo.notifications.delete.success.content": "تم حذف شعار الحاوية بنجاح", + + // "collection.edit.logo.notifications.delete.error.title": "Error deleting logo", "collection.edit.logo.notifications.delete.error.title": "حدث خطأ أثناء حذف الشعار", - "collection.edit.logo.upload": "قم بإسقاط شعار العلامة للتحميل", - "collection.edit.notifications.success": "تم تحرير فعال", + + // "collection.edit.logo.upload": "Drop a Collection Logo to upload", + "collection.edit.logo.upload": "قم بإسقاط شعار الحاوية للتحميل", + + // "collection.edit.notifications.success": "Successfully edited the Collection", + "collection.edit.notifications.success": "تم تحرير الحاوية بنجاح", + + // "collection.edit.return": "Back", "collection.edit.return": "رجوع", + + // "collection.edit.tabs.access-control.head": "Access Control", "collection.edit.tabs.access-control.head": "التحكم في الوصول", - "collection.edit.tabs.access-control.title": "تحرير البدء - التحكم في الوصول", + + // "collection.edit.tabs.access-control.title": "Collection Edit - Access Control", + "collection.edit.tabs.access-control.title": "تحرير الحاوية - التحكم في الوصول", + + // "collection.edit.tabs.curate.head": "Curate", "collection.edit.tabs.curate.head": "أكرتة", - "collection.edit.tabs.curate.title": "تحرير تحرير - كرتة", - "collection.edit.tabs.authorizations.head": ".تصاريح", - "collection.edit.tabs.authorizations.title": "تحرير - تصاريح", + + // "collection.edit.tabs.curate.title": "Collection Edit - Curate", + "collection.edit.tabs.curate.title": "تحرير الحاوية - أكرتة", + + // "collection.edit.tabs.authorizations.head": "Authorizations", + "collection.edit.tabs.authorizations.head": "تصاريح", + + // "collection.edit.tabs.authorizations.title": "Collection Edit - Authorizations", + "collection.edit.tabs.authorizations.title": "تحرير الحاوية - تصاريح", + + // "collection.edit.item.authorizations.load-bundle-button": "Load more bundles", "collection.edit.item.authorizations.load-bundle-button": "تحميل المزيد من الحزم", + + // "collection.edit.item.authorizations.load-more-button": "Load more", "collection.edit.item.authorizations.load-more-button": "تحميل المزيد", - "collection.edit.item.authorizations.show-bitstreams-button": "عرض سياسات التدفق الكامل", + + // "collection.edit.item.authorizations.show-bitstreams-button": "Show bitstream policies for bundle", + "collection.edit.item.authorizations.show-bitstreams-button": "عرض سياسات تدفق البت للحزمة", + + // "collection.edit.tabs.metadata.head": "Edit Metadata", "collection.edit.tabs.metadata.head": "تحرير الميتاداتا", - "collection.edit.tabs.metadata.title": "تحرير تحرير - الميتاداتا", - "collection.edit.tabs.roles.head": "تم تعيينه", - "collection.edit.tabs.roles.title": "تحرير - التعديل", - "collection.edit.tabs.source.external": "لتتمكن من هذه بحصاد محتوياتها من مصدر خارجي", - "collection.edit.tabs.source.form.errors.oaiSource.required": "يجب عليك تقديم معرف حزمة التفاصيل الخاصة.", - "collection.edit.tabs.source.form.harvestType": "استمرار المحتوى", - "collection.edit.tabs.source.form.head": "قوة مصدر خارجي", - "collection.edit.tabs.source.form.metadataConfigId": "تنسيق الميثاداتا", + + // "collection.edit.tabs.metadata.title": "Collection Edit - Metadata", + "collection.edit.tabs.metadata.title": "تحرير الحاوية - الميتاداتا", + + // "collection.edit.tabs.roles.head": "Assign Roles", + "collection.edit.tabs.roles.head": "تعيين الأدوار", + + // "collection.edit.tabs.roles.title": "Collection Edit - Roles", + "collection.edit.tabs.roles.title": "تحرير الحاوية - الأدوار", + + // "collection.edit.tabs.source.external": "This collection harvests its content from an external source", + "collection.edit.tabs.source.external": "تقوم هذه الحاوية بحصاد محتواها من مصدر خارجي", + + // "collection.edit.tabs.source.form.errors.oaiSource.required": "You must provide a set id of the target collection.", + "collection.edit.tabs.source.form.errors.oaiSource.required": "يجب عليك تقديم معرف حزمة للحاوية المستهدفة.", + + // "collection.edit.tabs.source.form.harvestType": "Content being harvested", + "collection.edit.tabs.source.form.harvestType": "المحتوى الجاري حصاده", + + // "collection.edit.tabs.source.form.head": "Configure an external source", + "collection.edit.tabs.source.form.head": "تهيئة مصدر خارجي", + + // "collection.edit.tabs.source.form.metadataConfigId": "Metadata Format", + "collection.edit.tabs.source.form.metadataConfigId": "تنسيق الميتاداتا", + + // "collection.edit.tabs.source.form.oaiSetId": "OAI specific set id", "collection.edit.tabs.source.form.oaiSetId": "معرف حزمة محددة لمبادرة الأرشيفات المفتوحة", - "collection.edit.tabs.source.form.oaiSource": "مقدمة لخدمة المعلومات الأرشيفات المفتوحة", - "collection.edit.tabs.source.form.options.harvestType.METADATA_AND_BITSTREAMS": "ميتاداتا وتدفقات البت (يتطلب دعم ORE)", - "collection.edit.tabs.source.form.options.harvestType.METADATA_AND_REF": "غاب الميتاداتا والمراجع إلى تدفقات البت (يطلب دعم ORE)", - "collection.edit.tabs.source.form.options.harvestType.METADATA_ONLY": "موت الميتاتا فقط", + + // "collection.edit.tabs.source.form.oaiSource": "OAI Provider", + "collection.edit.tabs.source.form.oaiSource": "مقدم خدمة مبادرة الأرشيفات المفتوحة", + + // "collection.edit.tabs.source.form.options.harvestType.METADATA_AND_BITSTREAMS": "Harvest metadata and bitstreams (requires ORE support)", + "collection.edit.tabs.source.form.options.harvestType.METADATA_AND_BITSTREAMS": "حصاد الميتاداتا وتدفقات البت (يتطلب دعم ORE)", + + // "collection.edit.tabs.source.form.options.harvestType.METADATA_AND_REF": "Harvest metadata and references to bitstreams (requires ORE support)", + "collection.edit.tabs.source.form.options.harvestType.METADATA_AND_REF": "حصاد الميتاداتا والمراجع إلى تدفقات البت (يتطلب دعم ORE)", + + // "collection.edit.tabs.source.form.options.harvestType.METADATA_ONLY": "Harvest metadata only", + "collection.edit.tabs.source.form.options.harvestType.METADATA_ONLY": "حصاد الميتاداتا فقط", + + // "collection.edit.tabs.source.head": "Content Source", "collection.edit.tabs.source.head": "مصدر المحتوى", - "collection.edit.tabs.source.notifications.discarded.content": "تم تجاهل تجاهلك. ", + + // "collection.edit.tabs.source.notifications.discarded.content": "Your changes were discarded. To reinstate your changes click the 'Undo' button", + "collection.edit.tabs.source.notifications.discarded.content": "تم تجاهل تغييراتك. لإعادة تعيين تغييراتك قم النقر على زر 'تراجع'", + + // "collection.edit.tabs.source.notifications.discarded.title": "Changes discarded", "collection.edit.tabs.source.notifications.discarded.title": "تم تجاهل التغييرات", - "collection.edit.tabs.source.notifications.invalid.content": "لم يتم الحفاظ على جديدك. ", - "collection.edit.tabs.source.notifications.invalid.title": "دياداتا غير صالحة", - "collection.edit.tabs.source.notifications.saved.content": "تم حفظ تفاصيلك على مصدر محتوى هذه الرسالة.", + + // "collection.edit.tabs.source.notifications.invalid.content": "Your changes were not saved. Please make sure all fields are valid before you save.", + "collection.edit.tabs.source.notifications.invalid.content": "لم يتم حفظ تغييراتك. يرجى التأكد من صحة كل الحقول قبل الحفظ.", + + // "collection.edit.tabs.source.notifications.invalid.title": "Metadata invalid", + "collection.edit.tabs.source.notifications.invalid.title": "الميتاداتا غير صالحة", + + // "collection.edit.tabs.source.notifications.saved.content": "Your changes to this collection's content source were saved.", + "collection.edit.tabs.source.notifications.saved.content": "تم حفظ تغييراتك على مصدر محتوى هذه الحاوية.", + + // "collection.edit.tabs.source.notifications.saved.title": "Content Source saved", "collection.edit.tabs.source.notifications.saved.title": "تم حفظ مصدر المحتوى", - "collection.edit.tabs.source.title": "تحرير - مصدر المحتوى", + + // "collection.edit.tabs.source.title": "Collection Edit - Content Source", + "collection.edit.tabs.source.title": "تحرير الحاوية - مصدر المحتوى", + + // "collection.edit.template.add-button": "Add", "collection.edit.template.add-button": "إضافة", + + // "collection.edit.template.breadcrumbs": "Item template", "collection.edit.template.breadcrumbs": "قالب المادة", + + // "collection.edit.template.cancel": "Cancel", "collection.edit.template.cancel": "إلغاء", + + // "collection.edit.template.delete-button": "Delete", "collection.edit.template.delete-button": "حذف", + + // "collection.edit.template.edit-button": "Edit", "collection.edit.template.edit-button": "تحرير", - "collection.edit.template.error": "حدث خطأ أثناء حذف التصميم الإلكتروني", - "collection.edit.template.head": "تحرير قالب القالب للعباوية \"{{ collection }}\"", - "collection.edit.template.label": "قالب", - "collection.edit.template.loading": "جاري تحميل التصميم المعماري...", - "collection.edit.template.notifications.delete.error": "فشل في حذف قالب المادة", - "collection.edit.template.notifications.delete.success": "تم حذف القالب الفعال", - "collection.edit.template.title": "تحرير النموذج على موقع الكتروني", - "collection.form.abstract": "وصف قصير", - "collection.form.description": "نص استعدادي (HTML)", - "collection.form.errors.title.required": "يرجى الإدخال اسم العلبة", - "collection.form.license": "com", + + // "collection.edit.template.error": "An error occurred retrieving the template item", + "collection.edit.template.error": "حدث خطأ أثناء استرداد عنصر القالب", + + // "collection.edit.template.head": "Edit Template Item for Collection \"{{ collection }}\"", + "collection.edit.template.head": "تحرير عنصر القالب للحاوية \"{{ collection }}\"", + + // "collection.edit.template.label": "Template item", + "collection.edit.template.label": "عنصر القالب", + + // "collection.edit.template.loading": "Loading template item...", + "collection.edit.template.loading": "جاري تحميل عنصر القالب...", + + // "collection.edit.template.notifications.delete.error": "Failed to delete the item template", + "collection.edit.template.notifications.delete.error": "فشل حذف قالب المادة", + + // "collection.edit.template.notifications.delete.success": "Successfully deleted the item template", + "collection.edit.template.notifications.delete.success": "تم حذف قالب المادة بنجاح", + + // "collection.edit.template.title": "Edit Template Item", + "collection.edit.template.title": "تحرير عنصر القالب", + + // "collection.form.abstract": "Short Description", + "collection.form.abstract": "وصف مختصر", + + // "collection.form.description": "Introductory text (HTML)", + "collection.form.description": "نص تمهيدي (HTML)", + + // "collection.form.errors.title.required": "Please enter a collection name", + "collection.form.errors.title.required": "يرجى إدخال اسم الحاوية", + + // "collection.form.license": "License", + "collection.form.license": "الترخيص", + + // "collection.form.provenance": "Provenance", "collection.form.provenance": "المنشأ", + + // "collection.form.rights": "Copyright text (HTML)", "collection.form.rights": "نص حقوق النشر (HTML)", + + // "collection.form.tableofcontents": "News (HTML)", "collection.form.tableofcontents": "الأخبار (HTML)", + + // "collection.form.title": "Name", "collection.form.title": "الاسم", + + // "collection.form.entityType": "Entity Type", "collection.form.entityType": "نوع الكينونة", - "collection.listelement.badge": "ابدأ", - "collection.logo": "شعار تجاري", - "collection.page.browse.search.head": "يبحث", - "collection.page.edit": "تحرير هذه الجزئية", - "collection.page.handle": "URI الجديد لهذه الكائنات", - "collection.page.license": "com", + + // "collection.listelement.badge": "Collection", + "collection.listelement.badge": "الحاوية", + + // "collection.logo": "Collection logo", + "collection.logo": "شعار الحاوية", + + // "collection.page.browse.search.head": "Search", + // TODO New key - Add a translation + "collection.page.browse.search.head": "Search", + + // "collection.page.edit": "Edit this collection", + "collection.page.edit": "تحرير هذه الحاوية", + + // "collection.page.handle": "Permanent URI for this collection", + "collection.page.handle": "URI الدائم لهذه الحاوية", + + // "collection.page.license": "License", + "collection.page.license": "الترخيص", + + // "collection.page.news": "News", "collection.page.news": "الأخبار", - "collection.search.results.head": "نتائج البحث", - "collection.select.confirm": "بالتأكيد", - "collection.select.empty": "لا يوجد شيء للعرض", - "collection.select.table.selected": "محدد المعالم", - "collection.select.table.select": "تحديد الحاوية", - "collection.select.table.deselect": "إلغاء تحديد الحاوية", - "collection.select.table.title": "عنوان العنوان", - "collection.source.controls.head": "إعدادات التحكم في", - "collection.source.controls.test.submit.error": "حدث خطأ ما أثناء بدء الاختبار", - "collection.source.controls.test.failed": "فشل العناصر المكونة لها", - "collection.source.controls.test.completed": "كلمات بمعنى: أدى إلى النهاية", - "collection.source.controls.test.submit": "تم اختبار التهيئة", + + // "collection.search.results.head": "Search Results", + // TODO New key - Add a translation + "collection.search.results.head": "Search Results", + + // "collection.select.confirm": "Confirm selected", + "collection.select.confirm": "تأكيد المحدد", + + // "collection.select.empty": "No collections to show", + "collection.select.empty": "لا توجد حاويات للعرض", + + // "collection.select.table.selected": "Selected collections", + "collection.select.table.selected": "الحاويات المحددة", + + // "collection.select.table.select": "Select collection", + "collection.select.table.select": "تحديد حاوية", + + // "collection.select.table.deselect": "Deselect collection", + "collection.select.table.deselect": "إلغاء تحديد حاوية", + + // "collection.select.table.title": "Title", + "collection.select.table.title": "العنوان", + + // "collection.source.controls.head": "Harvest Controls", + "collection.source.controls.head": "إعدادات التحكم في الحصاد", + + // "collection.source.controls.test.submit.error": "Something went wrong with initiating the testing of the settings", + "collection.source.controls.test.submit.error": "حدث خطأ ما أثناء بدء اختبار الإعدادات", + + // "collection.source.controls.test.failed": "The script to test the settings has failed", + "collection.source.controls.test.failed": "فشل البرنامج النصي لاختبار الإعدادات", + + // "collection.source.controls.test.completed": "The script to test the settings has successfully finished", + "collection.source.controls.test.completed": "انتهى البرنامج النصي لاختبار الإعدادات بنجاح", + + // "collection.source.controls.test.submit": "Test configuration", + "collection.source.controls.test.submit": "اختبار التهيئة", + + // "collection.source.controls.test.running": "Testing configuration...", "collection.source.controls.test.running": "جاري اختبار التهيئة...", - "collection.source.controls.import.submit.success": "تم البدء بالتنشيط الفعال", + + // "collection.source.controls.import.submit.success": "The import has been successfully initiated", + "collection.source.controls.import.submit.success": "تم بدء الاستيراد بنجاح", + + // "collection.source.controls.import.submit.error": "Something went wrong with initiating the import", "collection.source.controls.import.submit.error": "حدث خطأ ما أثناء بدء الاستيراد", + + // "collection.source.controls.import.submit": "Import now", "collection.source.controls.import.submit": "استيراد الآن", + + // "collection.source.controls.import.running": "Importing...", "collection.source.controls.import.running": "جاري الاستيراد...", + + // "collection.source.controls.import.failed": "An error occurred during the import", "collection.source.controls.import.failed": "حدث خطأ أثناء الاستيراد", + + // "collection.source.controls.import.completed": "The import completed", "collection.source.controls.import.completed": "اكتمل الاستيراد", - "collection.source.controls.reset.submit.success": "تم البدء في البدء في المستقبل البعيد للاستيراد الفعال", - "collection.source.controls.reset.submit.error": "حدث خطأ ما أثناء البدء في إعادة الاستيراد", - "collection.source.controls.reset.failed": "حدث خطأ أثناء إعادة الاستيراد", - "collection.source.controls.reset.completed": "اكتملت العملية المتعلقة بإعادة الاستيراد", - "collection.source.controls.reset.submit": "أعد تعيينه لإعادة الاستيراد", - "collection.source.controls.reset.running": "جاري إعادة المركز للاستيراد...", - "collection.source.controls.harvest.status": "حالة:", - "collection.source.controls.harvest.start": "وقت البدء:", - "collection.source.controls.harvest.last": "تم آخر مرة:", - "collection.source.controls.harvest.message": "معلومات هناك:", - "collection.source.controls.harvest.no-information": "غير محتمل", - "collection.source.update.notifications.error.content": "تم اختبارها ولم لا تعمل ك.", + + // "collection.source.controls.reset.submit.success": "The reset and reimport has been successfully initiated", + "collection.source.controls.reset.submit.success": "تم بدء عملية إعادة التعيين وإعادة الاستيراد بنجاح", + + // "collection.source.controls.reset.submit.error": "Something went wrong with initiating the reset and reimport", + "collection.source.controls.reset.submit.error": "حدث خطأ ما أثناء بدء إعادة التعيين وإعادة الاستيراد", + + // "collection.source.controls.reset.failed": "An error occurred during the reset and reimport", + "collection.source.controls.reset.failed": "حدث خطأ أثناء إعادة التعيين وإعادة الاستيراد", + + // "collection.source.controls.reset.completed": "The reset and reimport completed", + "collection.source.controls.reset.completed": "اكتملت عملية إعادة التعيين وإعادة الاستيراد", + + // "collection.source.controls.reset.submit": "Reset and reimport", + "collection.source.controls.reset.submit": "إعادة تعيين وإعادة استيراد", + + // "collection.source.controls.reset.running": "Resetting and reimporting...", + "collection.source.controls.reset.running": "جاري إعادة التعيين وإعادة الاستيراد...", + + // "collection.source.controls.harvest.status": "Harvest status:", + "collection.source.controls.harvest.status": "حالة الحصاد:", + + // "collection.source.controls.harvest.start": "Harvest start time:", + "collection.source.controls.harvest.start": "وقت بدء الحصاد:", + + // "collection.source.controls.harvest.last": "Last time harvested:", + "collection.source.controls.harvest.last": "آخر مرة تم الحصاد:", + + // "collection.source.controls.harvest.message": "Harvest info:", + "collection.source.controls.harvest.message": "معلومات الحصاد:", + + // "collection.source.controls.harvest.no-information": "N/A", + "collection.source.controls.harvest.no-information": "غير قابل للتطبيق", + + // "collection.source.update.notifications.error.content": "The provided settings have been tested and didn't work.", + "collection.source.update.notifications.error.content": "تم اختبار الإعدادات المتوفرة ولم تعملk.", + + // "collection.source.update.notifications.error.title": "Server Error", "collection.source.update.notifications.error.title": "خطأ في الخادم", - "communityList.breadcrumbs": "اجمعها", - "communityList.tabTitle": "اجمعها", - "communityList.title": "اجمعها", + + // "communityList.breadcrumbs": "Community List", + "communityList.breadcrumbs": "قائمة المجتمعات", + + // "communityList.tabTitle": "Community List", + "communityList.tabTitle": "قائمة المجتمعات", + + // "communityList.title": "List of Communities", + "communityList.title": "قائمة المجتمعات", + + // "communityList.showMore": "Show More", "communityList.showMore": "عرض المزيد", - "communityList.expand": "الأوقات {{ name }}", - "communityList.collapse": "طيء {{ name }}", - "community.browse.logo": "تم الحصول على معلومات حول شعار المجتمع", - "community.subcoms-cols.breadcrumbs": "المجتمعات الفرعية والمجموعات", + + // "communityList.expand": "Expand {{ name }}", + "communityList.expand": "توسيع {{ name }}", + + // "communityList.collapse": "Collapse {{ name }}", + "communityList.collapse": "طي {{ name }}", + + // "community.browse.logo": "Browse for a community logo", + "community.browse.logo": "استعراض للحصول على شعار المجتمع", + + // "community.subcoms-cols.breadcrumbs": "Subcommunities and Collections", + // TODO New key - Add a translation + "community.subcoms-cols.breadcrumbs": "Subcommunities and Collections", + + // "community.create.head": "Create a Community", "community.create.head": "إنشاء مجتمع", - "community.create.notifications.success": "تم إنشاء المجتمع الفعال", - "community.create.sub-head": "إنشاء مجتمع فرعي متاح {{ parent }}", + + // "community.create.notifications.success": "Successfully created the Community", + "community.create.notifications.success": "تم إنشاء المجتمع بنجاح", + + // "community.create.sub-head": "Create a Sub-Community for Community {{ parent }}", + "community.create.sub-head": "إنشاء مجتمع فرعي للمجتمع {{ parent }}", + + // "community.curate.header": "Curate Community: {{community}}", "community.curate.header": "أكرتة المجتمع: {{community}}", + + // "community.delete.cancel": "Cancel", "community.delete.cancel": "إلغاء", - "community.delete.confirm": "بالتأكيد", + + // "community.delete.confirm": "Confirm", + "community.delete.confirm": "تأكيد", + + // "community.delete.processing": "Deleting...", "community.delete.processing": "جاري الحذف...", + + // "community.delete.head": "Delete Community", "community.delete.head": "حذف المجتمع", - "community.delete.notification.fail": "عذرًا لحذف المجتمع", - "community.delete.notification.success": "تم حذف المجتمع الفعال", + + // "community.delete.notification.fail": "Community could not be deleted", + "community.delete.notification.fail": "تعذر حذف المجتمع", + + // "community.delete.notification.success": "Successfully deleted community", + "community.delete.notification.success": "تم حذف المجتمع بنجاح", + + // "community.delete.text": "Are you sure you want to delete community \"{{ dso }}\"", "community.delete.text": "هل أنت متأكد من أنك تريد حذف المجتمع \"{{ dso }}\"", + + // "community.edit.delete": "Delete this community", "community.edit.delete": "حذف هذا المجتمع", + + // "community.edit.head": "Edit Community", "community.edit.head": "تحرير المجتمع", + + // "community.edit.breadcrumbs": "Edit Community", "community.edit.breadcrumbs": "تحرير المجتمع", + + // "community.edit.logo.delete.title": "Delete logo", "community.edit.logo.delete.title": "حذف الشعار", - "community.edit.logo.delete-undo.title": "السماء عن الحذف", + + // "community.edit.logo.delete-undo.title": "Undo delete", + "community.edit.logo.delete-undo.title": "التراجع عن الحذف", + + // "community.edit.logo.label": "Community logo", "community.edit.logo.label": "شعار المجتمع", - "community.edit.logo.notifications.add.error": "فشل تحميل شعار المجتمع. ", - "community.edit.logo.notifications.add.success": "تم تحميل شعار المجتمع الفعال.", + + // "community.edit.logo.notifications.add.error": "Uploading community logo failed. Please verify the content before retrying.", + "community.edit.logo.notifications.add.error": "فشل تحميل شعار المجتمع. يرجى التحقق من المحتوى قبل إعادة المحاولة.", + + // "community.edit.logo.notifications.add.success": "Upload community logo successful.", + "community.edit.logo.notifications.add.success": "تم تحميل شعار المجتمع بنجاح.", + + // "community.edit.logo.notifications.delete.success.title": "Logo deleted", "community.edit.logo.notifications.delete.success.title": "تم حذف الشعار", - "community.edit.logo.notifications.delete.success.content": "تم حذف العنصر الفعال", + + // "community.edit.logo.notifications.delete.success.content": "Successfully deleted the community's logo", + "community.edit.logo.notifications.delete.success.content": "تم حذف شعار المجتمع بنجاح", + + // "community.edit.logo.notifications.delete.error.title": "Error deleting logo", "community.edit.logo.notifications.delete.error.title": "حدث خطأ أثناء حذف الشعار", + + // "community.edit.logo.upload": "Drop a community logo to upload", "community.edit.logo.upload": "قم بإسقاط شعار المجتمع للتحميل", - "community.edit.notifications.success": "تم تحرير المجتمع الفعال", - "community.edit.notifications.unauthorized": "ليس لديك امتيازات لهذا الغد", + + // "community.edit.notifications.success": "Successfully edited the Community", + "community.edit.notifications.success": "تم تحرير المجتمع بنجاح", + + // "community.edit.notifications.unauthorized": "You do not have privileges to make this change", + "community.edit.notifications.unauthorized": "ليس لديك امتيازات لإجراء هذا التغيير", + + // "community.edit.notifications.error": "An error occured while editing the community", "community.edit.notifications.error": "حدث خطأ أثناء تحرير المجتمع", + + // "community.edit.return": "Back", "community.edit.return": "رجوع", + + // "community.edit.tabs.curate.head": "Curate", "community.edit.tabs.curate.head": "أكرتة", - "community.edit.tabs.curate.title": "تحرير المجتمع - كورة", + + // "community.edit.tabs.curate.title": "Community Edit - Curate", + "community.edit.tabs.curate.title": "تحرير المجتمع - أكرتة", + + // "community.edit.tabs.access-control.head": "Access Control", "community.edit.tabs.access-control.head": "التحكم في الوصول", + + // "community.edit.tabs.access-control.title": "Community Edit - Access Control", "community.edit.tabs.access-control.title": "تحرير المجتمع - التحكم في الوصول", + + // "community.edit.tabs.metadata.head": "Edit Metadata", "community.edit.tabs.metadata.head": "تحرير الميتاداتا", + + // "community.edit.tabs.metadata.title": "Community Edit - Metadata", "community.edit.tabs.metadata.title": "تحرير المجتمع - الميتاداتا", - "community.edit.tabs.roles.head": "مواعيد محددة", + + // "community.edit.tabs.roles.head": "Assign Roles", + "community.edit.tabs.roles.head": "تعيين أدوار", + + // "community.edit.tabs.roles.title": "Community Edit - Roles", "community.edit.tabs.roles.title": "تحرير المجتمع - أدوار", + + // "community.edit.tabs.authorizations.head": "Authorizations", "community.edit.tabs.authorizations.head": "التصاريح", + + // "community.edit.tabs.authorizations.title": "Community Edit - Authorizations", "community.edit.tabs.authorizations.title": "تحرير المجتمع - التصاريح", + + // "community.listelement.badge": "Community", "community.listelement.badge": "مجتمع", + + // "community.logo": "Community logo", "community.logo": "شعار المجتمع", + + // "comcol-role.edit.no-group": "None", "comcol-role.edit.no-group": "لا شيء", + + // "comcol-role.edit.create": "Create", "comcol-role.edit.create": "إنشاء", + + // "comcol-role.edit.create.error.title": "Failed to create a group for the '{{ role }}' role", "comcol-role.edit.create.error.title": "فشل إنشاء مجموعة لدور '{{ role }}'", - "comcol-role.edit.restrict": "انها", + + // "comcol-role.edit.restrict": "Restrict", + "comcol-role.edit.restrict": "تقييد", + + // "comcol-role.edit.delete": "Delete", "comcol-role.edit.delete": "حذف", - "comcol-role.edit.delete.error.title": "فشل في حذف مجموعة الدور '{{ role }}'", + + // "comcol-role.edit.delete.error.title": "Failed to delete the '{{ role }}' role's group", + "comcol-role.edit.delete.error.title": "فشل حذف مجموعة الدور '{{ role }}'", + + // "comcol-role.edit.community-admin.name": "Administrators", "comcol-role.edit.community-admin.name": "المسؤولون", + + // "comcol-role.edit.collection-admin.name": "Administrators", "comcol-role.edit.collection-admin.name": "المسؤولون", - "comcol-role.edit.community-admin.description": "يمكن لمديري المجتمع إنشاء مجتمعات فرعية أو العهد، وإدارة أو تعيين المديرين المجتمعيين أو المعتمدين. ", - "comcol-role.edit.collection-admin.description": "تحديد مديري يبدأ من البدء في المواد إلى هذه المشاركة، وتحرير ميتاداتا المادة (بعد الحضور)، بحضور (تخطيط) المواد يبدأ من الآخر إلى هذه المشاركة (ترغب في المشاركة في المشاركة).", - "comcol-role.edit.submitters.name": "شيرون", - "comcol-role.edit.submitters.description": "الأشخاص الإلكترونيين والمجموعات الذين يملكون القدرة على تقديم منتجات جديدة إلى هذه البسيطة.", - "comcol-role.edit.item_read.name": "وصول قراءة المادة الافتراضية", - "comcol-role.edit.item_read.description": "الأشخاص الإلكترونيون والمجموعات الذين يمكنهم قراءة المواد الجديدة تم تقديمها إلى هذه البسيطة. ", - "comcol-role.edit.item_read.anonymous-group": "تم تعيين القراءة الإلكترونية للمواد حاليًا إلى معرف غير معرف.", + + // "comcol-role.edit.community-admin.description": "Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).", + "comcol-role.edit.community-admin.description": "يمكن لمديري المجتمع إنشاء مجتمعات فرعية أو حاويات، وإدارة أو تعيين الإدارة لتلك المجتمعات الفرعية أو الحاويات. بالإضافة إلى ذلك، يقومون بتقرير من يمكنه تقديم المواد إلى أي حاويات فرعية، وتحرير ميتاداتا المادة (بعد التقديم)، وإضافة (تخطيط) المواد الحالية من الحاويات الأخرى (تخضع للتصريح).", + + // "comcol-role.edit.collection-admin.description": "Collection administrators decide who can submit items to the collection, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization for that collection).", + "comcol-role.edit.collection-admin.description": "يقرر مديري الحاوية من يمكنه تقديم المواد إلى الحاوية، وتحريرميتاداتا المادة (بعد التقديم)، وإضافة (تخطيط) المواد الحاوية من الحاويات الأخرى إلى هذه الحاوية (تخضع للتصريح لتلك الحاوية).", + + // "comcol-role.edit.submitters.name": "Submitters", + "comcol-role.edit.submitters.name": "المقدمون", + + // "comcol-role.edit.submitters.description": "The E-People and Groups that have permission to submit new items to this collection.", + "comcol-role.edit.submitters.description": "الأشخاص الإلكترونيين والمجموعات الذين يملكون صلاحية تقديم مواد جديدة إلى هذه الحاوية.", + + // "comcol-role.edit.item_read.name": "Default item read access", + "comcol-role.edit.item_read.name": "وصول قراءة المادة الافتراضي", + + // "comcol-role.edit.item_read.description": "E-People and Groups that can read new items submitted to this collection. Changes to this role are not retroactive. Existing items in the system will still be viewable by those who had read access at the time of their addition.", + "comcol-role.edit.item_read.description": "الأشخاص الإلكترونيون والمجموعات الذين يمكنهم قراءة المواد الجديدة التي تم تقديمها إلى هذه الحاوية. التغييرات على هذا الدور ليست بأثر رجعي. ستظل المواد الحالية الموجودة في النظام قابلة للعرض بواسطة أولئك الذين يملكون الوصول للقراءة في وقت إضافتها.", + + // "comcol-role.edit.item_read.anonymous-group": "Default read for incoming items is currently set to Anonymous.", + "comcol-role.edit.item_read.anonymous-group": "تم تعيين القراءة الافتراضية للمواد الواردة حاليًا إلى غير معرف الهوية.", + + // "comcol-role.edit.bitstream_read.name": "Default bitstream read access", "comcol-role.edit.bitstream_read.name": "وصول قراءة تدفق البت الافتراضي", - "comcol-role.edit.bitstream_read.description": "يمكن لمديري المجتمع إنشاء مجتمعات فرعية أو العهد، وإدارة أو تعيين المديرين المجتمعيين أو المعتمدين. ", - "comcol-role.edit.bitstream_read.anonymous-group": "تم تعيين القراءة الافتراضية لتدفقات البت حاليا إلى غير معرف الهوية.", + + // "comcol-role.edit.bitstream_read.description": "E-People and Groups that can read new bitstreams submitted to this collection. Changes to this role are not retroactive. Existing bitstreams in the system will still be viewable by those who had read access at the time of their addition.", + "comcol-role.edit.bitstream_read.description": "يمكن لمديري المجتمع إنشاء مجتمعات فرعية أو حاويات، وإدارة أو تعيين الإدارة لتلك المجتمعات الفرعية أو الحاويات. بالإضافة إلى ذلك، يقومون بتقرير من يمكنه تقديم المواد إلى أي حاويات فرعية، وتحرير ميتاداتا المادة (بعد التقديم)، وإضافة (تخطيط) المواد الحالية من الحاويات الأخرى (تخضع للتصريح).", + + // "comcol-role.edit.bitstream_read.anonymous-group": "Default read for incoming bitstreams is currently set to Anonymous.", + "comcol-role.edit.bitstream_read.anonymous-group": "تم تعيين القراءة الافتراضية لتدفقات البت الواردة حاليًا إلى غير معرف الهوية.", + + // "comcol-role.edit.editor.name": "Editors", "comcol-role.edit.editor.name": "المحررون", - "comcol-role.edit.editor.description": "يمكن للمحررون تحرير ميتاداتا للعروض المقدمة، ثم قبولها أو رفضها.", + + // "comcol-role.edit.editor.description": "Editors are able to edit the metadata of incoming submissions, and then accept or reject them.", + "comcol-role.edit.editor.description": "يمكن للمحررون تحرير ميتاداتا التقديمات الواردة، ثم قبولها أو رفضها.", + + // "comcol-role.edit.finaleditor.name": "Final editors", "comcol-role.edit.finaleditor.name": "المحررون النهائيون", - "comcol-role.edit.finaleditor.description": "يمكن للمحرر النهائي لتحرير ميتاداتا التقديمات المقدمة، لكن لا يمكنهم رفضها.", + + // "comcol-role.edit.finaleditor.description": "Final editors are able to edit the metadata of incoming submissions, but will not be able to reject them.", + "comcol-role.edit.finaleditor.description": "يمكن للمحررون النهائيون تحرير ميتاداتا التقديمات الواردة، لكن لا يمكنهم رفضها.", + + // "comcol-role.edit.reviewer.name": "Reviewers", "comcol-role.edit.reviewer.name": "المراجعون", - "comcol-role.edit.reviewer.description": "يمكن للمراجعين قبول أو رفض التقديم. ", - "comcol-role.edit.scorereviewers.name": "نقاط الضعفاء", - "comcol-role.edit.scorereviewers.description": "يمكن للمراجعين أن ترسل المشاركات إلينا، وهذا ما يحدد ما إذا كان الرفض أم لا.", - "community.form.abstract": "وصف قصير", - "community.form.description": "نص استعدادي (HTML)", - "community.form.errors.title.required": "الرجاء الاتصال باسم مجتمع", + + // "comcol-role.edit.reviewer.description": "Reviewers are able to accept or reject incoming submissions. However, they are not able to edit the submission's metadata.", + "comcol-role.edit.reviewer.description": "يمكن للمراجعين قبول أو رفض التقديمات الواردة. غير أنه لا يمكنهم تحرير ميتاداتا التقديم..", + + // "comcol-role.edit.scorereviewers.name": "Score Reviewers", + "comcol-role.edit.scorereviewers.name": "نقاط المراجعين", + + // "comcol-role.edit.scorereviewers.description": "Reviewers are able to give a score to incoming submissions, this will define whether the submission will be rejected or not.", + "comcol-role.edit.scorereviewers.description": "يمكن للمراجعين منح نقاط للمشاركات الواردة، وهذا سيحدد ما إذا كان سيتم رفض التقديم أم لا.", + + // "community.form.abstract": "Short Description", + "community.form.abstract": "وصف مختصر", + + // "community.form.description": "Introductory text (HTML)", + "community.form.description": "نص تمهيدي (HTML)", + + // "community.form.errors.title.required": "Please enter a community name", + "community.form.errors.title.required": "يرجى إدخال اسم مجتمع", + + // "community.form.rights": "Copyright text (HTML)", "community.form.rights": "نص حقوق النشر (HTML)", + + // "community.form.tableofcontents": "News (HTML)", "community.form.tableofcontents": "الأخبار (HTML)", + + // "community.form.title": "Name", "community.form.title": "الاسم", + + // "community.page.edit": "Edit this community", "community.page.edit": "تحرير هذا المجتمع", - "community.page.handle": "URI الجديد لهذا المجتمع", - "community.page.license": "com", + + // "community.page.handle": "Permanent URI for this community", + "community.page.handle": "ال URI الدائم لهذا المجتمع", + + // "community.page.license": "License", + "community.page.license": "الترخيص", + + // "community.page.news": "News", "community.page.news": "الأخبار", - "community.all-lists.head": "الكونيات الحاويات", - "community.search.results.head": "نتائج البحث", - "community.sub-collection-list.head": "توفيق هذا المجتمع", + + // "community.all-lists.head": "Subcommunities and Collections", + "community.all-lists.head": "المجتمعات الفرعية والحاويات", + + // "community.search.results.head": "Search Results", + // TODO New key - Add a translation + "community.search.results.head": "Search Results", + + // "community.sub-collection-list.head": "Collections in this Community", + "community.sub-collection-list.head": "حاويات هذا المجتمع", + + // "community.sub-community-list.head": "Communities in this Community", "community.sub-community-list.head": "مجتمعات هذا المجتمع", + + // "cookies.consent.accept-all": "Accept all", "cookies.consent.accept-all": "قبول الكل", - "cookies.consent.accept-selected": "قبول البناء", - "cookies.consent.app.opt-out.description": "تم تحميل هذا التطبيق افتراضياً (لكن يمكنك اختيار)", + + // "cookies.consent.accept-selected": "Accept selected", + "cookies.consent.accept-selected": "قبول المحدد", + + // "cookies.consent.app.opt-out.description": "This app is loaded by default (but you can opt out)", + "cookies.consent.app.opt-out.description": "تم تحميل هذا التطبيق افتراضياً (لكن يمكنك الانسحاب)", + + // "cookies.consent.app.opt-out.title": "(opt-out)", "cookies.consent.app.opt-out.title": "(انسحاب)", - "cookies.consent.app.purpose": "اللحوم", - "cookies.consent.app.required.description": "هذا التطبيق مطلوب تكرارا", - "cookies.consent.app.required.title": "(مطلوب مرة أخرى)", - "cookies.consent.app.disable-all.description": "استخدم هذا الزر لتفعيل جميع الخدمات أو جونسونها.", - "cookies.consent.app.disable-all.title": "تفعيل أو تفعيل كل الخدمات", - "cookies.consent.update": "لقد قمت بتغيير بعض التغييرات منذ الآن، يرجى تحديث موافقتك.", + + // "cookies.consent.app.purpose": "purpose", + "cookies.consent.app.purpose": "الغرض", + + // "cookies.consent.app.required.description": "This application is always required", + "cookies.consent.app.required.description": "هذا التطبيق مطلوب دائماً", + + // "cookies.consent.app.required.title": "(always required)", + "cookies.consent.app.required.title": "(مطلوب دائماً)", + + // "cookies.consent.app.disable-all.description": "Use this switch to enable or disable all services.", + "cookies.consent.app.disable-all.description": "استخدم هذا التبديل لتفعيل كل الخدمات أو تعطيلها.", + + // "cookies.consent.app.disable-all.title": "Enable or disable all services", + "cookies.consent.app.disable-all.title": "تفعيل أو تعطيل كل الخدمات", + + // "cookies.consent.update": "There were changes since your last visit, please update your consent.", + "cookies.consent.update": "لقد حدثت بعض التغييرات منذ زيارتك الأخيرة، يرجى تحديث موافقتك.", + + // "cookies.consent.close": "Close", "cookies.consent.close": "إغلاق", - "cookies.consent.decline": "الرفض", + + // "cookies.consent.decline": "Decline", + "cookies.consent.decline": "رفض", + + // "cookies.consent.ok": "That's ok", "cookies.consent.ok": "لا بأس", + + // "cookies.consent.save": "Save", "cookies.consent.save": "حفظ", + + // "cookies.consent.content-notice.title": "Cookie Consent", "cookies.consent.content-notice.title": "الموافقة على ملفات تعريف الارتباط", - "cookies.consent.content-notice.description": "لإصلاح بجمع ومعالجة معلوماتك الشخصية للأغراض التالية: الاستثناء، والتفضيلات، والاستخلاص، والإحصاء.
لمعرفة المزيد، يرجى قراءة {privacyPolicy}.", - "cookies.consent.content-notice.description.no-privacy": "لإصلاح بجمع ومعالجة معلوماتك الشخصية للأغراض التالية: الاستثناء، والتفضيلات، والاستخلاص، والإحصاء.", + + // "cookies.consent.content-notice.description": "We collect and process your personal information for the following purposes: Authentication, Preferences, Acknowledgement and Statistics.
To learn more, please read our {privacyPolicy}.", + "cookies.consent.content-notice.description": "نقوم بجمع ومعالجة معلوماتك الشخصية للأغراض التالية: الاستيثاق، والتفضيلات، والإقرار، والإحصائيات.
لمعرفة المزيد، يرجى قراءة {privacyPolicy}.", + + // "cookies.consent.content-notice.description.no-privacy": "We collect and process your personal information for the following purposes: Authentication, Preferences, Acknowledgement and Statistics.", + "cookies.consent.content-notice.description.no-privacy": "نقوم بجمع ومعالجة معلوماتك الشخصية للأغراض التالية: الاستيثاق، والتفضيلات، والإقرار، والإحصائيات.", + + // "cookies.consent.content-notice.learnMore": "Customize", "cookies.consent.content-notice.learnMore": "تخصيص", - "cookies.consent.content-modal.description": "من هنا يمكنك رؤية وتخصيص المعلومات التي تجمعها عنك.", + + // "cookies.consent.content-modal.description": "Here you can see and customize the information that we collect about you.", + "cookies.consent.content-modal.description": "من هنا يمكنك رؤية وتخصيص المعلومات التي نقوم بجمعها عنك.", + + // "cookies.consent.content-modal.privacy-policy.name": "privacy policy", "cookies.consent.content-modal.privacy-policy.name": "سياسة الخصوصية", + + // "cookies.consent.content-modal.privacy-policy.text": "To learn more, please read our {privacyPolicy}.", "cookies.consent.content-modal.privacy-policy.text": "لمعرفة المزيد، يرجى قراءة {privacyPolicy}.", - "cookies.consent.content-modal.title": "المعلومات التي بجمعها", + + // "cookies.consent.content-modal.title": "Information that we collect", + "cookies.consent.content-modal.title": "المعلومات التي نقوم بجمعها", + + // "cookies.consent.content-modal.services": "services", "cookies.consent.content-modal.services": "خدمات", + + // "cookies.consent.content-modal.service": "service", "cookies.consent.content-modal.service": "خدمة", + + // "cookies.consent.app.title.authentication": "Authentication", "cookies.consent.app.title.authentication": "استيثاق", + + // "cookies.consent.app.description.authentication": "Required for signing you in", "cookies.consent.app.description.authentication": "مطلوب لتسجيل دخولك", + + // "cookies.consent.app.title.preferences": "Preferences", "cookies.consent.app.title.preferences": "التفضيلات", - "cookies.consent.app.description.preferences": "مطلوب تحسين تفضيلاتك", - "cookies.consent.app.title.acknowledgement": "تأهيل", - "cookies.consent.app.description.acknowledgement": "مطلوب حفظك وموافقتك", + + // "cookies.consent.app.description.preferences": "Required for saving your preferences", + "cookies.consent.app.description.preferences": "مطلوب لحفظ تفضيلاتك", + + // "cookies.consent.app.title.acknowledgement": "Acknowledgement", + "cookies.consent.app.title.acknowledgement": "إقرار", + + // "cookies.consent.app.description.acknowledgement": "Required for saving your acknowledgements and consents", + "cookies.consent.app.description.acknowledgement": "مطلوب لحفظ إقراراتك وموافقاتك", + + // "cookies.consent.app.title.google-analytics": "Google Analytics", "cookies.consent.app.title.google-analytics": "تحليلات جوجل", - "cookies.consent.app.description.google-analytics": "يسمح لنا بتتبع البيانات الإحصائية", + + // "cookies.consent.app.description.google-analytics": "Allows us to track statistical data", + "cookies.consent.app.description.google-analytics": "Allows us to track statistical data", + + // "cookies.consent.app.title.google-recaptcha": "Google reCaptcha", "cookies.consent.app.title.google-recaptcha": "جوجل ريكابتشا", - "cookies.consent.app.description.google-recaptcha": "نحن نستخدم خدمة google reCAPTCHA أثناء التسجيل واستعادة كلمة المرور", - "cookies.consent.purpose.functional": "فعالة", + + // "cookies.consent.app.description.google-recaptcha": "We use google reCAPTCHA service during registration and password recovery", + // TODO New key - Add a translation + "cookies.consent.app.description.google-recaptcha": "We use google reCAPTCHA service during registration and password recovery", + + // "cookies.consent.purpose.functional": "Functional", + "cookies.consent.purpose.functional": "وظيفي", + + // "cookies.consent.purpose.statistical": "Statistical", "cookies.consent.purpose.statistical": "إحصائي", - "cookies.consent.purpose.registration-password-recovery": "التسجيل و استعادة كلمة المرور", + + // "cookies.consent.purpose.registration-password-recovery": "Registration and Password recovery", + "cookies.consent.purpose.registration-password-recovery": "التسجيل واستعادة كلمة المرور", + + // "cookies.consent.purpose.sharing": "Sharing", "cookies.consent.purpose.sharing": "مشاركة", + + // "curation-task.task.citationpage.label": "Generate Citation Page", "curation-task.task.citationpage.label": "إنشاء صفحة الاقتباس", + + // "curation-task.task.checklinks.label": "Check Links in Metadata", "curation-task.task.checklinks.label": "التحقق من الروابط في الميتاداتا", + + // "curation-task.task.noop.label": "NOOP", "curation-task.task.noop.label": "لا توجد مهمة", + + // "curation-task.task.profileformats.label": "Profile Bitstream Formats", "curation-task.task.profileformats.label": "تنسيقات تدفق بت البروفايل", - "curation-task.task.requiredmetadata.label": "التحقق من الميتاداتا المطلوبة", + + // "curation-task.task.requiredmetadata.label": "Check for Required Metadata", + "curation-task.task.requiredmetadata.label": "التحقق للميتاداتا المطلوبة", + + // "curation-task.task.translate.label": "Microsoft Translator", "curation-task.task.translate.label": "مترجم ميكروسوفت", - "curation-task.task.vscan.label": "حذف الفيروسات", - "curation-task.task.registerdoi.label": "تسجيل المعرفة الرقمية", - "curation.form.task-select.label": "مهم:", + + // "curation-task.task.vscan.label": "Virus Scan", + "curation-task.task.vscan.label": "مسح الفيروسات", + + // "curation-task.task.registerdoi.label": "Register DOI", + "curation-task.task.registerdoi.label": "تسجيل معرف الكائن الرقمي", + + // "curation.form.task-select.label": "Task:", + "curation.form.task-select.label": "المهمة:", + + // "curation.form.submit": "Start", "curation.form.submit": "بدء", - "curation.form.submit.success.head": "تم بدء مهمة فعالة فعالة", - "curation.form.submit.success.content": "ستتم إعادة توجيهك إلى السجن.", - "curation.form.submit.error.head": "فشل تشغيل مهمة أخرى", + + // "curation.form.submit.success.head": "The curation task has been started successfully", + "curation.form.submit.success.head": "تم بدء مهمة الأكرتة بنجاح", + + // "curation.form.submit.success.content": "You will be redirected to the corresponding process page.", + "curation.form.submit.success.content": "ستتم إعادة توجيهك إلى صفحة العملية المقابلة.", + + // "curation.form.submit.error.head": "Running the curation task failed", + "curation.form.submit.error.head": "فشل تشغيل مهمة الأكرتة", + + // "curation.form.submit.error.content": "An error occured when trying to start the curation task.", "curation.form.submit.error.content": "حدث خطأ أثناء محاولة بدء مهمة الأكرتة.", - "curation.form.submit.error.invalid-handle": "تعذر تحديد يد هذا", - "curation.form.handle.label": "مقبض:", - "curation.form.handle.hint": "تلميح: قم برجاء زيارة [your-handle-prefix]/0 لاستخدام مهمة عبر الموقع قادرة (قد لا تدعم جميع هذه الإمكانية)", - "deny-request-copy.email.message": "عزيزي {{ recipientName }},\n{{ itemUrl }}\"({{ itemName }})، والتي قمت بتأليفها.\n\n\n{{ authorName }} <{{ authorEmail }}>", - "deny-request-copy.email.subject": "طلب نسخة من الوثيقة", + + // "curation.form.submit.error.invalid-handle": "Couldn't determine the handle for this object", + "curation.form.submit.error.invalid-handle": "تعذر تحديد هاندل هذا الكائن", + + // "curation.form.handle.label": "Handle:", + "curation.form.handle.label": "هاندل:", + + // "curation.form.handle.hint": "Hint: Enter [your-handle-prefix]/0 to run a task across entire site (not all tasks may support this capability)", + "curation.form.handle.hint": "تلميح: قم بإدخال [your-handle-prefix]/0 لتشغيل مهمة عبر الموقع بأكمله (قد لا تدعم جميع المهام هذه الإمكانية)", + + // "deny-request-copy.email.message": "Dear {{ recipientName }},\nIn response to your request I regret to inform you that it's not possible to send you a copy of the file(s) you have requested, concerning the document: \"{{ itemUrl }}\" ({{ itemName }}), of which I am an author.\n\nBest regards,\n{{ authorName }} <{{ authorEmail }}>", + "deny-request-copy.email.message": "عزيزي {{ recipientName }},\nردًا على طلبك، يؤسفني إبلاغك أنه لا يمكن إرسال نسخة من الملف الذي قمت بطلبه، فيما يتعلق بالوثيقة: \"{{ itemUrl }}\" ({{ itemName }}), والتي قمت بتأليفها.\n\nمع أطيب التحيات,\n{{ authorName }} <{{ authorEmail }}>", + + // "deny-request-copy.email.subject": "Request copy of document", + "deny-request-copy.email.subject": "طلب نسخة من وثيقة", + + // "deny-request-copy.error": "An error occurred", "deny-request-copy.error": "لقد حدث خطأ", - "deny-request-copy.header": "طلب طلب نسخة أوكلاند", + + // "deny-request-copy.header": "Deny document copy request", + "deny-request-copy.header": "رفض طلب نسخ الوثيقة", + + // "deny-request-copy.intro": "This message will be sent to the applicant of the request", "deny-request-copy.intro": "سيتم إرسال هذه الرسالة إلى مقدم الطلب", - "deny-request-copy.success": "تم الرفض للطلب الفعال", + + // "deny-request-copy.success": "Successfully denied item request", + "deny-request-copy.success": "تم رفض طلب المادة بنجاح", + + // "dso.name.untitled": "Untitled", "dso.name.untitled": "بدون عنوان", + + // "dso.name.unnamed": "Unnamed", "dso.name.unnamed": "بدون اسم", + + // "dso-selector.create.collection.head": "New collection", "dso-selector.create.collection.head": "حاوية جديدة", + + // "dso-selector.create.collection.sub-level": "Create a new collection in", "dso-selector.create.collection.sub-level": "إنشاء حاوية جديدة في", + + // "dso-selector.create.community.head": "New community", "dso-selector.create.community.head": "مجتمع جديد", + + // "dso-selector.create.community.or-divider": "or", "dso-selector.create.community.or-divider": "أو", + + // "dso-selector.create.community.sub-level": "Create a new community in", "dso-selector.create.community.sub-level": "إنشاء مجتمع جديد في", + + // "dso-selector.create.community.top-level": "Create a new top-level community", "dso-selector.create.community.top-level": "إنشاء مجتمع مستوى أعلى جديد", + + // "dso-selector.create.item.head": "New item", "dso-selector.create.item.head": "مادة جديدة", + + // "dso-selector.create.item.sub-level": "Create a new item in", "dso-selector.create.item.sub-level": "إنشاء مادة جديدة في", + + // "dso-selector.create.submission.head": "New submission", "dso-selector.create.submission.head": "تقديم جديد", - "dso-selector.edit.collection.head": "تحرير", + + // "dso-selector.edit.collection.head": "Edit collection", + "dso-selector.edit.collection.head": "تحرير الحاوية", + + // "dso-selector.edit.community.head": "Edit community", "dso-selector.edit.community.head": "تحرير المجتمع", + + // "dso-selector.edit.item.head": "Edit item", "dso-selector.edit.item.head": "تحرير المادة", - "dso-selector.error.title": "حدث خطأ أثناء البحث عنه {{ type }}", - "dso-selector.export-metadata.dspaceobject.head": "قم باستيراد بيانات ميتا من", - "dso-selector.export-batch.dspaceobject.head": "قم باستيراد دفعة (ZIP) من", - "dso-selector.import-batch.dspaceobject.head": "قم باستيراد دفعة من", - "dso-selector.no-results": "لم يتم العثور عليها {{ type }}", - "dso-selector.placeholder": "بحثت عن {{ type }}", - "dso-selector.select.collection.head": "تحديد الحاوية", + + // "dso-selector.error.title": "An error occurred searching for a {{ type }}", + "dso-selector.error.title": "حدث خطأ أثناء البحث عن {{ type }}", + + // "dso-selector.export-metadata.dspaceobject.head": "Export metadata from", + "dso-selector.export-metadata.dspaceobject.head": "استيراد ميتاداتا من", + + // "dso-selector.export-batch.dspaceobject.head": "Export Batch (ZIP) from", + "dso-selector.export-batch.dspaceobject.head": "استيراد دفعة (ZIP) من", + + // "dso-selector.import-batch.dspaceobject.head": "Import batch from", + "dso-selector.import-batch.dspaceobject.head": "استيراد دفعة من", + + // "dso-selector.no-results": "No {{ type }} found", + "dso-selector.no-results": "لم يتم العثور على {{ type }}", + + // "dso-selector.placeholder": "Search for a {{ type }}", + "dso-selector.placeholder": "بحث عن {{ type }}", + + // "dso-selector.select.collection.head": "Select a collection", + "dso-selector.select.collection.head": "تحديد حاوية", + + // "dso-selector.set-scope.community.head": "Select a search scope", "dso-selector.set-scope.community.head": "تحديد نطاق البحث", + + // "dso-selector.set-scope.community.button": "Search all of DSpace", "dso-selector.set-scope.community.button": "بحث دي سبيس بالكامل", + + // "dso-selector.set-scope.community.or-divider": "or", "dso-selector.set-scope.community.or-divider": "أو", - "dso-selector.set-scope.community.input-header": "ابحث عن حاوية أو مجتمع", + + // "dso-selector.set-scope.community.input-header": "Search for a community or collection", + "dso-selector.set-scope.community.input-header": "البحث عن حاوية أو مجتمع", + + // "dso-selector.claim.item.head": "Profile tips", "dso-selector.claim.item.head": "نصائح الملف الشخصي", - "dso-selector.claim.item.body": "هذه هي الملفات الشخصية التي قد تكون ذات صلة بك. ", + + // "dso-selector.claim.item.body": "These are existing profiles that may be related to you. If you recognize yourself in one of these profiles, select it and on the detail page, among the options, choose to claim it. Otherwise you can create a new profile from scratch using the button below.", + "dso-selector.claim.item.body": "هذه هي الملفات الشخصية الموجودة التي قد تكون ذات صلة بك. إذا تعرفت على نفسك في أحد هذه الملفات الشخصية، قم بتحديده وفي صفحة التفاصيل، من بين الخيارات، اختر المطالبة به. بخلاف ذلك، يمكنك إنشاء ملف شخصي جديد من البداية باستخدام الزر أدناه.", + + // "dso-selector.claim.item.not-mine-label": "None of these are mine", "dso-selector.claim.item.not-mine-label": "لا يعود أي من هذا لي", + + // "dso-selector.claim.item.create-from-scratch": "Create a new one", "dso-selector.claim.item.create-from-scratch": "إنشاء واحد جديد", - "dso-selector.results-could-not-be-retrieved": "حدث خطأ ما، يرجى تحديث مرة أخرى ↻", + + // "dso-selector.results-could-not-be-retrieved": "Something went wrong, please refresh again ↻", + "dso-selector.results-could-not-be-retrieved": "حدث خطأ ما، يرجى التحديث مرة أخرى ↻", + + // "supervision-group-selector.header": "Supervision Group Selector", "supervision-group-selector.header": "محدد مجموعة الإشراف", - "supervision-group-selector.select.type-of-order.label": "حدد نوع الصف", + + // "supervision-group-selector.select.type-of-order.label": "Select a type of Order", + "supervision-group-selector.select.type-of-order.label": "حدد نوع الرتبة", + + // "supervision-group-selector.select.type-of-order.option.none": "NONE", "supervision-group-selector.select.type-of-order.option.none": "لا شيء", + + // "supervision-group-selector.select.type-of-order.option.editor": "EDITOR", "supervision-group-selector.select.type-of-order.option.editor": "محرر", - "supervision-group-selector.select.type-of-order.option.observer": "انتبه", - "supervision-group-selector.select.group.label": "حدد المجموعة", + + // "supervision-group-selector.select.type-of-order.option.observer": "OBSERVER", + "supervision-group-selector.select.type-of-order.option.observer": "مراقب", + + // "supervision-group-selector.select.group.label": "Select a Group", + "supervision-group-selector.select.group.label": "حدد مجموعة", + + // "supervision-group-selector.button.cancel": "Cancel", "supervision-group-selector.button.cancel": "إلغاء", + + // "supervision-group-selector.button.save": "Save", "supervision-group-selector.button.save": "حفظ", - "supervision-group-selector.select.type-of-order.error": "يرجى تحديد نوع الطائرة", - "supervision-group-selector.select.group.error": "يرجى تحديد المجموعة", - "supervision-group-selector.notification.create.success.title": "تم إنشاء تشكيلة متنوعة فعالة {{ name }}", + + // "supervision-group-selector.select.type-of-order.error": "Please select a type of order", + "supervision-group-selector.select.type-of-order.error": "يرجى تحديد نوع الرتبة", + + // "supervision-group-selector.select.group.error": "Please select a group", + "supervision-group-selector.select.group.error": "يرجى تحديد مجموعة", + + // "supervision-group-selector.notification.create.success.title": "Successfully created supervision order for group {{ name }}", + "supervision-group-selector.notification.create.success.title": "تم إنشاء رتبة الإشراف للمجموعة بنجاح {{ name }}", + + // "supervision-group-selector.notification.create.failure.title": "Error", "supervision-group-selector.notification.create.failure.title": "خطأ", - "supervision-group-selector.notification.create.already-existing": "هناك بالفعل خيار البحث عن هذه المواد المحددة", + + // "supervision-group-selector.notification.create.already-existing": "A supervision order already exists on this item for selected group", + "supervision-group-selector.notification.create.already-existing": "يوجد بالفعل رتبة إشراف على هذه المادة للمجموعة المحددة", + + // "confirmation-modal.export-metadata.header": "Export metadata for {{ dsoName }}", "confirmation-modal.export-metadata.header": "تصدير الميتاداتا لـ {{ dsoName }}", + + // "confirmation-modal.export-metadata.info": "Are you sure you want to export metadata for {{ dsoName }}", "confirmation-modal.export-metadata.info": "هل أنت متأكد أنك تريد تصدير الميتاداتا لـ {{ dsoName }}", + + // "confirmation-modal.export-metadata.cancel": "Cancel", "confirmation-modal.export-metadata.cancel": "إلغاء", + + // "confirmation-modal.export-metadata.confirm": "Export", "confirmation-modal.export-metadata.confirm": "تصدير", + + // "confirmation-modal.export-batch.header": "Export batch (ZIP) for {{ dsoName }}", "confirmation-modal.export-batch.header": "تصدير دفعة (ZIP) لـ {{ dsoName }}", + + // "confirmation-modal.export-batch.info": "Are you sure you want to export batch (ZIP) for {{ dsoName }}", "confirmation-modal.export-batch.info": "هل أنت متأكد أنك تريد تصدير دفعة (ZIP) لـ {{ dsoName }}", + + // "confirmation-modal.export-batch.cancel": "Cancel", "confirmation-modal.export-batch.cancel": "إلغاء", + + // "confirmation-modal.export-batch.confirm": "Export", "confirmation-modal.export-batch.confirm": "تصدير", + + // "confirmation-modal.delete-eperson.header": "Delete EPerson \"{{ dsoName }}\"", "confirmation-modal.delete-eperson.header": "حذف الشخص الإلكتروني \"{{ dsoName }}\"", - "confirmation-modal.delete-eperson.info": "هل أنت متأكد من أنك تريد حذف الهاتف الإلكتروني \"{{ dsoName }}\"", + + // "confirmation-modal.delete-eperson.info": "Are you sure you want to delete EPerson \"{{ dsoName }}\"", + "confirmation-modal.delete-eperson.info": "هل أنت متأكد من أنك تريد حذف الشخص الإلكتروني \"{{ dsoName }}\"", + + // "confirmation-modal.delete-eperson.cancel": "Cancel", "confirmation-modal.delete-eperson.cancel": "إلغاء", + + // "confirmation-modal.delete-eperson.confirm": "Delete", "confirmation-modal.delete-eperson.confirm": "حذف", + + // "confirmation-modal.delete-profile.header": "Delete Profile", "confirmation-modal.delete-profile.header": "حذف الملف الشخصي", - "confirmation-modal.delete-profile.info": "هل أنت متأكد من أنك تريد حذف ملفك الشخصي", + + // "confirmation-modal.delete-profile.info": "Are you sure you want to delete your profile", + "confirmation-modal.delete-profile.info": "هل أنت متأكد أنك تريد حذف ملف الشخصي الخاص بك", + + // "confirmation-modal.delete-profile.cancel": "Cancel", "confirmation-modal.delete-profile.cancel": "إلغاء", + + // "confirmation-modal.delete-profile.confirm": "Delete", "confirmation-modal.delete-profile.confirm": "حذف", + + // "confirmation-modal.delete-subscription.header": "Delete Subscription", "confirmation-modal.delete-subscription.header": "حذف الاشتراك", + + // "confirmation-modal.delete-subscription.info": "Are you sure you want to delete subscription for \"{{ dsoName }}\"", "confirmation-modal.delete-subscription.info": "هل أنت متأكد من أنك تريد حذف الاشتراك لـ \"{{ dsoName }}\"", + + // "confirmation-modal.delete-subscription.cancel": "Cancel", "confirmation-modal.delete-subscription.cancel": "إلغاء", + + // "confirmation-modal.delete-subscription.confirm": "Delete", "confirmation-modal.delete-subscription.confirm": "حذف", - "error.bitstream": "حدث خطأ أثناء تدفق البالت", - "error.browse-by": "حدث خطأ أثناء المواد", - "error.collection": "حدث خطأ أثناء دخول", - "error.collections": "حدث خطأ أثناء فترة مقبولة", - "error.community": "حدث خطأ أثناء المجتمع", + + // "error.bitstream": "Error fetching bitstream", + "error.bitstream": "حدث خطأ أثناء جلب تدفق البت", + + // "error.browse-by": "Error fetching items", + "error.browse-by": "حدث خطأ أثناء جلب المواد", + + // "error.collection": "Error fetching collection", + "error.collection": "حدث خطأ أثناء جلب الحاوية", + + // "error.collections": "Error fetching collections", + "error.collections": "حدث خطأ أثناء جلب الحاويات", + + // "error.community": "Error fetching community", + "error.community": "حدث خطأ أثناء جلب المجتمع", + + // "error.identifier": "No item found for the identifier", "error.identifier": "لم يتم العثور على أي مادة للمعرف", + + // "error.default": "Error", "error.default": "خطأ", - "error.item": "حدث خطأ أثناء حضور المادة", - "error.items": "حدث خطأ أثناء المواد", - "error.objects": "حدث خطأ أثناء إجراء الكائنات الفضائية", - "error.recent-submissions": "حدث خطأ أثناء جلب أحدث العروض", - "error.search-results": "حدث خطأ أثناء نتائج البحث", - "error.invalid-search-query": "استعلام البحث غير صالح. بناء جملة استعلام Solr أفضل الممارسات للحصول على قراءة المعلومات حول هذا الخطأ.", - "error.sub-collections": "حدث خطأ أثناء تقديم العرض", - "error.sub-communities": "حدث خطأ أثناء النظر في الجسد", - "error.submission.sections.init-form-error": "حدث خطأ أثناء تهيئة القسم، يرجى التحقق من تهيئة نموذج العنصر الخاص بك.

", - "error.top-level-communities": "حدث خطأ خلال مجتمعات المستوى الأعلى", - "error.validation.license.notgranted": "يجب عليك أن تطلب من هذا الأمر التقديم الخاص بك. ", + + // "error.item": "Error fetching item", + "error.item": "حدث خطأ أثناء جلب المادة", + + // "error.items": "Error fetching items", + "error.items": "حدث خطأ أثناء جلب المواد", + + // "error.objects": "Error fetching objects", + "error.objects": "حدث خطأ أثناء جلب الكائنات", + + // "error.recent-submissions": "Error fetching recent submissions", + "error.recent-submissions": "حدث خطأ أثناء جلب أحدث التقديمات", + + // "error.search-results": "Error fetching search results", + "error.search-results": "حدث خطأ أثناء جلب نتائج البحث", + + // "error.invalid-search-query": "Search query is not valid. Please check Solr query syntax best practices for further information about this error.", + "error.invalid-search-query": "استعلام البحث غير صالح. يرجى مراجعة بناء جملة استعلام Solr أفضل الممارسات للحصول على مزيد من المعلومات حول هذا الخطأ.", + + // "error.sub-collections": "Error fetching sub-collections", + "error.sub-collections": "حدث خطأ أثناء جلب الحاويات الفرعية", + + // "error.sub-communities": "Error fetching sub-communities", + "error.sub-communities": "حدث خطأ أثناء جلب المجتمعات الفرعية", + + // "error.submission.sections.init-form-error": "An error occurred during section initialize, please check your input-form configuration. Details are below :

", + "error.submission.sections.init-form-error": "حدث خطأ أثناء تهيئة القسم، يرجى التحقق من تهيئة نموذج الإدخال الخاص بك. التفاصيل أدناه :

", + + // "error.top-level-communities": "Error fetching top-level communities", + "error.top-level-communities": "حدث خطأ أثناء جلب مجتمعات المستوى الأعلى", + + // "error.validation.license.notgranted": "You must grant this license to complete your submission. If you are unable to grant this license at this time you may save your work and return later or remove the submission.", + "error.validation.license.notgranted": "يجب عليك منح هذا الترخيص لإكمال عملية التقديم الخاصة بك. إذا لم تتمكن من منح هذا الترخيص في هذا الوقت، يمكنك حفظ عملك والعودة لاحقاً أو إزالة التقديم.", + + // "error.validation.pattern": "This input is restricted by the current pattern: {{ pattern }}.", "error.validation.pattern": "هذا الإدخال مقيد بالنمط الحالي: {{ pattern }}.", - "error.validation.filerequired": "تحميل الملف المشروط", - "error.validation.required": "هذا مطلوب الحقل", + + // "error.validation.filerequired": "The file upload is mandatory", + "error.validation.filerequired": "تحميل الملف إلزامي", + + // "error.validation.required": "This field is required", + "error.validation.required": "هذا الحقل مطلوب", + + // "error.validation.NotValidEmail": "This is not a valid email", "error.validation.NotValidEmail": "البريد الإلكتروني غير صالح", - "error.validation.emailTaken": "هذا البريد الإلكتروني السؤال بالفعل", + + // "error.validation.emailTaken": "This email is already taken", + "error.validation.emailTaken": "هذا البريد الإلكتروني مأخوذ بالفعل", + + // "error.validation.groupExists": "This group already exists", "error.validation.groupExists": "هذه المجموعة موجودة بالفعل", - "error.validation.metadata.name.invalid-pattern": "لا يمكن أن يحتوي هذا الحقل على نقاط أو فواصل أو مسافات. ", + + // "error.validation.metadata.name.invalid-pattern": "This field cannot contain dots, commas or spaces. Please use the Element & Qualifier fields instead", + "error.validation.metadata.name.invalid-pattern": "لا يمكن أن يحتوي هذا الحقل على نقاط أو فواصل أو مسافات. يرجى استخدام حقول العنصر والمؤهل بدلاً من ذلك", + + // "error.validation.metadata.name.max-length": "This field may not contain more than 32 characters", "error.validation.metadata.name.max-length": "يجب ألا يحتوي هذا الحقل على أكثر من 32 حرفاً", - "error.validation.metadata.namespace.max-length": "يجب ألا يحتوي هذا الحقل على أكثر من 256 حرفاً", - "error.validation.metadata.element.invalid-pattern": "لا يمكن أن يحتوي هذا الحقل على نقاط أو فواصل أو مسافات. ", + + // "error.validation.metadata.namespace.max-length": "This field may not contain more than 256 characters", + "error.validation.metadata.namespace.max-length": "يجب ألا يحتوي هذا الحقل على أكثر من 256 حرفاًs", + + // "error.validation.metadata.element.invalid-pattern": "This field cannot contain dots, commas or spaces. Please use the Qualifier field instead", + "error.validation.metadata.element.invalid-pattern": "لا يمكن أن يحتوي هذا الحقل على نقاط أو فواصل أو مسافات. يرجى استخدام حقل المؤهل بدلاً من ذلك", + + // "error.validation.metadata.element.max-length": "This field may not contain more than 64 characters", "error.validation.metadata.element.max-length": "يجب ألا يحتوي هذا الحقل على أكثر من 64 حرفاً", + + // "error.validation.metadata.qualifier.invalid-pattern": "This field cannot contain dots, commas or spaces", "error.validation.metadata.qualifier.invalid-pattern": "لا يمكن أن يحتوي هذا الحقل على نقاط أو فواصل أو مسافات", + + // "error.validation.metadata.qualifier.max-length": "This field may not contain more than 64 characters", "error.validation.metadata.qualifier.max-length": "يجب ألا يحتوي هذا الحقل على أكثر من 64 حرفاً", - "feed.description": " مشاركة التعليقات", + + // "feed.description": "Syndication feed", + "feed.description": " ملاحظات Syndication", + + // "file-download-link.restricted": "Restricted bitstream", "file-download-link.restricted": "دفق البت المقيد", - "file-section.error.header": "حدث خطأ أثناء الحصول على ملفات هذه المادة", + + // "file-section.error.header": "Error obtaining files for this item", + "file-section.error.header": "حدث خطأ أثناء الحصول على ملفات لهذه المادة", + + // "footer.copyright": "copyright © 2002-{{ year }}", "footer.copyright": "حقوق النشر © 2002-{{ year }}", + + // "footer.link.dspace": "DSpace software", "footer.link.dspace": "برنامج دي سبيس", + + // "footer.link.lyrasis": "LYRASIS", "footer.link.lyrasis": "ليراسيس", + + // "footer.link.cookies": "Cookie settings", "footer.link.cookies": "إعدادات ملفات تعريف الارتباط", + + // "footer.link.privacy-policy": "Privacy policy", "footer.link.privacy-policy": "سياسة الخصوصية", - "footer.link.end-user-agreement": "الاستخدام النهائي", + + // "footer.link.end-user-agreement": "End User Agreement", + "footer.link.end-user-agreement": "اتفاقية المستخدم النهائي", + + // "footer.link.feedback": "Send Feedback", "footer.link.feedback": "إرسال الملاحظات", - "footer.link.coar-notify-support": "إخطار COAR", + + // "footer.link.coar-notify-support": "COAR Notify", + // TODO New key - Add a translation + "footer.link.coar-notify-support": "COAR Notify", + + // "forgot-email.form.header": "Forgot Password", "forgot-email.form.header": "هل نسيت كلمة المرور", - "forgot-email.form.info": "قم بالضغط على عنوان البريد الإلكتروني ليس بالحساب.", + + // "forgot-email.form.info": "Enter the email address associated with the account.", + "forgot-email.form.info": "قم بإدخال عنوان البريد الإلكتروني المرتبط بالحساب.", + + // "forgot-email.form.email": "Email Address *", "forgot-email.form.email": "عنوان البريد الإلكتروني *", - "forgot-email.form.email.error.required": "الرجاء ملء عنوان البريد الإلكتروني", - "forgot-email.form.email.error.not-email-form": "برجاء ملء عنوان بريد إلكتروني صالح", - "forgot-email.form.email.hint": "سيتم إرسال بريد الإلكتروني إلى هذا العنوان ويتضمن المزيد من التعليمات.", + + // "forgot-email.form.email.error.required": "Please fill in an email address", + "forgot-email.form.email.error.required": "يرجى ملء عنوان البريد الإلكتروني", + + // "forgot-email.form.email.error.not-email-form": "Please fill in a valid email address", + "forgot-email.form.email.error.not-email-form": "يرجى ملء عنوان بريد إلكتروني صالح", + + // "forgot-email.form.email.hint": "An email will be sent to this address with a further instructions.", + "forgot-email.form.email.hint": "سيتم إرسال بريد إلكتروني إلى هذا العنوان يتضمن المزيد من التعليمات.", + + // "forgot-email.form.submit": "Reset password", "forgot-email.form.submit": "إعادة تعيين كلمة المرور", - "forgot-email.form.success.head": "تم إرسال رسالة عبر البريد الإلكتروني وإعادة تعيين كلمة المرور", - "forgot-email.form.success.content": "تم إرسال بريد إلكتروني إلى {{ email }} يحتوي على عنوان URL الخاص بالمزيد.", + + // "forgot-email.form.success.head": "Password reset email sent", + "forgot-email.form.success.head": "تم إرسال رسالة عبر البريد الإلكتروني لإعادة تعيين كلمة المرور", + + // "forgot-email.form.success.content": "An email has been sent to {{ email }} containing a special URL and further instructions.", + "forgot-email.form.success.content": "تم إرسال بريد إلكتروني إلى {{ email }} يحتوي على عنوان URL خاص وتعليمات إضافية.", + + // "forgot-email.form.error.head": "Error when trying to reset password", "forgot-email.form.error.head": "حدث خطأ أثناء محاولة إعادة تعيين كلمة المرور", - "forgot-email.form.error.content": "حدث خطأ أثناء محاولة إعادة تعيين كلمة المرور للحساب بالإضافة إلى عنوان البريد الإلكتروني التالي: {{ email }}", + + // "forgot-email.form.error.content": "An error occured when attempting to reset the password for the account associated with the following email address: {{ email }}", + "forgot-email.form.error.content": "حدث خطأ أثناء محاولة إعادة تعيين كلمة المرور للحساب المرتبط بعنوان البريد الإلكتروني التالي: {{ email }}", + + // "forgot-password.title": "Forgot Password", "forgot-password.title": "نسيت كلمة المرور", + + // "forgot-password.form.head": "Forgot Password", "forgot-password.form.head": "نسيت كلمة المرور", - "forgot-password.form.info": "قم بتأكيد كلمة المرور الجديدة في الشريط أدناه، وقم بتأكيدها عن طريق كتابتها مرة أخرى في الشريط الثاني.", + + // "forgot-password.form.info": "Enter a new password in the box below, and confirm it by typing it again into the second box.", + "forgot-password.form.info": "قم بإدخال كلمة المرور الجديدة في المربع أدناه، وقم بتأكيدها عن طريق كتابتها مرة أخرى في المربع الثاني.", + + // "forgot-password.form.card.security": "Security", "forgot-password.form.card.security": "الحماية والأمان", + + // "forgot-password.form.identification.header": "Identify", "forgot-password.form.identification.header": "تعريف", + + // "forgot-password.form.identification.email": "Email address: ", "forgot-password.form.identification.email": "عنوان البريد الإلكتروني: ", + + // "forgot-password.form.label.password": "Password", "forgot-password.form.label.password": "كلمة المرور", - "forgot-password.form.label.passwordrepeat": "إعادة الكتابة للتأكيد", - "forgot-password.form.error.empty-password": "يرجى الاتصال بكلمة المرور في المجالات السابقة.", + + // "forgot-password.form.label.passwordrepeat": "Retype to confirm", + "forgot-password.form.label.passwordrepeat": "أعد الكتابة للتأكيد", + + // "forgot-password.form.error.empty-password": "Please enter a password in the boxes above.", + "forgot-password.form.error.empty-password": "يرجى إدخال كلمة المرور في المربعات أعلاه.", + + // "forgot-password.form.error.matching-passwords": "The passwords do not match.", "forgot-password.form.error.matching-passwords": "كلمات المرور غير متطابقة.", + + // "forgot-password.form.notification.error.title": "Error when trying to submit new password", "forgot-password.form.notification.error.title": "حدث خطأ أثناء محاولة تقديم كلمة المرور الجديدة", - "forgot-password.form.notification.success.content": "تمت إعادة تعيين كلمة فعالة. ", + + // "forgot-password.form.notification.success.content": "The password reset was successful. You have been logged in as the created user.", + "forgot-password.form.notification.success.content": "تمت إعادة تعيين كلمة المرور بنجاح. لقد قمت بتسجيل الدخول كمستخدم تم إنشاؤه.", + + // "forgot-password.form.notification.success.title": "Password reset completed", "forgot-password.form.notification.success.title": "اكتملت إعادة تعيين كلمة المرور", + + // "forgot-password.form.submit": "Submit password", "forgot-password.form.submit": "تقديم كلمة المرور", + + // "form.add": "Add more", "form.add": "إضافة المزيد", - "form.add-help": "انقر هنا لإدخال النص الحالي", + + // "form.add-help": "Click here to add the current entry and to add another one", + "form.add-help": "انقر هنا لإضافة الإدخال الحالي وإضافة إدخال آخر", + + // "form.cancel": "Cancel", "form.cancel": "إلغاء", - "form.clear": "تعديل التعديل", - "form.clear-help": "انقر هنا القيمة المحددة", - "form.discard": "لا", - "form.drag": "يسحب", + + // "form.clear": "Clear", + "form.clear": "مسح", + + // "form.clear-help": "Click here to remove the selected value", + "form.clear-help": "انقر هنا لإزالة القيمة المحددة", + + // "form.discard": "Discard", + "form.discard": "تجاهل", + + // "form.drag": "Drag", + "form.drag": "سحب", + + // "form.edit": "Edit", "form.edit": "تحرير", + + // "form.edit-help": "Click here to edit the selected value", "form.edit-help": "انقر هنا لتحرير القيمة المحددة", + + // "form.first-name": "First name", "form.first-name": "الاسم الأول", - "form.group-collapse": "طيء", + + // "form.group-collapse": "Collapse", + "form.group-collapse": "طي", + + // "form.group-collapse-help": "Click here to collapse", "form.group-collapse-help": "انقر هنا للطي", - "form.group-expand": "الأوقات", - "form.group-expand-help": "انقر هنا للتوسيع ولم المزيد من العناصر", + + // "form.group-expand": "Expand", + "form.group-expand": "توسيع", + + // "form.group-expand-help": "Click here to expand and add more elements", + "form.group-expand-help": "انقر هنا للتوسيع وإضافة المزيد من العناصر", + + // "form.last-name": "Last name", "form.last-name": "اسم العائلة", + + // "form.loading": "Loading...", "form.loading": "جاري التحميل...", - "form.lookup": "هان عن", - "form.lookup-help": "انقر هنا للبحث عن علاقة حالة", - "form.no-results": "لم يتم العثور على النتائج", - "form.no-value": "لم يتم توفير أي قيمة", + + // "form.lookup": "Lookup", + "form.lookup": "ابحث عن", + + // "form.lookup-help": "Click here to look up an existing relation", + "form.lookup-help": "انقر هنا للبحث عن علاقة حالية", + + // "form.no-results": "No results found", + "form.no-results": "لم يتم العثور على نتائج", + + // "form.no-value": "No value entered", + "form.no-value": "لم يتم إدخال أي قيمة", + + // "form.other-information.email": "Email", "form.other-information.email": "البريد الإلكتروني", + + // "form.other-information.first-name": "First Name", "form.other-information.first-name": "الاسم الأول", + + // "form.other-information.insolr": "In Solr Index", "form.other-information.insolr": "في فهرس سولر", + + // "form.other-information.institution": "Institution", "form.other-information.institution": "المؤسسة", + + // "form.other-information.last-name": "Last Name", "form.other-information.last-name": "اسم العائلة", + + // "form.other-information.orcid": "ORCID", "form.other-information.orcid": "أوركيد", + + // "form.remove": "Remove", "form.remove": "إزالة", + + // "form.save": "Save", "form.save": "حفظ", + + // "form.save-help": "Save changes", "form.save-help": "حفظ التغييرات", + + // "form.search": "Search", "form.search": "بحث", + + // "form.search-help": "Click here to look for an existing correspondence", "form.search-help": "انقر هنا للبحث عن المراسلات الحالية", + + // "form.submit": "Save", "form.submit": "حفظ", + + // "form.create": "Create", "form.create": "إنشاء", - "form.number-picker.decrement": "إن.قاص {{field}}", + + // "form.number-picker.decrement": "Decrement {{field}}", + "form.number-picker.decrement": "إنقاص {{field}}", + + // "form.number-picker.increment": "Increment {{field}}", "form.number-picker.increment": "زيادة {{field}}", + + // "form.repeatable.sort.tip": "Drop the item in the new position", "form.repeatable.sort.tip": "قم بإسقاط المادة في الموضع الجديد", - "grant-deny-request-copy.deny": "لا تهتم بقراءة", + + // "grant-deny-request-copy.deny": "Don't send copy", + "grant-deny-request-copy.deny": "لا تقم بإرسال نسخة", + + // "grant-deny-request-copy.email.back": "Back", "grant-deny-request-copy.email.back": "رجوع", + + // "grant-deny-request-copy.email.message": "Optional additional message", "grant-deny-request-copy.email.message": "رسالة إضافية اختيارية", - "grant-deny-request-copy.email.message.empty": "الرجاء إرسال الرسالة", - "grant-deny-request-copy.email.permissions.info": "يمكنك إلغاء هذه الطريقة لإلغاء النظر في الإلكترونيات للوصول إلى أكسفورد، وتقليل الاضطرار إلى الرد على هذه الطلبات. ", - "grant-deny-request-copy.email.permissions.label": "تغيير للوصول حر", + + // "grant-deny-request-copy.email.message.empty": "Please enter a message", + "grant-deny-request-copy.email.message.empty": "يرجى إدخال رسالة", + + // "grant-deny-request-copy.email.permissions.info": "You may use this occasion to reconsider the access restrictions on the document, to avoid having to respond to these requests. If you’d like to ask the repository administrators to remove these restrictions, please check the box below.", + "grant-deny-request-copy.email.permissions.info": "يمكنك استغلال هذه المناسبة لإعادة النظر في قيود الوصول على الوثيقة، لتجنب الاضطرار إلى الرد على هذه الطلبات. إذا كنت ترغب في مطالبة مديري المستودع بإزالة هذه القيود، فيرجى تحديد المربع أدناه.", + + // "grant-deny-request-copy.email.permissions.label": "Change to open access", + "grant-deny-request-copy.email.permissions.label": "تغيير إلى وصول حر", + + // "grant-deny-request-copy.email.send": "Send", "grant-deny-request-copy.email.send": "إرسال", + + // "grant-deny-request-copy.email.subject": "Subject", "grant-deny-request-copy.email.subject": "الموضوع", - "grant-deny-request-copy.email.subject.empty": "يرجى الإرسال موضوع", + + // "grant-deny-request-copy.email.subject.empty": "Please enter a subject", + "grant-deny-request-copy.email.subject.empty": "يرجى إدخال موضوع", + + // "grant-deny-request-copy.grant": "Send copy", "grant-deny-request-copy.grant": "إرسال نسخة", - "grant-deny-request-copy.header": "نسخة الطلب من أوكسلي", + + // "grant-deny-request-copy.header": "Document copy request", + "grant-deny-request-copy.header": "طلب نسخة من الوثيقة", + + // "grant-deny-request-copy.home-page": "Take me to the home page", "grant-deny-request-copy.home-page": "انتقل بي إلى الصفحة الرئيسية", - "grant-deny-request-copy.intro1": "إذا كنت أحد الكتبي في جامعة أكسفورد {{ name }}، يرجى استخدام أحد الخيارات أدناه للرد على طلب المستخدم.", - "grant-deny-request-copy.intro2": "بعد اختيار أحد الخيارات، سيُعرض عليك رسالة رد على آلية البريد الإلكتروني يمكنك تحريرها.", - "grant-deny-request-copy.processed": "تنفيذ هذا الطلب بالفعل. ", - "grant-request-copy.email.subject": "طلب نسخة من الوثيقة", + + // "grant-deny-request-copy.intro1": "If you are one of the authors of the document {{ name }}, then please use one of the options below to respond to the user's request.", + "grant-deny-request-copy.intro1": "إذا كنت أحد مؤلفي الوثيقة {{ name }}, فيرجى استخدام أحد الخيارات أدناه للرد على طلب المستخدم.", + + // "grant-deny-request-copy.intro2": "After choosing an option, you will be presented with a suggested email reply which you may edit.", + "grant-deny-request-copy.intro2": "بعد اختيار أحد الخيارات، سيُعرض عليك رسالة رد مقترحة بالبريد الإلكتروني يمكنك تحريرها.", + + // "grant-deny-request-copy.processed": "This request has already been processed. You can use the button below to get back to the home page.", + "grant-deny-request-copy.processed": "تمت معالجة هذا الطلب بالفعل. يمكنك استخدام الزر أدناه للعودة إلى الصفحة الرئيسية.", + + // "grant-request-copy.email.subject": "Request copy of document", + "grant-request-copy.email.subject": "طلب نسخة من وثيقة", + + // "grant-request-copy.error": "An error occurred", "grant-request-copy.error": "لقد حدث خطأ", - "grant-request-copy.header": "طلب منح نسخة من أوسكار", - "grant-request-copy.intro": "سيتم إرسال هذه الرسالة إلى مقدم الطلب. ", - "grant-request-copy.success": "تم تقديم المساعدة الفعالة", + + // "grant-request-copy.header": "Grant document copy request", + "grant-request-copy.header": "طلب منح نسخة من الوثيقة", + + // "grant-request-copy.intro": "A message will be sent to the applicant of the request. The requested document(s) will be attached.", + "grant-request-copy.intro": "سيتم إرسال هذه الرسالة إلى مقدم الطلب. وسيتم إرفاق الوثيقة المطلوبة.", + + // "grant-request-copy.success": "Successfully granted item request", + "grant-request-copy.success": "تم منح طلب المادة بنجاح", + + // "health.breadcrumbs": "Health", "health.breadcrumbs": "كشف الصحة", + + // "health-page.heading": "Health", "health-page.heading": "كشف الصحة", + + // "health-page.info-tab": "Info", "health-page.info-tab": "معلومات", + + // "health-page.status-tab": "Status", "health-page.status-tab": "الحالة", - "health-page.error.msg": "خدمة الكتاب العام غير المؤقت", + + // "health-page.error.msg": "The health check service is temporarily unavailable", + "health-page.error.msg": "خدمة الفحص الصحي غير متاحة مؤقتاً", + + // "health-page.property.status": "Status code", "health-page.property.status": "رمز الحالة", - "health-page.section.db.title": "قاعدة بيانات البيانات", + + // "health-page.section.db.title": "Database", + "health-page.section.db.title": "قاعدة البيانات", + + // "health-page.section.geoIp.title": "GeoIp", "health-page.section.geoIp.title": "GeoIp", + + // "health-page.section.solrAuthorityCore.title": "Solr: authority core", "health-page.section.solrAuthorityCore.title": "سولر: جوهر الاستناد", - "health-page.section.solrOaiCore.title": "سولر: جو أوي", + + // "health-page.section.solrOaiCore.title": "Solr: oai core", + "health-page.section.solrOaiCore.title": "سولر: جوهر oai", + + // "health-page.section.solrSearchCore.title": "Solr: search core", "health-page.section.solrSearchCore.title": "سولر: جوهر البحث", + + // "health-page.section.solrStatisticsCore.title": "Solr: statistics core", "health-page.section.solrStatisticsCore.title": "سولر: جوهر الإحصائيات", - "health-page.section-info.app.title": "النهاية", + + // "health-page.section-info.app.title": "Application Backend", + "health-page.section-info.app.title": "الواجهة الخلفية للتطبيق", + + // "health-page.section-info.java.title": "Java", "health-page.section-info.java.title": "جافا", + + // "health-page.status": "Status", "health-page.status": "الحالة", + + // "health-page.status.ok.info": "Operational", "health-page.status.ok.info": "تشغيلي", - "health-page.status.error.info": "تم كشف المشاكل", - "health-page.status.warning.info": "تم الكشف عن المشاكل الصغيرة", + + // "health-page.status.error.info": "Problems detected", + "health-page.status.error.info": "تم الكشف عن مشاكل", + + // "health-page.status.warning.info": "Possible issues detected", + "health-page.status.warning.info": "تم الكشف عن مشاكل محتملة", + + // "health-page.title": "Health", "health-page.title": "كشف الصحة", - "health-page.section.no-issues": "لم يتم اكتشاف أي شيء", + + // "health-page.section.no-issues": "No issues detected", + "health-page.section.no-issues": "لم يتم اكتشاف أي مشكلات", + + // "home.description": "", "home.description": "", + + // "home.breadcrumbs": "Home", "home.breadcrumbs": "الرئيسية", - "home.search-form.placeholder": "بحث المستودع...", + + // "home.search-form.placeholder": "Search the repository ...", + "home.search-form.placeholder": "بحث المستودع ...", + + // "home.title": "Home", "home.title": "الرئيسية", + + // "home.top-level-communities.head": "Communities in DSpace", "home.top-level-communities.head": "المجتمعات في دي سبيس", - "home.top-level-communities.help": "هيا مجتمع لاستعراض مستحضراته.", - "info.end-user-agreement.accept": "لقد قمت بقراءة المنتج النهائي ووافقت عليه", - "info.end-user-agreement.accept.error": "حدث خطأ أثناء استخدام الاستخدام النهائي", - "info.end-user-agreement.accept.success": "تم تحديث الاستخدام النهائي بشكل فعال", - "info.end-user-agreement.breadcrumbs": "الاستخدام النهائي", + + // "home.top-level-communities.help": "Select a community to browse its collections.", + "home.top-level-communities.help": "قم بتحديد مجتمع لاستعراض حاوياته.", + + // "info.end-user-agreement.accept": "I have read and I agree to the End User Agreement", + "info.end-user-agreement.accept": "لقد قمت بقراءة اتفاقية المستخدم النهائي وأوافق عليها", + + // "info.end-user-agreement.accept.error": "An error occurred accepting the End User Agreement", + "info.end-user-agreement.accept.error": "حدث خطأ أثناء قبول اتفاقية المستخدم النهائي", + + // "info.end-user-agreement.accept.success": "Successfully updated the End User Agreement", + "info.end-user-agreement.accept.success": "تم بنجاح تحديث اتفاقية المستخدم النهائي", + + // "info.end-user-agreement.breadcrumbs": "End User Agreement", + "info.end-user-agreement.breadcrumbs": "اتفاقية المستخدم النهائي", + + // "info.end-user-agreement.buttons.cancel": "Cancel", "info.end-user-agreement.buttons.cancel": "إلغاء", + + // "info.end-user-agreement.buttons.save": "Save", "info.end-user-agreement.buttons.save": "حفظ", - "info.end-user-agreement.head": "الاستخدام النهائي", - "info.end-user-agreement.title": "الاستخدام النهائي", + + // "info.end-user-agreement.head": "End User Agreement", + "info.end-user-agreement.head": "اتفاقية المستخدم النهائي", + + // "info.end-user-agreement.title": "End User Agreement", + "info.end-user-agreement.title": "اتفاقية المستخدم النهائي", + + // "info.end-user-agreement.hosting-country": "the United States", "info.end-user-agreement.hosting-country": "الولايات المتحدة", + + // "info.privacy.breadcrumbs": "Privacy Statement", "info.privacy.breadcrumbs": "بيان الخصوصية", + + // "info.privacy.head": "Privacy Statement", "info.privacy.head": "بيان الخصوصية", + + // "info.privacy.title": "Privacy Statement", "info.privacy.title": "بيان الخصوصية", - "info.feedback.breadcrumbs": "مراجعة", - "info.feedback.head": "مراجعة", - "info.feedback.title": "مراجعة", - "info.feedback.info": "شكراً لمشاركتنا آراءك حول نظام دي سبيس. ", - "info.feedback.email_help": "سيتم استخدام هذا البريد الالكتروني لمتابعة بياناتك.", - "info.feedback.send": "قم بزيارة تعليقاتك", + + // "info.feedback.breadcrumbs": "Feedback", + "info.feedback.breadcrumbs": "ملاحظات", + + // "info.feedback.head": "Feedback", + "info.feedback.head": "ملاحظات", + + // "info.feedback.title": "Feedback", + "info.feedback.title": "ملاحظات", + + // "info.feedback.info": "Thanks for sharing your feedback about the DSpace system. Your comments are appreciated!", + "info.feedback.info": "شكراً لمشاركتنا ملاحظاتك حول نظام دي سبيس. نقدر تعليقاتكم!", + + // "info.feedback.email_help": "This address will be used to follow up on your feedback.", + "info.feedback.email_help": "سيتم استخدام هذا البريد الالكتروني لمتابعة ملاحظاتك.", + + // "info.feedback.send": "Send Feedback", + "info.feedback.send": "قم بإرسال ملاحظاتك", + + // "info.feedback.comments": "Comments", "info.feedback.comments": "تعليقات", + + // "info.feedback.email-label": "Your Email", "info.feedback.email-label": "البريد الإلكتروني الخاص بك", - "info.feedback.create.success": "تم تحفيزه بشكل فعال!", - "info.feedback.error.email.required": "مطلوب عنوان بريد الإلكتروني صالح", + + // "info.feedback.create.success": "Feedback Sent Successfully!", + "info.feedback.create.success": "تم إرسال الملاحظات بنجاح!", + + // "info.feedback.error.email.required": "A valid email address is required", + "info.feedback.error.email.required": "مطلوب عنوان بريد إلكتروني صالح", + + // "info.feedback.error.message.required": "A comment is required", "info.feedback.error.message.required": "مطلوب تعليق", + + // "info.feedback.page-label": "Page", "info.feedback.page-label": "صفحة", + + // "info.feedback.page_help": "The page related to your feedback", "info.feedback.page_help": "الصفحة ذات الصلة بملاحظاتك", - "info.coar-notify-support.title": "COAR إخطار الدعم", - "info.coar-notify-support.breadcrumbs": "COAR إخطار الدعم", + + // "info.coar-notify-support.title": "COAR Notify Support", + // TODO New key - Add a translation + "info.coar-notify-support.title": "COAR Notify Support", + + // "info.coar-notify-support.breadcrumbs": "COAR Notify Support", + // TODO New key - Add a translation + "info.coar-notify-support.breadcrumbs": "COAR Notify Support", + + // "item.alerts.private": "This item is non-discoverable", "item.alerts.private": "هذه المادة غير قابلة للاكتشاف", + + // "item.alerts.withdrawn": "This item has been withdrawn", "item.alerts.withdrawn": "تم سحب هذه المادة", - "item.alerts.reinstate-request": "طلب إعادة", - "quality-assurance.event.table.person-who-requested": "بتوصية من", - "item.edit.authorizations.heading": "باستخدام هذا المحرر، يمكنك عرض تغيير سياساتنا، بالإضافة إلى تغيير سياسات عناصر العناصر: الحزم والبنية. ", - "item.edit.authorizations.title": "تحرير سياسة المادة", - "item.badge.private": "غير للاكتشاف", + + // "item.alerts.reinstate-request": "Request reinstate", + // TODO New key - Add a translation + "item.alerts.reinstate-request": "Request reinstate", + + // "quality-assurance.event.table.person-who-requested": "Requested by", + // TODO New key - Add a translation + "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.heading": "باستخدام هذا المحرر ، يمكنك عرض وتغيير سياسات مادة ما، بالإضافة إلى تغيير سياسات مكونات المادة الفردية: الحزم وتدفق البت. باختصار، المادة عبارة عن حاوية من الحزم، والحزم عبارة عن حاويات لتدفقات البت. للحاويات في المعتاد سياسات ADD/REMOVE/READ/WRITE ، بينما يكون لتدفقات البت سياسات READ/WRITE فقط.", + + // "item.edit.authorizations.title": "Edit item's Policies", + "item.edit.authorizations.title": "تحرير سياسات المادة", + + // "item.badge.private": "Non-discoverable", + "item.badge.private": "غير قابل للاكتشاف", + + // "item.badge.withdrawn": "Withdrawn", "item.badge.withdrawn": "مسحوب", + + // "item.bitstreams.upload.bundle": "Bundle", "item.bitstreams.upload.bundle": "الحزمة", - "item.bitstreams.upload.bundle.placeholder": "قم بالضغط على حزمة أو تسجيل اسم حزمة جديدة", + + // "item.bitstreams.upload.bundle.placeholder": "Select a bundle or input new bundle name", + "item.bitstreams.upload.bundle.placeholder": "قم بتحديد حزمة أو إدخال اسم حزمة جديدة", + + // "item.bitstreams.upload.bundle.new": "Create bundle", "item.bitstreams.upload.bundle.new": "إنشاء حزمة", - "item.bitstreams.upload.bundles.empty": "لا تحتوي على هذه المادة على أي حزم لتحميل تدفقات البت لها.", + + // "item.bitstreams.upload.bundles.empty": "This item doesn't contain any bundles to upload a bitstream to.", + "item.bitstreams.upload.bundles.empty": "لا تحتوي هذه المادة على أية حزم لتحميل تدفقات البت لها.", + + // "item.bitstreams.upload.cancel": "Cancel", "item.bitstreams.upload.cancel": "إلغاء", - "item.bitstreams.upload.drop-message": "قم بإسقاط ملف PDFه", + + // "item.bitstreams.upload.drop-message": "Drop a file to upload", + "item.bitstreams.upload.drop-message": "قم بإسقاط ملف لتحميله", + + // "item.bitstreams.upload.item": "Item: ", "item.bitstreams.upload.item": "المواد: ", - "item.bitstreams.upload.notifications.bundle.created.content": "تم إنشاء حزمة جديدة وفعالة.", - "item.bitstreams.upload.notifications.bundle.created.title": "الحزمة التي تم تحديدها", - "item.bitstreams.upload.notifications.upload.failed": "فشل التحميل. ", + + // "item.bitstreams.upload.notifications.bundle.created.content": "Successfully created new bundle.", + "item.bitstreams.upload.notifications.bundle.created.content": "تم إنشاء حزمة جديدة بنجاح.", + + // "item.bitstreams.upload.notifications.bundle.created.title": "Created bundle", + "item.bitstreams.upload.notifications.bundle.created.title": "الحزمة التي تم إنشاؤها", + + // "item.bitstreams.upload.notifications.upload.failed": "Upload failed. Please verify the content before retrying.", + "item.bitstreams.upload.notifications.upload.failed": "فشل التحميل. يرجى التحقق من المحتوى قبل إعادة المحاولة.", + + // "item.bitstreams.upload.title": "Upload bitstream", "item.bitstreams.upload.title": "تحميل تدفق البت", + + // "item.edit.bitstreams.bundle.edit.buttons.upload": "Upload", "item.edit.bitstreams.bundle.edit.buttons.upload": "تحميل", - "item.edit.bitstreams.bundle.displaying": "يتم العرض حاليًا {{ amount }} تدفقات بت من {{ total }}.", + + // "item.edit.bitstreams.bundle.displaying": "Currently displaying {{ amount }} bitstreams of {{ total }}.", + "item.edit.bitstreams.bundle.displaying": "يتم حالياً عرض {{ amount }} تدفقات بت من {{ total }}.", + + // "item.edit.bitstreams.bundle.load.all": "Load all ({{ total }})", "item.edit.bitstreams.bundle.load.all": "تحميل الكل ({{ total }})", + + // "item.edit.bitstreams.bundle.load.more": "Load more", "item.edit.bitstreams.bundle.load.more": "تحميل المزيد", - "item.edit.bitstreams.bundle.name": "الصندوق: {{ name }}", - "item.edit.bitstreams.discard-button": "لا", + + // "item.edit.bitstreams.bundle.name": "BUNDLE: {{ name }}", + "item.edit.bitstreams.bundle.name": "الحزمة: {{ name }}", + + // "item.edit.bitstreams.discard-button": "Discard", + "item.edit.bitstreams.discard-button": "تجاهل", + + // "item.edit.bitstreams.edit.buttons.download": "Download", "item.edit.bitstreams.edit.buttons.download": "تنزيل", - "item.edit.bitstreams.edit.buttons.drag": "يسحب", + + // "item.edit.bitstreams.edit.buttons.drag": "Drag", + "item.edit.bitstreams.edit.buttons.drag": "سحب", + + // "item.edit.bitstreams.edit.buttons.edit": "Edit", "item.edit.bitstreams.edit.buttons.edit": "تحرير", + + // "item.edit.bitstreams.edit.buttons.remove": "Remove", "item.edit.bitstreams.edit.buttons.remove": "إزالة", - "item.edit.bitstreams.edit.buttons.undo": "الحكمة عن التغييرات", - "item.edit.bitstreams.empty": "لا تحتوي على هذه المادة على أي تدفقات بت. ", + + // "item.edit.bitstreams.edit.buttons.undo": "Undo changes", + "item.edit.bitstreams.edit.buttons.undo": "التراجع عن التغييرات", + + // "item.edit.bitstreams.empty": "This item doesn't contain any bitstreams. Click the upload button to create one.", + "item.edit.bitstreams.empty": "لا تحتوي هذه المادة على أية تدفقات بت. انقر على زر التحميل لإنشاء واحد.", + + // "item.edit.bitstreams.headers.actions": "Actions", "item.edit.bitstreams.headers.actions": "إجراءات", + + // "item.edit.bitstreams.headers.bundle": "Bundle", "item.edit.bitstreams.headers.bundle": "الحزمة", + + // "item.edit.bitstreams.headers.description": "Description", "item.edit.bitstreams.headers.description": "الوصف", - "item.edit.bitstreams.headers.format": "حتى", + + // "item.edit.bitstreams.headers.format": "Format", + "item.edit.bitstreams.headers.format": "التنسيق", + + // "item.edit.bitstreams.headers.name": "Name", "item.edit.bitstreams.headers.name": "الاسم", - "item.edit.bitstreams.notifications.discarded.content": "تم تجاهل تجاهلك. ", + + // "item.edit.bitstreams.notifications.discarded.content": "Your changes were discarded. To reinstate your changes click the 'Undo' button", + "item.edit.bitstreams.notifications.discarded.content": "تم تجاهل تغييراتك. لإعادة تعيين تغييراتك قم بالنقر على زر 'تراجع'", + + // "item.edit.bitstreams.notifications.discarded.title": "Changes discarded", "item.edit.bitstreams.notifications.discarded.title": "تم تجاهل التغييرات", + + // "item.edit.bitstreams.notifications.move.failed.title": "Error moving bitstreams", "item.edit.bitstreams.notifications.move.failed.title": "خطأ أثناء نقل تدفقات البت", - "item.edit.bitstreams.notifications.move.saved.content": "تم حفظ التطورات الجديدة بك على حزم وتدفقات بت هذه المادة.", - "item.edit.bitstreams.notifications.move.saved.title": "تم الحفاظ على التطورات الجديدة", - "item.edit.bitstreams.notifications.outdated.content": "المادة التي تعمل بها حاليًا تم تغييرها بواسطة مستخدم آخر. ", - "item.edit.bitstreams.notifications.outdated.title": "اختر التغييرات", - "item.edit.bitstreams.notifications.remove.failed.title": "حدث خطأ أثناء حذف تدفق البت", - "item.edit.bitstreams.notifications.remove.saved.content": "تم حفظ التغييرات الخاصة بك على تدفقات بت هذه المادة.", - "item.edit.bitstreams.notifications.remove.saved.title": "تم حفظ التغييرات الإزالة", - "item.edit.bitstreams.reinstate-button": "ديب", + + // "item.edit.bitstreams.notifications.move.saved.content": "Your move changes to this item's bitstreams and bundles have been saved.", + "item.edit.bitstreams.notifications.move.saved.content": "تم حفظ تغييرات النقل الخاصة بك على حزم وتدفقات بت هذه المادة.", + + // "item.edit.bitstreams.notifications.move.saved.title": "Move changes saved", + "item.edit.bitstreams.notifications.move.saved.title": "تم حفظ تغييرات النقل", + + // "item.edit.bitstreams.notifications.outdated.content": "The item you're currently working on has been changed by another user. Your current changes are discarded to prevent conflicts", + "item.edit.bitstreams.notifications.outdated.content": "المادة التي تعمل عليها حالياً تم تغييرها بواسطة مستخدم آخر. تم تجاهل تغييراتك الحالية لتجنب التعارض", + + // "item.edit.bitstreams.notifications.outdated.title": "Changes outdated", + "item.edit.bitstreams.notifications.outdated.title": "انتهت صلاحية التغييرات", + + // "item.edit.bitstreams.notifications.remove.failed.title": "Error deleting bitstream", + "item.edit.bitstreams.notifications.remove.failed.title": "خطأ أثناء حذف تدفق البت", + + // "item.edit.bitstreams.notifications.remove.saved.content": "Your removal changes to this item's bitstreams have been saved.", + "item.edit.bitstreams.notifications.remove.saved.content": "تم حفظ تغييرات الإزالة الخاصة بك على تدفقات بت هذه المادة.", + + // "item.edit.bitstreams.notifications.remove.saved.title": "Removal changes saved", + "item.edit.bitstreams.notifications.remove.saved.title": "تم حفظ تغييرات الإزالة", + + // "item.edit.bitstreams.reinstate-button": "Undo", + "item.edit.bitstreams.reinstate-button": "تراجع", + + // "item.edit.bitstreams.save-button": "Save", "item.edit.bitstreams.save-button": "حفظ", + + // "item.edit.bitstreams.upload-button": "Upload", "item.edit.bitstreams.upload-button": "تحميل", + + // "item.edit.delete.cancel": "Cancel", "item.edit.delete.cancel": "إلغاء", + + // "item.edit.delete.confirm": "Delete", "item.edit.delete.confirm": "حذف", - "item.edit.delete.description": "هل أنت متأكد من حذف هذه المادة التجارية؟ ", + + // "item.edit.delete.description": "Are you sure this item should be completely deleted? Caution: At present, no tombstone would be left.", + "item.edit.delete.description": "هل أنت متأكد من حذف هذه المادة تماماً؟ تحذير: في الوقت الحالي لن تتبقى أي آثار.", + + // "item.edit.delete.error": "An error occurred while deleting the item", "item.edit.delete.error": "حدث خطأ أثناء حذف المادة", + + // "item.edit.delete.header": "Delete item: {{ id }}", "item.edit.delete.header": "حذف المادة: {{ id }}", + + // "item.edit.delete.success": "The item has been deleted", "item.edit.delete.success": "تم حذف هذه المادة", + + // "item.edit.head": "Edit Item", "item.edit.head": "تحرير المادة", + + // "item.edit.breadcrumbs": "Edit Item", "item.edit.breadcrumbs": "تحرير المادة", + + // "item.edit.tabs.disabled.tooltip": "You're not authorized to access this tab", "item.edit.tabs.disabled.tooltip": "غير مصرح لك بالوصول إلى هذا التبويب", - "item.edit.tabs.mapper.head": "خطة مخططة", - "item.edit.tabs.item-mapper.title": "تحرير المادة - مخطط الغذاء", + + // "item.edit.tabs.mapper.head": "Collection Mapper", + "item.edit.tabs.mapper.head": "مخطط الحاوية", + + // "item.edit.tabs.item-mapper.title": "Item Edit - Collection Mapper", + "item.edit.tabs.item-mapper.title": "تحرير المادة - مخطط الحاوية", + + // "item.edit.identifiers.doi.status.UNKNOWN": "Unknown", "item.edit.identifiers.doi.status.UNKNOWN": "غير معروف", - "item.edit.identifiers.doi.status.TO_BE_REGISTERED": "في قائمة الانتظار للتشغيل", + + // "item.edit.identifiers.doi.status.TO_BE_REGISTERED": "Queued for registration", + "item.edit.identifiers.doi.status.TO_BE_REGISTERED": "في قائمة الانتظار للتسجيل", + + // "item.edit.identifiers.doi.status.TO_BE_RESERVED": "Queued for reservation", "item.edit.identifiers.doi.status.TO_BE_RESERVED": "في قائمة الانتظار للحجز", + + // "item.edit.identifiers.doi.status.IS_REGISTERED": "Registered", "item.edit.identifiers.doi.status.IS_REGISTERED": "مسجل", + + // "item.edit.identifiers.doi.status.IS_RESERVED": "Reserved", "item.edit.identifiers.doi.status.IS_RESERVED": "محجوز", + + // "item.edit.identifiers.doi.status.UPDATE_RESERVED": "Reserved (update queued)", "item.edit.identifiers.doi.status.UPDATE_RESERVED": "محجوز (تحديث قائمة الانتظار)", + + // "item.edit.identifiers.doi.status.UPDATE_REGISTERED": "Registered (update queued)", "item.edit.identifiers.doi.status.UPDATE_REGISTERED": "مسجل (تحديث قائمة الانتظار)", + + // "item.edit.identifiers.doi.status.UPDATE_BEFORE_REGISTRATION": "Queued for update and registration", "item.edit.identifiers.doi.status.UPDATE_BEFORE_REGISTRATION": "في قائمة الانتظار للتحديث والتسجيل", + + // "item.edit.identifiers.doi.status.TO_BE_DELETED": "Queued for deletion", "item.edit.identifiers.doi.status.TO_BE_DELETED": "في قائمة الانتظار للحذف", + + // "item.edit.identifiers.doi.status.DELETED": "Deleted", "item.edit.identifiers.doi.status.DELETED": "تم الحذف", + + // "item.edit.identifiers.doi.status.PENDING": "Pending (not registered)", "item.edit.identifiers.doi.status.PENDING": "في الانتظار (غير مسجل)", + + // "item.edit.identifiers.doi.status.MINTED": "Minted (not registered)", "item.edit.identifiers.doi.status.MINTED": "مسكوك (غير مسجل)", - "item.edit.tabs.status.buttons.register-doi.label": "تسجيل الكائن المعرفي الرقمي الجديد أو في الانتظار", - "item.edit.tabs.status.buttons.register-doi.button": "تسجيل الهوية الرقمية...", - "item.edit.register-doi.header": "تسجيل الكائن المعرفي الرقمي الجديد أو في الانتظار", - "item.edit.register-doi.description": "قم بمراجعة أي معرفات في الانتظار وميتاداتا المادة أدناه والنقر المؤكد على متابعة تسجيل المعرفة الرقمية، أو إلغاء القفل للتراجع", - "item.edit.register-doi.confirm": "بالتأكيد", + + // "item.edit.tabs.status.buttons.register-doi.label": "Register a new or pending DOI", + "item.edit.tabs.status.buttons.register-doi.label": "تسجيل معرف كائن رقمي جديد أو في الانتظار", + + // "item.edit.tabs.status.buttons.register-doi.button": "Register DOI...", + "item.edit.tabs.status.buttons.register-doi.button": "تسجيل معرف كائن رقمي...", + + // "item.edit.register-doi.header": "Register a new or pending DOI", + "item.edit.register-doi.header": "تسجيل معرف كائن رقمي جديد أو في الانتظار", + + // "item.edit.register-doi.description": "Review any pending identifiers and item metadata below and click Confirm to proceed with DOI registration, or Cancel to back out", + "item.edit.register-doi.description": "قم بمراجعة أي معرفات في الانتظار وميتاداتا المادة أدناه والنقر على تأكيد لمتابعة تسجيل معرف الكائن الرقمي، أو إلغاء للتراجع", + + // "item.edit.register-doi.confirm": "Confirm", + "item.edit.register-doi.confirm": "تأكيد", + + // "item.edit.register-doi.cancel": "Cancel", "item.edit.register-doi.cancel": "إلغاء", - "item.edit.register-doi.success": "تم وضع الإعدادات الرقمية في قائمة الانتظار الفعالة.", - "item.edit.register-doi.error": "خطأ في تسجيل المدخلات الرقمية", - "item.edit.register-doi.to-update": "لقد تم بالفعل إنشاء المفتاح الرقمي التالي ووضعه في قائمة الانتظار للتشغيل عبر الإنترنت", - "item.edit.item-mapper.buttons.add": "تخطيط المادة إلى مادة محددة", + + // "item.edit.register-doi.success": "DOI queued for registration successfully.", + "item.edit.register-doi.success": "تم وضع معرف الكائن الرقمي في قائمة الانتظار للتسجيل بنجاح.", + + // "item.edit.register-doi.error": "Error registering DOI", + "item.edit.register-doi.error": "خطأ في تسجيل معرف الكائن الرقمي", + + // "item.edit.register-doi.to-update": "The following DOI has already been minted and will be queued for registration online", + "item.edit.register-doi.to-update": "لقد تم بالفعل سك معرف الكائن الرقمي التالي وسيتم وضعه في قائمة الانتظار للتسجيل عبر الإنترنت", + + // "item.edit.item-mapper.buttons.add": "Map item to selected collections", + "item.edit.item-mapper.buttons.add": "تخطيط مادة إلى حاويات محددة", + + // "item.edit.item-mapper.buttons.remove": "Remove item's mapping for selected collections", "item.edit.item-mapper.buttons.remove": "إزالة تحطيط مادة لحاويات محددة", + + // "item.edit.item-mapper.cancel": "Cancel", "item.edit.item-mapper.cancel": "إلغاء", - "item.edit.item-mapper.description": "هذه أداة مخططة للمادة التي بدأت لمديرين تخطيط هذه المادة لتوثيق أخرى. ", - "item.edit.item-mapper.head": "المادة - تخطيط المادة إلى مادة الفينيل", + + // "item.edit.item-mapper.description": "This is the item mapper tool that allows administrators to map this item to other collections. You can search for collections and map them, or browse the list of collections the item is currently mapped to.", + "item.edit.item-mapper.description": "هذه أداة مخطط المادة التي تتيح للمديرين تخطيط هذه المادة إلى حاويات أخرى. يمكنك البحث عن الحاويات وتخطيطها، أو استعراض قائمة بالحاويات التي تم تخطيط هذه المادة لها حالياً.", + + // "item.edit.item-mapper.head": "Item Mapper - Map Item to Collections", + "item.edit.item-mapper.head": "مخطط المادة - تخطيط مادة إلى حاويات", + + // "item.edit.item-mapper.item": "Item: \"{{name}}\"", "item.edit.item-mapper.item": "المادة: \"{{name}}\"", - "item.edit.item-mapper.no-search": "يرجى الاتصال باستعلام للبحث", - "item.edit.item-mapper.notifications.add.error.content": "أحدث الأخطاء أثناء تخطيط المادة إلى {{amount}} حاوية.", + + // "item.edit.item-mapper.no-search": "Please enter a query to search", + "item.edit.item-mapper.no-search": "يرجى إدخال استعلام للبحث", + + // "item.edit.item-mapper.notifications.add.error.content": "Errors occurred for mapping of item to {{amount}} collections.", + "item.edit.item-mapper.notifications.add.error.content": "حدثت أخطاء أثناء تخطيط مادة إلى {{amount}} حاوية.", + + // "item.edit.item-mapper.notifications.add.error.head": "Mapping errors", "item.edit.item-mapper.notifications.add.error.head": "أخطاء التخطيط", - "item.edit.item-mapper.notifications.add.success.content": "تم تخطيط المادة {{amount}} حاوية فعالة.", + + // "item.edit.item-mapper.notifications.add.success.content": "Successfully mapped item to {{amount}} collections.", + "item.edit.item-mapper.notifications.add.success.content": "تم تخطيط المادة إلى {{amount}} حاوية بنجاح.", + + // "item.edit.item-mapper.notifications.add.success.head": "Mapping completed", "item.edit.item-mapper.notifications.add.success.head": "اكتمل التخطيط", - "item.edit.item-mapper.notifications.remove.error.content": "أخطاء أثناء إزالة التخطيط إلى {{amount}} حاوية.", + + // "item.edit.item-mapper.notifications.remove.error.content": "Errors occurred for the removal of the mapping to {{amount}} collections.", + "item.edit.item-mapper.notifications.remove.error.content": "حدثت أخطاء أثناء إزالة التخطيط إلى {{amount}} حاوية.", + + // "item.edit.item-mapper.notifications.remove.error.head": "Removal of mapping errors", "item.edit.item-mapper.notifications.remove.error.head": "أخطاء إزالة التخطيط", - "item.edit.item-mapper.notifications.remove.success.content": "بعد إزالة تخطيط المادة {{amount}} حاوية فعالة.", + + // "item.edit.item-mapper.notifications.remove.success.content": "Successfully removed mapping of item to {{amount}} collections.", + "item.edit.item-mapper.notifications.remove.success.content": "تمت إزالة تخطيط المادة إلى {{amount}} حاوية بنجاح.", + + // "item.edit.item-mapper.notifications.remove.success.head": "Removal of mapping completed", "item.edit.item-mapper.notifications.remove.success.head": "اكتملت إزالة التخطيط", - "item.edit.item-mapper.search-form.placeholder": "بحث مقبول...", - "item.edit.item-mapper.tabs.browse": "تم الاسترجاع المؤجل", - "item.edit.item-mapper.tabs.map": "تخطيط وثيقة جديدة", + + // "item.edit.item-mapper.search-form.placeholder": "Search collections...", + "item.edit.item-mapper.search-form.placeholder": "بحث الحاويات...", + + // "item.edit.item-mapper.tabs.browse": "Browse mapped collections", + "item.edit.item-mapper.tabs.browse": "استعراض الحاويات المخططة", + + // "item.edit.item-mapper.tabs.map": "Map new collections", + "item.edit.item-mapper.tabs.map": "تخطيط حاويات جديدة", + + // "item.edit.metadata.add-button": "Add", "item.edit.metadata.add-button": "إضافة", - "item.edit.metadata.discard-button": "لا", + + // "item.edit.metadata.discard-button": "Discard", + "item.edit.metadata.discard-button": "تجاهل", + + // "item.edit.metadata.edit.language": "Edit language", "item.edit.metadata.edit.language": "تحرير اللغة", + + // "item.edit.metadata.edit.value": "Edit value", "item.edit.metadata.edit.value": "تحرير القيمة", - "item.edit.metadata.edit.authority.key": "تحرير مفتاح السلطة", - "item.edit.metadata.edit.buttons.confirm": "بالتأكيد", - "item.edit.metadata.edit.buttons.drag": "احصل على إعادة الترتيب", + + // "item.edit.metadata.edit.authority.key": "Edit authority key", + // TODO New key - Add a translation + "item.edit.metadata.edit.authority.key": "Edit authority key", + + // "item.edit.metadata.edit.buttons.confirm": "Confirm", + "item.edit.metadata.edit.buttons.confirm": "تأكيد", + + // "item.edit.metadata.edit.buttons.drag": "Drag to reorder", + "item.edit.metadata.edit.buttons.drag": "اسحب لإعادة ترتيب", + + // "item.edit.metadata.edit.buttons.edit": "Edit", "item.edit.metadata.edit.buttons.edit": "تحرير", + + // "item.edit.metadata.edit.buttons.remove": "Remove", "item.edit.metadata.edit.buttons.remove": "إزالة", - "item.edit.metadata.edit.buttons.undo": "انقلب عن التغييرات", + + // "item.edit.metadata.edit.buttons.undo": "Undo changes", + "item.edit.metadata.edit.buttons.undo": "تراجع عن التغييرات", + + // "item.edit.metadata.edit.buttons.unedit": "Stop editing", "item.edit.metadata.edit.buttons.unedit": "توقف عن التحرير", - "item.edit.metadata.edit.buttons.virtual": "هذه القيمة ميتا افتراضية، أي قيمة موروثة من كينونة ذات صلة. ", - "item.edit.metadata.empty": "لا تحتوي المادة حاليا على أي ميتاداتا. ", + + // "item.edit.metadata.edit.buttons.virtual": "This is a virtual metadata value, i.e. a value inherited from a related entity. It can’t be modified directly. Add or remove the corresponding relationship in the \"Relationships\" tab", + "item.edit.metadata.edit.buttons.virtual": "هذه قيمة ميتاداتا افتراضية، أي قيمة موروثة من كينونة ذات صلة. ولا يمكن تعديلها مباشرة. إضافة أو إزالة العلاقة المقابلة في تبويب \"العلاقات\" ", + + // "item.edit.metadata.empty": "The item currently doesn't contain any metadata. Click Add to start adding a metadata value.", + "item.edit.metadata.empty": "لا تحتوي المادة حاليًا على أي ميتاداتا. انقر فوق إضافة لبدء إضافة قيمة ميتاداتا.", + + // "item.edit.metadata.headers.edit": "Edit", "item.edit.metadata.headers.edit": "تحرير", - "item.edit.metadata.headers.field": "حقل", + + // "item.edit.metadata.headers.field": "Field", + "item.edit.metadata.headers.field": "الحقل", + + // "item.edit.metadata.headers.language": "Lang", "item.edit.metadata.headers.language": "اللغة", + + // "item.edit.metadata.headers.value": "Value", "item.edit.metadata.headers.value": "القيمة", + + // "item.edit.metadata.metadatafield": "Edit field", "item.edit.metadata.metadatafield": "تحرير الحقل", - "item.edit.metadata.metadatafield.error": "حدث خطأ أثناء التحقق من صحة البحث في الميتاداتا", - "item.edit.metadata.metadatafield.invalid": "يرجى اختيار البحث ميتاداتا صالح", - "item.edit.metadata.notifications.discarded.content": "تم تجاهل تجاهلك. ", + + // "item.edit.metadata.metadatafield.error": "An error occurred validating the metadata field", + "item.edit.metadata.metadatafield.error": "حدث خطأ أثناء التحقق من صحة حقل الميتاداتا", + + // "item.edit.metadata.metadatafield.invalid": "Please choose a valid metadata field", + "item.edit.metadata.metadatafield.invalid": "يرجى اختيار حقل ميتاداتا صالح", + + // "item.edit.metadata.notifications.discarded.content": "Your changes were discarded. To reinstate your changes click the 'Undo' button", + "item.edit.metadata.notifications.discarded.content": "تم تجاهل تغييراتك. لإعادة تعيين التغييرات قم بالنقر على زر 'تراجع'", + + // "item.edit.metadata.notifications.discarded.title": "Changes discarded", "item.edit.metadata.notifications.discarded.title": "تم تجاهل التغييرات", + + // "item.edit.metadata.notifications.error.title": "An error occurred", "item.edit.metadata.notifications.error.title": "لقد حدث خطأ", - "item.edit.metadata.notifications.invalid.content": "لم يتم الحفاظ على جديدك. ", - "item.edit.metadata.notifications.invalid.title": "دياداتا غير صالحة", - "item.edit.metadata.notifications.outdated.content": "المادة التي تعمل بها حاليًا تم تغييرها بواسطة مستخدم آخر. ", - "item.edit.metadata.notifications.outdated.title": "اختر التغييرات", - "item.edit.metadata.notifications.saved.content": "تم الحفاظ على نقصانك في ميتاداتا لهذه المادة.", + + // "item.edit.metadata.notifications.invalid.content": "Your changes were not saved. Please make sure all fields are valid before you save.", + "item.edit.metadata.notifications.invalid.content": "لم يتم حفظ تغييراتك. يرجى التأكد من صحة جميع الحقول قبل الحفظ.", + + // "item.edit.metadata.notifications.invalid.title": "Metadata invalid", + "item.edit.metadata.notifications.invalid.title": "الميتاداتا غير صالحة", + + // "item.edit.metadata.notifications.outdated.content": "The item you're currently working on has been changed by another user. Your current changes are discarded to prevent conflicts", + "item.edit.metadata.notifications.outdated.content": "المادة التي تعمل عليها حالياً تم تغييرها بواسطة مستخدم آخر. تم تجاهل تغييراتك الحالية لتجنب التعارض", + + // "item.edit.metadata.notifications.outdated.title": "Changes outdated", + "item.edit.metadata.notifications.outdated.title": "انتهت صلاحية التغييرات", + + // "item.edit.metadata.notifications.saved.content": "Your changes to this item's metadata were saved.", + "item.edit.metadata.notifications.saved.content": "تم حفظ تغييراتك على ميتاداتا هذه المادة.", + + // "item.edit.metadata.notifications.saved.title": "Metadata saved", "item.edit.metadata.notifications.saved.title": "تم حفظ الميتاداتا", - "item.edit.metadata.reinstate-button": "ديب", - "item.edit.metadata.reset-order-button": "انعكاس عن إعادة الترتيب", + + // "item.edit.metadata.reinstate-button": "Undo", + "item.edit.metadata.reinstate-button": "تراجع", + + // "item.edit.metadata.reset-order-button": "Undo reorder", + "item.edit.metadata.reset-order-button": "تراجع عن إعادة الترتيب", + + // "item.edit.metadata.save-button": "Save", "item.edit.metadata.save-button": "حفظ", - "item.edit.metadata.authority.label": "سلطة: ", - "item.edit.metadata.edit.buttons.open-authority-edition": "افتح قيمة مفتاح السلطة للتحرير اليدوي", - "item.edit.metadata.edit.buttons.close-authority-edition": "قفل قيمة مفتاح السلطة للتحرير اليدوي", - "item.edit.modify.overview.field": "بحث متقدم", + + // "item.edit.metadata.authority.label": "Authority: ", + // TODO New key - Add a translation + "item.edit.metadata.authority.label": "Authority: ", + + // "item.edit.metadata.edit.buttons.open-authority-edition": "Unlock the authority key value for manual editing", + // TODO New key - Add a translation + "item.edit.metadata.edit.buttons.open-authority-edition": "Unlock the authority key value for manual editing", + + // "item.edit.metadata.edit.buttons.close-authority-edition": "Lock the authority key value for manual editing", + // TODO New key - Add a translation + "item.edit.metadata.edit.buttons.close-authority-edition": "Lock the authority key value for manual editing", + + // "item.edit.modify.overview.field": "Field", + "item.edit.modify.overview.field": "حقل", + + // "item.edit.modify.overview.language": "Language", "item.edit.modify.overview.language": "اللغة", - "item.edit.modify.overview.value": "القيمة", + + // "item.edit.modify.overview.value": "Value", + "item.edit.modify.overview.value": "قيمة", + + // "item.edit.move.cancel": "Back", "item.edit.move.cancel": "رجوع", + + // "item.edit.move.save-button": "Save", "item.edit.move.save-button": "حفظ", - "item.edit.move.discard-button": "لا", - "item.edit.move.description": "اختر ما تريد في نقل هذه المادة لها. ", + + // "item.edit.move.discard-button": "Discard", + "item.edit.move.discard-button": "تجاهل", + + // "item.edit.move.description": "Select the collection you wish to move this item to. To narrow down the list of displayed collections, you can enter a search query in the box.", + "item.edit.move.description": "اختر الحاوية التي ترغب في نقل هذه المادة لها. لتضييق قائمة الحاويات المعروضة، يمكنك إدخال استعلام بحث في المربع.", + + // "item.edit.move.error": "An error occurred when attempting to move the item", "item.edit.move.error": "حدث خطأ أثناء محاولة نقل المادة", - "item.edit.move.head": "المادة: {{id}}", - "item.edit.move.inheritpolicies.checkbox": "توريث", - "item.edit.move.inheritpolicies.description": "توريث خصيصاً للضوءية", - "item.edit.move.inheritpolicies.tooltip": "تحذير: عند التفعيل، ستستبدل سيجروم الوصول للقراءة الخاصة بالمادة وأي ملفات لاستخدام بسياسة الوصول للقراءة افتراضية للغاوية. ", + + // "item.edit.move.head": "Move item: {{id}}", + "item.edit.move.head": "نقل المادة: {{id}}", + + // "item.edit.move.inheritpolicies.checkbox": "Inherit policies", + "item.edit.move.inheritpolicies.checkbox": "توريث السياسات", + + // "item.edit.move.inheritpolicies.description": "Inherit the default policies of the destination collection", + "item.edit.move.inheritpolicies.description": "توريث السياسات الافتراضية للحاوية المقصودة", + + // "item.edit.move.inheritpolicies.tooltip": "Warning: When enabled, the read access policy for the item and any files associated with the item will be replaced by the default read access policy of the collection. This cannot be undone.", + "item.edit.move.inheritpolicies.tooltip": "تحذير: عند التفعيل، سيتم استبدال سياسة الوصول للقراءة الخاصة بالمادة وأي ملفات مرتبطة بالمادة بسياسة الوصول للقراءة الافتراضية للحاوية. لا يمكن التراجع عنه هذا الإجراء.", + + // "item.edit.move.move": "Move", "item.edit.move.move": "نقل", + + // "item.edit.move.processing": "Moving...", "item.edit.move.processing": "جاري النقل...", - "item.edit.move.search.placeholder": "قم برجاء التأكيد على البحث عن تيفين", - "item.edit.move.success": "تم نقل المادة الفعالة", + + // "item.edit.move.search.placeholder": "Enter a search query to look for collections", + "item.edit.move.search.placeholder": "قم بإدخال استعلام بحث للبحث عن حاويات", + + // "item.edit.move.success": "The item has been moved successfully", + "item.edit.move.success": "تم نقل المادة بنجاح", + + // "item.edit.move.title": "Move item", "item.edit.move.title": "نقل المادة", + + // "item.edit.private.cancel": "Cancel", "item.edit.private.cancel": "إلغاء", + + // "item.edit.private.confirm": "Make it non-discoverable", "item.edit.private.confirm": "اجعلها غير قابلة للاكتشاف", + + // "item.edit.private.description": "Are you sure this item should be made non-discoverable in the archive?", "item.edit.private.description": "هل أنت متأكد من أن هذه المادة يجب أن تكون غير قابلة للاكتشاف في الأرشيف؟", - "item.edit.private.error": "حدث خطأ أثناء وضع المادة غير قابلة للاكتشاف", - "item.edit.private.header": "المادة غير قابلة للاكتشاف: {{ id }}", + + // "item.edit.private.error": "An error occurred while making the item non-discoverable", + "item.edit.private.error": "حدث خطأ أثناء جعل المادة غير قابلة للاكتشاف", + + // "item.edit.private.header": "Make item non-discoverable: {{ id }}", + "item.edit.private.header": "اجعل المادة غير قابلة للاكتشاف: {{ id }}", + + // "item.edit.private.success": "The item is now non-discoverable", "item.edit.private.success": "المادة الآن غير قابلة للاكتشاف", + + // "item.edit.public.cancel": "Cancel", "item.edit.public.cancel": "إلغاء", - "item.edit.public.confirm": "اجعلها للاكتشاف", - "item.edit.public.description": "هل أنت متأكد من أنه يجب أن تمتلك هذه المادة القابلة للاكتشاف في الأرشيف؟", - "item.edit.public.error": "حدث خطأ أثناء المادة القابلة للاكتشاف", - "item.edit.public.header": "المادة قابلة للاكتشاف: {{ id }}", - "item.edit.public.success": "المادة الآن للاكتشاف", + + // "item.edit.public.confirm": "Make it discoverable", + "item.edit.public.confirm": "اجعلها قابلة للاكتشاف", + + // "item.edit.public.description": "Are you sure this item should be made discoverable in the archive?", + "item.edit.public.description": "هل أنت متأكد من أنه يجب جعل هذه المادة قابلة للاكتشاف في الأرشيف؟", + + // "item.edit.public.error": "An error occurred while making the item discoverable", + "item.edit.public.error": "حدث خطأ أثناء جعل المادة قابلة للاكتشاف", + + // "item.edit.public.header": "Make item discoverable: {{ id }}", + "item.edit.public.header": "اجعل المادة قابلة للاكتشاف: {{ id }}", + + // "item.edit.public.success": "The item is now discoverable", + "item.edit.public.success": "المادة الآن قابلة للاكتشاف", + + // "item.edit.reinstate.cancel": "Cancel", "item.edit.reinstate.cancel": "إلغاء", + + // "item.edit.reinstate.confirm": "Reinstate", "item.edit.reinstate.confirm": "إعادة تعيين", + + // "item.edit.reinstate.description": "Are you sure this item should be reinstated to the archive?", "item.edit.reinstate.description": "هل أنت متأكد من إعادة تعيين هذه المادة إلى الأرشيف؟", + + // "item.edit.reinstate.error": "An error occurred while reinstating the item", "item.edit.reinstate.error": "حدث خطأ أثناء إعادة تعيين المادة", + + // "item.edit.reinstate.header": "Reinstate item: {{ id }}", "item.edit.reinstate.header": "إعادة تعيين المادة: {{ id }}", - "item.edit.reinstate.success": "إعادة تعيين المادة الفعالة", - "item.edit.relationships.discard-button": "لا", + + // "item.edit.reinstate.success": "The item was reinstated successfully", + "item.edit.reinstate.success": "تمت إعادة تعيين المادة بنجاح", + + // "item.edit.relationships.discard-button": "Discard", + "item.edit.relationships.discard-button": "تجاهل", + + // "item.edit.relationships.edit.buttons.add": "Add", "item.edit.relationships.edit.buttons.add": "إضافة", + + // "item.edit.relationships.edit.buttons.remove": "Remove", "item.edit.relationships.edit.buttons.remove": "إزالة", - "item.edit.relationships.edit.buttons.undo": "انقلب عن التغييرات", + + // "item.edit.relationships.edit.buttons.undo": "Undo changes", + "item.edit.relationships.edit.buttons.undo": "تراجع عن التغييرات", + + // "item.edit.relationships.no-relationships": "No relationships", "item.edit.relationships.no-relationships": "لا توجد علاقات", - "item.edit.relationships.notifications.discarded.content": "تم تجاهل تجاهلك. ", + + // "item.edit.relationships.notifications.discarded.content": "Your changes were discarded. To reinstate your changes click the 'Undo' button", + "item.edit.relationships.notifications.discarded.content": "تم تجاهل تغييراتك. لإعادة تعيين التغييرات قم بالنقر على زر 'تراجع'", + + // "item.edit.relationships.notifications.discarded.title": "Changes discarded", "item.edit.relationships.notifications.discarded.title": "تم تجاهل التغييرات", + + // "item.edit.relationships.notifications.failed.title": "Error editing relationships", "item.edit.relationships.notifications.failed.title": "حدث خطأ أثناء تحرير العلاقات", - "item.edit.relationships.notifications.outdated.content": "المادة التي تعمل بها حاليًا تم تغييرها بواسطة مستخدم آخر. ", - "item.edit.relationships.notifications.outdated.title": "اختر التغييرات", - "item.edit.relationships.notifications.saved.content": "تم الحفاظ على أفكارك على علاقات هذه المادة.", + + // "item.edit.relationships.notifications.outdated.content": "The item you're currently working on has been changed by another user. Your current changes are discarded to prevent conflicts", + "item.edit.relationships.notifications.outdated.content": "المادة التي تعمل عليها حالياً تم تغييرها بواسطة مستخدم آخر. تم تجاهل تغييراتك الحالية لتجنب التعارض", + + // "item.edit.relationships.notifications.outdated.title": "Changes outdated", + "item.edit.relationships.notifications.outdated.title": "انتهت صلاحية التغييرات", + + // "item.edit.relationships.notifications.saved.content": "Your changes to this item's relationships were saved.", + "item.edit.relationships.notifications.saved.content": "تم حفظ تغييراتك على علاقات هذه المادة.", + + // "item.edit.relationships.notifications.saved.title": "Relationships saved", "item.edit.relationships.notifications.saved.title": "تم حفظ العلاقات", - "item.edit.relationships.reinstate-button": "ديب", + + // "item.edit.relationships.reinstate-button": "Undo", + "item.edit.relationships.reinstate-button": "تراجع", + + // "item.edit.relationships.save-button": "Save", "item.edit.relationships.save-button": "حفظ", - "item.edit.relationships.no-entity-type": "قم بإضافة ميتا 'dspace.entity.type' لتفعيل هذه العلاقات", + + // "item.edit.relationships.no-entity-type": "Add 'dspace.entity.type' metadata to enable relationships for this item", + "item.edit.relationships.no-entity-type": "قم بإضافة ميتاداتا 'dspace.entity.type' لتفعيل العلاقات لهذه المادة", + + // "item.edit.return": "Back", "item.edit.return": "رجوع", + + // "item.edit.tabs.bitstreams.head": "Bitstreams", "item.edit.tabs.bitstreams.head": "تدفقات البت", - "item.edit.tabs.bitstreams.title": "المادة الخام - تدفقات البت", + + // "item.edit.tabs.bitstreams.title": "Item Edit - Bitstreams", + "item.edit.tabs.bitstreams.title": "تحرير المادة - تدفقات البت", + + // "item.edit.tabs.curate.head": "Curate", "item.edit.tabs.curate.head": "أكرتة", + + // "item.edit.tabs.curate.title": "Item Edit - Curate", "item.edit.tabs.curate.title": "تحرير المادة - أكرتة", - "item.edit.curate.title": "المادة المادة: {{item}}", + + // "item.edit.curate.title": "Curate Item: {{item}}", + "item.edit.curate.title": "أكرتة المادة: {{item}}", + + // "item.edit.tabs.access-control.head": "Access Control", "item.edit.tabs.access-control.head": "التحكم في الوصول", + + // "item.edit.tabs.access-control.title": "Item Edit - Access Control", "item.edit.tabs.access-control.title": "تحرير المادة - التحكم في الوصول", - "item.edit.tabs.metadata.head": "ميداداتا", - "item.edit.tabs.metadata.title": "تحرير المادة - الميتاداتا", + + // "item.edit.tabs.metadata.head": "Metadata", + "item.edit.tabs.metadata.head": "الميتاداتا", + + // "item.edit.tabs.metadata.title": "Item Edit - Metadata", + "item.edit.tabs.metadata.title": "تحرير المادة - الميتاداتا", + + // "item.edit.tabs.relationships.head": "Relationships", "item.edit.tabs.relationships.head": "العلاقات", + + // "item.edit.tabs.relationships.title": "Item Edit - Relationships", "item.edit.tabs.relationships.title": "تحرير الماة - العلاقات", - "item.edit.tabs.status.buttons.authorizations.button": "...تصاريح", - "item.edit.tabs.status.buttons.authorizations.label": "تحرير سياسات المادة", - "item.edit.tabs.status.buttons.delete.button": "حذف", - "item.edit.tabs.status.buttons.delete.label": "شطب المادة", - "item.edit.tabs.status.buttons.mappedCollections.button": "وثيقة الوثيقة", - "item.edit.tabs.status.buttons.mappedCollections.label": "غير متوقعة", - "item.edit.tabs.status.buttons.move.button": "قم بنقل هذه المادة إلى حاوية مختلفة", - "item.edit.tabs.status.buttons.move.label": "قم بنقل هذه المادة إلى حاوية مختلفة", + + // "item.edit.tabs.status.buttons.authorizations.button": "Authorizations...", + "item.edit.tabs.status.buttons.authorizations.button": "تصاريح...", + + // "item.edit.tabs.status.buttons.authorizations.label": "Edit item's authorization policies", + "item.edit.tabs.status.buttons.authorizations.label": "تحرير سياسات تصاريح المادة", + + // "item.edit.tabs.status.buttons.delete.button": "Permanently delete", + "item.edit.tabs.status.buttons.delete.button": "حذف نهائي", + + // "item.edit.tabs.status.buttons.delete.label": "Completely expunge item", + "item.edit.tabs.status.buttons.delete.label": "شطب المادة تماماً", + + // "item.edit.tabs.status.buttons.mappedCollections.button": "Mapped collections", + "item.edit.tabs.status.buttons.mappedCollections.button": "حاويات مخططة", + + // "item.edit.tabs.status.buttons.mappedCollections.label": "Manage mapped collections", + "item.edit.tabs.status.buttons.mappedCollections.label": "أدر الحاويات المخططة", + + // "item.edit.tabs.status.buttons.move.button": "Move this Item to a different Collection", + "item.edit.tabs.status.buttons.move.button": "نقل هذه المادة إلى حاوية مختلفة", + + // "item.edit.tabs.status.buttons.move.label": "Move item to another collection", + "item.edit.tabs.status.buttons.move.label": "نقل هذه المادة إلى حاوية مختلفة", + + // "item.edit.tabs.status.buttons.private.button": "Make it non-discoverable...", "item.edit.tabs.status.buttons.private.button": "اجعلها غير قابلة للاكتشاف...", - "item.edit.tabs.status.buttons.private.label": "المادة غير قابلة للاكتشاف", - "item.edit.tabs.status.buttons.public.button": "اجعلها للاكتشاف...", - "item.edit.tabs.status.buttons.public.label": "المادة قابلة للاكتشاف", + + // "item.edit.tabs.status.buttons.private.label": "Make item non-discoverable", + "item.edit.tabs.status.buttons.private.label": "اجعل المادة غير قابلة للاكتشاف", + + // "item.edit.tabs.status.buttons.public.button": "Make it discoverable...", + "item.edit.tabs.status.buttons.public.button": "اجعلها قابلة للاكتشاف...", + + // "item.edit.tabs.status.buttons.public.label": "Make item discoverable", + "item.edit.tabs.status.buttons.public.label": "اجعل المادة قابلة للاكتشاف", + + // "item.edit.tabs.status.buttons.reinstate.button": "Reinstate...", "item.edit.tabs.status.buttons.reinstate.button": "إعادة تعيين...", + + // "item.edit.tabs.status.buttons.reinstate.label": "Reinstate item into the repository", "item.edit.tabs.status.buttons.reinstate.label": "إعادة تعيين المادة في المستودع", - "item.edit.tabs.status.buttons.unauthorized": "غير مصرح لك بهذا الاقتراح", - "item.edit.tabs.status.buttons.withdraw.button": "اسحب هذه المادة", - "item.edit.tabs.status.buttons.withdraw.label": "اسحب هذه المادة من المستودع", - "item.edit.tabs.status.description": "مرحبا بك في صفحة إدارة المادة. ", + + // "item.edit.tabs.status.buttons.unauthorized": "You're not authorized to perform this action", + "item.edit.tabs.status.buttons.unauthorized": "غير مصرح لك بالقيام بهذا الإجراء", + + // "item.edit.tabs.status.buttons.withdraw.button": "Withdraw this item", + "item.edit.tabs.status.buttons.withdraw.button": "سحب هذه المادة", + + // "item.edit.tabs.status.buttons.withdraw.label": "Withdraw item from the repository", + "item.edit.tabs.status.buttons.withdraw.label": "سحب هذه المادة من المستودع", + + // "item.edit.tabs.status.description": "Welcome to the item management page. From here you can withdraw, reinstate, move or delete the item. You may also update or add new metadata / bitstreams on the other tabs.", + "item.edit.tabs.status.description": "مرحباً بك في صفحة إدارة المادة. من هنا يمكنك سحب المادة، أو إعادة تعيينها، أو نقلها أو حذفها. كما يمكنك تحديث أو إضافة ميتاداتا/ تدفقات بت جديدة في التبويبات الأخرى.", + + // "item.edit.tabs.status.head": "Status", "item.edit.tabs.status.head": "الحالة", - "item.edit.tabs.status.labels.handle": "مقبض", - "item.edit.tabs.status.labels.id": "تم تعريف المادة داخليًا", + + // "item.edit.tabs.status.labels.handle": "Handle", + "item.edit.tabs.status.labels.handle": "هاندل", + + // "item.edit.tabs.status.labels.id": "Item Internal ID", + "item.edit.tabs.status.labels.id": "معرّف المادة الداخلي", + + // "item.edit.tabs.status.labels.itemPage": "Item Page", "item.edit.tabs.status.labels.itemPage": "صفحة المادة", + + // "item.edit.tabs.status.labels.lastModified": "Last Modified", "item.edit.tabs.status.labels.lastModified": "آخر تعديل", - "item.edit.tabs.status.title": "تحرير المادة - الحالة", - "item.edit.tabs.versionhistory.head": "نسخة السجل", - "item.edit.tabs.versionhistory.title": "تحرير المادة - سجل النسخة", - "item.edit.tabs.versionhistory.under-construction": "تحرير أو إضافة إصدار جديد ليس ممكناً بعد في واجهة المستخدم هذه..", + + // "item.edit.tabs.status.title": "Item Edit - Status", + "item.edit.tabs.status.title": "تحرير المادة - الحالة", + + // "item.edit.tabs.versionhistory.head": "Version History", + "item.edit.tabs.versionhistory.head": "سجل الإصدارة", + + // "item.edit.tabs.versionhistory.title": "Item Edit - Version History", + "item.edit.tabs.versionhistory.title": "تحرير المادة - سجل الإصدارة", + + // "item.edit.tabs.versionhistory.under-construction": "Editing or adding new versions is not yet possible in this user interface.", + "item.edit.tabs.versionhistory.under-construction": "تحرير أو إضافة إصدارات جديدة ليس ممكناً بعد في واجهة المستخدم هذه..", + + // "item.edit.tabs.view.head": "View Item", "item.edit.tabs.view.head": "عرض المادة", - "item.edit.tabs.view.title": "تحرير المادة - عرض", + + // "item.edit.tabs.view.title": "Item Edit - View", + "item.edit.tabs.view.title": "تحرير المادة - عرض", + + // "item.edit.withdraw.cancel": "Cancel", "item.edit.withdraw.cancel": "إلغاء", - "item.edit.withdraw.confirm": "يسحب", - "item.edit.withdraw.description": "هل أنت متأكد من أنك لا تستطيع سحب هذه المادة من الأرشيف؟", - "item.edit.withdraw.error": "حدث خطأ أثناء المادة", - "item.edit.withdraw.header": "المادة: {{ id }}", - "item.edit.withdraw.success": "تم سحب المادة الفعالة", + + // "item.edit.withdraw.confirm": "Withdraw", + "item.edit.withdraw.confirm": "سحب", + + // "item.edit.withdraw.description": "Are you sure this item should be withdrawn from the archive?", + "item.edit.withdraw.description": "هل أنت متأكد من ضرورة سحب هذه المادة من الأرشيف؟", + + // "item.edit.withdraw.error": "An error occurred while withdrawing the item", + "item.edit.withdraw.error": "حدث خطأ أثناء سحب المادة", + + // "item.edit.withdraw.header": "Withdraw item: {{ id }}", + "item.edit.withdraw.header": "سحب المادة: {{ id }}", + + // "item.edit.withdraw.success": "The item was withdrawn successfully", + "item.edit.withdraw.success": "تم سحب المادة بنجاح", + + // "item.orcid.return": "Back", "item.orcid.return": "رجوع", + + // "item.listelement.badge": "Item", "item.listelement.badge": "المادة", + + // "item.page.description": "Description", "item.page.description": "الوصف", + + // "item.page.journal-issn": "Journal ISSN", "item.page.journal-issn": "ردمد الدورية", - "item.page.journal-title": "عنوان الدوري", + + // "item.page.journal-title": "Journal Title", + "item.page.journal-title": "عنوان الدورية", + + // "item.page.publisher": "Publisher", "item.page.publisher": "الناشر", + + // "item.page.titleprefix": "Item: ", "item.page.titleprefix": "المادة: ", + + // "item.page.volume-title": "Volume Title", "item.page.volume-title": "عنوان المجلد", - "item.search.results.head": "نتائج بحثت المواد", - "item.search.title": "بحثت المواد", + + // "item.search.results.head": "Item Search Results", + "item.search.results.head": "نتائج بحث المواد", + + // "item.search.title": "Item Search", + "item.search.title": "بحث المواد", + + // "item.truncatable-part.show-more": "Show more", "item.truncatable-part.show-more": "عرض المواد", - "item.truncatable-part.show-less": "طيء", - "item.qa-event-notification.check.notification-info": "هناك {{num}} في انتظار الاقتراحات المتعلقة بحسابك", - "item.qa-event-notification-info.check.button": "منظر", - "mydspace.qa-event-notification.check.notification-info": "هناك {{num}} في انتظار الاقتراحات المتعلقة بحسابك", - "mydspace.qa-event-notification-info.check.button": "منظر", + + // "item.truncatable-part.show-less": "Collapse", + "item.truncatable-part.show-less": "طي", + + // "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": "حذف أمر الإشراف", - "workflow-item.search.result.delete-supervision.modal.info": "هل أنت متأكد من أنك تريد حذف أمر مهم؟", + + // "workflow-item.search.result.delete-supervision.modal.info": "Are you sure you want to delete Supervision Order", + "workflow-item.search.result.delete-supervision.modal.info": "هل أنت متأكد من أنك تريد حذف أمر الإشراف", + + // "workflow-item.search.result.delete-supervision.modal.cancel": "Cancel", "workflow-item.search.result.delete-supervision.modal.cancel": "إلغاء", + + // "workflow-item.search.result.delete-supervision.modal.confirm": "Delete", "workflow-item.search.result.delete-supervision.modal.confirm": "حذف", - "workflow-item.search.result.notification.deleted.success": "تم الحذف أمر فعال فعال \"{{name}}\"", + + // "workflow-item.search.result.notification.deleted.success": "Successfully deleted supervision order \"{{name}}\"", + "workflow-item.search.result.notification.deleted.success": "تم حذف أمر الإشراف بنجاح \"{{name}}\"", + + // "workflow-item.search.result.notification.deleted.failure": "Failed to delete supervision order \"{{name}}\"", "workflow-item.search.result.notification.deleted.failure": "فشل في حذف أمر الإشراف \"{{name}}\"", - "workflow-item.search.result.list.element.supervised-by": "تحت الضربة:", + + // "workflow-item.search.result.list.element.supervised-by": "Supervised by:", + "workflow-item.search.result.list.element.supervised-by": "تحت إشراف:", + + // "workflow-item.search.result.list.element.supervised.remove-tooltip": "Remove supervision group", "workflow-item.search.result.list.element.supervised.remove-tooltip": "إزالة مجموعة الإشراف", - "confidence.indicator.help-text.accepted": "تم تأكيد دقة قيمة الاستناد هذه من قبل مستخدم تفاعلي", - "confidence.indicator.help-text.uncertain": "القيمة مفردة وصالحة ولكن لم يراها الإنسان ويقبلها، لذا فهي لا تزال غير مؤكدة", - "confidence.indicator.help-text.ambiguous": "هناك العديد من قيم السلطة المطابقة ذات الصلاحية المتساوية", - "confidence.indicator.help-text.notfound": "لا توجد إجابات مطابقة في السلطة", - "confidence.indicator.help-text.failed": "واجهت السلطة فشلا داخليا", - "confidence.indicator.help-text.rejected": "توصي الهيئة برفض هذا التقديم", - "confidence.indicator.help-text.novalue": "ولم يتم إرجاع أي قيمة ثقة معقولة من الهيئة", - "confidence.indicator.help-text.unset": "لم يتم تسجيل الثقة بهذه القيمة أبدًا", - "confidence.indicator.help-text.unknown": "قيمة ثقة غير معروفة", - "item.page.abstract": "أ", + + // "confidence.indicator.help-text.accepted": "This authority value has been confirmed as accurate by an interactive user", + // TODO New key - Add a translation + "confidence.indicator.help-text.accepted": "This authority value has been confirmed as accurate by an interactive user", + + // "confidence.indicator.help-text.uncertain": "Value is singular and valid but has not been seen and accepted by a human so it is still uncertain", + // TODO New key - Add a translation + "confidence.indicator.help-text.uncertain": "Value is singular and valid but has not been seen and accepted by a human so it is still uncertain", + + // "confidence.indicator.help-text.ambiguous": "There are multiple matching authority values of equal validity", + // TODO New key - Add a translation + "confidence.indicator.help-text.ambiguous": "There are multiple matching authority values of equal validity", + + // "confidence.indicator.help-text.notfound": "There are no matching answers in the authority", + // TODO New key - Add a translation + "confidence.indicator.help-text.notfound": "There are no matching answers in the authority", + + // "confidence.indicator.help-text.failed": "The authority encountered an internal failure", + // TODO New key - Add a translation + "confidence.indicator.help-text.failed": "The authority encountered an internal failure", + + // "confidence.indicator.help-text.rejected": "The authority recommends this submission be rejected", + // TODO New key - Add a translation + "confidence.indicator.help-text.rejected": "The authority recommends this submission be rejected", + + // "confidence.indicator.help-text.novalue": "No reasonable confidence value was returned from the authority", + // TODO New key - Add a translation + "confidence.indicator.help-text.novalue": "No reasonable confidence value was returned from the authority", + + // "confidence.indicator.help-text.unset": "Confidence was never recorded for this value", + // TODO New key - Add a translation + "confidence.indicator.help-text.unset": "Confidence was never recorded for this value", + + // "confidence.indicator.help-text.unknown": "Unknown confidence value", + // TODO New key - Add a translation + "confidence.indicator.help-text.unknown": "Unknown confidence value", + + // "item.page.abstract": "Abstract", + "item.page.abstract": "خلاصة", + + // "item.page.author": "Authors", "item.page.author": "المؤلفين", - "item.page.citation": "المرسل", - "item.page.collections": "مقبول", + + // "item.page.citation": "Citation", + "item.page.citation": "اقتباس", + + // "item.page.collections": "Collections", + "item.page.collections": "الحاويات", + + // "item.page.collections.loading": "Loading...", "item.page.collections.loading": "جاري التحميل...", + + // "item.page.collections.load-more": "Load more", "item.page.collections.load-more": "تحميل المزيد", + + // "item.page.date": "Date", "item.page.date": "التاريخ", + + // "item.page.edit": "Edit this item", "item.page.edit": "تحرير هذه المادة", + + // "item.page.files": "Files", "item.page.files": "ملفات", + + // "item.page.filesection.description": "Description:", "item.page.filesection.description": "الوصف:", + + // "item.page.filesection.download": "Download", "item.page.filesection.download": "تنزيل", - "item.page.filesection.format": "التنسيق:", + + // "item.page.filesection.format": "Format:", + "item.page.filesection.format": "تنسيق:", + + // "item.page.filesection.name": "Name:", "item.page.filesection.name": "الاسم:", + + // "item.page.filesection.size": "Size:", "item.page.filesection.size": "الحجم:", + + // "item.page.journal.search.title": "Articles in this journal", "item.page.journal.search.title": "مقالات في هذه الدورية", - "item.page.link.full": "صفحة المادة كاملة", + + // "item.page.link.full": "Full item page", + "item.page.link.full": "صفحة المادة الكاملة", + + // "item.page.link.simple": "Simple item page", "item.page.link.simple": "صفحة المادة البسيطة", + + // "item.page.orcid.title": "ORCID", "item.page.orcid.title": "أوركيد", + + // "item.page.orcid.tooltip": "Open ORCID setting page", "item.page.orcid.tooltip": "فتح صفحة إعداد أوركيد", + + // "item.page.person.search.title": "Articles by this author", "item.page.person.search.title": "مقالات بواسطة هذا المؤلف", - "item.page.related-items.view-more": "الإظهار {{ amount }} أكثر", + + // "item.page.related-items.view-more": "Show {{ amount }} more", + "item.page.related-items.view-more": "إظهار {{ amount }} أكثر", + + // "item.page.related-items.view-less": "Hide last {{ amount }}", "item.page.related-items.view-less": "إخفاء آخر {{ amount }}", - "item.page.relationships.isAuthorOfPublication": "منشورات", - "item.page.relationships.isJournalOfPublication": "منشورات", + + // "item.page.relationships.isAuthorOfPublication": "Publications", + "item.page.relationships.isAuthorOfPublication": "المنشورات", + + // "item.page.relationships.isJournalOfPublication": "Publications", + "item.page.relationships.isJournalOfPublication": "المنشورات", + + // "item.page.relationships.isOrgUnitOfPerson": "Authors", "item.page.relationships.isOrgUnitOfPerson": "المؤلفين", + + // "item.page.relationships.isOrgUnitOfProject": "Research Projects", "item.page.relationships.isOrgUnitOfProject": "مشاريع البحث", - "item.page.subject": "الكلمات الرئيسية", + + // "item.page.subject": "Keywords", + "item.page.subject": "كلمات رئيسية", + + // "item.page.uri": "URI", "item.page.uri": "URI", + + // "item.page.bitstreams.view-more": "Show more", "item.page.bitstreams.view-more": "عرض المزيد", - "item.page.bitstreams.collapse": "طيء", - "item.page.bitstreams.primary": "أساسي", + + // "item.page.bitstreams.collapse": "Collapse", + "item.page.bitstreams.collapse": "طي", + + // "item.page.bitstreams.primary": "Primary", + // TODO New key - Add a translation + "item.page.bitstreams.primary": "Primary", + + // "item.page.filesection.original.bundle": "Original bundle", "item.page.filesection.original.bundle": "الحزمة الرئيسية", - "item.page.filesection.license.bundle": "حزمة الحزمة", + + // "item.page.filesection.license.bundle": "License bundle", + "item.page.filesection.license.bundle": "حزمة الترخيص", + + // "item.page.return": "Back", "item.page.return": "رجوع", - "item.page.version.create": "إنشاء طبعة جديدة", - "item.page.withdrawn": "طلب سحب لهذا البند", - "item.page.reinstate": "طلب الإعادة", - "item.page.version.hasDraft": "لا يمكن إنشاء نسخة جديدة إذًا هناك تقديم قيد التقدم في نسخة النسخة", + + // "item.page.version.create": "Create new version", + "item.page.version.create": "إنشاء إصدارة جديدة", + + // "item.page.withdrawn": "Request a withdrawal for this item", + // TODO New key - Add a translation + "item.page.withdrawn": "Request a withdrawal for this item", + + // "item.page.reinstate": "Request reinstatement", + // TODO New key - Add a translation + "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.version.hasDraft": "لا يمكن إنشاء إصدارة جديدة نظراً لوجود تقديم قيد التقدم في سجل الإصدارة", + + // "item.page.claim.button": "Claim", "item.page.claim.button": "مطالبة", - "item.page.claim.tooltip": "بسبب هذه المادة الشخصية", - "item.page.image.alt.ROR": "شعار ROR", + + // "item.page.claim.tooltip": "Claim this item as profile", + "item.page.claim.tooltip": "المطالبة بهذه المادة كملف شخصي", + + // "item.page.image.alt.ROR": "ROR logo", + "item.page.image.alt.ROR": "ROR شعار", + + // "item.preview.dc.identifier.uri": "Identifier:", "item.preview.dc.identifier.uri": "المعرف:", + + // "item.preview.dc.contributor.author": "Authors:", "item.preview.dc.contributor.author": "المؤلفين:", + + // "item.preview.dc.date.issued": "Published date:", "item.preview.dc.date.issued": "تاريخ النشر:", - "item.preview.dc.description.abstract": "السرعة:", + + // "item.preview.dc.description.abstract": "Abstract:", + "item.preview.dc.description.abstract": "مستخلص:", + + // "item.preview.dc.identifier.other": "Other identifier:", "item.preview.dc.identifier.other": "معرف آخر:", + + // "item.preview.dc.language.iso": "Language:", "item.preview.dc.language.iso": "اللغة:", - "item.preview.dc.subject": "الموضوع:", - "item.preview.dc.title": "عنوان العنوان:", + + // "item.preview.dc.subject": "Subjects:", + "item.preview.dc.subject": "الموضوعات:", + + // "item.preview.dc.title": "Title:", + "item.preview.dc.title": "العنوان:", + + // "item.preview.dc.type": "Type:", "item.preview.dc.type": "النوع:", + + // "item.preview.oaire.citation.issue": "Issue", "item.preview.oaire.citation.issue": "العدد", - "item.preview.oaire.citation.volume": "مجلد", - "item.preview.dc.relation.issn": "الرقم الدولي الموحد للدوريات", - "item.preview.dc.identifier.isbn": "رقم ISBN", + + // "item.preview.oaire.citation.volume": "Volume", + "item.preview.oaire.citation.volume": "المجلد", + + // "item.preview.dc.relation.issn": "ISSN", + "item.preview.dc.relation.issn": "ISSN", + + // "item.preview.dc.identifier.isbn": "ISBN", + "item.preview.dc.identifier.isbn": "ISBN", + + // "item.preview.dc.identifier": "Identifier:", "item.preview.dc.identifier": "المعرف:", - "item.preview.dc.relation.ispartof": "الدوري", - "item.preview.dc.identifier.doi": "المعرفة الرقمية", + + // "item.preview.dc.relation.ispartof": "Journal or Series", + "item.preview.dc.relation.ispartof": "الدورية", + + // "item.preview.dc.identifier.doi": "DOI", + "item.preview.dc.identifier.doi": "معرف الكائن الرقمي", + + // "item.preview.dc.publisher": "Publisher:", "item.preview.dc.publisher": "الناشر:", - "item.preview.person.familyName": "يتمنى:", + + // "item.preview.person.familyName": "Surname:", + "item.preview.person.familyName": "اللقب:", + + // "item.preview.person.givenName": "Name:", "item.preview.person.givenName": "الاسم:", + + // "item.preview.person.identifier.orcid": "ORCID:", "item.preview.person.identifier.orcid": "أوركيد:", + + // "item.preview.project.funder.name": "Funder:", "item.preview.project.funder.name": "الممول:", + + // "item.preview.project.funder.identifier": "Funder Identifier:", "item.preview.project.funder.identifier": "معرف الممول:", + + // "item.preview.oaire.awardNumber": "Funding ID:", "item.preview.oaire.awardNumber": "معرف التمويل:", + + // "item.preview.dc.title.alternative": "Acronym:", "item.preview.dc.title.alternative": "الحروف المختصرة:", - "item.preview.dc.coverage.spatial": "عدم التفويض:", - "item.preview.oaire.fundingStream": "التدفق:", + + // "item.preview.dc.coverage.spatial": "Jurisdiction:", + "item.preview.dc.coverage.spatial": "الاختصاص القضائي:", + + // "item.preview.oaire.fundingStream": "Funding Stream:", + "item.preview.oaire.fundingStream": "تدفق التمويل:", + + // "item.preview.oairecerif.identifier.url": "URL", "item.preview.oairecerif.identifier.url": "عنوان URL", + + // "item.preview.organization.address.addressCountry": "Country", "item.preview.organization.address.addressCountry": "البلد", + + // "item.preview.organization.foundingDate": "Founding Date", "item.preview.organization.foundingDate": "تاريخ التأسيس", - "item.preview.organization.identifier.crossrefid": "معرف Crossref", - "item.preview.organization.identifier.isni": "إسني", - "item.preview.organization.identifier.ror": "معرف ROR", - "item.preview.organization.legalName": "الاسم الساقي", - "item.preview.dspace.entity.type": "نوع الكيان:", - "item.select.confirm": "بالتأكيد", - "item.select.empty": "لا يوجد شيء للعرض", + + // "item.preview.organization.identifier.crossrefid": "CrossRef ID", + "item.preview.organization.identifier.crossrefid": "CrossRef معرف", + + // "item.preview.organization.identifier.isni": "ISNI", + "item.preview.organization.identifier.isni": "ISNI", + + // "item.preview.organization.identifier.ror": "ROR ID", + "item.preview.organization.identifier.ror": "ROR معرف", + + // "item.preview.organization.legalName": "Legal Name", + "item.preview.organization.legalName": "الاسم القانوني", + + // "item.preview.dspace.entity.type": "Entity Type:", + // TODO New key - Add a translation + "item.preview.dspace.entity.type": "Entity Type:", + + // "item.select.confirm": "Confirm selected", + "item.select.confirm": "تأكيد المحدد", + + // "item.select.empty": "No items to show", + "item.select.empty": "لا توجد مواد للعرض", + + // "item.select.table.selected": "Selected items", "item.select.table.selected": "المواد المحددة", - "item.select.table.select": "المادة المحددة", - "item.select.table.deselect": "قم بإلغاء تحديد المادة", + + // "item.select.table.select": "Select item", + "item.select.table.select": "تحديد المادة", + + // "item.select.table.deselect": "Deselect item", + "item.select.table.deselect": "إلغاء تحديد المادة", + + // "item.select.table.author": "Author", "item.select.table.author": "المؤلف", - "item.select.table.collection": "ابدأ", - "item.select.table.title": "عنوان العنوان", - "item.version.history.empty": "لا توجد إصدارات أخرى من هذه الخامة حتى الآن.", - "item.version.history.head": "نسخة السجل", + + // "item.select.table.collection": "Collection", + "item.select.table.collection": "الحاوية", + + // "item.select.table.title": "Title", + "item.select.table.title": "العنوان", + + // "item.version.history.empty": "There are no other versions for this item yet.", + "item.version.history.empty": "لا توجد إصدارات أخرى لهذه المادة حتى الآن.", + + // "item.version.history.head": "Version History", + "item.version.history.head": "سجل الإصدارة", + + // "item.version.history.return": "Back", "item.version.history.return": "رجوع", + + // "item.version.history.selected": "Selected version", "item.version.history.selected": "افصدارة المحددة", - "item.version.history.selected.alert": "أنت حاليا تقوم بعرض النسخة {{version}} لذلك.", - "item.version.history.table.version": "النسخة", + + // "item.version.history.selected.alert": "You are currently viewing version {{version}} of the item.", + "item.version.history.selected.alert": "أنت حالياً تقوم بعرض الإصدارة {{version}} للمادة.", + + // "item.version.history.table.version": "Version", + "item.version.history.table.version": "الإصدارة", + + // "item.version.history.table.item": "Item", "item.version.history.table.item": "المادة", + + // "item.version.history.table.editor": "Editor", "item.version.history.table.editor": "المحرر", + + // "item.version.history.table.date": "Date", "item.version.history.table.date": "التاريخ", + + // "item.version.history.table.summary": "Summary", "item.version.history.table.summary": "الملخص", - "item.version.history.table.workspaceItem": "نطاق العمل", + + // "item.version.history.table.workspaceItem": "Workspace item", + "item.version.history.table.workspaceItem": "مادة نطاق العمل", + + // "item.version.history.table.workflowItem": "Workflow item", "item.version.history.table.workflowItem": "مادة سير العمل", + + // "item.version.history.table.actions": "Action", "item.version.history.table.actions": "الإجراء", - "item.version.history.table.action.editWorkspaceItem": "تحرير مساحة العمل", + + // "item.version.history.table.action.editWorkspaceItem": "Edit workspace item", + "item.version.history.table.action.editWorkspaceItem": "تحرير مادة نطاق العمل", + + // "item.version.history.table.action.editSummary": "Edit summary", "item.version.history.table.action.editSummary": "تحرير الملخص", - "item.version.history.table.action.saveSummary": "حفظ الملخص", - "item.version.history.table.action.discardSummary": "أهمل الملخص", - "item.version.history.table.action.newVersion": "إنشاء نسخة جديدة من هذه النسخة", - "item.version.history.table.action.deleteVersion": "حذف النسخة", - "item.version.history.table.action.hasDraft": "لا يمكن إنشاء نسخة جديدة إذًا هناك تقديم قيد التقدم في نسخة النسخة", - "item.version.notice": "هذه ليست آخر نسخة من هذه المادة. هنا.", - "item.version.create.modal.header": "نسخة جديدة", - "item.qa.withdrawn.modal.header": "طلب الانسحاب", - "item.qa.reinstate.modal.header": "طلب إعادة", - "item.qa.reinstate.create.modal.header": "نسخة جديدة", - "item.version.create.modal.text": "خلق نسخة جديدة لهذه المادة", - "item.version.create.modal.text.startingFrom": "البدء من النسخة {{version}}", + + // "item.version.history.table.action.saveSummary": "Save summary edits", + "item.version.history.table.action.saveSummary": "حفظ تعديلات الملخص", + + // "item.version.history.table.action.discardSummary": "Discard summary edits", + "item.version.history.table.action.discardSummary": "تجاهل تعديلات الملخص", + + // "item.version.history.table.action.newVersion": "Create new version from this one", + "item.version.history.table.action.newVersion": "إنشاء إصدارة جديدة من هذه الإصدارة", + + // "item.version.history.table.action.deleteVersion": "Delete version", + "item.version.history.table.action.deleteVersion": "حذف الإصدارة", + + // "item.version.history.table.action.hasDraft": "A new version cannot be created because there is an inprogress submission in the version history", + "item.version.history.table.action.hasDraft": "لا يمكن إنشاء إصدارة جديدة نظراً لوجود تقديم قيد التقدم في سجل الإصدارة", + + // "item.version.notice": "This is not the latest version of this item. The latest version can be found here.", + "item.version.notice": "هذه ليست آخر إصدارة من هذه المادة. يمكن العثور على آخر إصدارة من هنا.", + + // "item.version.create.modal.header": "New version", + "item.version.create.modal.header": "إصدارة جديدة", + + // "item.qa.withdrawn.modal.header": "Request withdrawal", + // TODO New key - Add a translation + "item.qa.withdrawn.modal.header": "Request withdrawal", + + // "item.qa.reinstate.modal.header": "Request reinstate", + // TODO New key - Add a translation + "item.qa.reinstate.modal.header": "Request reinstate", + + // "item.qa.reinstate.create.modal.header": "New version", + // TODO New key - Add a translation + "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": "إنشاء إصدارة جديدة لهذه المادة", + + // "item.version.create.modal.text.startingFrom": "starting from version {{version}}", + "item.version.create.modal.text.startingFrom": "بدءاً من الإصدارة {{version}}", + + // "item.version.create.modal.button.confirm": "Create", "item.version.create.modal.button.confirm": "إنشاء", - "item.version.create.modal.button.confirm.tooltip": "إنشاء طبعة جديدة", - "item.qa.withdrawn-reinstate.modal.button.confirm.tooltip": "ارسل طلب", - "qa-withdrown.create.modal.button.confirm": "ينسحب", - "qa-reinstate.create.modal.button.confirm": "إعادة", + + // "item.version.create.modal.button.confirm.tooltip": "Create new version", + "item.version.create.modal.button.confirm.tooltip": "إنشاء إصدارة جديدة", + + // "item.qa.withdrawn-reinstate.modal.button.confirm.tooltip": "Send request", + // TODO New key - Add a translation + "item.qa.withdrawn-reinstate.modal.button.confirm.tooltip": "Send request", + + // "qa-withdrown.create.modal.button.confirm": "Withdraw", + // TODO New key - Add a translation + "qa-withdrown.create.modal.button.confirm": "Withdraw", + + // "qa-reinstate.create.modal.button.confirm": "Reinstate", + // TODO New key - Add a translation + "qa-reinstate.create.modal.button.confirm": "Reinstate", + + // "item.version.create.modal.button.cancel": "Cancel", "item.version.create.modal.button.cancel": "إلغاء", - "item.qa.withdrawn-reinstate.create.modal.button.cancel": "يلغي", - "item.version.create.modal.button.cancel.tooltip": "لا لتوقف عن الاصدار الجديد", - "item.qa.withdrawn-reinstate.create.modal.button.cancel.tooltip": "لا ترسل الطلب", + + // "item.qa.withdrawn-reinstate.create.modal.button.cancel": "Cancel", + // TODO New key - Add a translation + "item.qa.withdrawn-reinstate.create.modal.button.cancel": "Cancel", + + // "item.version.create.modal.button.cancel.tooltip": "Do not create new version", + "item.version.create.modal.button.cancel.tooltip": "لا تقم بإنشاء إصدارة جديدة", + + // "item.qa.withdrawn-reinstate.create.modal.button.cancel.tooltip": "Do not send request", + // TODO New key - Add a translation + "item.qa.withdrawn-reinstate.create.modal.button.cancel.tooltip": "Do not send request", + + // "item.version.create.modal.form.summary.label": "Summary", "item.version.create.modal.form.summary.label": "الملخص", - "qa-withdrawn.create.modal.form.summary.label": "أنت تطلب سحب هذا البند", - "qa-withdrawn.create.modal.form.summary2.label": "الرجاء إدخال سبب الانسحاب", - "qa-reinstate.create.modal.form.summary.label": "أنت تطلب إعادة هذا العنصر", - "qa-reinstate.create.modal.form.summary2.label": "الرجاء إدخال سبب الإعادة", - "item.version.create.modal.form.summary.placeholder": "قم بالضغط على النسخة الجديدة", - "qa-withdrown.modal.form.summary.placeholder": "أدخل سبب السحب", - "qa-reinstate.modal.form.summary.placeholder": "أدخل سبب الإعادة", - "item.version.create.modal.submitted.header": "إنشاء طبعة جديدة...", - "item.qa.withdrawn.modal.submitted.header": "جارٍ إرسال الطلب المسحوب...", - "correction-type.manage-relation.action.notification.reinstate": "تم إرسال طلب الاستعادة.", - "correction-type.manage-relation.action.notification.withdrawn": "تم إرسال طلب السحب.", - "item.version.create.modal.submitted.text": "جاري إنشاء نسخة جديدة. ", - "item.version.create.notification.success": "تم إنشاء نسخة جديدة برقم الإصدار {{version}}", - "item.version.create.notification.failure": "لم يتم إنشاء إصدار جديد", - "item.version.create.notification.inProgress": "لا يمكن إنشاء نسخة جديدة إذًا هناك تقديم قيد التقدم في نسخة النسخة", - "item.version.delete.modal.header": "حذف النسخة", - "item.version.delete.modal.text": "هل ترغب في حذف النسخة {{version}}؟", + + // "qa-withdrawn.create.modal.form.summary.label": "You are requesting to withdraw this item", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "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", + "item.version.create.modal.form.summary.placeholder": "قم بإدخال ملخص الإصدارة الجديدة", + + // "qa-withdrown.modal.form.summary.placeholder": "Enter the reason for the withdrawal", + // TODO New key - Add a translation + "qa-withdrown.modal.form.summary.placeholder": "Enter the reason for the withdrawal", + + // "qa-reinstate.modal.form.summary.placeholder": "Enter the reason for the reinstatement", + // TODO New key - Add a translation + "qa-reinstate.modal.form.summary.placeholder": "Enter the reason for the reinstatement", + + // "item.version.create.modal.submitted.header": "Creating new version...", + "item.version.create.modal.submitted.header": "إنشاء إصدارة جديدة...", + + // "item.qa.withdrawn.modal.submitted.header": "Sending withdrawn request...", + // TODO New key - Add a translation + "item.qa.withdrawn.modal.submitted.header": "Sending withdrawn request...", + + // "correction-type.manage-relation.action.notification.reinstate": "Reinstate request sent.", + // TODO New key - Add a translation + "correction-type.manage-relation.action.notification.reinstate": "Reinstate request sent.", + + // "correction-type.manage-relation.action.notification.withdrawn": "Withdraw request sent.", + // TODO New key - Add a translation + "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.modal.submitted.text": "جاري إنشاء الإصدارة الجديدة. قد يستغرق هذا بعض الوقت إذا كان لهذه المادة الكثير من العلاقات.", + + // "item.version.create.notification.success": "New version has been created with version number {{version}}", + "item.version.create.notification.success": "تم إنشاء إصدارة جديدة برقم الإصدار {{version}}", + + // "item.version.create.notification.failure": "New version has not been created", + "item.version.create.notification.failure": "لم يتم إنشاء إصدارة جديدة", + + // "item.version.create.notification.inProgress": "A new version cannot be created because there is an inprogress submission in the version history", + "item.version.create.notification.inProgress": "لا يمكن إنشاء إصدارة جديدة نظراً لوجود تقديم قيد التقدم في سجل الإصدارة", + + // "item.version.delete.modal.header": "Delete version", + "item.version.delete.modal.header": "حذف الإصدارة", + + // "item.version.delete.modal.text": "Do you want to delete version {{version}}?", + "item.version.delete.modal.text": "هل ترغب في حذف الإصدارة {{version}}؟", + + // "item.version.delete.modal.button.confirm": "Delete", "item.version.delete.modal.button.confirm": "حذف", - "item.version.delete.modal.button.confirm.tooltip": "حذف هذه النسخة", + + // "item.version.delete.modal.button.confirm.tooltip": "Delete this version", + "item.version.delete.modal.button.confirm.tooltip": "حذف هذه الإصدارة", + + // "item.version.delete.modal.button.cancel": "Cancel", "item.version.delete.modal.button.cancel": "إلغاء", - "item.version.delete.modal.button.cancel.tooltip": "لا تنسى حذف هذه النسخة", - "item.version.delete.notification.success": "تم حذف النسخة رقم {{version}}", - "item.version.delete.notification.failure": "لن يتم حذف النسخة رقم {{version}}", - "item.version.edit.notification.success": "تم تغيير ملخص النسخة رقم {{version}}", - "item.version.edit.notification.failure": "لم يتم تغيير ملخص النسخة رقم {{version}}", + + // "item.version.delete.modal.button.cancel.tooltip": "Do not delete this version", + "item.version.delete.modal.button.cancel.tooltip": "لا تقم بحذف هذه الإصدارة", + + // "item.version.delete.notification.success": "Version number {{version}} has been deleted", + "item.version.delete.notification.success": "تم حذف الإصدارة رقم {{version}}", + + // "item.version.delete.notification.failure": "Version number {{version}} has not been deleted", + "item.version.delete.notification.failure": "لم يتم حذف الإصدارة رقم {{version}}", + + // "item.version.edit.notification.success": "The summary of version number {{version}} has been changed", + "item.version.edit.notification.success": "تم تغيير ملخص الإصدارة رقم {{version}}", + + // "item.version.edit.notification.failure": "The summary of version number {{version}} has not been changed", + "item.version.edit.notification.failure": "لم يتم تغيير ملخص الإصدارة رقم {{version}}", + + // "itemtemplate.edit.metadata.add-button": "Add", "itemtemplate.edit.metadata.add-button": "إضافة", - "itemtemplate.edit.metadata.discard-button": "لا", + + // "itemtemplate.edit.metadata.discard-button": "Discard", + "itemtemplate.edit.metadata.discard-button": "تجاهل", + + // "itemtemplate.edit.metadata.edit.language": "Edit language", "itemtemplate.edit.metadata.edit.language": "تحرير اللغة", + + // "itemtemplate.edit.metadata.edit.value": "Edit value", "itemtemplate.edit.metadata.edit.value": "تحرير القيمة", - "itemtemplate.edit.metadata.edit.buttons.confirm": "بالتأكيد", - "itemtemplate.edit.metadata.edit.buttons.drag": "قم بإعادة الترتيب", + + // "itemtemplate.edit.metadata.edit.buttons.confirm": "Confirm", + "itemtemplate.edit.metadata.edit.buttons.confirm": "تأكيد", + + // "itemtemplate.edit.metadata.edit.buttons.drag": "Drag to reorder", + "itemtemplate.edit.metadata.edit.buttons.drag": "اسحب لإعادة الترتيب", + + // "itemtemplate.edit.metadata.edit.buttons.edit": "Edit", "itemtemplate.edit.metadata.edit.buttons.edit": "تحرير", + + // "itemtemplate.edit.metadata.edit.buttons.remove": "Remove", "itemtemplate.edit.metadata.edit.buttons.remove": "إزالة", - "itemtemplate.edit.metadata.edit.buttons.undo": "انقلب عن التغييرات", + + // "itemtemplate.edit.metadata.edit.buttons.undo": "Undo changes", + "itemtemplate.edit.metadata.edit.buttons.undo": "تراجع عن التغييرات", + + // "itemtemplate.edit.metadata.edit.buttons.unedit": "Stop editing", "itemtemplate.edit.metadata.edit.buttons.unedit": "إيقاف التحرير", - "itemtemplate.edit.metadata.empty": "القالب الحالي لا يحتوي على أي ميتاداتا. ", + + // "itemtemplate.edit.metadata.empty": "The item template currently doesn't contain any metadata. Click Add to start adding a metadata value.", + "itemtemplate.edit.metadata.empty": "قالب العنصر حاليًا لا يحتوي على أي ميتاداتا. انقر فوق إضافة لبدء إضافة قيمة ميتاداتا.", + + // "itemtemplate.edit.metadata.headers.edit": "Edit", "itemtemplate.edit.metadata.headers.edit": "تحرير", - "itemtemplate.edit.metadata.headers.field": "حقل", + + // "itemtemplate.edit.metadata.headers.field": "Field", + "itemtemplate.edit.metadata.headers.field": "الحقل", + + // "itemtemplate.edit.metadata.headers.language": "Lang", "itemtemplate.edit.metadata.headers.language": "اللغة", + + // "itemtemplate.edit.metadata.headers.value": "Value", "itemtemplate.edit.metadata.headers.value": "القيمة", + + // "itemtemplate.edit.metadata.metadatafield": "Edit field", "itemtemplate.edit.metadata.metadatafield": "تحرير الحقل", - "itemtemplate.edit.metadata.metadatafield.error": "حدث خطأ أثناء التحقق من البحث في الميتاداتا", - "itemtemplate.edit.metadata.metadatafield.invalid": "يرجى اختيار البحث ميتاداتا صالح", - "itemtemplate.edit.metadata.notifications.discarded.content": "تم تجاهل التغييرات التي اختارتها. ", + + // "itemtemplate.edit.metadata.metadatafield.error": "An error occurred validating the metadata field", + "itemtemplate.edit.metadata.metadatafield.error": "حدث خطأ أثناء التحقق من حقل الميتاداتا", + + // "itemtemplate.edit.metadata.metadatafield.invalid": "Please choose a valid metadata field", + "itemtemplate.edit.metadata.metadatafield.invalid": "يرجى اختيار حقل ميتاداتا صالح", + + // "itemtemplate.edit.metadata.notifications.discarded.content": "Your changes were discarded. To reinstate your changes click the 'Undo' button", + "itemtemplate.edit.metadata.notifications.discarded.content": "تم تجاهل التغييرات التي أجريتها. لاستعادة التغييرات، قم بالنقر على زر 'تراجع' ", + + // "itemtemplate.edit.metadata.notifications.discarded.title": "Changes discarded", "itemtemplate.edit.metadata.notifications.discarded.title": "تم تجاهل التغييرات", + + // "itemtemplate.edit.metadata.notifications.error.title": "An error occurred", "itemtemplate.edit.metadata.notifications.error.title": "حدث خطأ", - "itemtemplate.edit.metadata.notifications.invalid.content": "لم يتم حفظ التغييرات. ", - "itemtemplate.edit.metadata.notifications.invalid.title": "دياداتا غير صالحة", - "itemtemplate.edit.metadata.notifications.outdated.content": "تم تغيير المادة التي تعمل حاليا بواسطة مستخدم آخر. ", - "itemtemplate.edit.metadata.notifications.outdated.title": "اختر التغييرات", - "itemtemplate.edit.metadata.notifications.saved.content": "تم حفظ التغييرات التي استخدمتها على الميتاداتا لقالب المادة هذه.", + + // "itemtemplate.edit.metadata.notifications.invalid.content": "Your changes were not saved. Please make sure all fields are valid before you save.", + "itemtemplate.edit.metadata.notifications.invalid.content": "لم يتم حفظ التغييرات. يرجى التأكد من أن جميع الحقول صالحة قبل الحفظ.", + + // "itemtemplate.edit.metadata.notifications.invalid.title": "Metadata invalid", + "itemtemplate.edit.metadata.notifications.invalid.title": "الميتاداتا غير صالحة", + + // "itemtemplate.edit.metadata.notifications.outdated.content": "The item template you're currently working on has been changed by another user. Your current changes are discarded to prevent conflicts", + "itemtemplate.edit.metadata.notifications.outdated.content": "تم تغيير قالب المادة الذي تعمل عليه حالياً بواسطة مستخدم آخر. تم تجاهل التغييرات الحالية لمنع التعارضات", + + // "itemtemplate.edit.metadata.notifications.outdated.title": "Changes outdated", + "itemtemplate.edit.metadata.notifications.outdated.title": "انتهت صلاحية التغييرات", + + // "itemtemplate.edit.metadata.notifications.saved.content": "Your changes to this item template's metadata were saved.", + "itemtemplate.edit.metadata.notifications.saved.content": "تم حفظ التغييرات التي أجريتها على الميتاداتا لقالب المادة هذا.", + + // "itemtemplate.edit.metadata.notifications.saved.title": "Metadata saved", "itemtemplate.edit.metadata.notifications.saved.title": "تم حفظ الميتاداتا", - "itemtemplate.edit.metadata.reinstate-button": "ديب", - "itemtemplate.edit.metadata.reset-order-button": "الادارة عن إعادة الترتيب", + + // "itemtemplate.edit.metadata.reinstate-button": "Undo", + "itemtemplate.edit.metadata.reinstate-button": "تراجع", + + // "itemtemplate.edit.metadata.reset-order-button": "Undo reorder", + "itemtemplate.edit.metadata.reset-order-button": "التراجع عن إعادة الترتيب", + + // "itemtemplate.edit.metadata.save-button": "Save", "itemtemplate.edit.metadata.save-button": "حفظ", - "journal.listelement.badge": "الدوري", + + // "journal.listelement.badge": "Journal", + "journal.listelement.badge": "الدورية", + + // "journal.page.description": "Description", "journal.page.description": "الوصف", + + // "journal.page.edit": "Edit this item", "journal.page.edit": "تحرير هذه المادة", + + // "journal.page.editor": "Editor-in-Chief", "journal.page.editor": "رئيس التحرير", - "journal.page.issn": "الرقم الدولي الموحد للدوريات", + + // "journal.page.issn": "ISSN", + "journal.page.issn": "ISSN", + + // "journal.page.publisher": "Publisher", "journal.page.publisher": "الناشر", - "journal.page.titleprefix": "الدوري: ", - "journal.search.results.head": "نتائج الدورية التي بحثتها", - "journal-relationships.search.results.head": "نتائج الدورية التي بحثتها", - "journal.search.title": "الدورية الدورية", - "journalissue.listelement.badge": "عدد الدوري", + + // "journal.page.titleprefix": "Journal: ", + "journal.page.titleprefix": "الدورية: ", + + // "journal.search.results.head": "Journal Search Results", + "journal.search.results.head": "نتائج بحث الدورية", + + // "journal-relationships.search.results.head": "Journal Search Results", + "journal-relationships.search.results.head": "نتائج بحث الدورية", + + // "journal.search.title": "Journal Search", + "journal.search.title": "بحث الدورية", + + // "journalissue.listelement.badge": "Journal Issue", + "journalissue.listelement.badge": "عدد الدورية", + + // "journalissue.page.description": "Description", "journalissue.page.description": "الوصف", + + // "journalissue.page.edit": "Edit this item", "journalissue.page.edit": "تحرير هذه المادة", + + // "journalissue.page.issuedate": "Issue Date", "journalissue.page.issuedate": "تاريخ العدد", + + // "journalissue.page.journal-issn": "Journal ISSN", "journalissue.page.journal-issn": "ردمد الدورية", - "journalissue.page.journal-title": "عنوان الدوري", - "journalissue.page.keyword": "الكلمات الرئيسية", + + // "journalissue.page.journal-title": "Journal Title", + "journalissue.page.journal-title": "عنوان الدورية", + + // "journalissue.page.keyword": "Keywords", + "journalissue.page.keyword": "كلمات رئيسية", + + // "journalissue.page.number": "Number", "journalissue.page.number": "رقم", - "journalissue.page.titleprefix": "عدد الدوري: ", - "journalissue.search.results.head": "نتائج البحث عدد الدوري", - "journalvolume.listelement.badge": "سلسلة الدورية", + + // "journalissue.page.titleprefix": "Journal Issue: ", + "journalissue.page.titleprefix": "عدد الدورية: ", + + // "journalissue.search.results.head": "Journal Issue Search Results", + "journalissue.search.results.head": "نتائج بحث عدد الدورية", + + // "journalvolume.listelement.badge": "Journal Volume", + "journalvolume.listelement.badge": "مجلد الدورية", + + // "journalvolume.page.description": "Description", "journalvolume.page.description": "الوصف", + + // "journalvolume.page.edit": "Edit this item", "journalvolume.page.edit": "تحرير هذه المادة", + + // "journalvolume.page.issuedate": "Issue Date", "journalvolume.page.issuedate": "تاريخ الإصدار", - "journalvolume.page.titleprefix": "دورة دورية: ", - "journalvolume.page.volume": "مجلد", - "journalvolume.search.results.head": "نتائج البحث في الدوري", - "iiifsearchable.listelement.badge": "وسائط الوسائط", - "iiifsearchable.page.titleprefix": "أوكلاند: ", - "iiifsearchable.page.doi": "الرابط الجديد: ", + + // "journalvolume.page.titleprefix": "Journal Volume: ", + "journalvolume.page.titleprefix": "مجلد دورية: ", + + // "journalvolume.page.volume": "Volume", + "journalvolume.page.volume": "المجلد", + + // "journalvolume.search.results.head": "Journal Volume Search Results", + "journalvolume.search.results.head": "نتائج بحث مجلد الدورية", + + // "iiifsearchable.listelement.badge": "Document Media", + "iiifsearchable.listelement.badge": "وسائط الوثائق", + + // "iiifsearchable.page.titleprefix": "Document: ", + "iiifsearchable.page.titleprefix": "الوثيقة: ", + + // "iiifsearchable.page.doi": "Permanent Link: ", + "iiifsearchable.page.doi": "الرابط الدائم: ", + + // "iiifsearchable.page.issue": "Issue: ", "iiifsearchable.page.issue": "العدد: ", + + // "iiifsearchable.page.description": "Description: ", "iiifsearchable.page.description": "الوصف: ", - "iiifviewer.fullscreen.notice": "استخدم الشاشة بالكامل لمشاهدة أفضل.", + + // "iiifviewer.fullscreen.notice": "Use full screen for better viewing.", + "iiifviewer.fullscreen.notice": "استخدم الشاشة الكاملة لمشاهدة أفضل.", + + // "iiif.listelement.badge": "Image Media", "iiif.listelement.badge": "وسائط الصور", + + // "iiif.page.titleprefix": "Image: ", "iiif.page.titleprefix": "الصورة: ", - "iiif.page.doi": "الرابط الجديد: ", + + // "iiif.page.doi": "Permanent Link: ", + "iiif.page.doi": "الرابط الدائم: ", + + // "iiif.page.issue": "Issue: ", "iiif.page.issue": "العدد: ", + + // "iiif.page.description": "Description: ", "iiif.page.description": "الوصف: ", + + // "loading.bitstream": "Loading bitstream...", "loading.bitstream": "جاري تحميل تدفق البت...", + + // "loading.bitstreams": "Loading bitstreams...", "loading.bitstreams": "جاري تحميل تدفقات البت...", + + // "loading.browse-by": "Loading items...", "loading.browse-by": "جاري تحميل المواد...", + + // "loading.browse-by-page": "Loading page...", "loading.browse-by-page": "جاري تحميل الصفحة...", - "loading.collection": "جاري تحميل...", - "loading.collections": "جاري التحميل ...", + + // "loading.collection": "Loading collection...", + "loading.collection": "جاري تحميل الحاوية...", + + // "loading.collections": "Loading collections...", + "loading.collections": "جاري تحميل الحاويات...", + + // "loading.content-source": "Loading content source...", "loading.content-source": "جاري تحميل مصدر المحتوى...", + + // "loading.community": "Loading community...", "loading.community": "جاري تحميل المجتمع...", + + // "loading.default": "Loading...", "loading.default": "جاري التحميل...", + + // "loading.item": "Loading item...", "loading.item": "جاري تحميل المادة...", + + // "loading.items": "Loading items...", "loading.items": "جاري تحميل المواد...", + + // "loading.mydspace-results": "Loading items...", "loading.mydspace-results": "جاري تحميل المواد...", + + // "loading.objects": "Loading...", "loading.objects": "جاري التحميل...", - "loading.recent-submissions": "جاري تحميل أحدث العروض...", + + // "loading.recent-submissions": "Loading recent submissions...", + "loading.recent-submissions": "جاري تحميل أحدث التقديمات...", + + // "loading.search-results": "Loading search results...", "loading.search-results": "جاري تحميل نتائج البحث...", - "loading.sub-collections": "جاري تحميل مؤقت...", - "loading.sub-communities": "جاري تحميل الكنيسة...", + + // "loading.sub-collections": "Loading sub-collections...", + "loading.sub-collections": "جاري تحميل الحاويات الفرعية...", + + // "loading.sub-communities": "Loading sub-communities...", + "loading.sub-communities": "جاري تحميل المجتمعات الفرعية...", + + // "loading.top-level-communities": "Loading top-level communities...", "loading.top-level-communities": "جاري تحميل مجتمعات المستوى الأعلى...", + + // "login.form.email": "Email address", "login.form.email": "عنوان البريد الإلكتروني", + + // "login.form.forgot-password": "Have you forgotten your password?", "login.form.forgot-password": "هل نسيت كلمة المرور؟", + + // "login.form.header": "Please log in to DSpace", "login.form.header": "يرجى تسجيل الدخول إلى دي سبيس", - "login.form.new-user": "مستخدم جديد؟ ", + + // "login.form.new-user": "New user? Click here to register.", + "login.form.new-user": "مستخدم جديد؟ اضغط هنا للتسجيل.", + + // "login.form.oidc": "Log in with OIDC", "login.form.oidc": "تسجيل الدخول باستخدام أوركيد", + + // "login.form.orcid": "Log in with ORCID", "login.form.orcid": "تسجيل الدخول باستخدام أوركيد", + + // "login.form.password": "Password", "login.form.password": "كلمة المرور", + + // "login.form.shibboleth": "Log in with Shibboleth", "login.form.shibboleth": "تسجيل الدخول باستخدام Shibboleth", + + // "login.form.submit": "Log in", "login.form.submit": "تسجيل الدخول", + + // "login.title": "Login", "login.title": "تسجيل الدخول", + + // "login.breadcrumbs": "Login", "login.breadcrumbs": "تسجيل الدخول", + + // "logout.form.header": "Log out from DSpace", "logout.form.header": "تسجيل الخروج من دي سبيس", + + // "logout.form.submit": "Log out", "logout.form.submit": "خروج", + + // "logout.title": "Logout", "logout.title": "خروج", - "menu.header.nav.description": "شريط التنقل المشرف", + + // "menu.header.nav.description": "Admin navigation bar", + // TODO New key - Add a translation + "menu.header.nav.description": "Admin navigation bar", + + // "menu.header.admin": "Management", "menu.header.admin": "إدارة", - "menu.header.image.logo": "مستودع الشعار", + + // "menu.header.image.logo": "Repository logo", + "menu.header.image.logo": "شعار المستودع", + + // "menu.header.admin.description": "Management menu", "menu.header.admin.description": "قائمة الإدارة", + + // "menu.section.access_control": "Access Control", "menu.section.access_control": "التحكم في الوصول", - "menu.section.access_control_authorizations": ".تصاريح", + + // "menu.section.access_control_authorizations": "Authorizations", + "menu.section.access_control_authorizations": "تصاريح", + + // "menu.section.access_control_bulk": "Bulk Access Management", "menu.section.access_control_bulk": "إدارة الوصول بالجملة", + + // "menu.section.access_control_groups": "Groups", "menu.section.access_control_groups": "مجموعات", - "menu.section.access_control_people": "الأشخاص", - "menu.section.reports": "التقارير", - "menu.section.reports.collections": "المجموعات التي تمت تصفيتها", - "menu.section.reports.queries": "استعلام بيانات التعريف", + + // "menu.section.access_control_people": "People", + "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": "بحث إداري", + + // "menu.section.browse_community": "This Community", "menu.section.browse_community": "هذا المجتمع", + + // "menu.section.browse_community_by_author": "By Author", "menu.section.browse_community_by_author": "حسب المؤلف", + + // "menu.section.browse_community_by_issue_date": "By Issue Date", "menu.section.browse_community_by_issue_date": "حسب تاريخ الإصدار", - "menu.section.browse_community_by_title": "عنوان حسب الطلب", + + // "menu.section.browse_community_by_title": "By Title", + "menu.section.browse_community_by_title": "حسب العنوان", + + // "menu.section.browse_global": "All of DSpace", "menu.section.browse_global": "كل دي سبيس", + + // "menu.section.browse_global_by_author": "By Author", "menu.section.browse_global_by_author": "حسب المؤلف", + + // "menu.section.browse_global_by_dateissued": "By Issue Date", "menu.section.browse_global_by_dateissued": "حسب تاريخ الإصدار", + + // "menu.section.browse_global_by_subject": "By Subject", "menu.section.browse_global_by_subject": "حسب الموضوع", + + // "menu.section.browse_global_by_srsc": "By Subject Category", "menu.section.browse_global_by_srsc": "حسب فئة الموضوع", - "menu.section.browse_global_by_nsi": "حسب فرس العلوم النرويجي", - "menu.section.browse_global_by_title": "عنوان حسب الطلب", - "menu.section.browse_global_communities_and_collections": "المجتمعات والاويات", - "menu.section.control_panel": "التحكم باللوحة", - "menu.section.curation_task": "مهمة اخرى", + + // "menu.section.browse_global_by_nsi": "By Norwegian Science Index", + "menu.section.browse_global_by_nsi": "حسب فهرس العلوم النرويجي", + + // "menu.section.browse_global_by_title": "By Title", + "menu.section.browse_global_by_title": "حسب العنوان", + + // "menu.section.browse_global_communities_and_collections": "Communities & Collections", + "menu.section.browse_global_communities_and_collections": "المجتمعات والحاويات", + + // "menu.section.control_panel": "Control Panel", + "menu.section.control_panel": "لوحة التحكم", + + // "menu.section.curation_task": "Curation Task", + "menu.section.curation_task": "مهمة الأكرتة", + + // "menu.section.edit": "Edit", "menu.section.edit": "تحرير", + + // "menu.section.edit_collection": "Collection", "menu.section.edit_collection": "حاوية", + + // "menu.section.edit_community": "Community", "menu.section.edit_community": "مجتمع", + + // "menu.section.edit_item": "Item", "menu.section.edit_item": "مادة", + + // "menu.section.export": "Export", "menu.section.export": "تصدير", + + // "menu.section.export_collection": "Collection", "menu.section.export_collection": "حاوية", + + // "menu.section.export_community": "Community", "menu.section.export_community": "مجتمع", + + // "menu.section.export_item": "Item", "menu.section.export_item": "مادة", + + // "menu.section.export_metadata": "Metadata", "menu.section.export_metadata": "ميتاداتا", - "menu.section.export_batch": "التصدير بالدفعة (ZIP)", + + // "menu.section.export_batch": "Batch Export (ZIP)", + "menu.section.export_batch": "تصدير بالدفعة (ZIP)", + + // "menu.section.icon.access_control": "Access Control menu section", "menu.section.icon.access_control": "قسم قائمة التحكم في الوصول", - "menu.section.icon.reports": "قسم قائمة التقارير", - "menu.section.icon.admin_search": "قسم قائمة البحث الإضافي", + + // "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": "قسم قائمة البحث الإداري", + + // "menu.section.icon.control_panel": "Control Panel menu section", "menu.section.icon.control_panel": "قسم قائمة لوحة التحكم", - "menu.section.icon.curation_tasks": "قسم قائمة مهمة الاخرة", + + // "menu.section.icon.curation_tasks": "Curation Task menu section", + "menu.section.icon.curation_tasks": "قسم قائمة مهمة الأكرتة", + + // "menu.section.icon.edit": "Edit menu section", "menu.section.icon.edit": "قسم قائمة التحرير", + + // "menu.section.icon.export": "Export menu section", "menu.section.icon.export": "قسم قائمة التصدير", + + // "menu.section.icon.find": "Find menu section", "menu.section.icon.find": "قسم قائمة البحث", + + // "menu.section.icon.health": "Health check menu section", "menu.section.icon.health": "قسم قائمة التحقق من الصحة", + + // "menu.section.icon.import": "Import menu section", "menu.section.icon.import": "قسم قائمة الاستيراد", - "menu.section.icon.new": "قسم قائمة جديدة", + + // "menu.section.icon.new": "New menu section", + "menu.section.icon.new": "قسم قائمة جديد", + + // "menu.section.icon.pin": "Pin sidebar", "menu.section.icon.pin": "تدبيس الشريط الجانبي", + + // "menu.section.icon.processes": "Processes Health", "menu.section.icon.processes": "قسم قائمة العمليات", - "menu.section.icon.registries": "قسم تسجيل التسجيل", + + // "menu.section.icon.registries": "Registries menu section", + "menu.section.icon.registries": "قسم قائمة السجلات", + + // "menu.section.icon.statistics_task": "Statistics Task menu section", "menu.section.icon.statistics_task": "قسم قائمة مهام الإحصائيات", + + // "menu.section.icon.workflow": "Administer workflow menu section", "menu.section.icon.workflow": "قسم قائمة إدارة عمليات سير العمل", + + // "menu.section.icon.unpin": "Unpin sidebar", "menu.section.icon.unpin": "إلغاء تدبيس الشريط الجانبي", - "menu.section.icon.notifications": "قسم قائمة الإخطارات", + + // "menu.section.icon.notifications": "Notifications menu section", + "menu.section.icon.notifications": "قسم قائمة الإشعارات", + + // "menu.section.import": "Import", "menu.section.import": "استيراد", - "menu.section.import_batch": "اتصل بالدفعة (ملف صيفي)", + + // "menu.section.import_batch": "Batch Import (ZIP)", + "menu.section.import_batch": "استيراد بالدفعة (ملف مضغوط)", + + // "menu.section.import_metadata": "Metadata", "menu.section.import_metadata": "ميتاداتا", + + // "menu.section.new": "New", "menu.section.new": "جديد", + + // "menu.section.new_collection": "Collection", "menu.section.new_collection": "حاوية", + + // "menu.section.new_community": "Community", "menu.section.new_community": "مجتمع", + + // "menu.section.new_item": "Item", "menu.section.new_item": "مادة", - "menu.section.new_item_version": "المادة الإصدار", + + // "menu.section.new_item_version": "Item Version", + "menu.section.new_item_version": "إصدارة المادة", + + // "menu.section.new_process": "Process", "menu.section.new_process": "عملية", + + // "menu.section.notifications": "Notifications", "menu.section.notifications": "الإشعارات", + + // "menu.section.quality-assurance": "Quality Assurance", "menu.section.quality-assurance": "ضمان الجودة", - "menu.section.notifications_publication-claim": "المطالبة بالنشر", + + // "menu.section.notifications_publication-claim": "Publication Claim", + // TODO New key - Add a translation + "menu.section.notifications_publication-claim": "Publication Claim", + + // "menu.section.pin": "Pin sidebar", "menu.section.pin": "تدبيس الشريط الجانبي", + + // "menu.section.unpin": "Unpin sidebar", "menu.section.unpin": "إلغاء تدبيس الشريط الجانبي", + + // "menu.section.processes": "Processes", "menu.section.processes": "العمليات", + + // "menu.section.health": "Health", "menu.section.health": "كشف الصحة", - "menu.section.registries": "TI", - "menu.section.registries_format": "حتى", - "menu.section.registries_metadata": "ميداداتا", + + // "menu.section.registries": "Registries", + "menu.section.registries": "السجلات", + + // "menu.section.registries_format": "Format", + "menu.section.registries_format": "التنسيق", + + // "menu.section.registries_metadata": "Metadata", + "menu.section.registries_metadata": "الميتاداتا", + + // "menu.section.statistics": "Statistics", "menu.section.statistics": "الإحصائيات", + + // "menu.section.statistics_task": "Statistics Task", "menu.section.statistics_task": "مهمة الإحصائيات", + + // "menu.section.toggle.access_control": "Toggle Access Control section", "menu.section.toggle.access_control": "قسم التحكم في الوصول للبدل", - "menu.section.toggle.reports": "تبديل قسم التقارير", + + // "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": "قسم لوحة التحكم في البدل", + + // "menu.section.toggle.curation_task": "Toggle Curation Task section", "menu.section.toggle.curation_task": "قسم مهمة أكرتة البدل", + + // "menu.section.toggle.edit": "Toggle Edit section", "menu.section.toggle.edit": "قسم تحرير البدل", + + // "menu.section.toggle.export": "Toggle Export section", "menu.section.toggle.export": "قسم تصدير البدل", + + // "menu.section.toggle.find": "Toggle Find section", "menu.section.toggle.find": "قسم بحث البدل", + + // "menu.section.toggle.import": "Toggle Import section", "menu.section.toggle.import": "قسم استيراد البدل", + + // "menu.section.toggle.new": "Toggle New section", "menu.section.toggle.new": "قسم بدل جديد", + + // "menu.section.toggle.registries": "Toggle Registries section", "menu.section.toggle.registries": "قسم سجلات البدل", + + // "menu.section.toggle.statistics_task": "Toggle Statistics Task section", "menu.section.toggle.statistics_task": "قسم مهمة إحصائيات البدل", + + // "menu.section.workflow": "Administer Workflow", "menu.section.workflow": "أدر سير العمل", + + // "metadata-export-search.tooltip": "Export search results as CSV", "metadata-export-search.tooltip": "تصدير نتائج البحث كملف CSV", - "metadata-export-search.submit.success": "تم تفعيل التنفيذ الفعال", - "metadata-export-search.submit.error": "فشل في إنشاء التصدير", + + // "metadata-export-search.submit.success": "The export was started successfully", + "metadata-export-search.submit.success": "تم بدء التصدير بنجاح", + + // "metadata-export-search.submit.error": "Starting the export has failed", + "metadata-export-search.submit.error": "فشل بدء التصدير", + + // "mydspace.breadcrumbs": "MyDSpace", "mydspace.breadcrumbs": "ماي دي سبيس", + + // "mydspace.description": "", "mydspace.description": "", - "mydspace.messages.controller-help": "حدد هذا الخيار لإنشاء رسالة إلى مقدم المادة.", - "mydspace.messages.description-placeholder": "قم بتأكيد رسالتك هنا...", - "mydspace.messages.hide-msg": "استمرار الرسالة", + + // "mydspace.messages.controller-help": "Select this option to send a message to item's submitter.", + "mydspace.messages.controller-help": "حدد هذا الخيار لإرسال رسالة إلى مقدم المادة.", + + // "mydspace.messages.description-placeholder": "Insert your message here...", + "mydspace.messages.description-placeholder": "قم بإدخال رسالتك هنا...", + + // "mydspace.messages.hide-msg": "Hide message", + "mydspace.messages.hide-msg": "إخفاء الرسالة", + + // "mydspace.messages.mark-as-read": "Mark as read", "mydspace.messages.mark-as-read": "حدد كمقروء", + + // "mydspace.messages.mark-as-unread": "Mark as unread", "mydspace.messages.mark-as-unread": "حدد كغير مقروء", + + // "mydspace.messages.no-content": "No content.", "mydspace.messages.no-content": "لا يوجد محتوى.", + + // "mydspace.messages.no-messages": "No messages yet.", "mydspace.messages.no-messages": "لا توجد رسائل بعد.", + + // "mydspace.messages.send-btn": "Send", "mydspace.messages.send-btn": "إرسال", + + // "mydspace.messages.show-msg": "Show message", "mydspace.messages.show-msg": "عرض الرسالة", + + // "mydspace.messages.subject-placeholder": "Subject...", "mydspace.messages.subject-placeholder": "الموضوع...", - "mydspace.messages.submitter-help": "حدد هذا الخيار لرسالة إلى وحدة التحكم.", + + // "mydspace.messages.submitter-help": "Select this option to send a message to controller.", + "mydspace.messages.submitter-help": "حدد هذا الخيار لإرسال رسالة إلى وحدة التحكم.", + + // "mydspace.messages.title": "Messages", "mydspace.messages.title": "الرسائل", + + // "mydspace.messages.to": "To", "mydspace.messages.to": "إلى", + + // "mydspace.new-submission": "New submission", "mydspace.new-submission": "تقديم جديد", - "mydspace.new-submission-external": "استيراد الميتاداتا من المصدر الخارجي", - "mydspace.new-submission-external-short": "قم باستيراد الميتاداتا", - "mydspace.results.head": "تقديمك", - "mydspace.results.no-abstract": "لا يوجد روح", - "mydspace.results.no-authors": "لا يوجد كاتبين", - "mydspace.results.no-collections": "لا توجد الوثيقة", + + // "mydspace.new-submission-external": "Import metadata from external source", + "mydspace.new-submission-external": "استيراد الميتاداتا من مصدر خارجي", + + // "mydspace.new-submission-external-short": "Import metadata", + "mydspace.new-submission-external-short": "استيراد الميتاداتا", + + // "mydspace.results.head": "Your submissions", + "mydspace.results.head": "تقديماتك", + + // "mydspace.results.no-abstract": "No Abstract", + "mydspace.results.no-abstract": "لا يوجد مستخلص", + + // "mydspace.results.no-authors": "No Authors", + "mydspace.results.no-authors": "لا يوجد مؤلفين", + + // "mydspace.results.no-collections": "No Collections", + "mydspace.results.no-collections": "لا توجد حاويات", + + // "mydspace.results.no-date": "No Date", "mydspace.results.no-date": "لا يوجد تاريخ", - "mydspace.results.no-files": "لا يوجد ملفات", - "mydspace.results.no-results": "لا يوجد شيء للعرض", + + // "mydspace.results.no-files": "No Files", + "mydspace.results.no-files": "لا توجد ملفات", + + // "mydspace.results.no-results": "There were no items to show", + "mydspace.results.no-results": "لا توجد مواد للعرض", + + // "mydspace.results.no-title": "No title", "mydspace.results.no-title": "لا يوجد عنوان", - "mydspace.results.no-uri": "لا يوجد أوري", + + // "mydspace.results.no-uri": "No URI", + "mydspace.results.no-uri": "لا يوجد Uri", + + // "mydspace.search-form.placeholder": "Search in MyDSpace...", "mydspace.search-form.placeholder": "بحث في ما دي سبيس...", + + // "mydspace.show.workflow": "Workflow tasks", "mydspace.show.workflow": "مهام سير العمل", - "mydspace.show.workspace": "تقديمك", + + // "mydspace.show.workspace": "Your submissions", + "mydspace.show.workspace": "تقديماتك", + + // "mydspace.show.supervisedWorkspace": "Supervised items", "mydspace.show.supervisedWorkspace": "مواد تحت الإشراف", + + // "mydspace.status.mydspaceArchived": "Archived", "mydspace.status.mydspaceArchived": "في الأرشيف", + + // "mydspace.status.mydspaceValidation": "Validation", "mydspace.status.mydspaceValidation": "تحقق", + + // "mydspace.status.mydspaceWaitingController": "Waiting for reviewer", "mydspace.status.mydspaceWaitingController": "في انتظار المتحكم", + + // "mydspace.status.mydspaceWorkflow": "Workflow", "mydspace.status.mydspaceWorkflow": "سير العمل", + + // "mydspace.status.mydspaceWorkspace": "Workspace", "mydspace.status.mydspaceWorkspace": "مساحة العمل", + + // "mydspace.title": "MyDSpace", "mydspace.title": "ماي دي سبيس", - "mydspace.upload.upload-failed": "خطأ أثناء إنشاء نطاق عمل جديد. ", - "mydspace.upload.upload-failed-manyentries": "ملف غير قابل للمعالجة. ", - "mydspace.upload.upload-failed-moreonefile": "طلب غير قابل للمعالجة. ", - "mydspace.upload.upload-multiple-successful": "تم إنشاء {{qty}} نطاق عمل جديد.", + + // "mydspace.upload.upload-failed": "Error creating new workspace. Please verify the content uploaded before retry.", + "mydspace.upload.upload-failed": "خطأ اثناء إنشاء نطاق عمل جديد. يرجى التأكد من المحتوى المرفوع قبل إعادة المحاولة.", + + // "mydspace.upload.upload-failed-manyentries": "Unprocessable file. Detected too many entries but allowed only one for file.", + "mydspace.upload.upload-failed-manyentries": "ملف غير قابل للمعالجة. تم اكتشاف عدد كبير جدًا من المدخلات ولكن تم السماح بإدخال واحد فقط للملف.", + + // "mydspace.upload.upload-failed-moreonefile": "Unprocessable request. Only one file is allowed.", + "mydspace.upload.upload-failed-moreonefile": "طلب غير قابل للمعالجة. يسمح بملف واحد فقط.", + + // "mydspace.upload.upload-multiple-successful": "{{qty}} new workspace items created.", + "mydspace.upload.upload-multiple-successful": "تم إنشاء {{qty}} مادة نطاق عمل جديدة.", + + // "mydspace.view-btn": "View", "mydspace.view-btn": "عرض", - "nav.expandable-navbar-section-suffix": "(قائمة فرعية)", - "notification.suggestion": "وجدنا {{count}} المنشورات في ال {{source}} يبدو أن هذا مرتبط بملفك الشخصي.
", - "notification.suggestion.review": "مراجعة الاقتراحات", - "notification.suggestion.please": "لو سمحت", + + // "nav.expandable-navbar-section-suffix": "(submenu)", + // TODO New key - Add a translation + "nav.expandable-navbar-section-suffix": "(submenu)", + + // "notification.suggestion": "We found {{count}} publications in the {{source}} that seems to be related to your profile.
", + // TODO New key - Add a translation + "notification.suggestion": "We found {{count}} publications in the {{source}} that seems to be related to your profile.
", + + // "notification.suggestion.review": "review the suggestions", + // TODO New key - Add a translation + "notification.suggestion.review": "review the suggestions", + + // "notification.suggestion.please": "Please", + // TODO New key - Add a translation + "notification.suggestion.please": "Please", + + // "nav.browse.header": "All of DSpace", "nav.browse.header": "كل دي سبيس", + + // "nav.community-browse.header": "By Community", "nav.community-browse.header": "حسب المجتمع", - "nav.context-help-toggle": "مساعدة تعطيل السياق", - "nav.language": "تغيير اللغة", + + // "nav.context-help-toggle": "Toggle context help", + "nav.context-help-toggle": "مساعدة تبديل السياق", + + // "nav.language": "Language switch", + "nav.language": "تبديل اللغة", + + // "nav.login": "Log In", "nav.login": "تسجيل الدخول", + + // "nav.user-profile-menu-and-logout": "User profile menu and log out", "nav.user-profile-menu-and-logout": "قائمة ملف تعريف المستخدم وتسجيل الخروج", + + // "nav.logout": "Log Out", "nav.logout": "خروج", + + // "nav.main.description": "Main navigation bar", "nav.main.description": "شريط التصفح الرئيسي", + + // "nav.mydspace": "MyDSpace", "nav.mydspace": "ماي دي سبيس", + + // "nav.profile": "Profile", "nav.profile": "الملف الشخصي", + + // "nav.search": "Search", "nav.search": "بحث", + + // "nav.search.button": "Submit search", "nav.search.button": "تقديم بحث", + + // "nav.statistics.header": "Statistics", "nav.statistics.header": "الإحصائيات", - "nav.stop-impersonating": "ضبط التصرف كشخص إلكتروني", + + // "nav.stop-impersonating": "Stop impersonating EPerson", + "nav.stop-impersonating": "التوقف عن التصرف كشخص إلكتروني", + + // "nav.subscriptions": "Subscriptions", "nav.subscriptions": "الاشتراكات", - "nav.toggle": "تغيير التصفح", - "nav.user.description": "شريط تعريف المستخدم", + + // "nav.toggle": "Toggle navigation", + "nav.toggle": "تبديل التصفح", + + // "nav.user.description": "User profile bar", + "nav.user.description": "شريط ملف تعريف المستخدم", + + // "none.listelement.badge": "Item", "none.listelement.badge": "المادة", + + // "quality-assurance.title": "Quality Assurance", "quality-assurance.title": "ضمان الجودة", - "quality-assurance.topics.description": "أدناه يمكنك رؤية جميع المواضيع المرسلة من الاشتراكات في {{source}}.", - "quality-assurance.source.description": "فيما يلي يمكنك رؤية جميع مصادر التنبيهات.", + + // "quality-assurance.topics.description": "Below you can see all the topics received from the subscriptions to {{source}}.", + "quality-assurance.topics.description": "أدناه يمكنك رؤية جميع المواضيع الواردة من الاشتراكات في {{source}}.", + + // "quality-assurance.source.description": "Below you can see all the notification's sources.", + "quality-assurance.source.description": "أدناه يمكنك رؤية جميع مصادر الإشعارات.", + + // "quality-assurance.topics": "Current Topics", "quality-assurance.topics": "المواضيع الحالية", - "quality-assurance.source": "المصدر الحالي", + + // "quality-assurance.source": "Current Sources", + "quality-assurance.source": "المصادر الحالية", + + // "quality-assurance.table.topic": "Topic", "quality-assurance.table.topic": "الموضوع", + + // "quality-assurance.table.source": "Source", "quality-assurance.table.source": "المصدر", - "quality-assurance.table.last-event": "نهاية المطاف فعالة", + + // "quality-assurance.table.last-event": "Last Event", + "quality-assurance.table.last-event": "آخر فعالية", + + // "quality-assurance.table.actions": "Actions", "quality-assurance.table.actions": "إجراءات", - "quality-assurance.source-list.button.detail": "عرض المواضيع ل {{param}}", - "quality-assurance.topics-list.button.detail": "عرض اقتراحات ل {{param}}", - "quality-assurance.noTopics": "لم يتم توفيرها على المواضيع.", - "quality-assurance.noSource": "لم يتم العثور على المصادر.", + + // "quality-assurance.source-list.button.detail": "Show topics for {{param}}", + // TODO New key - Add a translation + "quality-assurance.source-list.button.detail": "Show topics for {{param}}", + + // "quality-assurance.topics-list.button.detail": "Show suggestions for {{param}}", + // TODO New key - Add a translation + "quality-assurance.topics-list.button.detail": "Show suggestions for {{param}}", + + // "quality-assurance.noTopics": "No topics found.", + "quality-assurance.noTopics": "لم يتم العثور على مواضيع.", + + // "quality-assurance.noSource": "No sources found.", + "quality-assurance.noSource": "لم يتم العثور على مصادر.", + + // "notifications.events.title": "Quality Assurance Suggestions", "notifications.events.title": "اقتراحات ضمان الجودة", + + // "quality-assurance.topic.error.service.retrieve": "An error occurred while loading the Quality Assurance topics", "quality-assurance.topic.error.service.retrieve": "حدث خطأ أثناء تحميل موضوعات ضمان الجودة", - "quality-assurance.source.error.service.retrieve": "حدث خطأ أثناء تحميل ضمان الجودة", + + // "quality-assurance.source.error.service.retrieve": "An error occurred while loading the Quality Assurance source", + "quality-assurance.source.error.service.retrieve": "حدث خطأ أثناء تحميل مصدر ضمان الجودة", + + // "quality-assurance.loading": "Loading ...", "quality-assurance.loading": "جاري التحميل ...", + + // "quality-assurance.events.topic": "Topic:", "quality-assurance.events.topic": "الموضوع:", + + // "quality-assurance.noEvents": "No suggestions found.", "quality-assurance.noEvents": "لم يتم العثور على أي اقتراحات.", - "quality-assurance.event.table.trust": "ثا", + + // "quality-assurance.event.table.trust": "Trust", + "quality-assurance.event.table.trust": "ثقة", + + // "quality-assurance.event.table.publication": "Publication", "quality-assurance.event.table.publication": "النشر", + + // "quality-assurance.event.table.details": "Details", "quality-assurance.event.table.details": "تفاصيل", + + // "quality-assurance.event.table.project-details": "Project details", "quality-assurance.event.table.project-details": "تفاصيل المشروع", - "quality-assurance.event.table.reasons": "الأسباب", + + // "quality-assurance.event.table.reasons": "Reasons", + // TODO New key - Add a translation + "quality-assurance.event.table.reasons": "Reasons", + + // "quality-assurance.event.table.actions": "Actions", "quality-assurance.event.table.actions": "إجراءات", - "quality-assurance.event.action.accept": "قبول الاقتراحات", - "quality-assurance.event.action.ignore": "تجاهل الاقتراحات", - "quality-assurance.event.action.undo": "يمسح", + + // "quality-assurance.event.action.accept": "Accept suggestion", + "quality-assurance.event.action.accept": "قبول الاقتراح", + + // "quality-assurance.event.action.ignore": "Ignore suggestion", + "quality-assurance.event.action.ignore": "تجاهل الاقتراح", + + // "quality-assurance.event.action.undo": "DELETE", + // TODO New key - Add a translation + "quality-assurance.event.action.undo": "DELETE", + + // "quality-assurance.event.action.reject": "Reject suggestion", "quality-assurance.event.action.reject": "رفض الاقتراح", - "quality-assurance.event.action.import": "استيراد المشروع وقبول الاقتراحات", - "quality-assurance.event.table.pidtype": "نوع معرف المنتج:", - "quality-assurance.event.table.pidvalue": "قيمة معرف المنتج:", - "quality-assurance.event.table.subjectValue": "موضوع القيمة:", - "quality-assurance.event.table.abstract": "أخيرًا:", - "quality-assurance.event.table.suggestedProject": "بيانات المشروع من OpenAIRE", + + // "quality-assurance.event.action.import": "Import project and accept suggestion", + "quality-assurance.event.action.import": "استيراد المشروع وقبول الاقتراح", + + // "quality-assurance.event.table.pidtype": "PID Type:", + "quality-assurance.event.table.pidtype": "PID نوع:", + + // "quality-assurance.event.table.pidvalue": "PID Value:", + "quality-assurance.event.table.pidvalue": "PID قيمة:", + + // "quality-assurance.event.table.subjectValue": "Subject Value:", + "quality-assurance.event.table.subjectValue": "قيمة الموضوع:", + + // "quality-assurance.event.table.abstract": "Abstract:", + "quality-assurance.event.table.abstract": "خلاصة:", + + // "quality-assurance.event.table.suggestedProject": "OpenAIRE Suggested Project data", + "quality-assurance.event.table.suggestedProject": "بيانات المشروع المقترحة من OpenAIRE", + + // "quality-assurance.event.table.project": "Project title:", "quality-assurance.event.table.project": "عنوان المشروع:", + + // "quality-assurance.event.table.acronym": "Acronym:", "quality-assurance.event.table.acronym": "حروف مختصرة:", + + // "quality-assurance.event.table.code": "Code:", "quality-assurance.event.table.code": "رمز:", + + // "quality-assurance.event.table.funder": "Funder:", "quality-assurance.event.table.funder": "الممول:", + + // "quality-assurance.event.table.fundingProgram": "Funding program:", "quality-assurance.event.table.fundingProgram": "برنامج التمويل:", - "quality-assurance.event.table.jurisdiction": "عدم التفويض:", - "quality-assurance.events.back": "العودة إلى المواضيع", - "quality-assurance.events.back-to-sources": "العودة إلى المصادر", + + // "quality-assurance.event.table.jurisdiction": "Jurisdiction:", + "quality-assurance.event.table.jurisdiction": "الاختصاص القضائي:", + + // "quality-assurance.events.back": "Back to topics", + "quality-assurance.events.back": "رجوع إلى المواضيع", + + // "quality-assurance.events.back-to-sources": "Back to sources", + // TODO New key - Add a translation + "quality-assurance.events.back-to-sources": "Back to sources", + + // "quality-assurance.event.table.less": "Show less", "quality-assurance.event.table.less": "عرض أقل", + + // "quality-assurance.event.table.more": "Show more", "quality-assurance.event.table.more": "عرض المزيد", - "quality-assurance.event.project.found": "الارتباط المحلي:", - "quality-assurance.event.project.notFound": "لم يتم العثور على تسجيل محلي", + + // "quality-assurance.event.project.found": "Bound to the local record:", + "quality-assurance.event.project.found": "ربط بالتسجيلة المحلية:", + + // "quality-assurance.event.project.notFound": "No local record found", + "quality-assurance.event.project.notFound": "لم يتم العثور على تسجيلة محلية", + + // "quality-assurance.event.sure": "Are you sure?", "quality-assurance.event.sure": "هل أنت متأكد؟", - "quality-assurance.event.ignore.description": "لا يمكن السماء عن هذه الطريقة. ", - "quality-assurance.event.undo.description": "لا يمكن التراجع عن هذه العملية!", - "quality-assurance.event.reject.description": "لا يمكن السماء عن هذه الطريقة. ", - "quality-assurance.event.accept.description": "لم يتم تحديد أي مشروع من التجسس. ", + + // "quality-assurance.event.ignore.description": "This operation can't be undone. Ignore this suggestion?", + "quality-assurance.event.ignore.description": "لا يمكن التراجع عن هذه العملية. تجاهل هذا الاقتراح؟", + + // "quality-assurance.event.undo.description": "This operation can't be undone!", + // TODO New key - Add a translation + "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.reject.description": "لا يمكن التراجع عن هذه العملية. هل ترفض هذا الاقتراح؟", + + // "quality-assurance.event.accept.description": "No DSpace project selected. A new project will be created based on the suggestion data.", + "quality-assurance.event.accept.description": "لم يتم تحديد أي مشروع دي سبيس. سيتم إنشاء مشروع جديد بناءً على بيانات الاقتراح.", + + // "quality-assurance.event.action.cancel": "Cancel", "quality-assurance.event.action.cancel": "إلغاء", - "quality-assurance.event.action.saved": "لقد تم حفظك الفعال.", - "quality-assurance.event.action.error": "حدث خطأ. ", - "quality-assurance.event.modal.project.title": "قم بإنشاء مشروعاً للربط", + + // "quality-assurance.event.action.saved": "Your decision has been saved successfully.", + "quality-assurance.event.action.saved": "لقد تم حفظ قرارك بنجاح.", + + // "quality-assurance.event.action.error": "An error has occurred. Your decision has not been saved.", + "quality-assurance.event.action.error": "حدث خطأ. لم يتم حفظ قرارك.", + + // "quality-assurance.event.modal.project.title": "Choose a project to bound", + "quality-assurance.event.modal.project.title": "اختر مشروعاً للربط", + + // "quality-assurance.event.modal.project.publication": "Publication:", "quality-assurance.event.modal.project.publication": "النشر:", - "quality-assurance.event.modal.project.bountToLocal": "الارتباط المحلي:", + + // "quality-assurance.event.modal.project.bountToLocal": "Bound to the local record:", + "quality-assurance.event.modal.project.bountToLocal": "ربط بالتسجيلة المحلية:", + + // "quality-assurance.event.modal.project.select": "Project search", "quality-assurance.event.modal.project.select": "بحث المشروع", + + // "quality-assurance.event.modal.project.search": "Search", "quality-assurance.event.modal.project.search": "بحث", - "quality-assurance.event.modal.project.clear": "تعديل التعديل", + + // "quality-assurance.event.modal.project.clear": "Clear", + "quality-assurance.event.modal.project.clear": "مسح", + + // "quality-assurance.event.modal.project.cancel": "Cancel", "quality-assurance.event.modal.project.cancel": "إلغاء", + + // "quality-assurance.event.modal.project.bound": "Bound project", "quality-assurance.event.modal.project.bound": "ربط المشروع", + + // "quality-assurance.event.modal.project.remove": "Remove", "quality-assurance.event.modal.project.remove": "إزالة", - "quality-assurance.event.modal.project.placeholder": "قم بتأكيد اسم المشروع", - "quality-assurance.event.modal.project.notFound": "لم يتم العثور على المشروع.", - "quality-assurance.event.project.bounded": "تم التركيب الفعال.", - "quality-assurance.event.project.removed": "تم إلغاء الربط الفعال.", - "quality-assurance.event.project.error": "حدث خطأ. ", - "quality-assurance.event.reason": "هذا", + + // "quality-assurance.event.modal.project.placeholder": "Enter a project name", + "quality-assurance.event.modal.project.placeholder": "قم بإدخال اسم المشروع", + + // "quality-assurance.event.modal.project.notFound": "No project found.", + "quality-assurance.event.modal.project.notFound": "لم يتم العثور على مشروع.", + + // "quality-assurance.event.project.bounded": "The project has been linked successfully.", + "quality-assurance.event.project.bounded": "تم ربط المشروع بنجاح.", + + // "quality-assurance.event.project.removed": "The project has been successfully unlinked.", + "quality-assurance.event.project.removed": "تم إلغاء ربط المشروع بنجاح.", + + // "quality-assurance.event.project.error": "An error has occurred. No operation performed.", + "quality-assurance.event.project.error": "حدث خطأ. لم يتم تنفيذ أي عملية.", + + // "quality-assurance.event.reason": "Reason", + "quality-assurance.event.reason": "السبب", + + // "orgunit.listelement.badge": "Organizational Unit", "orgunit.listelement.badge": "وحدة مؤسسية", + + // "orgunit.listelement.no-title": "Untitled", "orgunit.listelement.no-title": "بدون عنوان", + + // "orgunit.page.city": "City", "orgunit.page.city": "المدينة", + + // "orgunit.page.country": "Country", "orgunit.page.country": "البلد", + + // "orgunit.page.dateestablished": "Date established", "orgunit.page.dateestablished": "تاريخ التأسيس", + + // "orgunit.page.description": "Description", "orgunit.page.description": "الوصف", + + // "orgunit.page.edit": "Edit this item", "orgunit.page.edit": "تحرير هذه المادة", + + // "orgunit.page.id": "ID", "orgunit.page.id": "المعرف", - "orgunit.page.titleprefix": "الوحدة الوطنية: ", - "orgunit.page.ror": "معرف ROR", + + // "orgunit.page.titleprefix": "Organizational Unit: ", + "orgunit.page.titleprefix": "الوحدة المؤسسية: ", + + // "orgunit.page.ror": "ROR Identifier", + "orgunit.page.ror": "ROR معرف", + + // "pagination.options.description": "Pagination options", "pagination.options.description": "خيارات ترقيم الصفحات", + + // "pagination.results-per-page": "Results Per Page", "pagination.results-per-page": "النتائج لكل صفحة", + + // "pagination.showing.detail": "{{ range }} of {{ total }}", "pagination.showing.detail": "{{ range }} من {{ total }}", + + // "pagination.showing.label": "Now showing ", "pagination.showing.label": "يظهر الآن ", + + // "pagination.sort-direction": "Sort Options", "pagination.sort-direction": "خيارات الفرز", - "person.listelement.badge": "شخصي", - "person.listelement.no-title": "لم يتم العثور على الأسماء", - "person.page.birthdate": "تاريخ ميلادي", + + // "person.listelement.badge": "Person", + "person.listelement.badge": "شخص", + + // "person.listelement.no-title": "No name found", + "person.listelement.no-title": "لم يتم العثور على أسماء", + + // "person.page.birthdate": "Birth Date", + "person.page.birthdate": "تاريخ الميلاد الميلادي", + + // "person.page.edit": "Edit this item", "person.page.edit": "تحرير هذه المادة", + + // "person.page.email": "Email Address", "person.page.email": "عنوان البريد الإلكتروني", - "person.page.firstname": "الاسم الأول", - "person.page.jobtitle": "مسؤول وظيفي", + + // "person.page.firstname": "First Name", + // TODO New key - Add a translation + "person.page.firstname": "First Name", + + // "person.page.jobtitle": "Job Title", + "person.page.jobtitle": "المسمي الوظيفي", + + // "person.page.lastname": "Last Name", "person.page.lastname": "اسم العائلة", + + // "person.page.name": "Name", "person.page.name": "الاسم", - "person.page.link.full": "عرض كل الدعوات", + + // "person.page.link.full": "Show all metadata", + "person.page.link.full": "عرض كل الميتاداتا", + + // "person.page.orcid": "ORCID", "person.page.orcid": "أوركيد", + + // "person.page.staffid": "Staff ID", "person.page.staffid": "معرف الموظف", + + // "person.page.titleprefix": "Person: ", "person.page.titleprefix": "الشخص: ", + + // "person.search.results.head": "Person Search Results", "person.search.results.head": "نتائج بحث الشخص", + + // "person-relationships.search.results.head": "Person Search Results", "person-relationships.search.results.head": "نتائج بحث الشخص", + + // "person.search.title": "Person Search", "person.search.title": "بحث الشخص", - "process.new.select-parameters": "لا تزال", - "process.new.select-parameter": "تحديد النص", - "process.new.add-parameter": "إضافة نصوص...", - "process.new.delete-parameter": "حذف التقليد", + + // "process.new.select-parameters": "Parameters", + "process.new.select-parameters": "المتغيرات", + + // "process.new.select-parameter": "Select parameter", + "process.new.select-parameter": "تحديد متغير", + + // "process.new.add-parameter": "Add a parameter...", + "process.new.add-parameter": "إضافة متغير...", + + // "process.new.delete-parameter": "Delete parameter", + "process.new.delete-parameter": "حذف متغير", + + // "process.new.parameter.label": "Parameter value", "process.new.parameter.label": "قيمة المتغير", + + // "process.new.cancel": "Cancel", "process.new.cancel": "إلغاء", + + // "process.new.submit": "Save", "process.new.submit": "حفظ", + + // "process.new.select-script": "Script", "process.new.select-script": "نص", + + // "process.new.select-script.placeholder": "Choose a script...", "process.new.select-script.placeholder": "اختر نص...", + + // "process.new.select-script.required": "Script is required", "process.new.select-script.required": "النص مطلوب", + + // "process.new.parameter.file.upload-button": "Select file...", "process.new.parameter.file.upload-button": "اختر ملف...", - "process.new.parameter.file.required": "يرجى تحديد الملف", + + // "process.new.parameter.file.required": "Please select a file", + "process.new.parameter.file.required": "يرجى تحديد ملف", + + // "process.new.parameter.string.required": "Parameter value is required", "process.new.parameter.string.required": "قيمة المتغير مطلوبة", + + // "process.new.parameter.type.value": "value", "process.new.parameter.type.value": "القيمة", + + // "process.new.parameter.type.file": "file", "process.new.parameter.type.file": "ملف", - "process.new.parameter.required.missing": "التالية مطلوبة ولكنها لا تزال ناقصة:", + + // "process.new.parameter.required.missing": "The following parameters are required but still missing:", + "process.new.parameter.required.missing": "المتغيرات التالية مطلوبة ولكنها لا تزال ناقصة:", + + // "process.new.notification.success.title": "Success", "process.new.notification.success.title": "نجاح", - "process.new.notification.success.content": "تم إنشاء فعال", + + // "process.new.notification.success.content": "The process was successfully created", + "process.new.notification.success.content": "تم إنشاء العملية بنجاح", + + // "process.new.notification.error.title": "Error", "process.new.notification.error.title": "خطأ", - "process.new.notification.error.content": "حدث خطأ أثناء إنشاء الطريق", - "process.new.notification.error.max-upload.content": "السماح بالملف الأقصى لحجم التحميل", - "process.new.header": "إنشاء إنشاءات جديدة", - "process.new.title": "إنشاء إنشاءات جديدة", - "process.new.breadcrumbs": "إنشاء إنشاءات جديدة", - "process.detail.arguments": "لماذا", - "process.detail.arguments.empty": "لا تحتوي هذه الطريقة على أي أسباب", + + // "process.new.notification.error.content": "An error occurred while creating this process", + "process.new.notification.error.content": "حدث خطأ أثناء إنشاء العملية", + + // "process.new.notification.error.max-upload.content": "The file exceeds the maximum upload size", + "process.new.notification.error.max-upload.content": "يتجاوز الملف الحد الأقصى لحجم التحميل", + + // "process.new.header": "Create a new process", + "process.new.header": "إنشاء عملية جديدة", + + // "process.new.title": "Create a new process", + "process.new.title": "إنشاء عملية جديدة", + + // "process.new.breadcrumbs": "Create a new process", + "process.new.breadcrumbs": "إنشاء عملية جديدة", + + // "process.detail.arguments": "Arguments", + "process.detail.arguments": "حجج", + + // "process.detail.arguments.empty": "This process doesn't contain any arguments", + "process.detail.arguments.empty": "لا تحتوي هذه العملية على أي حجج", + + // "process.detail.back": "Back", "process.detail.back": "رجوع", - "process.detail.output": "مخرجات الطريقة", - "process.detail.logs.button": "استرجاع مخرجات الحرارة", + + // "process.detail.output": "Process Output", + "process.detail.output": "مخرجات العملية", + + // "process.detail.logs.button": "Retrieve process output", + "process.detail.logs.button": "استرجاع مخرجات العملية", + + // "process.detail.logs.loading": "Retrieving", "process.detail.logs.loading": "استرجاع", - "process.detail.logs.none": "ولا يوجد مخرجات لهذه الغاية", - "process.detail.output-files": "ملفات المنتج", - "process.detail.output-files.empty": "لا تحتوي على هذه الطريقة على أي من المواد التي تم إخراجها", + + // "process.detail.logs.none": "This process has no output", + "process.detail.logs.none": "لا توجد مخرجات لهذه العملية", + + // "process.detail.output-files": "Output Files", + "process.detail.output-files": "ملفات الإخراج", + + // "process.detail.output-files.empty": "This process doesn't contain any output files", + "process.detail.output-files.empty": "لا تحتوي هذه العملية على أي ملفات إخراج", + + // "process.detail.script": "Script", "process.detail.script": "النص", - "process.detail.title": "الطريقة: {{ id }} - {{ name }}", + + // "process.detail.title": "Process: {{ id }} - {{ name }}", + "process.detail.title": "العملية: {{ id }} - {{ name }}", + + // "process.detail.start-time": "Start time", "process.detail.start-time": "وقت البدء", - "process.detail.end-time": "انتهى الوقت", + + // "process.detail.end-time": "Finish time", + "process.detail.end-time": "وقت الانتهاء", + + // "process.detail.status": "Status", "process.detail.status": "الحالة", - "process.detail.create": "إنشاء طريقة مماثلة", + + // "process.detail.create": "Create similar process", + "process.detail.create": "إنشاء عملية مماثلة", + + // "process.detail.actions": "Actions", "process.detail.actions": "إجراءات", - "process.detail.delete.button": "حذف المعاملة", - "process.detail.delete.header": "حذف المعاملة", - "process.detail.delete.body": "هل أنت متأكد من أنك ترغب في الحذف الصحيح؟", + + // "process.detail.delete.button": "Delete process", + "process.detail.delete.button": "حذف العملية", + + // "process.detail.delete.header": "Delete process", + "process.detail.delete.header": "حذف العملية", + + // "process.detail.delete.body": "Are you sure you want to delete the current process?", + "process.detail.delete.body": "هل أنت متأكد من أنك تريد حذف العملية الحالية؟", + + // "process.detail.delete.cancel": "Cancel", "process.detail.delete.cancel": "إلغاء", - "process.detail.delete.confirm": "حذف المعاملة", - "process.detail.delete.success": "تم الحذف الفعال.", - "process.detail.delete.error": "حدث خطأ ما أثناء الحذف", - "process.detail.refreshing": "التحديث التلقائي…", - "process.overview.table.completed.info": "وقت الانتهاء (التوقيت العالمي المنسق)", - "process.overview.table.completed.title": "العمليات الناجحة", - "process.overview.table.empty": "لم يتم العثور على عمليات مطابقة.", - "process.overview.table.failed.info": "وقت الانتهاء (التوقيت العالمي المنسق)", - "process.overview.table.failed.title": "العمليات الفاشلة", - "process.overview.table.finish": "انتهى الوقت (التوقيت العالمي)", - "process.overview.table.id": "معرف الطريقة", + + // "process.detail.delete.confirm": "Delete process", + "process.detail.delete.confirm": "حذف العملية", + + // "process.detail.delete.success": "The process was successfully deleted.", + "process.detail.delete.success": "تم حذف العملية بنجاح.", + + // "process.detail.delete.error": "Something went wrong when deleting the process", + "process.detail.delete.error": "حدث خطأ ما أثناء حذف العملية", + + // "process.detail.refreshing": "Auto-refreshing…", + // TODO New key - Add a translation + "process.detail.refreshing": "Auto-refreshing…", + + // "process.overview.table.completed.info": "Finish time (UTC)", + // TODO New key - Add a translation + "process.overview.table.completed.info": "Finish time (UTC)", + + // "process.overview.table.completed.title": "Succeeded processes", + // TODO New key - Add a translation + "process.overview.table.completed.title": "Succeeded processes", + + // "process.overview.table.empty": "No matching processes found.", + // TODO New key - Add a translation + "process.overview.table.empty": "No matching processes found.", + + // "process.overview.table.failed.info": "Finish time (UTC)", + // TODO New key - Add a translation + "process.overview.table.failed.info": "Finish time (UTC)", + + // "process.overview.table.failed.title": "Failed processes", + // TODO New key - Add a translation + "process.overview.table.failed.title": "Failed processes", + + // "process.overview.table.finish": "Finish time (UTC)", + "process.overview.table.finish": "وقت الانتهاء (التوقيت العالمي)", + + // "process.overview.table.id": "Process ID", + "process.overview.table.id": "معرف العملية", + + // "process.overview.table.name": "Name", "process.overview.table.name": "الاسم", - "process.overview.table.running.info": "وقت البدء (التوقيت العالمي المنسق)", - "process.overview.table.running.title": "ادارة العمليات", - "process.overview.table.scheduled.info": "وقت الإنشاء (التوقيت العالمي المنسق)", - "process.overview.table.scheduled.title": "العمليات المجدولة", - "process.overview.table.start": "التوقيت (التوقيت العالمي)", + + // "process.overview.table.running.info": "Start time (UTC)", + // TODO New key - Add a translation + "process.overview.table.running.info": "Start time (UTC)", + + // "process.overview.table.running.title": "Running processes", + // TODO New key - Add a translation + "process.overview.table.running.title": "Running processes", + + // "process.overview.table.scheduled.info": "Creation time (UTC)", + // TODO New key - Add a translation + "process.overview.table.scheduled.info": "Creation time (UTC)", + + // "process.overview.table.scheduled.title": "Scheduled processes", + // TODO New key - Add a translation + "process.overview.table.scheduled.title": "Scheduled processes", + + // "process.overview.table.start": "Start time (UTC)", + "process.overview.table.start": "وقت البدء (التوقيت العالمي)", + + // "process.overview.table.status": "Status", "process.overview.table.status": "الحالة", + + // "process.overview.table.user": "User", "process.overview.table.user": "المستخدم", + + // "process.overview.title": "Processes Overview", "process.overview.title": "نظرة عامة على العمليات", + + // "process.overview.breadcrumbs": "Processes Overview", "process.overview.breadcrumbs": "نظرة عامة على العمليات", + + // "process.overview.new": "New", "process.overview.new": "جديد", + + // "process.overview.table.actions": "Actions", "process.overview.table.actions": "إجراءات", + + // "process.overview.delete": "Delete {{count}} processes", "process.overview.delete": "حذف {{count}} عملية", - "process.overview.delete-process": "حذف المعاملة", - "process.overview.delete.clear": "حذف التحديد والحذف", - "process.overview.delete.processing": "سيتم حذفه {{count}} عملية. ", - "process.overview.delete.body": "هل أنت متأكد أنك تريد الحذف {{count}} العملية؟", + + // "process.overview.delete-process": "Delete process", + "process.overview.delete-process": "حذف العملية", + + // "process.overview.delete.clear": "Clear delete selection", + "process.overview.delete.clear": "مسح تحديد الحذف", + + // "process.overview.delete.processing": "{{count}} process(es) are being deleted. Please wait for the deletion to fully complete. Note that this can take a while.", + "process.overview.delete.processing": "يجري حذف {{count}} عملية. يرجى الانتظار حتى يكتمل الحذف بالكامل. لاحظ أن ذلك قد يستغرق بعض الوقت.", + + // "process.overview.delete.body": "Are you sure you want to delete {{count}} process(es)?", + "process.overview.delete.body": "هل أنت متأكد أنك تريد حذف {{count}} عملية؟", + + // "process.overview.delete.header": "Delete processes", "process.overview.delete.header": "حذف العمليات", + + // "process.bulk.delete.error.head": "Error on deleteing process", "process.bulk.delete.error.head": "خطأ في عملية الحذف", - "process.bulk.delete.error.body": "لا يمكن حذف الطريقة ذات المعرفة {{processId}}. ", - "process.bulk.delete.success": "تم الحذف {{count}} فعالية فعالة", + + // "process.bulk.delete.error.body": "The process with ID {{processId}} could not be deleted. The remaining processes will continue being deleted. ", + "process.bulk.delete.error.body": "لا يمكن حذف العملية ذات المعرف {{processId}}. وسيستمر حذف العمليات المتبقية. ", + + // "process.bulk.delete.success": "{{count}} process(es) have been succesfully deleted", + "process.bulk.delete.success": "تم حذف {{count}} عملية بنجاح", + + // "profile.breadcrumbs": "Update Profile", "profile.breadcrumbs": "تحديث الملف الشخصي", + + // "profile.card.identify": "Identify", "profile.card.identify": "تعريف", + + // "profile.card.security": "Security", "profile.card.security": "الحماية والأمان", + + // "profile.form.submit": "Save", "profile.form.submit": "حفظ", - "profile.groups.head": "المجموعات التي تقترحها", - "profile.special.groups.head": "المجموعات التي تقترحها", + + // "profile.groups.head": "Authorization groups you belong to", + "profile.groups.head": "مجموعات التفويض التي تنتمي إليها", + + // "profile.special.groups.head": "Authorization special groups you belong to", + "profile.special.groups.head": "مجموعات التفويض الخاصة التي تنتمي إليها", + + // "profile.metadata.form.error.firstname.required": "First Name is required", "profile.metadata.form.error.firstname.required": "الاسم الأول مطلوب", + + // "profile.metadata.form.error.lastname.required": "Last Name is required", "profile.metadata.form.error.lastname.required": "اسم العائلة مطلوب", + + // "profile.metadata.form.label.email": "Email Address", "profile.metadata.form.label.email": "عنوان البريد الإلكتروني", + + // "profile.metadata.form.label.firstname": "First Name", "profile.metadata.form.label.firstname": "الاسم الأول", + + // "profile.metadata.form.label.language": "Language", "profile.metadata.form.label.language": "اللغة", + + // "profile.metadata.form.label.lastname": "Last Name", "profile.metadata.form.label.lastname": "اسم العائلة", - "profile.metadata.form.label.phone": "هاتف", - "profile.metadata.form.notifications.success.content": "تم حفظ التغييرات التي استخدمتها على الملف الشخصي.", + + // "profile.metadata.form.label.phone": "Contact Telephone", + "profile.metadata.form.label.phone": "هاتف الاتصال", + + // "profile.metadata.form.notifications.success.content": "Your changes to the profile were saved.", + "profile.metadata.form.notifications.success.content": "تم حفظ التغييرات التي أجريتها على الملف الشخصي.", + + // "profile.metadata.form.notifications.success.title": "Profile saved", "profile.metadata.form.notifications.success.title": "تم حفظ الملف الشخصي", - "profile.notifications.warning.no-changes.content": "لم يتم عمل أي تغييرات على الملف الشخصي.", + + // "profile.notifications.warning.no-changes.content": "No changes were made to the Profile.", + "profile.notifications.warning.no-changes.content": "لم يتم إجراء أي تغييرات على الملف الشخصي.", + + // "profile.notifications.warning.no-changes.title": "No changes", "profile.notifications.warning.no-changes.title": "لا توجد تغييرات", + + // "profile.security.form.error.matching-passwords": "The passwords do not match.", "profile.security.form.error.matching-passwords": "كلمات المرور غير متطابقة.", - "profile.security.form.info": "اختياريًا، يمكنك تسجيل كلمة مرور في القسم السفلي، وتأكيدها عن طريق كتابتها مرة أخرى في الشريط الثاني.", + + // "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box.", + "profile.security.form.info": "اختيارياً، يمكنك إدخال كلمة مرور جديدة في المربع أدناه، وتأكيدها عن طريق كتابتها مرة أخرى في المربع الثاني.", + + // "profile.security.form.label.password": "Password", "profile.security.form.label.password": "كلمة المرور", - "profile.security.form.label.passwordrepeat": "إعادة الكتابة للتأكيد", + + // "profile.security.form.label.passwordrepeat": "Retype to confirm", + "profile.security.form.label.passwordrepeat": "أعد الكتابة للتأكيد", + + // "profile.security.form.label.current-password": "Current password", "profile.security.form.label.current-password": "كلمة المرور الحالية", - "profile.security.form.notifications.success.content": "تم حفظ التغييرات التي جربتها على كلمة المرور.", + + // "profile.security.form.notifications.success.content": "Your changes to the password were saved.", + "profile.security.form.notifications.success.content": "تم حفظ التغييرات التي أجريتها على كلمة المرور.", + + // "profile.security.form.notifications.success.title": "Password saved", "profile.security.form.notifications.success.title": "تم حفظ كلمة المرور", + + // "profile.security.form.notifications.error.title": "Error changing passwords", "profile.security.form.notifications.error.title": "حدث خطأ أثناء تغيير كلمات المرور", - "profile.security.form.notifications.error.change-failed": "حدث خطأ أثناء محاولة تغيير كلمة المرور. ", - "profile.security.form.notifications.error.not-same": "كلمات الترويج المختلفة.", - "profile.security.form.notifications.error.general": "يرجى استخدام الأغراض المتعددة في نموذج الحماية والأمان.", + + // "profile.security.form.notifications.error.change-failed": "An error occurred while trying to change the password. Please check if the current password is correct.", + "profile.security.form.notifications.error.change-failed": "حدث خطأ أثناء محاولة تغيير كلمة المرور. يرجى التحقق مما إذا كانت كلمة المرور الحالية صحيحة.", + + // "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", + "profile.security.form.notifications.error.not-same": "كلمات المرور المقدمة مختلفة.", + + // "profile.security.form.notifications.error.general": "Please fill required fields of security form.", + "profile.security.form.notifications.error.general": "يرجى ملء الحقول المطلوبة في نموذج الحماية والأمان.", + + // "profile.title": "Update Profile", "profile.title": "تحديث الملف الشخصي", - "profile.card.researcher": "الملف للباحث الشخصي", - "project.listelement.badge": "مشروع باحث", + + // "profile.card.researcher": "Researcher Profile", + "profile.card.researcher": "الملف الشخصي للباحث", + + // "project.listelement.badge": "Research Project", + "project.listelement.badge": "مشروع الباحث", + + // "project.page.contributor": "Contributors", "project.page.contributor": "المساهمون", + + // "project.page.description": "Description", "project.page.description": "الوصف", + + // "project.page.edit": "Edit this item", "project.page.edit": "تحرير هذه المادة", - "project.page.expectedcompletion": "الاكمال المصيبة", - "project.page.funder": "الأمولين", + + // "project.page.expectedcompletion": "Expected Completion", + "project.page.expectedcompletion": "الإكمال المتوقع", + + // "project.page.funder": "Funders", + "project.page.funder": "الممولين", + + // "project.page.id": "ID", "project.page.id": "المعرف", - "project.page.keyword": "الكلمات الرئيسية", + + // "project.page.keyword": "Keywords", + "project.page.keyword": "كلمات رئيسية", + + // "project.page.status": "Status", "project.page.status": "الحالة", + + // "project.page.titleprefix": "Research Project: ", "project.page.titleprefix": "مشورع البحث: ", - "project.search.results.head": "نتائج البحث في المشروع", - "project-relationships.search.results.head": "نتائج البحث في المشروع", + + // "project.search.results.head": "Project Search Results", + "project.search.results.head": "نتائج بحث المشروع", + + // "project-relationships.search.results.head": "Project Search Results", + "project-relationships.search.results.head": "نتائج بحث المشروع", + + // "publication.listelement.badge": "Publication", "publication.listelement.badge": "النشر", + + // "publication.page.description": "Description", "publication.page.description": "الوصف", + + // "publication.page.edit": "Edit this item", "publication.page.edit": "تحرير هذه المادة", + + // "publication.page.journal-issn": "Journal ISSN", "publication.page.journal-issn": "ردمد الدورية", - "publication.page.journal-title": "عنوان الدوري", + + // "publication.page.journal-title": "Journal Title", + "publication.page.journal-title": "عنوان الدورية", + + // "publication.page.publisher": "Publisher", "publication.page.publisher": "الناشر", - "publication.page.titleprefix": "النشر: ", + + // "publication.page.titleprefix": "Publication: ", + "publication.page.titleprefix": "المنشور: ", + + // "publication.page.volume-title": "Volume Title", "publication.page.volume-title": "عنوان المجلد", + + // "publication.search.results.head": "Publication Search Results", "publication.search.results.head": "نتائج بحث المنشور", + + // "publication-relationships.search.results.head": "Publication Search Results", "publication-relationships.search.results.head": "نتائج بحث المنشور", - "publication.search.title": "بحثت في المنشور", + + // "publication.search.title": "Publication Search", + "publication.search.title": "بحث المنشور", + + // "media-viewer.next": "Next", "media-viewer.next": "التالي", - "media-viewer.previous": "السابقة", + + // "media-viewer.previous": "Previous", + "media-viewer.previous": "السابق", + + // "media-viewer.playlist": "Playlist", "media-viewer.playlist": "قائمة التشغيل", - "suggestion.loading": "تحميل ...", - "suggestion.title": "المطالبة بالنشر", - "suggestion.title.breadcrumbs": "المطالبة بالنشر", - "suggestion.targets.description": "أدناه يمكنك رؤية جميع الاقتراحات ", - "suggestion.targets": "الاقتراحات الحالية", - "suggestion.table.name": "اسم الباحث", - "suggestion.table.actions": "أجراءات", - "suggestion.button.review": "مراجعة {{ total }} اقتراحات)", - "suggestion.button.review.title": "مراجعة {{ total }} اقتراح (اقتراحات) ل ", - "suggestion.noTargets": "لم يتم العثور على هدف.", - "suggestion.target.error.service.retrieve": "حدث خطأ أثناء تحميل أهداف الاقتراح", - "suggestion.evidence.type": "يكتب", - "suggestion.evidence.score": "نتيجة", - "suggestion.evidence.notes": "ملحوظات", - "suggestion.approveAndImport": "الموافقة والاستيراد", - "suggestion.approveAndImport.success": "تم استيراد الاقتراح بنجاح. منظر.", - "suggestion.approveAndImport.bulk": "الموافقة والاستيراد المحدد", - "suggestion.approveAndImport.bulk.success": "{{ count }} تم استيراد الاقتراحات بنجاح ", - "suggestion.approveAndImport.bulk.error": "{{ count }} لم يتم استيراد الاقتراحات بسبب حدوث أخطاء غير متوقعة في الخادم", - "suggestion.ignoreSuggestion": "تجاهل الاقتراح", - "suggestion.ignoreSuggestion.success": "لقد تم تجاهل الاقتراح", - "suggestion.ignoreSuggestion.bulk": "تجاهل الاقتراح المحدد", - "suggestion.ignoreSuggestion.bulk.success": "{{ count }} لقد تم تجاهل الاقتراحات ", - "suggestion.ignoreSuggestion.bulk.error": "{{ count }} لم يتم تجاهل الاقتراحات بسبب أخطاء غير متوقعة في الخادم", - "suggestion.seeEvidence": "انظر الأدلة", - "suggestion.hideEvidence": "إخفاء الأدلة", - "suggestion.suggestionFor": "اقتراحات ل", - "suggestion.suggestionFor.breadcrumb": "اقتراحات ل {{ name }}", - "suggestion.source.openaire": "الرسم البياني أوبن إير", - "suggestion.from.source": "من ", - "suggestion.count.missing": "لم يتبق لديك أي مطالبات بالنشر", - "suggestion.totalScore": "مجموع النقاط", - "suggestion.type.openaire": "أوبن إير", + + // "suggestion.loading": "Loading ...", + // TODO New key - Add a translation + "suggestion.loading": "Loading ...", + + // "suggestion.title": "Publication Claim", + // TODO New key - Add a translation + "suggestion.title": "Publication Claim", + + // "suggestion.title.breadcrumbs": "Publication Claim", + // TODO New key - Add a translation + "suggestion.title.breadcrumbs": "Publication Claim", + + // "suggestion.targets.description": "Below you can see all the suggestions ", + // TODO New key - Add a translation + "suggestion.targets.description": "Below you can see all the suggestions ", + + // "suggestion.targets": "Current Suggestions", + // TODO New key - Add a translation + "suggestion.targets": "Current Suggestions", + + // "suggestion.table.name": "Researcher Name", + // TODO New key - Add a translation + "suggestion.table.name": "Researcher Name", + + // "suggestion.table.actions": "Actions", + // TODO New key - Add a translation + "suggestion.table.actions": "Actions", + + // "suggestion.button.review": "Review {{ total }} suggestion(s)", + // TODO New key - Add a translation + "suggestion.button.review": "Review {{ total }} suggestion(s)", + + // "suggestion.button.review.title": "Review {{ total }} suggestion(s) for ", + // TODO New key - Add a translation + "suggestion.button.review.title": "Review {{ total }} suggestion(s) for ", + + // "suggestion.noTargets": "No target found.", + // TODO New key - Add a translation + "suggestion.noTargets": "No target found.", + + // "suggestion.target.error.service.retrieve": "An error occurred while loading the Suggestion targets", + // TODO New key - Add a translation + "suggestion.target.error.service.retrieve": "An error occurred while loading the Suggestion targets", + + // "suggestion.evidence.type": "Type", + // TODO New key - Add a translation + "suggestion.evidence.type": "Type", + + // "suggestion.evidence.score": "Score", + // TODO New key - Add a translation + "suggestion.evidence.score": "Score", + + // "suggestion.evidence.notes": "Notes", + // TODO New key - Add a translation + "suggestion.evidence.notes": "Notes", + + // "suggestion.approveAndImport": "Approve & import", + // TODO New key - Add a translation + "suggestion.approveAndImport": "Approve & import", + + // "suggestion.approveAndImport.success": "The suggestion has been imported successfully. View.", + // TODO New key - Add a translation + "suggestion.approveAndImport.success": "The suggestion has been imported successfully. View.", + + // "suggestion.approveAndImport.bulk": "Approve & import Selected", + // TODO New key - Add a translation + "suggestion.approveAndImport.bulk": "Approve & import Selected", + + // "suggestion.approveAndImport.bulk.success": "{{ count }} suggestions have been imported successfully ", + // TODO New key - Add a translation + "suggestion.approveAndImport.bulk.success": "{{ count }} suggestions have been imported successfully ", + + // "suggestion.approveAndImport.bulk.error": "{{ count }} suggestions haven't been imported due to unexpected server errors", + // TODO New key - Add a translation + "suggestion.approveAndImport.bulk.error": "{{ count }} suggestions haven't been imported due to unexpected server errors", + + // "suggestion.ignoreSuggestion": "Ignore Suggestion", + // TODO New key - Add a translation + "suggestion.ignoreSuggestion": "Ignore Suggestion", + + // "suggestion.ignoreSuggestion.success": "The suggestion has been discarded", + // TODO New key - Add a translation + "suggestion.ignoreSuggestion.success": "The suggestion has been discarded", + + // "suggestion.ignoreSuggestion.bulk": "Ignore Suggestion Selected", + // TODO New key - Add a translation + "suggestion.ignoreSuggestion.bulk": "Ignore Suggestion Selected", + + // "suggestion.ignoreSuggestion.bulk.success": "{{ count }} suggestions have been discarded ", + // TODO New key - Add a translation + "suggestion.ignoreSuggestion.bulk.success": "{{ count }} suggestions have been discarded ", + + // "suggestion.ignoreSuggestion.bulk.error": "{{ count }} suggestions haven't been discarded due to unexpected server errors", + // TODO New key - Add a translation + "suggestion.ignoreSuggestion.bulk.error": "{{ count }} suggestions haven't been discarded due to unexpected server errors", + + // "suggestion.seeEvidence": "See evidence", + // TODO New key - Add a translation + "suggestion.seeEvidence": "See evidence", + + // "suggestion.hideEvidence": "Hide evidence", + // TODO New key - Add a translation + "suggestion.hideEvidence": "Hide evidence", + + // "suggestion.suggestionFor": "Suggestions for", + // TODO New key - Add a translation + "suggestion.suggestionFor": "Suggestions for", + + // "suggestion.suggestionFor.breadcrumb": "Suggestions for {{ name }}", + // TODO New key - Add a translation + "suggestion.suggestionFor.breadcrumb": "Suggestions for {{ name }}", + + // "suggestion.source.openaire": "OpenAIRE Graph", + // TODO New key - Add a translation + "suggestion.source.openaire": "OpenAIRE Graph", + + // "suggestion.from.source": "from the ", + // TODO New key - Add a translation + "suggestion.from.source": "from the ", + + // "suggestion.count.missing": "You have no publication claims left", + // TODO New key - Add a translation + "suggestion.count.missing": "You have no publication claims left", + + // "suggestion.totalScore": "Total Score", + // TODO New key - Add a translation + "suggestion.totalScore": "Total Score", + + // "suggestion.type.openaire": "OpenAIRE", + // TODO New key - Add a translation + "suggestion.type.openaire": "OpenAIRE", + + // "register-email.title": "New user registration", "register-email.title": "تسجيل مستخدم جديد", + + // "register-page.create-profile.header": "Create Profile", "register-page.create-profile.header": "إنشاء ملف شخصي", + + // "register-page.create-profile.identification.header": "Identify", "register-page.create-profile.identification.header": "تعريف", + + // "register-page.create-profile.identification.email": "Email Address", "register-page.create-profile.identification.email": "عنوان البريد الإلكتروني", + + // "register-page.create-profile.identification.first-name": "First Name *", "register-page.create-profile.identification.first-name": "الاسم الأول *", - "register-page.create-profile.identification.first-name.error": "يرجى الاتصال بالاسم الأول", + + // "register-page.create-profile.identification.first-name.error": "Please fill in a First Name", + "register-page.create-profile.identification.first-name.error": "يرجى إدخال الاسم الأول", + + // "register-page.create-profile.identification.last-name": "Last Name *", "register-page.create-profile.identification.last-name": "اسم العائلة *", - "register-page.create-profile.identification.last-name.error": "يرجى الاتصال باسم العائلة", + + // "register-page.create-profile.identification.last-name.error": "Please fill in a Last Name", + "register-page.create-profile.identification.last-name.error": "يرجى إدخال اسم العائلة", + + // "register-page.create-profile.identification.contact": "Contact Telephone", "register-page.create-profile.identification.contact": "الهاتف", + + // "register-page.create-profile.identification.language": "Language", "register-page.create-profile.identification.language": "اللغة", + + // "register-page.create-profile.security.header": "Security", "register-page.create-profile.security.header": "الحماية والأمان", - "register-page.create-profile.security.info": "يرجى الاتصال برقم المرور في الشريط أدناه، وتأكيدها عن طريق كتابها مرة أخرى في الشريط الثاني. ", + + // "register-page.create-profile.security.info": "Please enter a password in the box below, and confirm it by typing it again into the second box.", + "register-page.create-profile.security.info": "يرجى إدخال كلمة المرور في المربع أدناه، وتأكيدها عن طريق كتابتها مرة أخرى في المربع الثاني. يجب أن تتكون من ستة أحرف على الأقل.", + + // "register-page.create-profile.security.label.password": "Password *", "register-page.create-profile.security.label.password": "كلمة المرور *", - "register-page.create-profile.security.label.passwordrepeat": "خطة إعادة الكتابة للتأكيد *", - "register-page.create-profile.security.error.empty-password": "الرجاء الاتصال بكلمة المرور في النطاق أدناه.", - "register-page.create-profile.security.error.matching-passwords": "كلمتي الطلب التي قمت بتأكيدها غير متطابقتين.", + + // "register-page.create-profile.security.label.passwordrepeat": "Retype to confirm *", + "register-page.create-profile.security.label.passwordrepeat": "أعد الكتابة للتأكيد *", + + // "register-page.create-profile.security.error.empty-password": "Please enter a password in the box below.", + "register-page.create-profile.security.error.empty-password": "يرجى إدخال كلمة المرور في المربع أدناه.", + + // "register-page.create-profile.security.error.matching-passwords": "The passwords do not match.", + "register-page.create-profile.security.error.matching-passwords": "كلمتي المرور التي قمت بإدخالهما غير متطابقتين.", + + // "register-page.create-profile.submit": "Complete Registration", "register-page.create-profile.submit": "اكتمل التسجيل", + + // "register-page.create-profile.submit.error.content": "Something went wrong while registering a new user.", "register-page.create-profile.submit.error.content": "حدث خطأ ما أثناء تسجيل مستخدم جديد.", + + // "register-page.create-profile.submit.error.head": "Registration failed", "register-page.create-profile.submit.error.head": "فشل التسجيل", - "register-page.create-profile.submit.success.content": "تم التسجيل الفعال. ", + + // "register-page.create-profile.submit.success.content": "The registration was successful. You have been logged in as the created user.", + "register-page.create-profile.submit.success.content": "تم التسجيل بنجاح. لقد قمت بتسجيل الدخول كالمستخدم الذي تم إنشاؤه.", + + // "register-page.create-profile.submit.success.head": "Registration completed", "register-page.create-profile.submit.success.head": "اكتمل التسجيل", + + // "register-page.registration.header": "New user registration", "register-page.registration.header": "تسجيل مستخدم جديد", - "register-page.registration.info": "قام بتسجيل حساب للاشتراك في Vitten لتحديثات البريد الإلكتروني، المساهمة في منتجات جديدة إلى دي سبيس.", + + // "register-page.registration.info": "Register an account to subscribe to collections for email updates, and submit new items to DSpace.", + "register-page.registration.info": "قم بتسجيل حساب للاشتراك في حاويات لتحديثات البريد الإلكتروني، وتقديم مواد جديدة إلى دي سبيس.", + + // "register-page.registration.email": "Email Address *", "register-page.registration.email": "عنوان البريد الإلكتروني *", - "register-page.registration.email.error.required": "يرجى الاتصال بعنوان البريد الإلكتروني", - "register-page.registration.email.error.not-email-form": "يرجى الاتصال بعنوان بريد إلكتروني صالح.", - "register-page.registration.email.error.not-valid-domain": "استخدام البريد الإلكتروني بالنطاقات المخصصة: {{ domains }}", - "register-page.registration.email.hint": "تم التحقق من هذا العنوان نيكوله كاسم تسجيل الدخول الخاص بك.", + + // "register-page.registration.email.error.required": "Please fill in an email address", + "register-page.registration.email.error.required": "يرجى إدخال عنوان البريد الإلكتروني", + + // "register-page.registration.email.error.not-email-form": "Please fill in a valid email address.", + "register-page.registration.email.error.not-email-form": "يرجى إدخال عنوان بريد إلكتروني صالح.", + + // "register-page.registration.email.error.not-valid-domain": "Use email with allowed domains: {{ domains }}", + "register-page.registration.email.error.not-valid-domain": "استخدم البريد الإلكتروني بالنطاقات المسموح بها: {{ domains }}", + + // "register-page.registration.email.hint": "This address will be verified and used as your login name.", + "register-page.registration.email.hint": "سيتم التحقق من هذا العنوان واستخدامه كاسم تسجيل الدخول الخاص بك.", + + // "register-page.registration.submit": "Register", "register-page.registration.submit": "تسجيل", - "register-page.registration.success.head": "إرسال رسالة بريد إلكتروني مؤكدة", - "register-page.registration.success.content": "يتم إرسال رسالة بريد الإلكتروني إلى {{ email }} تحتوي على عنوان URL خاص ومتزايد من التعلميات.", - "register-page.registration.error.head": "حدث خطأ أثناء محاولة تسجيل البريد الإلكتروني", + + // "register-page.registration.success.head": "Verification email sent", + "register-page.registration.success.head": "تم إرسال رسالة تأكيد البريد الإلكتروني", + + // "register-page.registration.success.content": "An email has been sent to {{ email }} containing a special URL and further instructions.", + "register-page.registration.success.content": "تم إرسال رسالة بريد إلكتروني إلى {{ email }} تحتوي على عنوان URL خاص والمزيد من التعلميات.", + + // "register-page.registration.error.head": "Error when trying to register email", + "register-page.registration.error.head": "خطأ أثناء محاولة تسجيل البريد الإلكتروني", + + // "register-page.registration.error.content": "An error occured when registering the following email address: {{ email }}", "register-page.registration.error.content": "حدث خطأ أثناء تسجيل عنوان البريد الإلكتروني التالي: {{ email }}", + + // "register-page.registration.error.recaptcha": "Error when trying to authenticate with recaptcha", "register-page.registration.error.recaptcha": "حدث خطأ أثناء محاولة الاستيثاق باستخدام recaptcha", - "register-page.registration.google-recaptcha.must-accept-cookies": "للتسجيل، يجب عليك قبول ملفات تعريف الارتباط التسجيل و استعادة كلمة المرور (جوجل reCaptcha).", - "register-page.registration.error.maildomain": "عنوان البريد الإلكتروني غير موجود في قائمة النطاقات التي تناسب التسجيل. {{ domains }}", + + // "register-page.registration.google-recaptcha.must-accept-cookies": "In order to register you must accept the Registration and Password recovery (Google reCaptcha) cookies.", + "register-page.registration.google-recaptcha.must-accept-cookies": "للتسجيل، يجب عليك قبول ملفات تعريف ارتباط التسجيل واستعادة كلمة المرور (جوجل reCaptcha).", + + // "register-page.registration.error.maildomain": "This email address is not on the list of domains who can register. Allowed domains are {{ domains }}", + "register-page.registration.error.maildomain": "عنوان البريد الإلكتروني غير موجود في قائمة النطاقات التي يمكنها التسجيل. النطاقات المسموح بها هي {{ domains }}", + + // "register-page.registration.google-recaptcha.open-cookie-settings": "Open cookie settings", "register-page.registration.google-recaptcha.open-cookie-settings": "فتح إعدادات ملفات تعريف الارتباط", - "register-page.registration.google-recaptcha.notification.title": "جوجل ريكابتشا", + + // "register-page.registration.google-recaptcha.notification.title": "Google reCaptcha", + "register-page.registration.google-recaptcha.notification.title": "جوجل reCaptcha", + + // "register-page.registration.google-recaptcha.notification.message.error": "An error occurred during reCaptcha verification", "register-page.registration.google-recaptcha.notification.message.error": "حدث خطأ أثناء التحقق من reCaptcha", - "register-page.registration.google-recaptcha.notification.message.expired": "صلاحية التحقق. ", - "register-page.registration.info.maildomain": "يمكن تسجيل عقود لناوين البريد للنطاقات", - "relationships.add.error.relationship-type.content": "لا يمكن العثور على تطابق مناسب لنوع التوافق {{ type }} بين المادتين", - "relationships.add.error.server.content": "لقد ساعدت في خطأ", - "relationships.add.error.title": "غير قادر على الانضمام إلى إيران", + + // "register-page.registration.google-recaptcha.notification.message.expired": "Verification expired. Please verify again.", + "register-page.registration.google-recaptcha.notification.message.expired": "انتهت صلاحية التحقق. يرجى التحقق مرة أخرى.", + + // "register-page.registration.info.maildomain": "Accounts can be registered for mail addresses of the domains", + "register-page.registration.info.maildomain": "يمكن تسجيل الحسابات لعناوين البريد للنطاقات", + + // "relationships.add.error.relationship-type.content": "No suitable match could be found for relationship type {{ type }} between the two items", + "relationships.add.error.relationship-type.content": "لا يمكن العثور على تطابق مناسب لنوع العلاقة {{ type }} بين المادتين", + + // "relationships.add.error.server.content": "The server returned an error", + "relationships.add.error.server.content": "لقد أعاد الخادم خطأ", + + // "relationships.add.error.title": "Unable to add relationship", + "relationships.add.error.title": "غير قادر على إضافة العلاقة", + + // "relationships.isAuthorOf": "Authors", "relationships.isAuthorOf": "المؤلفين", - "relationships.isAuthorOf.Person": "المؤلفين (الأشخاص)", + + // "relationships.isAuthorOf.Person": "Authors (persons)", + "relationships.isAuthorOf.Person": "المؤلفين (أشخاص)", + + // "relationships.isAuthorOf.OrgUnit": "Authors (organizational units)", "relationships.isAuthorOf.OrgUnit": "المؤلفين (وحدات مؤسسية)", - "relationships.isIssueOf": "سجل الدوري", - "relationships.isIssueOf.JournalIssue": "عدد الدوري", - "relationships.isJournalIssueOf": "عدد الدوري", + + // "relationships.isIssueOf": "Journal Issues", + "relationships.isIssueOf": "أعداد الدورية", + + // "relationships.isIssueOf.JournalIssue": "Journal Issue", + "relationships.isIssueOf.JournalIssue": "عدد الدورية", + + // "relationships.isJournalIssueOf": "Journal Issue", + "relationships.isJournalIssueOf": "عدد الدورية", + + // "relationships.isJournalOf": "Journals", "relationships.isJournalOf": "الدوريات", - "relationships.isJournalVolumeOf": "سلسلة الدورية", + + // "relationships.isJournalVolumeOf": "Journal Volume", + "relationships.isJournalVolumeOf": "مجلد الدورية", + + // "relationships.isOrgUnitOf": "Organizational Units", "relationships.isOrgUnitOf": "وحدات مؤسسية", + + // "relationships.isPersonOf": "Authors", "relationships.isPersonOf": "المؤلفين", - "relationships.isProjectOf": "مشاريع البحث", + + // "relationships.isProjectOf": "Research Projects", + "relationships.isProjectOf": "مشروعات البحث", + + // "relationships.isPublicationOf": "Publications", "relationships.isPublicationOf": "منشورات", + + // "relationships.isPublicationOfJournalIssue": "Articles", "relationships.isPublicationOfJournalIssue": "مقالات", - "relationships.isSingleJournalOf": "الدوري", - "relationships.isSingleVolumeOf": "سلسلة الدورية", - "relationships.isVolumeOf": "سلسلة الدوريات", - "relationships.isVolumeOf.JournalVolume": "سلسلة الدورية", - "relationships.isContributorOf": "خذ", + + // "relationships.isSingleJournalOf": "Journal", + "relationships.isSingleJournalOf": "الدورية", + + // "relationships.isSingleVolumeOf": "Journal Volume", + "relationships.isSingleVolumeOf": "مجلد الدورية", + + // "relationships.isVolumeOf": "Journal Volumes", + "relationships.isVolumeOf": "مجلدات الدورية", + + // "relationships.isVolumeOf.JournalVolume": "Journal Volume", + "relationships.isVolumeOf.JournalVolume": "مجلد الدورية", + + // "relationships.isContributorOf": "Contributors", + "relationships.isContributorOf": "المساهمين", + + // "relationships.isContributorOf.OrgUnit": "Contributor (Organizational Unit)", "relationships.isContributorOf.OrgUnit": "المساهم (وحدة مؤسسية)", + + // "relationships.isContributorOf.Person": "Contributor", "relationships.isContributorOf.Person": "المساهم", + + // "relationships.isFundingAgencyOf.OrgUnit": "Funder", "relationships.isFundingAgencyOf.OrgUnit": "الممول", - "repository.image.logo": "مستودع الشعار", + + // "repository.image.logo": "Repository logo", + "repository.image.logo": "شعار المستودع", + + // "repository.title": "DSpace Repository", "repository.title": "مستودع دي سبيس", + + // "repository.title.prefix": "DSpace Repository :: ", "repository.title.prefix": "مستودع دي سبيس :: ", + + // "resource-policies.add.button": "Add", "resource-policies.add.button": "إضافة", - "resource-policies.add.for.": "إضافة جديدة", - "resource-policies.add.for.bitstream": "إضافة لمزيد من التدفق بت جديدة", - "resource-policies.add.for.bundle": "إضافة حزمة جديدة", - "resource-policies.add.for.item": "إضافة مادة جديدة", - "resource-policies.add.for.community": "اضافة الى مجتمع جديد", - "resource-policies.add.for.collection": "إضافة ابي كوبين جديدة", - "resource-policies.create.page.heading": "إنشاء أشياء جديدة لـ ", - "resource-policies.create.page.failure.content": "حدث خطأ أثناء إنشاء الموارد.", - "resource-policies.create.page.success.content": "فعال", - "resource-policies.create.page.title": "إنشاء أشياء جديدة", - "resource-policies.delete.btn": "حذف", - "resource-policies.delete.btn.title": "حذف الموارد المحددة", - "resource-policies.delete.failure.content": "حدث خطأ أثناء حذف سياسات المورد الهامة.", - "resource-policies.delete.success.content": "عملية", - "resource-policies.edit.page.heading": "تحرير بولي المورد ", - "resource-policies.edit.page.failure.content": "حدث خطأ أثناء تحرير المورد.", + + // "resource-policies.add.for.": "Add a new policy", + "resource-policies.add.for.": "إضافة سياسة جديدة", + + // "resource-policies.add.for.bitstream": "Add a new Bitstream policy", + "resource-policies.add.for.bitstream": "إضافة سياسة تدفق بت جديدة", + + // "resource-policies.add.for.bundle": "Add a new Bundle policy", + "resource-policies.add.for.bundle": "إضافة سياسة حزمة جديدة", + + // "resource-policies.add.for.item": "Add a new Item policy", + "resource-policies.add.for.item": "إضافة سياسة مادة جديدة", + + // "resource-policies.add.for.community": "Add a new Community policy", + "resource-policies.add.for.community": "إضافة سياسة مجتمع جديدة", + + // "resource-policies.add.for.collection": "Add a new Collection policy", + "resource-policies.add.for.collection": "إضافة سياسة حاوية جديدة", + + // "resource-policies.create.page.heading": "Create new resource policy for ", + "resource-policies.create.page.heading": "إنشاء سياسة موارد جديدة لـ ", + + // "resource-policies.create.page.failure.content": "An error occurred while creating the resource policy.", + "resource-policies.create.page.failure.content": "حدث خطأ أثناء إنشاء سياسة الموارد.", + + // "resource-policies.create.page.success.content": "Operation successful", + "resource-policies.create.page.success.content": "تمت العملية بنجاح", + + // "resource-policies.create.page.title": "Create new resource policy", + "resource-policies.create.page.title": "إنشاء سياسة موارد جديدة", + + // "resource-policies.delete.btn": "Delete selected", + "resource-policies.delete.btn": "حذف المحدد", + + // "resource-policies.delete.btn.title": "Delete selected resource policies", + "resource-policies.delete.btn.title": "حذف سياسات الموارد المحددة", + + // "resource-policies.delete.failure.content": "An error occurred while deleting selected resource policies.", + "resource-policies.delete.failure.content": "حدث خطأ أثناء حذف سياسات المورد المحددة.", + + // "resource-policies.delete.success.content": "Operation successful", + "resource-policies.delete.success.content": "عملية ناجحة", + + // "resource-policies.edit.page.heading": "Edit resource policy ", + "resource-policies.edit.page.heading": "تحرير سياسة المورد ", + + // "resource-policies.edit.page.failure.content": "An error occurred while editing the resource policy.", + "resource-policies.edit.page.failure.content": "حدث خطأ أثناء تحرير سياسة المورد.", + + // "resource-policies.edit.page.target-failure.content": "An error occurred while editing the target (ePerson or group) of the resource policy.", "resource-policies.edit.page.target-failure.content": "حدث خطأ أثناء تحرير الهدف (الشخص الإلكتروني أو المجموعة) لسياسة الموارد.", - "resource-policies.edit.page.other-failure.content": "حدث خطأ أثناء تحرير الموارد. ", - "resource-policies.edit.page.success.content": "عملية", - "resource-policies.edit.page.title": "تحرير بولي المورد", + + // "resource-policies.edit.page.other-failure.content": "An error occurred while editing the resource policy. The target (ePerson or group) has been successfully updated.", + "resource-policies.edit.page.other-failure.content": "حدث خطأ أثناء تحرير سياسة الموارد. تم تحديث الهدف (الشخص الإلكتروني أو المجموعة) بنجاح.", + + // "resource-policies.edit.page.success.content": "Operation successful", + "resource-policies.edit.page.success.content": "عملية ناجحة", + + // "resource-policies.edit.page.title": "Edit resource policy", + "resource-policies.edit.page.title": "تحرير سياسة المورد", + + // "resource-policies.form.action-type.label": "Select the action type", "resource-policies.form.action-type.label": "تحديد نوع الإجراء", - "resource-policies.form.action-type.required": "يجب عليك تحديد إجراء إجراء المورد.", - "resource-policies.form.eperson-group-list.label": "الشخص الإلكتروني أو المجموعة التي يستفيد منها من هذه الامتيازات", + + // "resource-policies.form.action-type.required": "You must select the resource policy action.", + "resource-policies.form.action-type.required": "يجب عليك تحديد إجراء سياسة المورد.", + + // "resource-policies.form.eperson-group-list.label": "The eperson or group that will be granted the permission", + "resource-policies.form.eperson-group-list.label": "الشخص الإلكتروني أو المجموعة التي سيتم منحها هذه الصلاحية", + + // "resource-policies.form.eperson-group-list.select.btn": "Select", "resource-policies.form.eperson-group-list.select.btn": "تحديد", + + // "resource-policies.form.eperson-group-list.tab.eperson": "Search for a ePerson", "resource-policies.form.eperson-group-list.tab.eperson": "بحث عن شخص إلكتروني", - "resource-policies.form.eperson-group-list.tab.group": "بحثت عن مجموعة", - "resource-policies.form.eperson-group-list.table.headers.action": "صنع", + + // "resource-policies.form.eperson-group-list.tab.group": "Search for a group", + "resource-policies.form.eperson-group-list.tab.group": "بحث عن مجموعة", + + // "resource-policies.form.eperson-group-list.table.headers.action": "Action", + "resource-policies.form.eperson-group-list.table.headers.action": "إجراء", + + // "resource-policies.form.eperson-group-list.table.headers.id": "ID", "resource-policies.form.eperson-group-list.table.headers.id": "المعرف", + + // "resource-policies.form.eperson-group-list.table.headers.name": "Name", "resource-policies.form.eperson-group-list.table.headers.name": "الاسم", + + // "resource-policies.form.eperson-group-list.modal.header": "Cannot change type", "resource-policies.form.eperson-group-list.modal.header": "لا يمكن تغيير النوع", - "resource-policies.form.eperson-group-list.modal.text1.toGroup": "لا يمكن استبدال الشخص الحياتي.", - "resource-policies.form.eperson-group-list.modal.text1.toEPerson": "لا يمكن استبدال مجموعة الإلكترونيات الشخصية.", - "resource-policies.form.eperson-group-list.modal.text2": "قم بحذف طلبات الموارد الحالية ونقلها بالنوع المطلوب.", - "resource-policies.form.eperson-group-list.modal.close": "حسنًا", + + // "resource-policies.form.eperson-group-list.modal.text1.toGroup": "It is not possible to replace an ePerson with a group.", + "resource-policies.form.eperson-group-list.modal.text1.toGroup": "لا يمكن استبدال الشخص الإلكتروني بمجموعة.", + + // "resource-policies.form.eperson-group-list.modal.text1.toEPerson": "It is not possible to replace a group with an ePerson.", + "resource-policies.form.eperson-group-list.modal.text1.toEPerson": "لا يمكن استبدال مجموعة بشخص إلكتروني.", + + // "resource-policies.form.eperson-group-list.modal.text2": "Delete the current resource policy and create a new one with the desired type.", + "resource-policies.form.eperson-group-list.modal.text2": "قم بحذف سياسة الموارد الحالية وإنشاء سياسة جديدة بالنوع المطلوب.", + + // "resource-policies.form.eperson-group-list.modal.close": "Ok", + "resource-policies.form.eperson-group-list.modal.close": "موافق", + + // "resource-policies.form.date.end.label": "End Date", "resource-policies.form.date.end.label": "تاريخ الانتهاء", - "resource-policies.form.date.start.label": "تاريخ الميلاد", + + // "resource-policies.form.date.start.label": "Start Date", + "resource-policies.form.date.start.label": "تاريخ البدء", + + // "resource-policies.form.description.label": "Description", "resource-policies.form.description.label": "الوصف", + + // "resource-policies.form.name.label": "Name", "resource-policies.form.name.label": "الاسم", + + // "resource-policies.form.policy-type.label": "Select the policy type", "resource-policies.form.policy-type.label": "حدد نوع السياسة", - "resource-policies.form.policy-type.required": "يجب عليك تحديد نوع أبو الموارد.", - "resource-policies.table.headers.action": "صنع", + + // "resource-policies.form.policy-type.required": "You must select the resource policy type.", + "resource-policies.form.policy-type.required": "يجب عليك تحديد نوع سياسة الموارد.", + + // "resource-policies.table.headers.action": "Action", + "resource-policies.table.headers.action": "إجراء", + + // "resource-policies.table.headers.date.end": "End Date", "resource-policies.table.headers.date.end": "تاريخ الانتهاء", - "resource-policies.table.headers.date.start": "تاريخ الميلاد", + + // "resource-policies.table.headers.date.start": "Start Date", + "resource-policies.table.headers.date.start": "تاريخ البدء", + + // "resource-policies.table.headers.edit": "Edit", "resource-policies.table.headers.edit": "تحرير", + + // "resource-policies.table.headers.edit.group": "Edit group", "resource-policies.table.headers.edit.group": "تحرير المجموعة", + + // "resource-policies.table.headers.edit.policy": "Edit policy", "resource-policies.table.headers.edit.policy": "تحرير السياسة", + + // "resource-policies.table.headers.eperson": "EPerson", "resource-policies.table.headers.eperson": "شخص إلكتروني", + + // "resource-policies.table.headers.group": "Group", "resource-policies.table.headers.group": "المجموعة", + + // "resource-policies.table.headers.select-all": "Select all", "resource-policies.table.headers.select-all": "تحديد الكل", + + // "resource-policies.table.headers.deselect-all": "Deselect all", "resource-policies.table.headers.deselect-all": "إلغاء تحديد الكل", + + // "resource-policies.table.headers.select": "Select", "resource-policies.table.headers.select": "تحديد", - "resource-policies.table.headers.deselect": "قم بإلغاء التحديد", + + // "resource-policies.table.headers.deselect": "Deselect", + "resource-policies.table.headers.deselect": "إلغاء تحديد", + + // "resource-policies.table.headers.id": "ID", "resource-policies.table.headers.id": "المعرف", + + // "resource-policies.table.headers.name": "Name", "resource-policies.table.headers.name": "الاسم", + + // "resource-policies.table.headers.policyType": "type", "resource-policies.table.headers.policyType": "النوع", - "resource-policies.table.headers.title.for.bitstream": "سياسة تدفق البت", + + // "resource-policies.table.headers.title.for.bitstream": "Policies for Bitstream", + "resource-policies.table.headers.title.for.bitstream": "سياسات تدفق البت", + + // "resource-policies.table.headers.title.for.bundle": "Policies for Bundle", "resource-policies.table.headers.title.for.bundle": "سياسات الحزمة", - "resource-policies.table.headers.title.for.item": "هذه المادة", - "resource-policies.table.headers.title.for.community": "سياسة المجتمع", - "resource-policies.table.headers.title.for.collection": "تمام", + + // "resource-policies.table.headers.title.for.item": "Policies for Item", + "resource-policies.table.headers.title.for.item": "سياسات المادة", + + // "resource-policies.table.headers.title.for.community": "Policies for Community", + "resource-policies.table.headers.title.for.community": "سياسات المجتمع", + + // "resource-policies.table.headers.title.for.collection": "Policies for Collection", + "resource-policies.table.headers.title.for.collection": "سياسات الحاوية", + + // "root.skip-to-content": "Skip to main content", "root.skip-to-content": "انتقل إلى المحتوى الرئيسي", + + // "search.description": "", "search.description": "", + + // "search.switch-configuration.title": "Show", "search.switch-configuration.title": "عرض", + + // "search.title": "Search", "search.title": "بحث", + + // "search.breadcrumbs": "Search", "search.breadcrumbs": "بحث", - "search.search-form.placeholder": "بحث المستودع...", - "search.filters.remove": "إزالة المنقح من النوع {{ type }} د {{ value }}", + + // "search.search-form.placeholder": "Search the repository ...", + "search.search-form.placeholder": "بحث المستودع ...", + + // "search.filters.remove": "Remove filter of type {{ type }} with value {{ value }}", + "search.filters.remove": "إزالة المنقح من النوع {{ type }} بقيمة {{ value }}", + + // "search.filters.applied.f.author": "Author", "search.filters.applied.f.author": "المؤلف", + + // "search.filters.applied.f.dateIssued.max": "End date", "search.filters.applied.f.dateIssued.max": "تاريخ الانتهاء", - "search.filters.applied.f.dateIssued.min": "تاريخ الميلاد", - "search.filters.applied.f.dateSubmitted": "التاريخ", - "search.filters.applied.f.discoverable": "غير للاكتشاف", + + // "search.filters.applied.f.dateIssued.min": "Start date", + "search.filters.applied.f.dateIssued.min": "تاريخ البدء", + + // "search.filters.applied.f.dateSubmitted": "Date submitted", + "search.filters.applied.f.dateSubmitted": "تاريخ التقديم", + + // "search.filters.applied.f.discoverable": "Non-discoverable", + "search.filters.applied.f.discoverable": "غير قابل للاكتشاف", + + // "search.filters.applied.f.entityType": "Item Type", "search.filters.applied.f.entityType": "نوع المادة", + + // "search.filters.applied.f.has_content_in_original_bundle": "Has files", "search.filters.applied.f.has_content_in_original_bundle": "بها ملفات", + + // "search.filters.applied.f.itemtype": "Type", "search.filters.applied.f.itemtype": "النوع", + + // "search.filters.applied.f.namedresourcetype": "Status", "search.filters.applied.f.namedresourcetype": "الحالة", - "search.filters.applied.f.subject": "بدلا", - "search.filters.applied.f.submitter": "شير", + + // "search.filters.applied.f.subject": "Subject", + "search.filters.applied.f.subject": "الموضع", + + // "search.filters.applied.f.submitter": "Submitter", + "search.filters.applied.f.submitter": "المقدم", + + // "search.filters.applied.f.jobTitle": "Job Title", "search.filters.applied.f.jobTitle": "المسمى الوظيفي", + + // "search.filters.applied.f.birthDate.max": "End birth date", "search.filters.applied.f.birthDate.max": "نهاية تاريخ الميلاد", + + // "search.filters.applied.f.birthDate.min": "Start birth date", "search.filters.applied.f.birthDate.min": "بداية تاريخ الميلاد", - "search.filters.applied.f.supervisedBy": "تحت النار", + + // "search.filters.applied.f.supervisedBy": "Supervised by", + "search.filters.applied.f.supervisedBy": "تحت إشراف", + + // "search.filters.applied.f.withdrawn": "Withdrawn", "search.filters.applied.f.withdrawn": "مسحوب", + + // "search.filters.filter.author.head": "Author", "search.filters.filter.author.head": "المؤلف", + + // "search.filters.filter.author.placeholder": "Author name", "search.filters.filter.author.placeholder": "اسم المؤلف", - "search.filters.filter.author.label": "بحثت باسم المؤلف", - "search.filters.filter.birthDate.head": "تاريخ", - "search.filters.filter.birthDate.placeholder": "تاريخ", - "search.filters.filter.birthDate.label": "تمت مناقشة تاريخ الميلاد", + + // "search.filters.filter.author.label": "Search author name", + "search.filters.filter.author.label": "بحث اسم المؤلف", + + // "search.filters.filter.birthDate.head": "Birth Date", + "search.filters.filter.birthDate.head": "تاريخ الميلاد", + + // "search.filters.filter.birthDate.placeholder": "Birth Date", + "search.filters.filter.birthDate.placeholder": "تاريخ الميلاد", + + // "search.filters.filter.birthDate.label": "Search birth date", + "search.filters.filter.birthDate.label": "بحث تاريخ الميلاد", + + // "search.filters.filter.collapse": "Collapse filter", "search.filters.filter.collapse": "طي المنقح", + + // "search.filters.filter.creativeDatePublished.head": "Date Published", "search.filters.filter.creativeDatePublished.head": "تاريخ النشر", + + // "search.filters.filter.creativeDatePublished.placeholder": "Date Published", "search.filters.filter.creativeDatePublished.placeholder": "تاريخ النشر", + + // "search.filters.filter.creativeDatePublished.label": "Search date published", "search.filters.filter.creativeDatePublished.label": "بحث تاريخ النشر", + + // "search.filters.filter.creativeWorkEditor.head": "Editor", "search.filters.filter.creativeWorkEditor.head": "المحرر", + + // "search.filters.filter.creativeWorkEditor.placeholder": "Editor", "search.filters.filter.creativeWorkEditor.placeholder": "المحرر", - "search.filters.filter.creativeWorkEditor.label": "المحرر المحرر", + + // "search.filters.filter.creativeWorkEditor.label": "Search editor", + "search.filters.filter.creativeWorkEditor.label": "بحث المحرر", + + // "search.filters.filter.creativeWorkKeywords.head": "Subject", "search.filters.filter.creativeWorkKeywords.head": "الموضوع", + + // "search.filters.filter.creativeWorkKeywords.placeholder": "Subject", "search.filters.filter.creativeWorkKeywords.placeholder": "الموضوع", - "search.filters.filter.creativeWorkKeywords.label": "موضوع البحث", + + // "search.filters.filter.creativeWorkKeywords.label": "Search subject", + "search.filters.filter.creativeWorkKeywords.label": "بحث الموضوع", + + // "search.filters.filter.creativeWorkPublisher.head": "Publisher", "search.filters.filter.creativeWorkPublisher.head": "الناشر", + + // "search.filters.filter.creativeWorkPublisher.placeholder": "Publisher", "search.filters.filter.creativeWorkPublisher.placeholder": "الناشر", + + // "search.filters.filter.creativeWorkPublisher.label": "Search publisher", "search.filters.filter.creativeWorkPublisher.label": "بحث الناشر", + + // "search.filters.filter.dateIssued.head": "Date", "search.filters.filter.dateIssued.head": "التاريخ", + + // "search.filters.filter.dateIssued.max.placeholder": "Maximum Date", "search.filters.filter.dateIssued.max.placeholder": "الحد الأقصى للتاريخ", - "search.filters.filter.dateIssued.max.label": "تنتهي", - "search.filters.filter.dateIssued.min.placeholder": "الحد للتاريخ", - "search.filters.filter.dateIssued.min.label": "المبتدئ", - "search.filters.filter.dateSubmitted.head": "التاريخ", - "search.filters.filter.dateSubmitted.placeholder": "التاريخ", - "search.filters.filter.dateSubmitted.label": "تاريخ العرض", - "search.filters.filter.discoverable.head": "غير للاكتشاف", + + // "search.filters.filter.dateIssued.max.label": "End", + "search.filters.filter.dateIssued.max.label": "انتهاء", + + // "search.filters.filter.dateIssued.min.placeholder": "Minimum Date", + "search.filters.filter.dateIssued.min.placeholder": "الحد الأدنى للتاريخ", + + // "search.filters.filter.dateIssued.min.label": "Start", + "search.filters.filter.dateIssued.min.label": "البدء", + + // "search.filters.filter.dateSubmitted.head": "Date submitted", + "search.filters.filter.dateSubmitted.head": "تاريخ التقديم", + + // "search.filters.filter.dateSubmitted.placeholder": "Date submitted", + "search.filters.filter.dateSubmitted.placeholder": "تاريخ التقديم", + + // "search.filters.filter.dateSubmitted.label": "Search date submitted", + "search.filters.filter.dateSubmitted.label": "بحث تاريخ التقديم", + + // "search.filters.filter.discoverable.head": "Non-discoverable", + "search.filters.filter.discoverable.head": "غير قابل للاكتشاف", + + // "search.filters.filter.withdrawn.head": "Withdrawn", "search.filters.filter.withdrawn.head": "مسحوب", + + // "search.filters.filter.entityType.head": "Item Type", "search.filters.filter.entityType.head": "نوع المادة", + + // "search.filters.filter.entityType.placeholder": "Item Type", "search.filters.filter.entityType.placeholder": "نوع المادة", - "search.filters.filter.entityType.label": "تمت مناقشة نوع المادة", - "search.filters.filter.expand": "الأوقات المنقحة", + + // "search.filters.filter.entityType.label": "Search item type", + "search.filters.filter.entityType.label": "بحث نوع المادة", + + // "search.filters.filter.expand": "Expand filter", + "search.filters.filter.expand": "توسيع المنقح", + + // "search.filters.filter.has_content_in_original_bundle.head": "Has files", "search.filters.filter.has_content_in_original_bundle.head": "بها ملفات", + + // "search.filters.filter.itemtype.head": "Type", "search.filters.filter.itemtype.head": "النوع", + + // "search.filters.filter.itemtype.placeholder": "Type", "search.filters.filter.itemtype.placeholder": "النوع", + + // "search.filters.filter.itemtype.label": "Search type", "search.filters.filter.itemtype.label": "بحث النوع", + + // "search.filters.filter.jobTitle.head": "Job Title", "search.filters.filter.jobTitle.head": "المسمى الوظيفي", + + // "search.filters.filter.jobTitle.placeholder": "Job Title", "search.filters.filter.jobTitle.placeholder": "المسمى الوظيفي", - "search.filters.filter.jobTitle.label": "بحث في المسمى الوظيفي", + + // "search.filters.filter.jobTitle.label": "Search job title", + "search.filters.filter.jobTitle.label": "بحث المسمى الوظيفي", + + // "search.filters.filter.knowsLanguage.head": "Known language", "search.filters.filter.knowsLanguage.head": "لغة معروفة", + + // "search.filters.filter.knowsLanguage.placeholder": "Known language", "search.filters.filter.knowsLanguage.placeholder": "لغة معروفة", - "search.filters.filter.knowsLanguage.label": "اتصل بـ اسم معروف", + + // "search.filters.filter.knowsLanguage.label": "Search known language", + "search.filters.filter.knowsLanguage.label": "بحث لغة معروفة", + + // "search.filters.filter.namedresourcetype.head": "Status", "search.filters.filter.namedresourcetype.head": "الحالة", + + // "search.filters.filter.namedresourcetype.placeholder": "Status", "search.filters.filter.namedresourcetype.placeholder": "الحالة", - "search.filters.filter.namedresourcetype.label": "الحالة المدروسة", - "search.filters.filter.objectpeople.head": "الأشخاص", - "search.filters.filter.objectpeople.placeholder": "الأشخاص", - "search.filters.filter.objectpeople.label": "بحث الناس", + + // "search.filters.filter.namedresourcetype.label": "Search status", + "search.filters.filter.namedresourcetype.label": "بحث الحالة", + + // "search.filters.filter.objectpeople.head": "People", + "search.filters.filter.objectpeople.head": "أشخاص", + + // "search.filters.filter.objectpeople.placeholder": "People", + "search.filters.filter.objectpeople.placeholder": "أشخاص", + + // "search.filters.filter.objectpeople.label": "Search people", + "search.filters.filter.objectpeople.label": "بحث الأشخاص", + + // "search.filters.filter.organizationAddressCountry.head": "Country", "search.filters.filter.organizationAddressCountry.head": "البلد", + + // "search.filters.filter.organizationAddressCountry.placeholder": "Country", "search.filters.filter.organizationAddressCountry.placeholder": "البلد", + + // "search.filters.filter.organizationAddressCountry.label": "Search country", "search.filters.filter.organizationAddressCountry.label": "بحث البلد", + + // "search.filters.filter.organizationAddressLocality.head": "City", "search.filters.filter.organizationAddressLocality.head": "المدينة", + + // "search.filters.filter.organizationAddressLocality.placeholder": "City", "search.filters.filter.organizationAddressLocality.placeholder": "المدينة", - "search.filters.filter.organizationAddressLocality.label": "بحثت المدينة", + + // "search.filters.filter.organizationAddressLocality.label": "Search city", + "search.filters.filter.organizationAddressLocality.label": "بحث المدينة", + + // "search.filters.filter.organizationFoundingDate.head": "Date Founded", "search.filters.filter.organizationFoundingDate.head": "تاريخ التأسيس", + + // "search.filters.filter.organizationFoundingDate.placeholder": "Date Founded", "search.filters.filter.organizationFoundingDate.placeholder": "تاريخ التأسيس", - "search.filters.filter.organizationFoundingDate.label": "بحثت في تاريخها", + + // "search.filters.filter.organizationFoundingDate.label": "Search date founded", + "search.filters.filter.organizationFoundingDate.label": "بحث تاريخ التأسيس", + + // "search.filters.filter.scope.head": "Scope", "search.filters.filter.scope.head": "النطاق", + + // "search.filters.filter.scope.placeholder": "Scope filter", "search.filters.filter.scope.placeholder": "منقح النطاق", + + // "search.filters.filter.scope.label": "Search scope filter", "search.filters.filter.scope.label": "منقح نطاق البحث", - "search.filters.filter.show-less": "طيء", + + // "search.filters.filter.show-less": "Collapse", + "search.filters.filter.show-less": "طي", + + // "search.filters.filter.show-more": "Show more", "search.filters.filter.show-more": "عرض المزيد", + + // "search.filters.filter.subject.head": "Subject", "search.filters.filter.subject.head": "الموضوع", + + // "search.filters.filter.subject.placeholder": "Subject", "search.filters.filter.subject.placeholder": "الموضوع", - "search.filters.filter.subject.label": "موضوع البحث", - "search.filters.filter.submitter.head": "شير", - "search.filters.filter.submitter.placeholder": "شير", + + // "search.filters.filter.subject.label": "Search subject", + "search.filters.filter.subject.label": "بحث الموضوع", + + // "search.filters.filter.submitter.head": "Submitter", + "search.filters.filter.submitter.head": "المقدم", + + // "search.filters.filter.submitter.placeholder": "Submitter", + "search.filters.filter.submitter.placeholder": "المقدم", + + // "search.filters.filter.submitter.label": "Search submitter", "search.filters.filter.submitter.label": "مقدم البحث", + + // "search.filters.filter.show-tree": "Browse {{ name }} tree", "search.filters.filter.show-tree": "استعراض شجرة {{ name }}", - "search.filters.filter.funding.head": "تمويل", - "search.filters.filter.funding.placeholder": "تمويل", - "search.filters.filter.supervisedBy.head": "تحت النار", - "search.filters.filter.supervisedBy.placeholder": "تحت النار", - "search.filters.filter.supervisedBy.label": "ابحث تحت البحث", - "search.filters.entityType.JournalIssue": "عدد الدوري", - "search.filters.entityType.JournalVolume": "سلسلة الدورية", + + // "search.filters.filter.funding.head": "Funding", + "search.filters.filter.funding.head": "التمويل", + + // "search.filters.filter.funding.placeholder": "Funding", + "search.filters.filter.funding.placeholder": "التمويل", + + // "search.filters.filter.supervisedBy.head": "Supervised By", + "search.filters.filter.supervisedBy.head": "تحت إشراف", + + // "search.filters.filter.supervisedBy.placeholder": "Supervised By", + "search.filters.filter.supervisedBy.placeholder": "تحت إشراف", + + // "search.filters.filter.supervisedBy.label": "Search Supervised By", + "search.filters.filter.supervisedBy.label": "البحث تحت إشراف", + + // "search.filters.entityType.JournalIssue": "Journal Issue", + "search.filters.entityType.JournalIssue": "عدد الدورية", + + // "search.filters.entityType.JournalVolume": "Journal Volume", + "search.filters.entityType.JournalVolume": "مجلد الدورية", + + // "search.filters.entityType.OrgUnit": "Organizational Unit", "search.filters.entityType.OrgUnit": "وحدة مؤسسية", - "search.filters.entityType.Person": "شخص", - "search.filters.entityType.Project": "مشروع", - "search.filters.entityType.Publication": "النشر", + + // "search.filters.entityType.Person": "Person", + // TODO New key - Add a translation + "search.filters.entityType.Person": "Person", + + // "search.filters.entityType.Project": "Project", + // TODO New key - Add a translation + "search.filters.entityType.Project": "Project", + + // "search.filters.entityType.Publication": "Publication", + // TODO New key - Add a translation + "search.filters.entityType.Publication": "Publication", + + // "search.filters.has_content_in_original_bundle.true": "Yes", "search.filters.has_content_in_original_bundle.true": "نعم", + + // "search.filters.has_content_in_original_bundle.false": "No", "search.filters.has_content_in_original_bundle.false": "لا", + + // "search.filters.discoverable.true": "No", "search.filters.discoverable.true": "لا", + + // "search.filters.discoverable.false": "Yes", "search.filters.discoverable.false": "نعم", + + // "search.filters.namedresourcetype.Archived": "Archived", "search.filters.namedresourcetype.Archived": "مؤرشف", + + // "search.filters.namedresourcetype.Validation": "Validation", "search.filters.namedresourcetype.Validation": "التحقق من الصحة", + + // "search.filters.namedresourcetype.Waiting for Controller": "Waiting for reviewer", "search.filters.namedresourcetype.Waiting for Controller": "في انتظار المراجع", + + // "search.filters.namedresourcetype.Workflow": "Workflow", "search.filters.namedresourcetype.Workflow": "سير العمل", + + // "search.filters.namedresourcetype.Workspace": "Workspace", "search.filters.namedresourcetype.Workspace": "مساحة العمل", + + // "search.filters.withdrawn.true": "Yes", "search.filters.withdrawn.true": "نعم", + + // "search.filters.withdrawn.false": "No", "search.filters.withdrawn.false": "لا", + + // "search.filters.head": "Filters", "search.filters.head": "المنقحات", - "search.filters.reset": "إعادة تعيين المقحات", + + // "search.filters.reset": "Reset filters", + "search.filters.reset": "إعادة تعيين المنقحات", + + // "search.filters.search.submit": "Submit", "search.filters.search.submit": "تقديم", + + // "search.form.search": "Search", "search.form.search": "بحث", + + // "search.form.search_dspace": "All repository", "search.form.search_dspace": "كل المستودع", + + // "search.form.scope.all": "All of DSpace", "search.form.scope.all": "كل دي سبيس", + + // "search.results.head": "Search Results", "search.results.head": "نتائج البحث", - "search.results.no-results": "لم أسافر لبحثك عن أي نتائج. ", - "search.results.no-results-link": "راسي نص حوله", - "search.results.empty": "لم أسافر لبحثك عن أي نتائج.", + + // "search.results.no-results": "Your search returned no results. Having trouble finding what you're looking for? Try putting", + "search.results.no-results": "لم يسفر بحثك عن أي نتائج. هل تجد صعوبة في العثور على ما تبحث عنه؟ جرب وضع", + + // "search.results.no-results-link": "quotes around it", + "search.results.no-results-link": "قوسي نص حوله", + + // "search.results.empty": "Your search returned no results.", + "search.results.empty": "لم يسفر بحثك عن أي نتائج.", + + // "search.results.view-result": "View", "search.results.view-result": "عرض", - "search.results.response.500": "حدث خطأ أثناء التخطيط، يرجى إعادة محاولة مرة أخرى لاحقاً", + + // "search.results.response.500": "An error occurred during query execution, please try again later", + "search.results.response.500": "حدث خطأ أثناء تنفيذ الاستعلام، يرجى إعادة المحاولة مرة أخرى لاحقاً", + + // "default.search.results.head": "Search Results", "default.search.results.head": "نتائج البحث", - "default-relationships.search.results.head": "نتائج البحث", + + // "default-relationships.search.results.head": "Search Results", + // TODO New key - Add a translation + "default-relationships.search.results.head": "Search Results", + + // "search.sidebar.close": "Back to results", "search.sidebar.close": "العودة إلى النتائج", + + // "search.sidebar.filters.title": "Filters", "search.sidebar.filters.title": "المنقحات", + + // "search.sidebar.open": "Search Tools", "search.sidebar.open": "أدوات البحث", + + // "search.sidebar.results": "results", "search.sidebar.results": "النتائج", + + // "search.sidebar.settings.rpp": "Results per page", "search.sidebar.settings.rpp": "النتائج لكل صفحة", - "search.sidebar.settings.sort-by": "فرز حسب الطلب", - "search.sidebar.settings.title": "عد", + + // "search.sidebar.settings.sort-by": "Sort By", + "search.sidebar.settings.sort-by": "فرز حسب", + + // "search.sidebar.settings.title": "Settings", + "search.sidebar.settings.title": "الإعدادات", + + // "search.view-switch.show-detail": "Show detail", "search.view-switch.show-detail": "عرض التفاصل", + + // "search.view-switch.show-grid": "Show as grid", "search.view-switch.show-grid": "عرض كشبكة", - "search.view-switch.show-list": "عرض القائمة", - "selectable-list-item-control.deselect": "قم بإلغاء تحديد المادة", - "selectable-list-item-control.select": "المادة المحددة", - "sorting.ASC": "تقييمياً", + + // "search.view-switch.show-list": "Show as list", + "search.view-switch.show-list": "عرض كقائمة", + + // "selectable-list-item-control.deselect": "Deselect item", + "selectable-list-item-control.deselect": "إلغاء تحديد المادة", + + // "selectable-list-item-control.select": "Select item", + "selectable-list-item-control.select": "تحديد المادة", + + // "sorting.ASC": "Ascending", + "sorting.ASC": "تصاعدياً", + + // "sorting.DESC": "Descending", "sorting.DESC": "تنازلياً", - "sorting.dc.title.ASC": "العنوان تقييمياً", + + // "sorting.dc.title.ASC": "Title Ascending", + "sorting.dc.title.ASC": "العنوان تصاعدياً", + + // "sorting.dc.title.DESC": "Title Descending", "sorting.dc.title.DESC": "العنوان تنازلياً", - "sorting.score.ASC": "أقل صلة", + + // "sorting.score.ASC": "Least Relevant", + "sorting.score.ASC": "الأقل صلة", + + // "sorting.score.DESC": "Most Relevant", "sorting.score.DESC": "الأكثر صلة", - "sorting.dc.date.issued.ASC": "تاريخ الإصدار التقييمي", + + // "sorting.dc.date.issued.ASC": "Date Issued Ascending", + "sorting.dc.date.issued.ASC": "تاريخ الإصدار تصاعدياً", + + // "sorting.dc.date.issued.DESC": "Date Issued Descending", "sorting.dc.date.issued.DESC": "تاريخ الإصدار تنازلياً", - "sorting.dc.date.accessioned.ASC": "تاريخ الإيداع تقييميًا", - "sorting.dc.date.accessioned.DESC": "تاريخ الإيداع التنازلي", - "sorting.lastModified.ASC": "آخر تعديل تقييمياً", + + // "sorting.dc.date.accessioned.ASC": "Accessioned Date Ascending", + "sorting.dc.date.accessioned.ASC": "تاريخ الإيداع تصاعدياً", + + // "sorting.dc.date.accessioned.DESC": "Accessioned Date Descending", + "sorting.dc.date.accessioned.DESC": "تاريخ الإيداع تنازلياً", + + // "sorting.lastModified.ASC": "Last modified Ascending", + "sorting.lastModified.ASC": "آخر تعديل تصاعدياً", + + // "sorting.lastModified.DESC": "Last modified Descending", "sorting.lastModified.DESC": "آخر تعديل تنازلياً", - "sorting.person.familyName.ASC": "اللقب تصاعدي", - "sorting.person.familyName.DESC": "اللقب تنازلي", - "sorting.person.givenName.ASC": "الاسم تصاعدي", - "sorting.person.givenName.DESC": "اسم تنازلي", - "sorting.person.birthDate.ASC": "تاريخ الميلاد تصاعدي", - "sorting.person.birthDate.DESC": "تاريخ الميلاد تنازلي", + + // "sorting.person.familyName.ASC": "Surname Ascending", + // TODO New key - Add a translation + "sorting.person.familyName.ASC": "Surname Ascending", + + // "sorting.person.familyName.DESC": "Surname Descending", + // TODO New key - Add a translation + "sorting.person.familyName.DESC": "Surname Descending", + + // "sorting.person.givenName.ASC": "Name Ascending", + // TODO New key - Add a translation + "sorting.person.givenName.ASC": "Name Ascending", + + // "sorting.person.givenName.DESC": "Name Descending", + // TODO New key - Add a translation + "sorting.person.givenName.DESC": "Name Descending", + + // "sorting.person.birthDate.ASC": "Birth Date Ascending", + // TODO New key - Add a translation + "sorting.person.birthDate.ASC": "Birth Date Ascending", + + // "sorting.person.birthDate.DESC": "Birth Date Descending", + // TODO New key - Add a translation + "sorting.person.birthDate.DESC": "Birth Date Descending", + + // "statistics.title": "Statistics", "statistics.title": "الاحصائيات", - "statistics.header": "إحصائيات لـ {{ scope }}", + + // "statistics.header": "Statistics for {{ scope }}", + "statistics.header": "احصائيات لـ {{ scope }}", + + // "statistics.breadcrumbs": "Statistics", "statistics.breadcrumbs": "الاحصائيات", - "statistics.page.no-data": "لا توفر أي بيانات", - "statistics.table.no-data": "لا توفر أي بيانات", - "statistics.table.title.TotalVisits": "زيارة إجمالية", + + // "statistics.page.no-data": "No data available", + "statistics.page.no-data": "لا تتوافر أي بيانات", + + // "statistics.table.no-data": "No data available", + "statistics.table.no-data": "لا تتوافر أي بيانات", + + // "statistics.table.title.TotalVisits": "Total visits", + "statistics.table.title.TotalVisits": "إجمالي الزيارات", + + // "statistics.table.title.TotalVisitsPerMonth": "Total visits per month", "statistics.table.title.TotalVisitsPerMonth": "إجمالي الزيارات لكل شهر", + + // "statistics.table.title.TotalDownloads": "File Visits", "statistics.table.title.TotalDownloads": "زيارات الملف", - "statistics.table.title.TopCountries": "أعلى المشاهدات على مستوى البلد", - "statistics.table.title.TopCities": "أعلى المشاهدات على مستوى المدينة", + + // "statistics.table.title.TopCountries": "Top country views", + "statistics.table.title.TopCountries": "أعلى مشاهدات على مستوى البلد", + + // "statistics.table.title.TopCities": "Top city views", + "statistics.table.title.TopCities": "أعلى مشاهدات على مستوى المدينة", + + // "statistics.table.header.views": "Views", "statistics.table.header.views": "المشاهدات", - "statistics.table.no-name": "(تعذر تحميل اسم سميث)", - "submission.edit.breadcrumbs": "تحرير.التقديم", - "submission.edit.title": "تحرير.التقديم", + + // "statistics.table.no-name": "(object name could not be loaded)", + "statistics.table.no-name": "(تعذر تحميل اسم الكائن)", + + // "submission.edit.breadcrumbs": "Edit Submission", + "submission.edit.breadcrumbs": "تحرير التقديم", + + // "submission.edit.title": "Edit Submission", + "submission.edit.title": "تحرير التقديم", + + // "submission.general.cancel": "Cancel", "submission.general.cancel": "إلغاء", - "submission.general.cannot_submit": "ليس لديك القدرة على تقديم الجديد.", + + // "submission.general.cannot_submit": "You don't have permission to make a new submission.", + "submission.general.cannot_submit": "ليس لديك صلاحية القيام بتقديم جديد.", + + // "submission.general.deposit": "Deposit", "submission.general.deposit": "إيداع", + + // "submission.general.discard.confirm.cancel": "Cancel", "submission.general.discard.confirm.cancel": "إلغاء", - "submission.general.discard.confirm.info": "لا يمكن السماء عن هذه الطريقة. ", - "submission.general.discard.confirm.submit": "نعم، بالتأكيد", - "submission.general.discard.confirm.title": "تجاهل", - "submission.general.discard.submit": "لا", - "submission.general.back.submit": "خلف", + + // "submission.general.discard.confirm.info": "This operation can't be undone. Are you sure?", + "submission.general.discard.confirm.info": "لا يمكن التراجع عن هذه العملية. هل أنت متأكد؟", + + // "submission.general.discard.confirm.submit": "Yes, I'm sure", + "submission.general.discard.confirm.submit": "نعم، متأكد", + + // "submission.general.discard.confirm.title": "Discard submission", + "submission.general.discard.confirm.title": "تجاهل التقديم", + + // "submission.general.discard.submit": "Discard", + "submission.general.discard.submit": "تجاهل", + + // "submission.general.back.submit": "Back", + // TODO New key - Add a translation + "submission.general.back.submit": "Back", + + // "submission.general.info.saved": "Saved", "submission.general.info.saved": "محفوظ", - "submission.general.info.pending-changes": "أخبار غير محفوظة", + + // "submission.general.info.pending-changes": "Unsaved changes", + "submission.general.info.pending-changes": "تغييرات غير محفوظة", + + // "submission.general.save": "Save", "submission.general.save": "حفظ", - "submission.general.save-later": "لوقت لاحق", - "submission.import-external.page.title": "استيراد ميتا من المصدر الخارجي", - "submission.import-external.title": "استيراد ميتا من المصدر الخارجي", - "submission.import-external.title.Journal": "استيراد دورية من المصدر الخارجي", - "submission.import-external.title.JournalIssue": "استيراد عدد دورية من المصدر الخارجي", - "submission.import-external.title.JournalVolume": "استيراد دورية من المصدر الخارجي", - "submission.import-external.title.OrgUnit": "استيراد ناشر من المصدر الخارجي", + + // "submission.general.save-later": "Save for later", + "submission.general.save-later": "حفظ لوقت لاحق", + + // "submission.import-external.page.title": "Import metadata from an external source", + "submission.import-external.page.title": "استيراد ميتاداتا من مصدر خارجي", + + // "submission.import-external.title": "Import metadata from an external source", + "submission.import-external.title": "استيراد ميتاداتا من مصدر خارجي", + + // "submission.import-external.title.Journal": "Import a journal from an external source", + "submission.import-external.title.Journal": "استيراد دورية من مصدر خارجي", + + // "submission.import-external.title.JournalIssue": "Import a journal issue from an external source", + "submission.import-external.title.JournalIssue": "استيراد عدد دورية من مصدر خارجيe", + + // "submission.import-external.title.JournalVolume": "Import a journal volume from an external source", + "submission.import-external.title.JournalVolume": "استيراد مجلد دورية من مصدر خارجي", + + // "submission.import-external.title.OrgUnit": "Import a publisher from an external source", + "submission.import-external.title.OrgUnit": "استيراد ناشر من مصدر خارجي", + + // "submission.import-external.title.Person": "Import a person from an external source", "submission.import-external.title.Person": "استيراد شخص من مصدر خارجي", + + // "submission.import-external.title.Project": "Import a project from an external source", "submission.import-external.title.Project": "استيراد مشروع من مصدر خارجي", - "submission.import-external.title.Publication": "استيراد منشور من المصدر الخارجي", - "submission.import-external.title.none": "استيراد ميتا من المصدر الخارجي", - "submission.import-external.page.hint": "قم دائمًا بالاستعلام عن بعد لاستيراد البيانات إلى دي سبيس.", + + // "submission.import-external.title.Publication": "Import a publication from an external source", + "submission.import-external.title.Publication": "استيراد منشور من مصدر خارجي", + + // "submission.import-external.title.none": "Import metadata from an external source", + "submission.import-external.title.none": "استيراد ميتاداتا من مصدر خارجي", + + // "submission.import-external.page.hint": "Enter a query above to find items from the web to import in to DSpace.", + "submission.import-external.page.hint": "قم بإدخال استعلام أعلاه للعثور على مواد من الويب لاستيرادها إلى دي سبيس.", + + // "submission.import-external.back-to-my-dspace": "Back to MyDSpace", "submission.import-external.back-to-my-dspace": "العودة إلى ماي سبيس", + + // "submission.import-external.search.placeholder": "Search the external source", "submission.import-external.search.placeholder": "بحث المصدر الخارجي", + + // "submission.import-external.search.button": "Search", "submission.import-external.search.button": "بحث", + + // "submission.import-external.search.button.hint": "Write some words to search", "submission.import-external.search.button.hint": "اكتب بعض الكلمات للبحث", + + // "submission.import-external.search.source.hint": "Pick an external source", "submission.import-external.search.source.hint": "اختر مصدراً خارجياً", + + // "submission.import-external.source.arxiv": "arXiv", "submission.import-external.source.arxiv": "arXiv", + + // "submission.import-external.source.ads": "NASA/ADS", "submission.import-external.source.ads": "ناسا/ADS", + + // "submission.import-external.source.cinii": "CiNii", "submission.import-external.source.cinii": "CiNii", + + // "submission.import-external.source.crossref": "CrossRef", "submission.import-external.source.crossref": "كروس ريف", + + // "submission.import-external.source.datacite": "DataCite", "submission.import-external.source.datacite": "داتاسايت", + + // "submission.import-external.source.doi": "DOI", + // TODO New key - Add a translation "submission.import-external.source.doi": "DOI", - "submission.import-external.source.scielo": "سيلو", + + // "submission.import-external.source.scielo": "SciELO", + "submission.import-external.source.scielo": "SciELO", + + // "submission.import-external.source.scopus": "Scopus", "submission.import-external.source.scopus": "سكوبس", + + // "submission.import-external.source.vufind": "VuFind", "submission.import-external.source.vufind": "فيوفايند", + + // "submission.import-external.source.wos": "Web Of Science", "submission.import-external.source.wos": "شبكة العلوم", + + // "submission.import-external.source.orcidWorks": "ORCID", "submission.import-external.source.orcidWorks": "أوركيد", - "submission.import-external.source.epo": "مكتب براءات الاصدار الأوروبي (EPO)", + + // "submission.import-external.source.epo": "European Patent Office (EPO)", + "submission.import-external.source.epo": "مكتب براءات الاختراع الأوروبي (EPO)", + + // "submission.import-external.source.loading": "Loading ...", "submission.import-external.source.loading": "جاري التحميل ...", + + // "submission.import-external.source.sherpaJournal": "SHERPA Journals", "submission.import-external.source.sherpaJournal": "دوريات شيربا", + + // "submission.import-external.source.sherpaJournalIssn": "SHERPA Journals by ISSN", "submission.import-external.source.sherpaJournalIssn": "دوريات شيربا بواسطة الردمد", - "submission.import-external.source.sherpaPublisher": "نشري شيربا", - "submission.import-external.source.openAIREFunding": "تمويل برمجة تطبيقات OpenAIRE", + + // "submission.import-external.source.sherpaPublisher": "SHERPA Publishers", + "submission.import-external.source.sherpaPublisher": "ناشري شيربا", + + // "submission.import-external.source.openAIREFunding": "Funding OpenAIRE API", + "submission.import-external.source.openAIREFunding": "تمويل واجهة برمجة تطبيقات OpenAIRE", + + // "submission.import-external.source.orcid": "ORCID", "submission.import-external.source.orcid": "أوركيد", - "submission.import-external.source.pubmed": "نشر", - "submission.import-external.source.pubmedeu": "أوروبا المنشورة", - "submission.import-external.source.lcname": "اسماء مكتبة الكونجرس", - "submission.import-external.source.ror": "سجل المنظمات البحثية (ROR)", - "submission.import-external.preview.title": "عرض المادة", - "submission.import-external.preview.title.Publication": "قم بمراجعة المنشور", - "submission.import-external.preview.title.none": "عرض المادة", - "submission.import-external.preview.title.Journal": "مراجعة الدورية", - "submission.import-external.preview.title.OrgUnit": "نظرة عامة على الوحدة الوطنية", - "submission.import-external.preview.title.Person": "نظرة على الشخص", - "submission.import-external.preview.title.Project": "نظرة على المشروع", - "submission.import-external.preview.subtitle": "تم استيراد الميتاداتا أدناه من المصدر الخارجي. ", - "submission.import-external.preview.button.import": "البدء", + + // "submission.import-external.source.pubmed": "Pubmed", + "submission.import-external.source.pubmed": "Pubmed", + + // "submission.import-external.source.pubmedeu": "Pubmed Europe", + "submission.import-external.source.pubmedeu": "Pubmed Europe", + + // "submission.import-external.source.lcname": "Library of Congress Names", + "submission.import-external.source.lcname": "أسماء مكتبة الكونجرس", + + // "submission.import-external.source.ror": "Research Organization Registry (ROR)", + "submission.import-external.source.ror": "سجل المؤسسات البحثية (ROR)", + + // "submission.import-external.preview.title": "Item Preview", + "submission.import-external.preview.title": "معاينة المادة", + + // "submission.import-external.preview.title.Publication": "Publication Preview", + "submission.import-external.preview.title.Publication": "معاينة المنشور", + + // "submission.import-external.preview.title.none": "Item Preview", + "submission.import-external.preview.title.none": "معاينة المادة", + + // "submission.import-external.preview.title.Journal": "Journal Preview", + "submission.import-external.preview.title.Journal": "معاينة الدورية", + + // "submission.import-external.preview.title.OrgUnit": "Organizational Unit Preview", + "submission.import-external.preview.title.OrgUnit": "معاينة الوحدة المؤسسية", + + // "submission.import-external.preview.title.Person": "Person Preview", + "submission.import-external.preview.title.Person": "معاينة الشخص", + + // "submission.import-external.preview.title.Project": "Project Preview", + "submission.import-external.preview.title.Project": "معاينة المشروع", + + // "submission.import-external.preview.subtitle": "The metadata below was imported from an external source. It will be pre-filled when you start the submission.", + "submission.import-external.preview.subtitle": "تم استيراد الميتاداتا أدناه من مصدر خارجي. ستتم تعبئتها بشكل مسبق عند بدء التقديم.", + + // "submission.import-external.preview.button.import": "Start submission", + "submission.import-external.preview.button.import": "بدء التقديم", + + // "submission.import-external.preview.error.import.title": "Submission error", "submission.import-external.preview.error.import.title": "خطأ في التقديم", - "submission.import-external.preview.error.import.body": "حدث خطأ أثناء عملية استيراد المصدر الخارجي.", + + // "submission.import-external.preview.error.import.body": "An error occurs during the external source entry import process.", + "submission.import-external.preview.error.import.body": "حدث خطأ أثناء عملية استيراد مدخل المصدر الخارجي.", + + // "submission.sections.describe.relationship-lookup.close": "Close", "submission.sections.describe.relationship-lookup.close": "إغلاق", - "submission.sections.describe.relationship-lookup.external-source.added": "تمت إضافة المدخل المحلي الفعال إلى التحديد", - "submission.sections.describe.relationship-lookup.external-source.import-button-title.isAuthorOfPublication": "استيراد الكاتب البعيد", + + // "submission.sections.describe.relationship-lookup.external-source.added": "Successfully added local entry to the selection", + "submission.sections.describe.relationship-lookup.external-source.added": "تمت إضافة المدخل المحلي بنجاح إلى التحديد", + + // "submission.sections.describe.relationship-lookup.external-source.import-button-title.isAuthorOfPublication": "Import remote author", + "submission.sections.describe.relationship-lookup.external-source.import-button-title.isAuthorOfPublication": "استيراد مؤلف بعيد", + + // "submission.sections.describe.relationship-lookup.external-source.import-button-title.Journal": "Import remote journal", "submission.sections.describe.relationship-lookup.external-source.import-button-title.Journal": "استيراد دورية بعيدة", - "submission.sections.describe.relationship-lookup.external-source.import-button-title.Journal Issue": "استيراد عدد دورية بعيدة", - "submission.sections.describe.relationship-lookup.external-source.import-button-title.Journal Volume": "استيراد دورية بعيدة", + + // "submission.sections.describe.relationship-lookup.external-source.import-button-title.Journal Issue": "Import remote journal issue", + "submission.sections.describe.relationship-lookup.external-source.import-button-title.Journal Issue": "استيراد عدد دورية بعيد", + + // "submission.sections.describe.relationship-lookup.external-source.import-button-title.Journal Volume": "Import remote journal volume", + "submission.sections.describe.relationship-lookup.external-source.import-button-title.Journal Volume": "استيراد مجلد دورية بعيد", + + // "submission.sections.describe.relationship-lookup.external-source.import-button-title.isProjectOfPublication": "Project", "submission.sections.describe.relationship-lookup.external-source.import-button-title.isProjectOfPublication": "المشروع", + + // "submission.sections.describe.relationship-lookup.external-source.import-button-title.none": "Import remote item", "submission.sections.describe.relationship-lookup.external-source.import-button-title.none": "استيراد مادة بعيدة", - "submission.sections.describe.relationship-lookup.external-source.import-button-title.Event": "زراعة فعالة بعيدة", - "submission.sections.describe.relationship-lookup.external-source.import-button-title.Product": "استيراد المنتج البعيد", - "submission.sections.describe.relationship-lookup.external-source.import-button-title.Equipment": "استيراد المعدات البعيدة", + + // "submission.sections.describe.relationship-lookup.external-source.import-button-title.Event": "Import remote event", + "submission.sections.describe.relationship-lookup.external-source.import-button-title.Event": "استيراد فعالية بعيدة", + + // "submission.sections.describe.relationship-lookup.external-source.import-button-title.Product": "Import remote product", + "submission.sections.describe.relationship-lookup.external-source.import-button-title.Product": "استيراد منتج بعيد", + + // "submission.sections.describe.relationship-lookup.external-source.import-button-title.Equipment": "Import remote equipment", + "submission.sections.describe.relationship-lookup.external-source.import-button-title.Equipment": "استيراد معدات بعيدة", + + // "submission.sections.describe.relationship-lookup.external-source.import-button-title.OrgUnit": "Import remote organizational unit", "submission.sections.describe.relationship-lookup.external-source.import-button-title.OrgUnit": "استيراد وحدة مؤسسية بعيدة", - "submission.sections.describe.relationship-lookup.external-source.import-button-title.Funding": "استيراد التمويل البعيد", + + // "submission.sections.describe.relationship-lookup.external-source.import-button-title.Funding": "Import remote fund", + "submission.sections.describe.relationship-lookup.external-source.import-button-title.Funding": "استيراد تمويل بعيد", + + // "submission.sections.describe.relationship-lookup.external-source.import-button-title.Person": "Import remote person", "submission.sections.describe.relationship-lookup.external-source.import-button-title.Person": "استيراد شخص بعيد", - "submission.sections.describe.relationship-lookup.external-source.import-button-title.Patent": "استيراد اختراع طويل", + + // "submission.sections.describe.relationship-lookup.external-source.import-button-title.Patent": "Import remote patent", + "submission.sections.describe.relationship-lookup.external-source.import-button-title.Patent": "استيراد براءة اختراع بعيدة", + + // "submission.sections.describe.relationship-lookup.external-source.import-button-title.Project": "Import remote project", "submission.sections.describe.relationship-lookup.external-source.import-button-title.Project": "استيراد مشروع بعيد", + + // "submission.sections.describe.relationship-lookup.external-source.import-button-title.Publication": "Import remote publication", "submission.sections.describe.relationship-lookup.external-source.import-button-title.Publication": "استيراد منشور بعيد", - "submission.sections.describe.relationship-lookup.external-source.import-modal.isProjectOfPublication.added.new-entity": "أكمل إضافة كينونة جديدة!", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.isProjectOfPublication.added.new-entity": "New Entity Added!", + "submission.sections.describe.relationship-lookup.external-source.import-modal.isProjectOfPublication.added.new-entity": "تمت إضافة كينونة جديدة!", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.isProjectOfPublication.title": "Project", "submission.sections.describe.relationship-lookup.external-source.import-modal.isProjectOfPublication.title": "مشروع", - "submission.sections.describe.relationship-lookup.external-source.import-modal.head.openAIREFunding": "تمويل برمجة تطبيقات OpenAIRE", - "submission.sections.describe.relationship-lookup.external-source.import-modal.isAuthorOfPublication.title": "استيراد الكاتب البعيد", - "submission.sections.describe.relationship-lookup.external-source.import-modal.isAuthorOfPublication.added.local-entity": "تمت إضافة المؤلف المحلي الفعال إلى التحديد", - "submission.sections.describe.relationship-lookup.external-source.import-modal.isAuthorOfPublication.added.new-entity": "تم استيراد المصنع الخارجي بفعالية إلى التحديد", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.head.openAIREFunding": "Funding OpenAIRE API", + "submission.sections.describe.relationship-lookup.external-source.import-modal.head.openAIREFunding": "تمويل واجهة برمجة تطبيقات OpenAIRE", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.isAuthorOfPublication.title": "Import Remote Author", + "submission.sections.describe.relationship-lookup.external-source.import-modal.isAuthorOfPublication.title": "استيراد مؤلف بعيد", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.isAuthorOfPublication.added.local-entity": "Successfully added local author to the selection", + "submission.sections.describe.relationship-lookup.external-source.import-modal.isAuthorOfPublication.added.local-entity": "تمت إضافة المؤلف المحلي بنجاح إلى التحديد", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.isAuthorOfPublication.added.new-entity": "Successfully imported and added external author to the selection", + "submission.sections.describe.relationship-lookup.external-source.import-modal.isAuthorOfPublication.added.new-entity": "تم استيراد وإضافة المؤلف الخارجي بنجاح إلى التحديد", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.authority": "Authority", "submission.sections.describe.relationship-lookup.external-source.import-modal.authority": "الاستناد", - "submission.sections.describe.relationship-lookup.external-source.import-modal.authority.new": "أدخل كإستنباط محلي جديد", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.authority.new": "Import as a new local authority entry", + "submission.sections.describe.relationship-lookup.external-source.import-modal.authority.new": "استيراد كإدخال استناد محلي جديد", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.cancel": "Cancel", "submission.sections.describe.relationship-lookup.external-source.import-modal.cancel": "إلغاء", - "submission.sections.describe.relationship-lookup.external-source.import-modal.collection": "اختر حاوية استيراد الإدخالات الجديدة الخاصة بها", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.collection": "Select a collection to import new entries to", + "submission.sections.describe.relationship-lookup.external-source.import-modal.collection": "حدد حاوية لاستيراد الإدخالات الجديدة إليها", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.entities": "Entities", "submission.sections.describe.relationship-lookup.external-source.import-modal.entities": "الكينونات", - "submission.sections.describe.relationship-lookup.external-source.import-modal.entities.new": "استيراد كيكونة محلية جديدة", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.entities.new": "Import as a new local entity", + "submission.sections.describe.relationship-lookup.external-source.import-modal.entities.new": "استيراد ككينونة محلية جديدة", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.head.lcname": "Importing from LC Name", "submission.sections.describe.relationship-lookup.external-source.import-modal.head.lcname": "استيراد من اسم مكتبة الكونجرس", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.head.orcid": "Importing from ORCID", "submission.sections.describe.relationship-lookup.external-source.import-modal.head.orcid": "استيراد من أوركيد", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.head.sherpaJournal": "Importing from Sherpa Journal", "submission.sections.describe.relationship-lookup.external-source.import-modal.head.sherpaJournal": "استيراد من دورية شيربا", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.head.sherpaPublisher": "Importing from Sherpa Publisher", "submission.sections.describe.relationship-lookup.external-source.import-modal.head.sherpaPublisher": "استيراد من ناشر شيربا", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.head.pubmed": "Importing from PubMed", "submission.sections.describe.relationship-lookup.external-source.import-modal.head.pubmed": "استيراد من PubMed", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.head.arxiv": "Importing from arXiv", "submission.sections.describe.relationship-lookup.external-source.import-modal.head.arxiv": "استيراد من arXiv", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.head.ror": "Import from ROR", "submission.sections.describe.relationship-lookup.external-source.import-modal.head.ror": "استيراد من ROR", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.import": "Import", "submission.sections.describe.relationship-lookup.external-source.import-modal.import": "استيراد", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal.title": "Import Remote Journal", "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal.title": "استيراد دورية بعيدة", - "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal.added.local-entity": "أكمل إضافة الدورية الفعالة إلى التحديد", - "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal.added.new-entity": "تم الانتهاء من حذف دورية خارجية إلى التحديد", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal.added.local-entity": "Successfully added local journal to the selection", + "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal.added.local-entity": "تمت إضافة الدورية المحلية بنجاح إلى التحديد", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal.added.new-entity": "Successfully imported and added external journal to the selection", + "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal.added.new-entity": "تم بنجاح استيراد وإضافة دورية خارجية إلى التحديد", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Issue.title": "Import Remote Journal Issue", "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Issue.title": "استيراد عدد دورية بعيدة", - "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Issue.added.local-entity": "تمت إضافة المزيد من الدوريات الفعالة إلى التحديد", - "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Issue.added.new-entity": "تم استيراد عدد الدوريات الخارجية وإضافتها الفعالة إلى التحديد", - "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Volume.title": "استيراد دورة طويلة", - "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Volume.added.local-entity": "أكمل إضافة الدورية الفعالة إلى التحديد", - "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Volume.added.new-entity": "تم استيراد سلسلة الدوري الخارجية وإضافتها الفعالة إلى التحديد", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Issue.added.local-entity": "Successfully added local journal issue to the selection", + "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Issue.added.local-entity": "تمت إضافة عدد الدورية المحلية بنجاح إلى التحديد", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Issue.added.new-entity": "Successfully imported and added external journal issue to the selection", + "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Issue.added.new-entity": "تم استيراد عدد الدورية الخارجية وإضافته بنجاح إلى التحديد", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Volume.title": "Import Remote Journal Volume", + "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Volume.title": "استيراد مجلد دورية بعيدة", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Volume.added.local-entity": "Successfully added local journal volume to the selection", + "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Volume.added.local-entity": "تمت إضافة مجلد الدورية المحلية بنجاح إلى التحديد", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Volume.added.new-entity": "Successfully imported and added external journal volume to the selection", + "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Volume.added.new-entity": "تم استيراد مجلد الدورية الخارجية وإضافته بنجاح إلى التحديد", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.select": "Select a local match:", "submission.sections.describe.relationship-lookup.external-source.import-modal.select": "تحديد تطابق محلي:", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.isOrgUnitOfProject.title": "Import Remote Organization", "submission.sections.describe.relationship-lookup.external-source.import-modal.isOrgUnitOfProject.title": "استيراد مؤسسة بعيدة", - "submission.sections.describe.relationship-lookup.external-source.import-modal.isOrgUnitOfProject.added.local-entity": "تمت إضافة المؤسسة المحلية إلى التحديد الفعال", - "submission.sections.describe.relationship-lookup.external-source.import-modal.isOrgUnitOfProject.added.new-entity": "تم التخلص من المصنع الخارجي إلى التحديد", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.isOrgUnitOfProject.added.local-entity": "Successfully added local organization to the selection", + "submission.sections.describe.relationship-lookup.external-source.import-modal.isOrgUnitOfProject.added.local-entity": "تمت إضافة المؤسسة المحلية إلى التحديد بنجاح", + + // "submission.sections.describe.relationship-lookup.external-source.import-modal.isOrgUnitOfProject.added.new-entity": "Successfully imported and added external organization to the selection", + "submission.sections.describe.relationship-lookup.external-source.import-modal.isOrgUnitOfProject.added.new-entity": "تم بنجاح استيراد وإضافة مؤسسة خارجية إلى التحديد", + + // "submission.sections.describe.relationship-lookup.search-tab.deselect-all": "Deselect all", "submission.sections.describe.relationship-lookup.search-tab.deselect-all": "إلغاء تحديد الكل", + + // "submission.sections.describe.relationship-lookup.search-tab.deselect-page": "Deselect page", "submission.sections.describe.relationship-lookup.search-tab.deselect-page": "إلغاء تحديد الصفحة", + + // "submission.sections.describe.relationship-lookup.search-tab.loading": "Loading...", "submission.sections.describe.relationship-lookup.search-tab.loading": "جاري التحميل...", + + // "submission.sections.describe.relationship-lookup.search-tab.placeholder": "Search query", "submission.sections.describe.relationship-lookup.search-tab.placeholder": "استعلام البحث", + + // "submission.sections.describe.relationship-lookup.search-tab.search": "Go", "submission.sections.describe.relationship-lookup.search-tab.search": "اذهب", - "submission.sections.describe.relationship-lookup.search-tab.search-form.placeholder": "بحثت...", + + // "submission.sections.describe.relationship-lookup.search-tab.search-form.placeholder": "Search...", + "submission.sections.describe.relationship-lookup.search-tab.search-form.placeholder": "بحث...", + + // "submission.sections.describe.relationship-lookup.search-tab.select-all": "Select all", "submission.sections.describe.relationship-lookup.search-tab.select-all": "تحديد الكل", + + // "submission.sections.describe.relationship-lookup.search-tab.select-page": "Select page", "submission.sections.describe.relationship-lookup.search-tab.select-page": "تحديد الصفحة", + + // "submission.sections.describe.relationship-lookup.selected": "Selected {{ size }} items", "submission.sections.describe.relationship-lookup.selected": "{{ size }} مادة محددة", - "submission.sections.describe.relationship-lookup.search-tab.tab-title.isAuthorOfPublication": "المؤلفين ({{ count }})", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.isAuthorOfPublication": "Local Authors ({{ count }})", + "submission.sections.describe.relationship-lookup.search-tab.tab-title.isAuthorOfPublication": "المؤلفين المحليين ({{ count }})", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.isJournalOfPublication": "Local Journals ({{ count }})", "submission.sections.describe.relationship-lookup.search-tab.tab-title.isJournalOfPublication": "الدوريات المحلية ({{ count }})", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.Project": "Local Projects ({{ count }})", "submission.sections.describe.relationship-lookup.search-tab.tab-title.Project": "المشاريع المحلية ({{ count }})", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.Publication": "Local Publications ({{ count }})", "submission.sections.describe.relationship-lookup.search-tab.tab-title.Publication": "المنشورات المحلية ({{ count }})", - "submission.sections.describe.relationship-lookup.search-tab.tab-title.Person": "المؤلفين ({{ count }})", - "submission.sections.describe.relationship-lookup.search-tab.tab-title.OrgUnit": "الوحدات الوطنية المحلية ({{ count }})", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.Person": "Local Authors ({{ count }})", + "submission.sections.describe.relationship-lookup.search-tab.tab-title.Person": "المؤلفين المحليين ({{ count }})", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.OrgUnit": "Local Organizational Units ({{ count }})", + "submission.sections.describe.relationship-lookup.search-tab.tab-title.OrgUnit": "الوحدات المؤسسية المحلية ({{ count }})", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.DataPackage": "Local Data Packages ({{ count }})", "submission.sections.describe.relationship-lookup.search-tab.tab-title.DataPackage": "حزم البيانات المحلية ({{ count }})", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.DataFile": "Local Data Files ({{ count }})", "submission.sections.describe.relationship-lookup.search-tab.tab-title.DataFile": "ملفات البيانات المحلية ({{ count }})", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.Journal": "Local Journals ({{ count }})", "submission.sections.describe.relationship-lookup.search-tab.tab-title.Journal": "الدوريات المحلية ({{ count }})", - "submission.sections.describe.relationship-lookup.search-tab.tab-title.isJournalIssueOfPublication": "سجل الدوريات المحلية ({{ count }})", - "submission.sections.describe.relationship-lookup.search-tab.tab-title.JournalIssue": "سجل الدوريات المحلية ({{ count }})", - "submission.sections.describe.relationship-lookup.search-tab.tab-title.isJournalVolumeOfPublication": "خطوط الدوريات المحلية ({{ count }})", - "submission.sections.describe.relationship-lookup.search-tab.tab-title.JournalVolume": "خطوط الدوريات المحلية ({{ count }})", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.isJournalIssueOfPublication": "Local Journal Issues ({{ count }})", + "submission.sections.describe.relationship-lookup.search-tab.tab-title.isJournalIssueOfPublication": "أعداد الدوريات المحلية ({{ count }})", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.JournalIssue": "Local Journal Issues ({{ count }})", + "submission.sections.describe.relationship-lookup.search-tab.tab-title.JournalIssue": "أعداد الدوريات المحلية ({{ count }})", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.isJournalVolumeOfPublication": "Local Journal Volumes ({{ count }})", + "submission.sections.describe.relationship-lookup.search-tab.tab-title.isJournalVolumeOfPublication": "مجلدات الدوريات المحلية ({{ count }})", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.JournalVolume": "Local Journal Volumes ({{ count }})", + "submission.sections.describe.relationship-lookup.search-tab.tab-title.JournalVolume": "مجلدات الدوريات المحلية ({{ count }})", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.sherpaJournal": "Sherpa Journals ({{ count }})", "submission.sections.describe.relationship-lookup.search-tab.tab-title.sherpaJournal": "دوريات شيربا ({{ count }})", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.sherpaPublisher": "Sherpa Publishers ({{ count }})", "submission.sections.describe.relationship-lookup.search-tab.tab-title.sherpaPublisher": "ناشري شيربا ({{ count }})", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.orcid": "ORCID ({{ count }})", "submission.sections.describe.relationship-lookup.search-tab.tab-title.orcid": "أوركيد ({{ count }})", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.lcname": "LC Names ({{ count }})", "submission.sections.describe.relationship-lookup.search-tab.tab-title.lcname": "أسماء مكتبة الكونجرس ({{ count }})", - "submission.sections.describe.relationship-lookup.search-tab.tab-title.pubmed": "مجلات ({{ count }})", - "submission.sections.describe.relationship-lookup.search-tab.tab-title.arxiv": "أرخايف ({{ count }})", - "submission.sections.describe.relationship-lookup.search-tab.tab-title.ror": "معدل العائد ({{ count }})", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.pubmed": "PubMed ({{ count }})", + "submission.sections.describe.relationship-lookup.search-tab.tab-title.pubmed": "PubMed ({{ count }})", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.arxiv": "arXiv ({{ count }})", + "submission.sections.describe.relationship-lookup.search-tab.tab-title.arxiv": "arXiv ({{ count }})", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.ror": "ROR ({{ count }})", + "submission.sections.describe.relationship-lookup.search-tab.tab-title.ror": "ROR ({{ count }})", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.orcidWorks": "ORCID ({{ count }})", "submission.sections.describe.relationship-lookup.search-tab.tab-title.orcidWorks": "أوركيد ({{ count }})", - "submission.sections.describe.relationship-lookup.search-tab.tab-title.crossref": "كروسريف ({{ count }})", - "submission.sections.describe.relationship-lookup.search-tab.tab-title.scopus": "سكوبس ({{ count }})", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.crossref": "CrossRef ({{ count }})", + "submission.sections.describe.relationship-lookup.search-tab.tab-title.crossref": "CrossRef ({{ count }})", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.scopus": "Scopus ({{ count }})", + "submission.sections.describe.relationship-lookup.search-tab.tab-title.scopus": "Scopus ({{ count }})", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.openaireFunding": "Funding OpenAIRE ({{ count }})", "submission.sections.describe.relationship-lookup.search-tab.tab-title.openaireFunding": "تمويل OpenAIRE ({{ count }})", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.sherpaJournalIssn": "Sherpa Journals by ISSN ({{ count }})", "submission.sections.describe.relationship-lookup.search-tab.tab-title.sherpaJournalIssn": "دوريات شيربا حسب ISSN ({{ count }})", - "submission.sections.describe.relationship-lookup.search-tab.tab-title.isFundingAgencyOfPublication": "ابحث عن وكالات ممولة", - "submission.sections.describe.relationship-lookup.search-tab.tab-title.isFundingOfPublication": "البحث عن التمويل", - "submission.sections.describe.relationship-lookup.search-tab.tab-title.isChildOrgUnitOf": "البحث عن الوحدات الوطنية", - "submission.sections.describe.relationship-lookup.search-tab.tab-title.openAIREFunding": "تمويل برمجة تطبيقات OpenAIRE", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.isFundingAgencyOfPublication": "Search for Funding Agencies", + "submission.sections.describe.relationship-lookup.search-tab.tab-title.isFundingAgencyOfPublication": "البحث عن وكالات ممولة", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.isFundingOfPublication": "Search for Funding", + "submission.sections.describe.relationship-lookup.search-tab.tab-title.isFundingOfPublication": "البحث عن تمويل", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.isChildOrgUnitOf": "Search for Organizational Units", + "submission.sections.describe.relationship-lookup.search-tab.tab-title.isChildOrgUnitOf": "البحث عن الوحدات المؤسسية", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.openAIREFunding": "Funding OpenAIRE API", + "submission.sections.describe.relationship-lookup.search-tab.tab-title.openAIREFunding": "تمويل واجهة برمجة تطبيقات OpenAIRE", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.isProjectOfPublication": "Projects", "submission.sections.describe.relationship-lookup.search-tab.tab-title.isProjectOfPublication": "المشاريع", - "submission.sections.describe.relationship-lookup.search-tab.tab-title.isFundingAgencyOfProject": "مول المشروع", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.isFundingAgencyOfProject": "Funder of the Project", + "submission.sections.describe.relationship-lookup.search-tab.tab-title.isFundingAgencyOfProject": "ممول المشروع", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.isPublicationOfAuthor": "Publication of the Author", "submission.sections.describe.relationship-lookup.search-tab.tab-title.isPublicationOfAuthor": "منشورات المؤلف", - "submission.sections.describe.relationship-lookup.search-tab.tab-title.isOrgUnitOfProject": "الوحدة التنظيمية", - "submission.sections.describe.relationship-lookup.selection-tab.title.openAIREFunding": "تمويل برمجة تطبيقات OpenAIRE", + + // "submission.sections.describe.relationship-lookup.search-tab.tab-title.isOrgUnitOfProject": "OrgUnit of the Project", + "submission.sections.describe.relationship-lookup.search-tab.tab-title.isOrgUnitOfProject": "الوحدة المؤسسية للمشروع", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.openAIREFunding": "Funding OpenAIRE API", + "submission.sections.describe.relationship-lookup.selection-tab.title.openAIREFunding": "تمويل واجهة برمجة تطبيقات OpenAIRE", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.isProjectOfPublication": "Project", "submission.sections.describe.relationship-lookup.selection-tab.title.isProjectOfPublication": "المشروع", + + // "submission.sections.describe.relationship-lookup.title.isProjectOfPublication": "Projects", "submission.sections.describe.relationship-lookup.title.isProjectOfPublication": "المشاريع", - "submission.sections.describe.relationship-lookup.title.isFundingAgencyOfProject": "مول المشروع", - "submission.sections.describe.relationship-lookup.selection-tab.search-form.placeholder": "بحثت...", - "submission.sections.describe.relationship-lookup.selection-tab.tab-title": "التحديد الفعلي ({{ count }})", - "submission.sections.describe.relationship-lookup.title.Journal": "الدوري", - "submission.sections.describe.relationship-lookup.title.isJournalIssueOfPublication": "سجل الدوري", - "submission.sections.describe.relationship-lookup.title.JournalIssue": "سجل الدوري", - "submission.sections.describe.relationship-lookup.title.isJournalVolumeOfPublication": "سلسلة الدوريات", - "submission.sections.describe.relationship-lookup.title.JournalVolume": "سلسلة الدوريات", + + // "submission.sections.describe.relationship-lookup.title.isFundingAgencyOfProject": "Funder of the Project", + "submission.sections.describe.relationship-lookup.title.isFundingAgencyOfProject": "ممول المشروع", + + // "submission.sections.describe.relationship-lookup.selection-tab.search-form.placeholder": "Search...", + "submission.sections.describe.relationship-lookup.selection-tab.search-form.placeholder": "بحث...", + + // "submission.sections.describe.relationship-lookup.selection-tab.tab-title": "Current Selection ({{ count }})", + "submission.sections.describe.relationship-lookup.selection-tab.tab-title": "التحديد الحالي ({{ count }})", + + // "submission.sections.describe.relationship-lookup.title.Journal": "Journal", + "submission.sections.describe.relationship-lookup.title.Journal": "الدورية", + + // "submission.sections.describe.relationship-lookup.title.isJournalIssueOfPublication": "Journal Issues", + "submission.sections.describe.relationship-lookup.title.isJournalIssueOfPublication": "أعداد الدورية", + + // "submission.sections.describe.relationship-lookup.title.JournalIssue": "Journal Issues", + "submission.sections.describe.relationship-lookup.title.JournalIssue": "أعداد الدورية", + + // "submission.sections.describe.relationship-lookup.title.isJournalVolumeOfPublication": "Journal Volumes", + "submission.sections.describe.relationship-lookup.title.isJournalVolumeOfPublication": "مجلدات الدورية", + + // "submission.sections.describe.relationship-lookup.title.JournalVolume": "Journal Volumes", + "submission.sections.describe.relationship-lookup.title.JournalVolume": "مجلدات الدورية", + + // "submission.sections.describe.relationship-lookup.title.isJournalOfPublication": "Journals", "submission.sections.describe.relationship-lookup.title.isJournalOfPublication": "الدوريات", + + // "submission.sections.describe.relationship-lookup.title.isAuthorOfPublication": "Authors", "submission.sections.describe.relationship-lookup.title.isAuthorOfPublication": "المؤلفين", + + // "submission.sections.describe.relationship-lookup.title.isFundingAgencyOfPublication": "Funding Agency", "submission.sections.describe.relationship-lookup.title.isFundingAgencyOfPublication": "الوكالة الممولة", - "submission.sections.describe.relationship-lookup.title.Project": "المشاريع", - "submission.sections.describe.relationship-lookup.title.Publication": "منشورات", + + // "submission.sections.describe.relationship-lookup.title.Project": "Projects", + "submission.sections.describe.relationship-lookup.title.Project": "المشروعات", + + // "submission.sections.describe.relationship-lookup.title.Publication": "Publications", + "submission.sections.describe.relationship-lookup.title.Publication": "المنشورات", + + // "submission.sections.describe.relationship-lookup.title.Person": "Authors", "submission.sections.describe.relationship-lookup.title.Person": "المؤلفين", - "submission.sections.describe.relationship-lookup.title.OrgUnit": "الوحدات الوطنية", + + // "submission.sections.describe.relationship-lookup.title.OrgUnit": "Organizational Units", + "submission.sections.describe.relationship-lookup.title.OrgUnit": "الوحدات المؤسسية", + + // "submission.sections.describe.relationship-lookup.title.DataPackage": "Data Packages", "submission.sections.describe.relationship-lookup.title.DataPackage": "حزم البيانات", - "submission.sections.describe.relationship-lookup.title.DataFile": "ملفات بيانات البيانات", + + // "submission.sections.describe.relationship-lookup.title.DataFile": "Data Files", + "submission.sections.describe.relationship-lookup.title.DataFile": "ملفات البيانات", + + // "submission.sections.describe.relationship-lookup.title.Funding Agency": "Funding Agency", "submission.sections.describe.relationship-lookup.title.Funding Agency": "الوكالة الممولة", + + // "submission.sections.describe.relationship-lookup.title.isFundingOfPublication": "Funding", "submission.sections.describe.relationship-lookup.title.isFundingOfPublication": "تمويل", - "submission.sections.describe.relationship-lookup.title.isChildOrgUnitOf": "الوحدة المحلية الأصلية", + + // "submission.sections.describe.relationship-lookup.title.isChildOrgUnitOf": "Parent Organizational Unit", + "submission.sections.describe.relationship-lookup.title.isChildOrgUnitOf": "الوحدة المؤسسية الأصلية", + + // "submission.sections.describe.relationship-lookup.title.isPublicationOfAuthor": "Publication", "submission.sections.describe.relationship-lookup.title.isPublicationOfAuthor": "النشر", + + // "submission.sections.describe.relationship-lookup.title.isOrgUnitOfProject": "OrgUnit", "submission.sections.describe.relationship-lookup.title.isOrgUnitOfProject": "وحدة مؤسسية", + + // "submission.sections.describe.relationship-lookup.search-tab.toggle-dropdown": "Toggle dropdown", "submission.sections.describe.relationship-lookup.search-tab.toggle-dropdown": "قائمة التبديل المنسدلة", - "submission.sections.describe.relationship-lookup.selection-tab.settings": "عد", - "submission.sections.describe.relationship-lookup.selection-tab.no-selection": "تحديدك بالكامل.", - "submission.sections.describe.relationship-lookup.selection-tab.title.isAuthorOfPublication": "المؤلفين", + + // "submission.sections.describe.relationship-lookup.selection-tab.settings": "Settings", + "submission.sections.describe.relationship-lookup.selection-tab.settings": "الإعدادات", + + // "submission.sections.describe.relationship-lookup.selection-tab.no-selection": "Your selection is currently empty.", + "submission.sections.describe.relationship-lookup.selection-tab.no-selection": "تحديدك فارغ حالياً.", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.isAuthorOfPublication": "Selected Authors", + "submission.sections.describe.relationship-lookup.selection-tab.title.isAuthorOfPublication": "المؤلفين المحددين", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.isJournalOfPublication": "Selected Journals", "submission.sections.describe.relationship-lookup.selection-tab.title.isJournalOfPublication": "الدوريات المحددة", - "submission.sections.describe.relationship-lookup.selection-tab.title.isJournalVolumeOfPublication": "دليل البحث", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.isJournalVolumeOfPublication": "Selected Journal Volume", + "submission.sections.describe.relationship-lookup.selection-tab.title.isJournalVolumeOfPublication": "مجلد الدورية المحدد", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.Project": "Selected Projects", "submission.sections.describe.relationship-lookup.selection-tab.title.Project": "المشاريع المحددة", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.Publication": "Selected Publications", "submission.sections.describe.relationship-lookup.selection-tab.title.Publication": "المنشورات المحددة", - "submission.sections.describe.relationship-lookup.selection-tab.title.Person": "المؤلفين", - "submission.sections.describe.relationship-lookup.selection-tab.title.OrgUnit": "الوحدات الوطنية المحددة", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.Person": "Selected Authors", + "submission.sections.describe.relationship-lookup.selection-tab.title.Person": "المؤلفين المحددين", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.OrgUnit": "Selected Organizational Units", + "submission.sections.describe.relationship-lookup.selection-tab.title.OrgUnit": "الوحدات المؤسسية المحددة", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.DataPackage": "Selected Data Packages", "submission.sections.describe.relationship-lookup.selection-tab.title.DataPackage": "حزم البيانات المحددة", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.DataFile": "Selected Data Files", "submission.sections.describe.relationship-lookup.selection-tab.title.DataFile": "ملفات البيانات المحددة", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.Journal": "Selected Journals", "submission.sections.describe.relationship-lookup.selection-tab.title.Journal": "الدوريات المحددة", - "submission.sections.describe.relationship-lookup.selection-tab.title.isJournalIssueOfPublication": "العثور على نتيجة", - "submission.sections.describe.relationship-lookup.selection-tab.title.JournalVolume": "دليل البحث", - "submission.sections.describe.relationship-lookup.selection-tab.title.isFundingAgencyOfPublication": "الوكالة الممولة", - "submission.sections.describe.relationship-lookup.selection-tab.title.isFundingOfPublication": "التمويل للبحث", - "submission.sections.describe.relationship-lookup.selection-tab.title.JournalIssue": "العثور على نتيجة", - "submission.sections.describe.relationship-lookup.selection-tab.title.isChildOrgUnitOf": "الوحدة الوطنية المحددة", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.isJournalIssueOfPublication": "Selected Issue", + "submission.sections.describe.relationship-lookup.selection-tab.title.isJournalIssueOfPublication": "العدد المحدد", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.JournalVolume": "Selected Journal Volume", + "submission.sections.describe.relationship-lookup.selection-tab.title.JournalVolume": "مجلد الدورية المحدد", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.isFundingAgencyOfPublication": "Selected Funding Agency", + "submission.sections.describe.relationship-lookup.selection-tab.title.isFundingAgencyOfPublication": "الوكالة الممولة المحددة", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.isFundingOfPublication": "Selected Funding", + "submission.sections.describe.relationship-lookup.selection-tab.title.isFundingOfPublication": "التمويل المحدد", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.JournalIssue": "Selected Issue", + "submission.sections.describe.relationship-lookup.selection-tab.title.JournalIssue": "العدد المحدد", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.isChildOrgUnitOf": "Selected Organizational Unit", + "submission.sections.describe.relationship-lookup.selection-tab.title.isChildOrgUnitOf": "الوحدة المؤسسية المحددة", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.sherpaJournal": "Search Results", "submission.sections.describe.relationship-lookup.selection-tab.title.sherpaJournal": "نتائج البحث", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.sherpaPublisher": "Search Results", "submission.sections.describe.relationship-lookup.selection-tab.title.sherpaPublisher": "نتائج البحث", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.orcid": "Search Results", "submission.sections.describe.relationship-lookup.selection-tab.title.orcid": "نتائج البحث", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.orcidv2": "Search Results", "submission.sections.describe.relationship-lookup.selection-tab.title.orcidv2": "نتائج البحث", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.lcname": "Search Results", "submission.sections.describe.relationship-lookup.selection-tab.title.lcname": "نتائج البحث", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.pubmed": "Search Results", "submission.sections.describe.relationship-lookup.selection-tab.title.pubmed": "نتائج البحث", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.arxiv": "Search Results", "submission.sections.describe.relationship-lookup.selection-tab.title.arxiv": "نتائج البحث", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.crossref": "Search Results", "submission.sections.describe.relationship-lookup.selection-tab.title.crossref": "نتائج البحث", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.epo": "Search Results", "submission.sections.describe.relationship-lookup.selection-tab.title.epo": "نتائج البحث", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.scopus": "Search Results", "submission.sections.describe.relationship-lookup.selection-tab.title.scopus": "نتائج البحث", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.scielo": "Search Results", "submission.sections.describe.relationship-lookup.selection-tab.title.scielo": "نتائج البحث", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.wos": "Search Results", "submission.sections.describe.relationship-lookup.selection-tab.title.wos": "نتائج البحث", + + // "submission.sections.describe.relationship-lookup.selection-tab.title.ror": "Search Results", "submission.sections.describe.relationship-lookup.selection-tab.title.ror": "نتائج البحث", + + // "submission.sections.describe.relationship-lookup.selection-tab.title": "Search Results", "submission.sections.describe.relationship-lookup.selection-tab.title": "نتائج البحث", - "submission.sections.describe.relationship-lookup.name-variant.notification.content": "هل ترغب في حفظ \"{{ value }}\" كمتغير اسم هذا الشخص حتى بدأت بالفعل في إعادة استخدامه بنجاح بنجاح؟ إذا لم تقم بذلك، فلا يزال بإمكانك استخدام هذا التقديم.", - "submission.sections.describe.relationship-lookup.name-variant.notification.confirm": "حفظ اسم جديد", - "submission.sections.describe.relationship-lookup.name-variant.notification.decline": "استخدم فقط هذا التقديم", - "submission.sections.ccLicense.type": "نوع الحكم", - "submission.sections.ccLicense.select": "قم بتحديد نوع الأمر…", - "submission.sections.ccLicense.change": "قم بتغيير نوع النظام…", - "submission.sections.ccLicense.none": "لا تتوفر أي تراخيص", - "submission.sections.ccLicense.option.select": "قم باختيار الخيار…", - "submission.sections.ccLicense.link": "لقد قمت بإلغاء الأمر التالي:", - "submission.sections.ccLicense.confirmation": "زيادة على ذلك", + + // "submission.sections.describe.relationship-lookup.name-variant.notification.content": "Would you like to save \"{{ value }}\" as a name variant for this person so you and others can reuse it for future submissions? If you don't you can still use it for this submission.", + "submission.sections.describe.relationship-lookup.name-variant.notification.content": "هل ترغب في حفظe \"{{ value }}\" كمتغير اسم لهذا الشخص حتى تتمكن أنت والآخرون من إعادة استخدامه لعمليات التقديم المستقبلية؟ إذا لم تقم بذلك، فلا يزال بإمكانك استخدامه لهذا التقديم.", + + // "submission.sections.describe.relationship-lookup.name-variant.notification.confirm": "Save a new name variant", + "submission.sections.describe.relationship-lookup.name-variant.notification.confirm": "حفظ متغير اسم جديد", + + // "submission.sections.describe.relationship-lookup.name-variant.notification.decline": "Use only for this submission", + "submission.sections.describe.relationship-lookup.name-variant.notification.decline": "استخدم فقط لهذا التقديم", + + // "submission.sections.ccLicense.type": "License Type", + "submission.sections.ccLicense.type": "نوع الترخيص", + + // "submission.sections.ccLicense.select": "Select a license type…", + "submission.sections.ccLicense.select": "قم بتحديد نوع الترخيص…", + + // "submission.sections.ccLicense.change": "Change your license type…", + "submission.sections.ccLicense.change": "قم بتغيير نوع الترخيص…", + + // "submission.sections.ccLicense.none": "No licenses available", + "submission.sections.ccLicense.none": "لا تتوافر أي تراخيص", + + // "submission.sections.ccLicense.option.select": "Select an option…", + "submission.sections.ccLicense.option.select": "قم بتحديد خيار…", + + // "submission.sections.ccLicense.link": "You’ve selected the following license:", + "submission.sections.ccLicense.link": "لقد قمت بتحديد الترخيص التالي:", + + // "submission.sections.ccLicense.confirmation": "I grant the license above", + "submission.sections.ccLicense.confirmation": "أمنحك الترخيص أعلاه", + + // "submission.sections.general.add-more": "Add more", "submission.sections.general.add-more": "إضافة المزيد", - "submission.sections.general.cannot_deposit": "لا يمكن تجاوز الإيداع بسبب وجود أخطاء في النموذج.
يرجى تعبئة جميع الأغراض المطلوبة لجميع الإيداع.", + + // "submission.sections.general.cannot_deposit": "Deposit cannot be completed due to errors in the form.
Please fill out all required fields to complete the deposit.", + "submission.sections.general.cannot_deposit": "لا يمكن إتمام الإيداع بسبب وجود أخطاء في النموذج.
يرجى ملء جميع الحقول المطلوبة لإتمام الإيداع.", + + // "submission.sections.general.collection": "Collection", "submission.sections.general.collection": "حاوية", - "submission.sections.general.deposit_error_notice": "تجربة تقديم المادة أثناء تقديم المادة، يرجى إعادة محاولة مرة أخرى لاحقاً.", - "submission.sections.general.deposit_success_notice": "تم تقديم التقديم الفعال.", - "submission.sections.general.discard_error_notice": "لا تتجاهل المشكلة، يرجى إعادة محاولة مرة أخرى لاحقًا.", - "submission.sections.general.discard_success_notice": "تم التقليل من التأثير.", - "submission.sections.general.metadata-extracted": "تم الانتهاء من ميتاداتا جديدة وإضافتها إلى القسم {{sectionId}}.", - "submission.sections.general.metadata-extracted-new-section": "أكمل إضافة قسم {{sectionId}} الجديد في التقديم.", - "submission.sections.general.no-collection": "لم يتم العثور على الوثيقة", + + // "submission.sections.general.deposit_error_notice": "There was an issue when submitting the item, please try again later.", + "submission.sections.general.deposit_error_notice": "حدثت مشكلة أثناء تقديم المادة، يرجى إعادة المحاولة مرة أخرى لاحقاً.", + + // "submission.sections.general.deposit_success_notice": "Submission deposited successfully.", + "submission.sections.general.deposit_success_notice": "تم إيداع التقديم بنجاح.", + + // "submission.sections.general.discard_error_notice": "There was an issue when discarding the item, please try again later.", + "submission.sections.general.discard_error_notice": "حدثت مشكلة أثناء تجاهل المادة، يرجى إعادة المحاولة مرة أخرى لاحقاً.", + + // "submission.sections.general.discard_success_notice": "Submission discarded successfully.", + "submission.sections.general.discard_success_notice": "تم تجاهل التقديم بنجاح.", + + // "submission.sections.general.metadata-extracted": "New metadata have been extracted and added to the {{sectionId}} section.", + "submission.sections.general.metadata-extracted": "تم استخلاص ميتاداتا جديدة وإضافتها إلى قسم {{sectionId}}.", + + // "submission.sections.general.metadata-extracted-new-section": "New {{sectionId}} section has been added to submission.", + "submission.sections.general.metadata-extracted-new-section": "تمت إضافة قسم {{sectionId}} جديد إلى التقديم.", + + // "submission.sections.general.no-collection": "No collection found", + "submission.sections.general.no-collection": "لم يتم العثور على حاويات", + + // "submission.sections.general.no-entity": "No entity types found", "submission.sections.general.no-entity": "لم يتم العثور على أنواع كينونات", - "submission.sections.general.no-sections": "لا تتوفر أي خيارات", - "submission.sections.general.save_error_notice": "حدثت مشكلة أثناء حفظ المادة، يرجى إعادة محاولة مرة أخرى لاحقًا.", - "submission.sections.general.save_success_notice": "تم دعم الفعال.", - "submission.sections.general.search-collection": "ابحث عن الحاوية", + + // "submission.sections.general.no-sections": "No options available", + "submission.sections.general.no-sections": "لا تتوافر أي خيارات", + + // "submission.sections.general.save_error_notice": "There was an issue when saving the item, please try again later.", + "submission.sections.general.save_error_notice": "حدثت مشكلة أثناء حفظ المادة، يرجى إعادة المحاولة مرة أخرى لاحقاً.", + + // "submission.sections.general.save_success_notice": "Submission saved successfully.", + "submission.sections.general.save_success_notice": "تم حفظ التقديم بنجاح.", + + // "submission.sections.general.search-collection": "Search for a collection", + "submission.sections.general.search-collection": "البحث عن حاوية", + + // "submission.sections.general.sections_not_valid": "There are incomplete sections.", "submission.sections.general.sections_not_valid": "هناك أقسام غير مكتملة.", - "submission.sections.identifiers.info": "سيتم إنشاء المعرفات التالية الجديدة بك:", - "submission.sections.identifiers.no_handle": "ولم يتم استخدام أي يد لهذه المادة.", - "submission.sections.identifiers.no_doi": "ولم يتم البحث عن أي معرفات كائنية رقمية لهذه المادة.", - "submission.sections.identifiers.handle_label": "مقبض: ", - "submission.sections.identifiers.doi_label": "المعرفة الرقمية: ", + + // "submission.sections.identifiers.info": "The following identifiers will be created for your item:", + "submission.sections.identifiers.info": "سيتم إنشاء المعرفات التالية للمادة الخاصة بك:", + + // "submission.sections.identifiers.no_handle": "No handles have been minted for this item.", + "submission.sections.identifiers.no_handle": "لم يتم سك أي هاندل لهذه المادة.", + + // "submission.sections.identifiers.no_doi": "No DOIs have been minted for this item.", + "submission.sections.identifiers.no_doi": "لم يتم سك أي معرفات كائنات رقمية لهذه المادة.", + + // "submission.sections.identifiers.handle_label": "Handle: ", + "submission.sections.identifiers.handle_label": "هاندل: ", + + // "submission.sections.identifiers.doi_label": "DOI: ", + "submission.sections.identifiers.doi_label": "معرف الكائن الرقمي: ", + + // "submission.sections.identifiers.otherIdentifiers_label": "Other identifiers: ", "submission.sections.identifiers.otherIdentifiers_label": "معرفات أخرى: ", - "submission.sections.submit.progressbar.accessCondition": "شروط الوصول إلى أبعد", + + // "submission.sections.submit.progressbar.accessCondition": "Item access conditions", + "submission.sections.submit.progressbar.accessCondition": "شروط الوصول للمادة", + + // "submission.sections.submit.progressbar.CClicense": "Creative commons license", "submission.sections.submit.progressbar.CClicense": "الإبداعية العامة", - "submission.sections.submit.progressbar.describe.recycle": "إعادة تدوير رياضي", + + // "submission.sections.submit.progressbar.describe.recycle": "Recycle", + "submission.sections.submit.progressbar.describe.recycle": "إعادة تدوير", + + // "submission.sections.submit.progressbar.describe.stepcustom": "Describe", "submission.sections.submit.progressbar.describe.stepcustom": "وصف", + + // "submission.sections.submit.progressbar.describe.stepone": "Describe", "submission.sections.submit.progressbar.describe.stepone": "وصف", + + // "submission.sections.submit.progressbar.describe.steptwo": "Describe", "submission.sections.submit.progressbar.describe.steptwo": "وصف", - "submission.sections.submit.progressbar.duplicates": "التكرارات المحتملة", + + // "submission.sections.submit.progressbar.duplicates": "Potential duplicates", + // TODO New key - Add a translation + "submission.sections.submit.progressbar.duplicates": "Potential duplicates", + + // "submission.sections.submit.progressbar.identifiers": "Identifiers", "submission.sections.submit.progressbar.identifiers": "المعرفات", - "submission.sections.submit.progressbar.license": "ترخيص الإيداع", - "submission.sections.submit.progressbar.sherpapolicy": "سياسة شيربا", + + // "submission.sections.submit.progressbar.license": "Deposit license", + "submission.sections.submit.progressbar.license": "رخصة الإيداع", + + // "submission.sections.submit.progressbar.sherpapolicy": "Sherpa policies", + "submission.sections.submit.progressbar.sherpapolicy": "سياسات شيربا", + + // "submission.sections.submit.progressbar.upload": "Upload files", "submission.sections.submit.progressbar.upload": "تحميل الملفات", - "submission.sections.submit.progressbar.sherpaPolicies": "معلومات عن الوصول الحر للناشر", - "submission.sections.sherpa-policy.title-empty": "لا اختيار معلومات حول الناشر. ", + + // "submission.sections.submit.progressbar.sherpaPolicies": "Publisher open access policy information", + "submission.sections.submit.progressbar.sherpaPolicies": "معلومات سياسة الوصول الحر للناشر", + + // "submission.sections.sherpa-policy.title-empty": "No publisher policy information available. If your work has an associated ISSN, please enter it above to see any related publisher open access policies.", + "submission.sections.sherpa-policy.title-empty": "لا تتوفر معلومات حول سياسة الناشر. إذا كان لعملك رقم ISSN مرتبط، يرجى إدخاله أعلاه للاطلاع على أي سياسة وصول حر للناشرين ذوي الصلة.", + + // "submission.sections.status.errors.title": "Errors", "submission.sections.status.errors.title": "أخطاء", + + // "submission.sections.status.valid.title": "Valid", "submission.sections.status.valid.title": "صالح", + + // "submission.sections.status.warnings.title": "Warnings", "submission.sections.status.warnings.title": "تحذيرات", - "submission.sections.status.errors.aria": "بسبب الأخطاء", + + // "submission.sections.status.errors.aria": "has errors", + "submission.sections.status.errors.aria": "به أخطاء", + + // "submission.sections.status.valid.aria": "is valid", "submission.sections.status.valid.aria": "صالح", + + // "submission.sections.status.warnings.aria": "has warnings", "submission.sections.status.warnings.aria": "ذو تحذيرات", - "submission.sections.status.info.title": "معلومات اضافية", - "submission.sections.status.info.aria": "معلومات اضافية", + + // "submission.sections.status.info.title": "Additional Information", + "submission.sections.status.info.title": "معلومات إضافية", + + // "submission.sections.status.info.aria": "Additional Information", + "submission.sections.status.info.aria": "معلومات إضافية", + + // "submission.sections.toggle.open": "Open section", "submission.sections.toggle.open": "فتح القسم", + + // "submission.sections.toggle.close": "Close section", "submission.sections.toggle.close": "إغلاق القسم", - "submission.sections.toggle.aria.open": "قسم النهائي {{sectionHeader}}", + + // "submission.sections.toggle.aria.open": "Expand {{sectionHeader}} section", + "submission.sections.toggle.aria.open": "توسيع قسم {{sectionHeader}}", + + // "submission.sections.toggle.aria.close": "Collapse {{sectionHeader}} section", "submission.sections.toggle.aria.close": "طي قسم {{sectionHeader}}", - "submission.sections.upload.primary.make": "يصنع {{fileName}} تيار البت الأساسي", - "submission.sections.upload.primary.remove": "يزيل {{fileName}} باعتباره دفق البت الأساسي", + + // "submission.sections.upload.primary.make": "Make {{fileName}} the primary bitstream", + // TODO New key - Add a translation + "submission.sections.upload.primary.make": "Make {{fileName}} the primary bitstream", + + // "submission.sections.upload.primary.remove": "Remove {{fileName}} as the primary bitstream", + // TODO New key - Add a translation + "submission.sections.upload.primary.remove": "Remove {{fileName}} as the primary bitstream", + + // "submission.sections.upload.delete.confirm.cancel": "Cancel", "submission.sections.upload.delete.confirm.cancel": "إلغاء", - "submission.sections.upload.delete.confirm.info": "لا يمكن السماء عن هذه الطريقة. ", - "submission.sections.upload.delete.confirm.submit": "نعم، بالتأكيد", + + // "submission.sections.upload.delete.confirm.info": "This operation can't be undone. Are you sure?", + "submission.sections.upload.delete.confirm.info": "لا يمكن التراجع عن هذه العملية. هل أنت متأكد؟", + + // "submission.sections.upload.delete.confirm.submit": "Yes, I'm sure", + "submission.sections.upload.delete.confirm.submit": "نعم، متأكد", + + // "submission.sections.upload.delete.confirm.title": "Delete bitstream", "submission.sections.upload.delete.confirm.title": "حذف تدفق البت", + + // "submission.sections.upload.delete.submit": "Delete", "submission.sections.upload.delete.submit": "حذف", + + // "submission.sections.upload.download.title": "Download bitstream", "submission.sections.upload.download.title": "تحميل تدفق البت", - "submission.sections.upload.drop-message": "قم بإسقاط الملفات لإختفاءها بالمادة", + + // "submission.sections.upload.drop-message": "Drop files to attach them to the item", + "submission.sections.upload.drop-message": "قم بإسقاط الملفات لإرفاقها بالمادة", + + // "submission.sections.upload.edit.title": "Edit bitstream", "submission.sections.upload.edit.title": "تحرير دفق البت", + + // "submission.sections.upload.form.access-condition-label": "Access condition type", "submission.sections.upload.form.access-condition-label": "نوع شرط الوصول", - "submission.sections.upload.form.access-condition-hint": "حدد شرط الوصول إليه على تدفق المادة بمجرد إيداعها", + + // "submission.sections.upload.form.access-condition-hint": "Select an access condition to apply on the bitstream once the item is deposited", + "submission.sections.upload.form.access-condition-hint": "حدد شرط الوصول لتطبيقه على تدفقات البت بمجرد إيداع المادة", + + // "submission.sections.upload.form.date-required": "Date is required.", "submission.sections.upload.form.date-required": "التاريخ مطلوب.", - "submission.sections.upload.form.date-required-from": "تاريخ منح الوصول قبل مطلوب.", + + // "submission.sections.upload.form.date-required-from": "Grant access from date is required.", + "submission.sections.upload.form.date-required-from": "تاريخ منح الوصول منذ مطلوب.", + + // "submission.sections.upload.form.date-required-until": "Grant access until date is required.", "submission.sections.upload.form.date-required-until": "تاريخ منح الوصول حتى مطلوب.", - "submission.sections.upload.form.from-label": "أمنح من الوصول", - "submission.sections.upload.form.from-hint": "حدد التاريخ الذي يتم فيه تطبيق شرط الوصول ذي الصلة منذ البداية", + + // "submission.sections.upload.form.from-label": "Grant access from", + "submission.sections.upload.form.from-label": "منح الوصول من", + + // "submission.sections.upload.form.from-hint": "Select the date from which the related access condition is applied", + "submission.sections.upload.form.from-hint": "حدد التاريخ الذي يتم تطبيق شرط الوصول ذي الصلة منذ بلوغه", + + // "submission.sections.upload.form.from-placeholder": "From", "submission.sections.upload.form.from-placeholder": "من", + + // "submission.sections.upload.form.group-label": "Group", "submission.sections.upload.form.group-label": "المجموعة", + + // "submission.sections.upload.form.group-required": "Group is required.", "submission.sections.upload.form.group-required": "المجموعة مطلوبة.", - "submission.sections.upload.form.until-label": "أمنح حتى الوصول", - "submission.sections.upload.form.until-hint": "حدد التاريخ الذي يتم فيه تطبيق شرط الوصول ذي الصلة حتى المضي قدمًا", + + // "submission.sections.upload.form.until-label": "Grant access until", + "submission.sections.upload.form.until-label": "منح الوصول حتى", + + // "submission.sections.upload.form.until-hint": "Select the date until which the related access condition is applied", + "submission.sections.upload.form.until-hint": "حدد التاريخ الذي يتم تطبيق شرط الوصول ذي الصلة حتى بلوغه", + + // "submission.sections.upload.form.until-placeholder": "Until", "submission.sections.upload.form.until-placeholder": "حتى", - "submission.sections.upload.header.policy.default.nolist": "ستكون الإجراءات المرفوعة في الكائنات الحية {{collectionName}} لا يمكن الوصول إلى المجموعات التالية:", - "submission.sections.upload.header.policy.default.withlist": "يرجى ملاحظة أن الملفات المرفوعة في الحاوية {{collectionName}} ستكون قادرة على الوصول، بالإضافة إلى ما يقرر بوضوح للملف المفرد، مع المجموعات التالية:", - "submission.sections.upload.info": "مساهمة هنا في كل القضايا الموجودة في المادة حاليا. تحميل الملفات الإضافية عن طريق سحبها وتسجيلها في أي مكان في الصفحة", + + // "submission.sections.upload.header.policy.default.nolist": "Uploaded files in the {{collectionName}} collection will be accessible according to the following group(s):", + "submission.sections.upload.header.policy.default.nolist": "ستكون الملفات المرفوعة في الحاوية {{collectionName}} قابلة للوصول وفقًا للمجموعات التالية:", + + // "submission.sections.upload.header.policy.default.withlist": "Please note that uploaded files in the {{collectionName}} collection will be accessible, in addition to what is explicitly decided for the single file, with the following group(s):", + "submission.sections.upload.header.policy.default.withlist": "يرجى ملاحظة أن الملفات المرفوعة في حاوية {{collectionName}} ستكون قابلة للوصول، بالإضافة إلى ما تقرر بوضوح للملف المفرد، مع المجموعات التالية:", + + // "submission.sections.upload.info": "Here you will find all the files currently in the item. You can update the file metadata and access conditions or upload additional files by dragging & dropping them anywhere on the page.", + "submission.sections.upload.info": "ستجد هنا كل الملفات الموجودة في المادة حاليًا. يمكنك تحديث ميتاداتا الملف وشروط الوصول أو تحميل ملفات إضافية عن طريق سحبها وإسقاطها في أي مكان في الصفحة", + + // "submission.sections.upload.no-entry": "No", "submission.sections.upload.no-entry": "لا", + + // "submission.sections.upload.no-file-uploaded": "No file uploaded yet.", "submission.sections.upload.no-file-uploaded": "لم يتم تحميل أي ملف حتى الآن.", + + // "submission.sections.upload.save-metadata": "Save metadata", "submission.sections.upload.save-metadata": "حفظ الميتاداتا", + + // "submission.sections.upload.undo": "Cancel", "submission.sections.upload.undo": "إلغاء", + + // "submission.sections.upload.upload-failed": "Upload failed", "submission.sections.upload.upload-failed": "فشل التحميل", - "submission.sections.upload.upload-successful": "بدأ التحميل", - "submission.sections.accesses.form.discoverable-description": "عند التحديد، ستكون هذه المادة قابلة للاكتشاف في البحث/الاستعراض. ", + + // "submission.sections.upload.upload-successful": "Upload successful", + "submission.sections.upload.upload-successful": "نجح التحميل", + + // "submission.sections.accesses.form.discoverable-description": "When checked, this item will be discoverable in search/browse. When unchecked, the item will only be available via a direct link and will never appear in search/browse.", + "submission.sections.accesses.form.discoverable-description": "عند التحديد، ستكون هذه المادة قابلة للاكتشاف في البحث/الاستعراض. عند إلغاء التحديد، ستكون المادة متاحة فقط عبر رابط مباشر ولن تظهر أبدًا في البحث/الاستعراض.", + + // "submission.sections.accesses.form.discoverable-label": "Discoverable", "submission.sections.accesses.form.discoverable-label": "قابل للاكتشاف", + + // "submission.sections.accesses.form.access-condition-label": "Access condition type", "submission.sections.accesses.form.access-condition-label": "نوع شرط الوصول", - "submission.sections.accesses.form.access-condition-hint": "حدد شرط الوصول إلى المادة بمجرد إيداعها", + + // "submission.sections.accesses.form.access-condition-hint": "Select an access condition to apply on the item once it is deposited", + "submission.sections.accesses.form.access-condition-hint": "حدد شرط الوصول لتطبيقه على المادة بمجرد إيداعها", + + // "submission.sections.accesses.form.date-required": "Date is required.", "submission.sections.accesses.form.date-required": "التاريخ مطلوب.", - "submission.sections.accesses.form.date-required-from": "تاريخ منح الوصول قبل مطلوب.", + + // "submission.sections.accesses.form.date-required-from": "Grant access from date is required.", + "submission.sections.accesses.form.date-required-from": "تاريخ منح الوصول منذ مطلوب.", + + // "submission.sections.accesses.form.date-required-until": "Grant access until date is required.", "submission.sections.accesses.form.date-required-until": "تاريخ منح الوصول حتى مطلوب.", - "submission.sections.accesses.form.from-label": "منح قبل الوصول", + + // "submission.sections.accesses.form.from-label": "Grant access from", + "submission.sections.accesses.form.from-label": "منح الوصول منذ", + + // "submission.sections.accesses.form.from-hint": "Select the date from which the related access condition is applied", "submission.sections.accesses.form.from-hint": "حدد التاريخ الذي يتم فيه تطبيق شرط الوصول ذي الصلة", + + // "submission.sections.accesses.form.from-placeholder": "From", "submission.sections.accesses.form.from-placeholder": "من", + + // "submission.sections.accesses.form.group-label": "Group", "submission.sections.accesses.form.group-label": "المجموعة", + + // "submission.sections.accesses.form.group-required": "Group is required.", "submission.sections.accesses.form.group-required": "المجموعة مطلوبة.", - "submission.sections.accesses.form.until-label": "أمنح حتى الوصول", - "submission.sections.accesses.form.until-hint": "حدد التاريخ الذي يتم فيه تطبيق شرط الوصول ذي الصلة حتى المضي قدمًا", + + // "submission.sections.accesses.form.until-label": "Grant access until", + "submission.sections.accesses.form.until-label": "منح الوصول حتى", + + // "submission.sections.accesses.form.until-hint": "Select the date until which the related access condition is applied", + "submission.sections.accesses.form.until-hint": "حدد التاريخ الذي يتم تطبيق شرط الوصول ذي الصلة حتى بلوغه", + + // "submission.sections.accesses.form.until-placeholder": "Until", "submission.sections.accesses.form.until-placeholder": "حتى", - "submission.sections.duplicates.none": "لم يتم اكتشاف أي تكرارات.", - "submission.sections.duplicates.detected": "تم الكشف عن التكرارات المحتملة. ", - "submission.sections.duplicates.in-workspace": "هذا العنصر موجود في مساحة العمل", - "submission.sections.duplicates.in-workflow": "هذا العنصر في سير العمل", - "submission.sections.license.granted-label": "وأرجح ذلك", - "submission.sections.license.required": "يجب عليك معارضة", - "submission.sections.license.notgranted": "يجب عليك معارضة", + + // "submission.sections.duplicates.none": "No duplicates were detected.", + // TODO New key - Add a translation + "submission.sections.duplicates.none": "No duplicates were detected.", + + // "submission.sections.duplicates.detected": "Potential duplicates were detected. Please review the list below.", + // TODO New key - Add a translation + "submission.sections.duplicates.detected": "Potential duplicates were detected. Please review the list below.", + + // "submission.sections.duplicates.in-workspace": "This item is in workspace", + // TODO New key - Add a translation + "submission.sections.duplicates.in-workspace": "This item is in workspace", + + // "submission.sections.duplicates.in-workflow": "This item is in workflow", + // TODO New key - Add a translation + "submission.sections.duplicates.in-workflow": "This item is in workflow", + + // "submission.sections.license.granted-label": "I confirm the license above", + "submission.sections.license.granted-label": "أؤكد الترخيص أعلاه", + + // "submission.sections.license.required": "You must accept the license", + "submission.sections.license.required": "يجب عليك قبول الترخيص", + + // "submission.sections.license.notgranted": "You must accept the license", + "submission.sections.license.notgranted": "يجب عليك قبول الترخيص", + + // "submission.sections.sherpa.publication.information": "Publication information", "submission.sections.sherpa.publication.information": "معلومات الناشر", - "submission.sections.sherpa.publication.information.title": "عنوان العنوان", + + // "submission.sections.sherpa.publication.information.title": "Title", + "submission.sections.sherpa.publication.information.title": "العنوان", + + // "submission.sections.sherpa.publication.information.issns": "ISSNs", "submission.sections.sherpa.publication.information.issns": "أرقام ردمد", + + // "submission.sections.sherpa.publication.information.url": "URL", "submission.sections.sherpa.publication.information.url": "عنوان URL", + + // "submission.sections.sherpa.publication.information.publishers": "Publisher", "submission.sections.sherpa.publication.information.publishers": "الناشر", - "submission.sections.sherpa.publication.information.romeoPub": "حانة روميو", - "submission.sections.sherpa.publication.information.zetoPub": "حانة زيتو", - "submission.sections.sherpa.publisher.policy": "للناشر", - "submission.sections.sherpa.publisher.policy.description": "تم العثور على المعلومات أدناه عبر شيربا روميو. ", - "submission.sections.sherpa.publisher.policy.openaccess": "مسارات الوصول الحر التي تتيح لها هذه الدورية المدرجة أدناه حسب إصدار المقال. ", - "submission.sections.sherpa.publisher.policy.more.information": "لمزيد من المعلومات، يرجى الاطلاع على الروابط التالية:", - "submission.sections.sherpa.publisher.policy.version": "النسخة", + + // "submission.sections.sherpa.publication.information.romeoPub": "Romeo Pub", + "submission.sections.sherpa.publication.information.romeoPub": "Romeo Pub", + + // "submission.sections.sherpa.publication.information.zetoPub": "Zeto Pub", + "submission.sections.sherpa.publication.information.zetoPub": "Zeto Pub", + + // "submission.sections.sherpa.publisher.policy": "Publisher Policy", + "submission.sections.sherpa.publisher.policy": "سياسة الناشر", + + // "submission.sections.sherpa.publisher.policy.description": "The below information was found via Sherpa Romeo. Based on the policies of your publisher, it provides advice regarding whether an embargo may be necessary and/or which files you are allowed to upload. If you have questions, please contact your site administrator via the feedback form in the footer.", + "submission.sections.sherpa.publisher.policy.description": "تم العثور على المعلومات أدناه عبر شيربا روميو. وبناءً على سياسات الناشر الخاص بك، فإنه يقدم النصائح بشأن ما إذا كان الحظر ضروريًا أو الملفات المسموح لك بتحميلها. إذا كانت لديك أسئلة، يرجى الاتصال بمسؤول موقعك عبر نموذج التعليقات الموجود في التذييل.", + + // "submission.sections.sherpa.publisher.policy.openaccess": "Open Access pathways permitted by this journal's policy are listed below by article version. Click on a pathway for a more detailed view", + "submission.sections.sherpa.publisher.policy.openaccess": "مسارات الوصول الحر التي تسمح بها سياسة هذه الدورية مدرجة أدناه حسب إصدار المقال. انقر على المسار للحصول على عرض أكثر تفصيلاً", + + // "submission.sections.sherpa.publisher.policy.more.information": "For more information, please see the following links:", + "submission.sections.sherpa.publisher.policy.more.information": "للمزيد من المعلومات، يرجى الاطلاع على الروابط التالية:", + + // "submission.sections.sherpa.publisher.policy.version": "Version", + "submission.sections.sherpa.publisher.policy.version": "الإصدارة", + + // "submission.sections.sherpa.publisher.policy.embargo": "Embargo", "submission.sections.sherpa.publisher.policy.embargo": "حظر", + + // "submission.sections.sherpa.publisher.policy.noembargo": "No Embargo", "submission.sections.sherpa.publisher.policy.noembargo": "بلا حظر", + + // "submission.sections.sherpa.publisher.policy.nolocation": "None", "submission.sections.sherpa.publisher.policy.nolocation": "لا شيء", - "submission.sections.sherpa.publisher.policy.license": "com", + + // "submission.sections.sherpa.publisher.policy.license": "License", + "submission.sections.sherpa.publisher.policy.license": "الترخيص", + + // "submission.sections.sherpa.publisher.policy.prerequisites": "Prerequisites", "submission.sections.sherpa.publisher.policy.prerequisites": "المتطلبات الأساسية", + + // "submission.sections.sherpa.publisher.policy.location": "Location", "submission.sections.sherpa.publisher.policy.location": "الموقع", + + // "submission.sections.sherpa.publisher.policy.conditions": "Conditions", "submission.sections.sherpa.publisher.policy.conditions": "الشروط", + + // "submission.sections.sherpa.publisher.policy.refresh": "Refresh", "submission.sections.sherpa.publisher.policy.refresh": "تحديث", - "submission.sections.sherpa.record.information": "تسجيل المعلومات", + + // "submission.sections.sherpa.record.information": "Record Information", + "submission.sections.sherpa.record.information": "معلومات التسجيلة", + + // "submission.sections.sherpa.record.information.id": "ID", "submission.sections.sherpa.record.information.id": "المعرّف", + + // "submission.sections.sherpa.record.information.date.created": "Date Created", "submission.sections.sherpa.record.information.date.created": "تاريخ الإنشاء", + + // "submission.sections.sherpa.record.information.date.modified": "Last Modified", "submission.sections.sherpa.record.information.date.modified": "آخر تعديل", + + // "submission.sections.sherpa.record.information.uri": "URI", "submission.sections.sherpa.record.information.uri": "URI", - "submission.sections.sherpa.error.message": "حدث خطأ أثناء حذف معلومات شيربا", + + // "submission.sections.sherpa.error.message": "There was an error retrieving sherpa informations", + "submission.sections.sherpa.error.message": "حدث خطأ أثناء استرداد معلومات شيربا", + + // "submission.submit.breadcrumbs": "New submission", "submission.submit.breadcrumbs": "تقديم جديد", + + // "submission.submit.title": "New submission", "submission.submit.title": "تقديم جديد", + + // "submission.workflow.generic.delete": "Delete", "submission.workflow.generic.delete": "حذف", - "submission.workflow.generic.delete-help": "حدد هذا الخيار لتجاهل هذه المادة. ", + + // "submission.workflow.generic.delete-help": "Select this option to discard this item. You will then be asked to confirm it.", + "submission.workflow.generic.delete-help": "حدد هذا الخيار لتجاهل هذه المادة. سيُطلب منك بعد ذلك تأكيد ذلك.", + + // "submission.workflow.generic.edit": "Edit", "submission.workflow.generic.edit": "تحرير", - "submission.workflow.generic.edit-help": "حدد هذا الخيار لتكوين المادة.", + + // "submission.workflow.generic.edit-help": "Select this option to change the item's metadata.", + "submission.workflow.generic.edit-help": "حدد هذا الخيار لتغيير ميتاداتا المادة.", + + // "submission.workflow.generic.view": "View", "submission.workflow.generic.view": "عرض", + + // "submission.workflow.generic.view-help": "Select this option to view the item's metadata.", "submission.workflow.generic.view-help": "حدد هذا الخيار لعرض ميتاداتا المادة.", + + // "submission.workflow.generic.submit_select_reviewer": "Select Reviewer", "submission.workflow.generic.submit_select_reviewer": "حدد المراجع", + + // "submission.workflow.generic.submit_select_reviewer-help": "", "submission.workflow.generic.submit_select_reviewer-help": "", + + // "submission.workflow.generic.submit_score": "Rate", "submission.workflow.generic.submit_score": "تقييم", + + // "submission.workflow.generic.submit_score-help": "", "submission.workflow.generic.submit_score-help": "", - "submission.workflow.tasks.claimed.approve": "أوافق", - "submission.workflow.tasks.claimed.approve_help": "إذا قمت بمراجعة المادة الداخلية للاستهلاك الغذائي، اختر \"قبول\".", + + // "submission.workflow.tasks.claimed.approve": "Approve", + "submission.workflow.tasks.claimed.approve": "قبول", + + // "submission.workflow.tasks.claimed.approve_help": "If you have reviewed the item and it is suitable for inclusion in the collection, select \"Approve\".", + "submission.workflow.tasks.claimed.approve_help": "إذا قمت بمراجعة المادة وكانت ملائمة للإدراج في الحاوية، اختر \"قبول\".", + + // "submission.workflow.tasks.claimed.edit": "Edit", "submission.workflow.tasks.claimed.edit": "تحرير", - "submission.workflow.tasks.claimed.edit_help": "سيقوم هذا الخيار بتغيير المادة.", - "submission.workflow.tasks.claimed.decline": "الرفض", + + // "submission.workflow.tasks.claimed.edit_help": "Select this option to change the item's metadata.", + "submission.workflow.tasks.claimed.edit_help": "قم بتحديد هذا الخيار لتغيير ميتاداتا المادة.", + + // "submission.workflow.tasks.claimed.decline": "Decline", + "submission.workflow.tasks.claimed.decline": "رفض", + + // "submission.workflow.tasks.claimed.decline_help": "", "submission.workflow.tasks.claimed.decline_help": "", - "submission.workflow.tasks.claimed.reject.reason.info": "يرجي التسجيل سبب الرفض في القسم أدناه، وقم بتوضيح ما إذا كان بإمكانه تصحيح المشكلة لتقديم الطلب.", + + // "submission.workflow.tasks.claimed.reject.reason.info": "Please enter your reason for rejecting the submission into the box below, indicating whether the submitter may fix a problem and resubmit.", + "submission.workflow.tasks.claimed.reject.reason.info": "يرجي إدخال سبب رفض التقديم في المربع أدناه، وقم بتوضيح ما إذا كان بإمكان المقدم تصحيح المشكلة وإعادة التقديم.", + + // "submission.workflow.tasks.claimed.reject.reason.placeholder": "Describe the reason of reject", "submission.workflow.tasks.claimed.reject.reason.placeholder": "قم بوصف سبب الرفض", - "submission.workflow.tasks.claimed.reject.reason.submit": "الموافقة على المادة", - "submission.workflow.tasks.claimed.reject.reason.title": "هذا", - "submission.workflow.tasks.claimed.reject.submit": "الرفض", - "submission.workflow.tasks.claimed.reject_help": "إذا قمت بمراجعة المادة وجدتها غير وجزء للإدراج في الصغار، اختر \"رفض\". ", + + // "submission.workflow.tasks.claimed.reject.reason.submit": "Reject item", + "submission.workflow.tasks.claimed.reject.reason.submit": "رفض المادة", + + // "submission.workflow.tasks.claimed.reject.reason.title": "Reason", + "submission.workflow.tasks.claimed.reject.reason.title": "السبب", + + // "submission.workflow.tasks.claimed.reject.submit": "Reject", + "submission.workflow.tasks.claimed.reject.submit": "رفض", + + // "submission.workflow.tasks.claimed.reject_help": "If you have reviewed the item and found it is not suitable for inclusion in the collection, select \"Reject\". You will then be asked to enter a message indicating why the item is unsuitable, and whether the submitter should change something and resubmit.", + "submission.workflow.tasks.claimed.reject_help": "إذا قمت بمراجعة المادة ووجدتها غير ملائمة للإدراج في الحاوية، اختر \"رفض\". سيُطلب منك إدخال رسالة لتوضيح سبب عدم ملاءمة المادة، وما إذا كان يجب على المقدم إجراء بعض التغييرات وإعادة التقديم.", + + // "submission.workflow.tasks.claimed.return": "Return to pool", "submission.workflow.tasks.claimed.return": "إعادة إلى الصحن", - "submission.workflow.tasks.claimed.return_help": "إعادة مهمة إلى السخن لكي يقوم مستخدم آخر المهرج.", - "submission.workflow.tasks.generic.error": "حدث خطأ أثناء...", - "submission.workflow.tasks.generic.processing": "جاريب...", - "submission.workflow.tasks.generic.submitter": "شير", - "submission.workflow.tasks.generic.success": "فعال", + + // "submission.workflow.tasks.claimed.return_help": "Return the task to the pool so that another user may perform the task.", + "submission.workflow.tasks.claimed.return_help": "إعادة المهمة إلى الصحن لكي يقوم مستخدم آخر بأداء المهمة.", + + // "submission.workflow.tasks.generic.error": "Error occurred during operation...", + "submission.workflow.tasks.generic.error": "حدث خطأ أثناء العملية...", + + // "submission.workflow.tasks.generic.processing": "Processing...", + "submission.workflow.tasks.generic.processing": "جاري المعالجة...", + + // "submission.workflow.tasks.generic.submitter": "Submitter", + "submission.workflow.tasks.generic.submitter": "المقدم", + + // "submission.workflow.tasks.generic.success": "Operation successful", + "submission.workflow.tasks.generic.success": "تمت العملية بنجاح", + + // "submission.workflow.tasks.pool.claim": "Claim", "submission.workflow.tasks.pool.claim": "مطالبة", - "submission.workflow.tasks.pool.claim_help": "قم بهذه المهمة لأجلك.", - "submission.workflow.tasks.pool.hide-detail": "حفظ التفاصيل", + + // "submission.workflow.tasks.pool.claim_help": "Assign this task to yourself.", + "submission.workflow.tasks.pool.claim_help": "قم بتعيين هذه المهمة لنفسك.", + + // "submission.workflow.tasks.pool.hide-detail": "Hide detail", + "submission.workflow.tasks.pool.hide-detail": "إخفاء التفاصيل", + + // "submission.workflow.tasks.pool.show-detail": "Show detail", "submission.workflow.tasks.pool.show-detail": "عرض التفاصيل", - "submission.workflow.tasks.duplicates": "تم الكشف عن التكرارات المحتملة لهذا العنصر. ", + + // "submission.workflow.tasks.duplicates": "potential duplicates were detected for this item. Claim and edit this item to see details.", + // TODO New key - Add a translation + "submission.workflow.tasks.duplicates": "potential duplicates were detected for this item. Claim and edit this item to see details.", + + // "submission.workspace.generic.view": "View", "submission.workspace.generic.view": "عرض", + + // "submission.workspace.generic.view-help": "Select this option to view the item's metadata.", "submission.workspace.generic.view-help": "حدد هذا الخيار لعرض ميتاداتا المادة.", - "submitter.empty": "غير محتمل", + + // "submitter.empty": "N/A", + "submitter.empty": "غير قابل للتطبيق", + + // "subscriptions.title": "Subscriptions", "subscriptions.title": "الاشتراكات", - "subscriptions.item": "الاشتراكات للمواد", + + // "subscriptions.item": "Subscriptions for items", + "subscriptions.item": "اشتراكات للمواد", + + // "subscriptions.collection": "Subscriptions for collections", "subscriptions.collection": "اشتراكات للحاويات", - "subscriptions.community": "الاشتراكات المتاحة", + + // "subscriptions.community": "Subscriptions for communities", + "subscriptions.community": "اشتراكات للمجتمعات", + + // "subscriptions.subscription_type": "Subscription type", "subscriptions.subscription_type": "نوع الاشتراك", + + // "subscriptions.frequency": "Subscription frequency", "subscriptions.frequency": "تواتر الاشتراك", + + // "subscriptions.frequency.D": "Daily", "subscriptions.frequency.D": "يومي", + + // "subscriptions.frequency.M": "Monthly", "subscriptions.frequency.M": "شهري", + + // "subscriptions.frequency.W": "Weekly", "subscriptions.frequency.W": "أسبوعي", + + // "subscriptions.tooltip": "Subscribe", "subscriptions.tooltip": "اشتراك", + + // "subscriptions.modal.title": "Subscriptions", "subscriptions.modal.title": "الاشتراكات", + + // "subscriptions.modal.type-frequency": "Type and frequency", "subscriptions.modal.type-frequency": "النوع والتواتر", + + // "subscriptions.modal.close": "Close", "subscriptions.modal.close": "إغلاق", - "subscriptions.modal.delete-info": "إزالة هذا الاشتراك، يرجى زيارة صفحة \"الاشتراكات\" أدنى ملف تعريف المستخدم الخاص بك", - "subscriptions.modal.new-subscription-form.type.content": "ال", + + // "subscriptions.modal.delete-info": "To remove this subscription, please visit the \"Subscriptions\" page under your user profile", + "subscriptions.modal.delete-info": "لإزالة هذا الاشتراك، يرجى زيارة صفحة \"الاشتراكات\" أدنى ملف تعريف المستخدم الخاص بك", + + // "subscriptions.modal.new-subscription-form.type.content": "Content", + "subscriptions.modal.new-subscription-form.type.content": "المحتوى", + + // "subscriptions.modal.new-subscription-form.frequency.D": "Daily", "subscriptions.modal.new-subscription-form.frequency.D": "يومي", + + // "subscriptions.modal.new-subscription-form.frequency.W": "Weekly", "subscriptions.modal.new-subscription-form.frequency.W": "أسبوعي", + + // "subscriptions.modal.new-subscription-form.frequency.M": "Monthly", "subscriptions.modal.new-subscription-form.frequency.M": "شهري", + + // "subscriptions.modal.new-subscription-form.submit": "Submit", "subscriptions.modal.new-subscription-form.submit": "تقديم", - "subscriptions.modal.new-subscription-form.processing": "جاريب...", - "subscriptions.modal.create.success": "تم الاشتراك في {{type}} فعالية.", - "subscriptions.modal.delete.success": "تم حذف الاشتراك الفعال", - "subscriptions.modal.update.success": "تم تحديث الاشتراك في {{type}} فعالية", + + // "subscriptions.modal.new-subscription-form.processing": "Processing...", + "subscriptions.modal.new-subscription-form.processing": "جاري المعالجة...", + + // "subscriptions.modal.create.success": "Subscribed to {{ type }} successfully.", + "subscriptions.modal.create.success": "تم الاشتراك في {{type}} بنجاح.", + + // "subscriptions.modal.delete.success": "Subscription deleted successfully", + "subscriptions.modal.delete.success": "تم حذف الاشتراك بنجاح", + + // "subscriptions.modal.update.success": "Subscription to {{ type }} updated successfully", + "subscriptions.modal.update.success": "تم تحديث الاشتراك في {{type}} بنجاح", + + // "subscriptions.modal.create.error": "An error occurs during the subscription creation", "subscriptions.modal.create.error": "حدث خطأ أثناء إنشاء الاشتراك", + + // "subscriptions.modal.delete.error": "An error occurs during the subscription delete", "subscriptions.modal.delete.error": "حدث خطأ أثناء حذف الاشتراك", + + // "subscriptions.modal.update.error": "An error occurs during the subscription update", "subscriptions.modal.update.error": "حدث خطأ أثناء تحديث الاشتراك", + + // "subscriptions.table.dso": "Subject", "subscriptions.table.dso": "الموضوع", + + // "subscriptions.table.subscription_type": "Subscription Type", "subscriptions.table.subscription_type": "نوع الاشتراك", + + // "subscriptions.table.subscription_frequency": "Subscription Frequency", "subscriptions.table.subscription_frequency": "تواتر الاشتراك", - "subscriptions.table.action": "صنع", + + // "subscriptions.table.action": "Action", + "subscriptions.table.action": "إجراء", + + // "subscriptions.table.edit": "Edit", "subscriptions.table.edit": "تحرير", + + // "subscriptions.table.delete": "Delete", "subscriptions.table.delete": "حذف", + + // "subscriptions.table.not-available": "Not available", "subscriptions.table.not-available": "غير متاح", - "subscriptions.table.not-available-message": "تم حذف مادة الاشتراك، أو ليس لديك صلاحية حاليا لمشاهدتها", - "subscriptions.table.empty.message": "ليس لديك أي اشتراك في هذا الوقت. ", + + // "subscriptions.table.not-available-message": "The subscribed item has been deleted, or you don't currently have the permission to view it", + "subscriptions.table.not-available-message": "تم حذف مادة الاشتراك، أو ليس لديك صلاحية حالياً لمشاهدتها", + + // "subscriptions.table.empty.message": "You do not have any subscriptions at this time. To subscribe to email updates for a Community or Collection, use the subscription button on the object's page.", + "subscriptions.table.empty.message": "ليس لديك أي اشتراكات في هذا الوقت. للاشتراك في تحديثات البريد الإلكتروني لمجتمع أو حاوية، استخدم زر الاشتراك الموجود في صفحة الكائن.", + + // "thumbnail.default.alt": "Thumbnail Image", "thumbnail.default.alt": "صورة مصغرة", - "thumbnail.default.placeholder": "لا اختيار صورة مصغرة", + + // "thumbnail.default.placeholder": "No Thumbnail Available", + "thumbnail.default.placeholder": "لا تتوفر صورة مصغرة", + + // "thumbnail.project.alt": "Project Logo", "thumbnail.project.alt": "شعار المشروع", - "thumbnail.project.placeholder": "صورة كمساهمة في المساهمة", - "thumbnail.orgunit.alt": "الشعار الوطني الوطني", - "thumbnail.orgunit.placeholder": "صورة الكارب النائي للوحدة الوطنية", + + // "thumbnail.project.placeholder": "Project Placeholder Image", + "thumbnail.project.placeholder": "صورة العنصر النائب للمشروع", + + // "thumbnail.orgunit.alt": "OrgUnit Logo", + "thumbnail.orgunit.alt": "شعار الوحدة المؤسسية", + + // "thumbnail.orgunit.placeholder": "OrgUnit Placeholder Image", + "thumbnail.orgunit.placeholder": "صورة العنصر النائي للوحدة المؤسسية", + + // "thumbnail.person.alt": "Profile Picture", "thumbnail.person.alt": "صورة الملف الشخصي", - "thumbnail.person.placeholder": "عدم توفر صورة للملف الشخصي", + + // "thumbnail.person.placeholder": "No Profile Picture Available", + "thumbnail.person.placeholder": "لا تتوافر صورة للملف الشخصي", + + // "title": "DSpace", "title": "دي سبيس", + + // "vocabulary-treeview.header": "Hierarchical tree view", "vocabulary-treeview.header": "عرض الشجرة الهرمية", + + // "vocabulary-treeview.load-more": "Load more", "vocabulary-treeview.load-more": "تحميل المزيد", + + // "vocabulary-treeview.search.form.reset": "Reset", "vocabulary-treeview.search.form.reset": "إعادة تعيين", + + // "vocabulary-treeview.search.form.search": "Search", "vocabulary-treeview.search.form.search": "بحث", - "vocabulary-treeview.search.form.search-placeholder": "تسهيل البحث عن طريق كتابة الرواية الأولى", + + // "vocabulary-treeview.search.form.search-placeholder": "Filter results by typing the first few letters", + "vocabulary-treeview.search.form.search-placeholder": "تنقيح النتائج عن طريق كتابة الأحرف الأولى", + + // "vocabulary-treeview.search.no-result": "There were no items to show", "vocabulary-treeview.search.no-result": "لم تكن هناك مواد للعرض", - "vocabulary-treeview.tree.description.nsi": "فرس العلوم النرويجي", - "vocabulary-treeview.tree.description.srsc": "موضوع البحث", - "vocabulary-treeview.info": "قم بزيارة موضوع لإضافته كمنقح بحثه", + + // "vocabulary-treeview.tree.description.nsi": "The Norwegian Science Index", + "vocabulary-treeview.tree.description.nsi": "فهرس العلوم النرويجي", + + // "vocabulary-treeview.tree.description.srsc": "Research Subject Categories", + "vocabulary-treeview.tree.description.srsc": "فئات موضوع البحث", + + // "vocabulary-treeview.info": "Select a subject to add as search filter", + "vocabulary-treeview.info": "قم بتحديد موضوع لإضافته كمنقح بحث", + + // "uploader.browse": "browse", "uploader.browse": "استعراض", - "uploader.drag-message": "قم بسحب وتسجيل ملفاتك هنا", + + // "uploader.drag-message": "Drag & Drop your files here", + "uploader.drag-message": "قم بسحب وإسقاط ملفاتك هنا", + + // "uploader.delete.btn-title": "Delete", "uploader.delete.btn-title": "حذف", + + // "uploader.or": ", or ", "uploader.or": ", أو ", - "uploader.processing": "الملفات الجارية التي تم تحميلها... (أصبح من الآن ينتهك هذه الصفحة)", + + // "uploader.processing": "Processing uploaded file(s)... (it's now safe to close this page)", + "uploader.processing": "جاري معالجة الملفات التي تم تحميلها... (أصبح من الآمن الآن إغلاق هذه الصفحة)", + + // "uploader.queue-length": "Queue length", "uploader.queue-length": "طول الصف", - "virtual-metadata.delete-item.info": "قم باختيار الأنواع التي تريد حفظ الميتاداتا لاستخدامها كميتاداتا فعلية", - "virtual-metadata.delete-item.modal-head": "استخدامات مفيدة لهذه المصالح", - "virtual-metadata.delete-relationship.modal-head": "قم بشراء المواد التي تريد حفظ الميتاداتا لاستخدامها كميتاداتا فعلية", - "supervisedWorkspace.search.results.head": "منتج للإشراف", + + // "virtual-metadata.delete-item.info": "Select the types for which you want to save the virtual metadata as real metadata", + "virtual-metadata.delete-item.info": "قم بتحديد الأنواع التي تريد حفظ الميتاداتا الافتراضية لها كميتاداتا فعلية", + + // "virtual-metadata.delete-item.modal-head": "The virtual metadata of this relation", + "virtual-metadata.delete-item.modal-head": "الميتاداتا الافتراضية لهذه العلاقة", + + // "virtual-metadata.delete-relationship.modal-head": "Select the items for which you want to save the virtual metadata as real metadata", + "virtual-metadata.delete-relationship.modal-head": "قم بتحديد المواد التي تريد حفظ الميتاداتا الافتراضية لها كميتاداتا فعلية", + + // "supervisedWorkspace.search.results.head": "Supervised Items", + "supervisedWorkspace.search.results.head": "مواد خاضعة للإشراف", + + // "workspace.search.results.head": "Your submissions", "workspace.search.results.head": "تقديمات", + + // "workflowAdmin.search.results.head": "Administer Workflow", "workflowAdmin.search.results.head": "أدر سير العمل", + + // "workflow.search.results.head": "Workflow tasks", "workflow.search.results.head": "مهام سير العمل", + + // "supervision.search.results.head": "Workflow and Workspace tasks", "supervision.search.results.head": "مهام سير العمل ومساحة العمل", - "orgunit.search.results.head": "نتائج البحث الوطني", - "workflow-item.edit.breadcrumbs": "تحرير سير العمل", - "workflow-item.edit.title": "تحرير سير العمل", + + // "orgunit.search.results.head": "Organizational Unit Search Results", + "orgunit.search.results.head": "نتائج بحث الوحدات المؤسسية", + + // "workflow-item.edit.breadcrumbs": "Edit workflowitem", + "workflow-item.edit.breadcrumbs": "تحرير مادة سير العمل", + + // "workflow-item.edit.title": "Edit workflowitem", + "workflow-item.edit.title": "تحرير مادة سير العمل", + + // "workflow-item.delete.notification.success.title": "Deleted", "workflow-item.delete.notification.success.title": "تم الحذف", - "workflow-item.delete.notification.success.content": "تم حذف المادة سير العمل هذه فعالة", + + // "workflow-item.delete.notification.success.content": "This workflow item was successfully deleted", + "workflow-item.delete.notification.success.content": "تم حذف مادة سير العمل هذه بنجاح", + + // "workflow-item.delete.notification.error.title": "Something went wrong", "workflow-item.delete.notification.error.title": "لقد حدث خطأ ما", - "workflow-item.delete.notification.error.content": "عذر حذف سير العمل", - "workflow-item.delete.title": "حذف سير العمل", - "workflow-item.delete.header": "حذف سير العمل", + + // "workflow-item.delete.notification.error.content": "The workflow item could not be deleted", + "workflow-item.delete.notification.error.content": "تعذر حذف مادة سير العمل", + + // "workflow-item.delete.title": "Delete workflow item", + "workflow-item.delete.title": "حذف مادة سير العمل", + + // "workflow-item.delete.header": "Delete workflow item", + "workflow-item.delete.header": "حذف مادة سير العمل", + + // "workflow-item.delete.button.cancel": "Cancel", "workflow-item.delete.button.cancel": "إلغاء", + + // "workflow-item.delete.button.confirm": "Delete", "workflow-item.delete.button.confirm": "حذف", - "workflow-item.send-back.notification.success.title": "إرسال إعادة إلى الأمام", - "workflow-item.send-back.notification.success.content": "أكمل إعادة صياغة سير العمل إلى هذه الإجراءات الفعالة", + + // "workflow-item.send-back.notification.success.title": "Sent back to submitter", + "workflow-item.send-back.notification.success.title": "إعادة إرسال إلى المقدم", + + // "workflow-item.send-back.notification.success.content": "This workflow item was successfully sent back to the submitter", + "workflow-item.send-back.notification.success.content": "تمت إعادة إرسال مادة سير العمل هذه إلى المقدم بنجاح", + + // "workflow-item.send-back.notification.error.title": "Something went wrong", "workflow-item.send-back.notification.error.title": "لقد حدث خطأ ما", - "workflow-item.send-back.notification.error.content": "تعذر إعادة إرسال المادة سير العمل إلى الأمام", - "workflow-item.send-back.title": "إرسال إعادة مادة سير العمل إلى شير", - "workflow-item.send-back.header": "إرسال إعادة مادة سير العمل إلى شير", + + // "workflow-item.send-back.notification.error.content": "The workflow item could not be sent back to the submitter", + "workflow-item.send-back.notification.error.content": "تعذر إعادة إرسال مادة سير العمل إلى المقدم", + + // "workflow-item.send-back.title": "Send workflow item back to submitter", + "workflow-item.send-back.title": "إعادة إرسال مادة سير العمل إلى المقدم", + + // "workflow-item.send-back.header": "Send workflow item back to submitter", + "workflow-item.send-back.header": "إعادة إرسال مادة سير العمل إلى المقدم", + + // "workflow-item.send-back.button.cancel": "Cancel", "workflow-item.send-back.button.cancel": "إلغاء", - "workflow-item.send-back.button.confirm": "إعادة الإرسال", + + // "workflow-item.send-back.button.confirm": "Send back", + "workflow-item.send-back.button.confirm": "إعادة إرسال", + + // "workflow-item.view.breadcrumbs": "Workflow View", "workflow-item.view.breadcrumbs": "عرض سير العمل", + + // "workspace-item.view.breadcrumbs": "Workspace View", "workspace-item.view.breadcrumbs": "عرض مساحة العمل", + + // "workspace-item.view.title": "Workspace View", "workspace-item.view.title": "عرض مساحة العمل", + + // "workspace-item.delete.breadcrumbs": "Workspace Delete", "workspace-item.delete.breadcrumbs": "حذف مساحة العمل", - "workspace-item.delete.header": "حذف مساحة العمل", + + // "workspace-item.delete.header": "Delete workspace item", + "workspace-item.delete.header": "حذف مادة مساحة العمل", + + // "workspace-item.delete.button.confirm": "Delete", "workspace-item.delete.button.confirm": "حذف", + + // "workspace-item.delete.button.cancel": "Cancel", "workspace-item.delete.button.cancel": "إلغاء", + + // "workspace-item.delete.notification.success.title": "Deleted", "workspace-item.delete.notification.success.title": "تم الحذف", - "workspace-item.delete.title": "تم حذف المساحة الفعالة", + + // "workspace-item.delete.title": "This workspace item was successfully deleted", + "workspace-item.delete.title": "تم حذف مادة مساحة العمل بنجاح", + + // "workspace-item.delete.notification.error.title": "Something went wrong", "workspace-item.delete.notification.error.title": "هناك خطأ ما", - "workspace-item.delete.notification.error.content": "عذر حذف مساحة العمل", + + // "workspace-item.delete.notification.error.content": "The workspace item could not be deleted", + "workspace-item.delete.notification.error.content": "تعذر حذف مادة مساحة العمل", + + // "workflow-item.advanced.title": "Advanced workflow", "workflow-item.advanced.title": "سير العمل المتقدم", - "workflow-item.selectrevieweraction.notification.success.title": "المراجع للبحث", - "workflow-item.selectrevieweraction.notification.success.content": "تم اختيار المراجع الخاصة بما في ذلك سير العمل الفعال", + + // "workflow-item.selectrevieweraction.notification.success.title": "Selected reviewer", + "workflow-item.selectrevieweraction.notification.success.title": "المراجع المحدد", + + // "workflow-item.selectrevieweraction.notification.success.content": "The reviewer for this workflow item has been successfully selected", + "workflow-item.selectrevieweraction.notification.success.content": "تم اختيار المراجع الخاص بمادة سير العمل هذه بنجاح", + + // "workflow-item.selectrevieweraction.notification.error.title": "Something went wrong", "workflow-item.selectrevieweraction.notification.error.title": "هناك خطأ ما", - "workflow-item.selectrevieweraction.notification.error.content": "عذر تحديد المراجع لعنصر سير العمل هذا", - "workflow-item.selectrevieweraction.title": "تحديد الزائر", - "workflow-item.selectrevieweraction.header": "تحديد الزائر", + + // "workflow-item.selectrevieweraction.notification.error.content": "Couldn't select the reviewer for this workflow item", + "workflow-item.selectrevieweraction.notification.error.content": "تعذر تحديد المراجع لعنصر سير العمل هذا", + + // "workflow-item.selectrevieweraction.title": "Select Reviewer", + "workflow-item.selectrevieweraction.title": "تحديد مراجع", + + // "workflow-item.selectrevieweraction.header": "Select Reviewer", + "workflow-item.selectrevieweraction.header": "تحديد مراجع", + + // "workflow-item.selectrevieweraction.button.cancel": "Cancel", "workflow-item.selectrevieweraction.button.cancel": "إلغاء", - "workflow-item.selectrevieweraction.button.confirm": "بالتأكيد", + + // "workflow-item.selectrevieweraction.button.confirm": "Confirm", + "workflow-item.selectrevieweraction.button.confirm": "تأكيد", + + // "workflow-item.scorereviewaction.notification.success.title": "Rating review", "workflow-item.scorereviewaction.notification.success.title": "مراجعة التقييم", - "workflow-item.scorereviewaction.notification.success.content": "تم تقديم التقييم الخاص بعنصر سير العمل الفعال", + + // "workflow-item.scorereviewaction.notification.success.content": "The rating for this item workflow item has been successfully submitted", + "workflow-item.scorereviewaction.notification.success.content": "تم إرسال التقييم الخاص بعنصر سير عمل هذه المادة بنجاح", + + // "workflow-item.scorereviewaction.notification.error.title": "Something went wrong", "workflow-item.scorereviewaction.notification.error.title": "هناك خطأ ما", + + // "workflow-item.scorereviewaction.notification.error.content": "Couldn't rate this item", "workflow-item.scorereviewaction.notification.error.content": "تعذر تقييم هذه المادة", + + // "workflow-item.scorereviewaction.title": "Rate this item", "workflow-item.scorereviewaction.title": "قم بتقيم هذه المادة", + + // "workflow-item.scorereviewaction.header": "Rate this item", "workflow-item.scorereviewaction.header": "قم بتقييم هذه المادة", + + // "workflow-item.scorereviewaction.button.cancel": "Cancel", "workflow-item.scorereviewaction.button.cancel": "إلغاء", - "workflow-item.scorereviewaction.button.confirm": "بالتأكيد", - "idle-modal.header": "ستنتهي بعد قليل", - "idle-modal.info": "النهاية، انتهاء الجلسات المستخدمة بعد ذلك {{ timeToExpire }} دقيقة من عدم النشاط. ", + + // "workflow-item.scorereviewaction.button.confirm": "Confirm", + "workflow-item.scorereviewaction.button.confirm": "تأكيد", + + // "idle-modal.header": "Session will expire soon", + "idle-modal.header": "ستنتهي الجلسة بعد قليل", + + // "idle-modal.info": "For security reasons, user sessions expire after {{ timeToExpire }} minutes of inactivity. Your session will expire soon. Would you like to extend it or log out?", + "idle-modal.info": "لأسباب أمنية، تنتهي جلسات المستخدم بعد {{ timeToExpire }} دقيقة من عدم النشاط. ستنتهي جلستك بعد قليل. هل ترغب في تمديدها أم تسجيل الخروج؟", + + // "idle-modal.log-out": "Log out", "idle-modal.log-out": "خروج", + + // "idle-modal.extend-session": "Extend session", "idle-modal.extend-session": "تمديد الجلسة", - "researcher.profile.action.processing": "جاريب...", - "researcher.profile.associated": "الملف للباحثين الشخصيين", - "researcher.profile.change-visibility.fail": "حدث خطأ غير متوقع أثناء تغيير الملف الشخصي", + + // "researcher.profile.action.processing": "Processing...", + "researcher.profile.action.processing": "جاري المعالجة...", + + // "researcher.profile.associated": "Researcher profile associated", + "researcher.profile.associated": "الملف الشخصي للباحث المرتبط", + + // "researcher.profile.change-visibility.fail": "An unexpected error occurs while changing the profile visibility", + "researcher.profile.change-visibility.fail": "حدث خطأ غير متوقع أثناء تغيير رؤية الملف الشخصي", + + // "researcher.profile.create.new": "Create new", "researcher.profile.create.new": "إنشاء جديد", - "researcher.profile.create.success": "تم إنشاء الملف الشخصي للباحث الفعال", + + // "researcher.profile.create.success": "Researcher profile created successfully", + "researcher.profile.create.success": "تم إنشاء الملف الشخصي للباحث بنجاح", + + // "researcher.profile.create.fail": "An error occurs during the researcher profile creation", "researcher.profile.create.fail": "حدث خطأ أثناء إنشاء الملف الشخصي للباحث", + + // "researcher.profile.delete": "Delete", "researcher.profile.delete": "حذف", + + // "researcher.profile.expose": "Expose", "researcher.profile.expose": "عرض", + + // "researcher.profile.hide": "Hide", "researcher.profile.hide": "إخفاء", - "researcher.profile.not.associated": "الملف للباحث شخصي غير مرتبط بعد", + + // "researcher.profile.not.associated": "Researcher profile not yet associated", + "researcher.profile.not.associated": "الملف الشخصي للباحث غير مرتبط بعد", + + // "researcher.profile.view": "View", "researcher.profile.view": "عرض", + + // "researcher.profile.private.visibility": "PRIVATE", "researcher.profile.private.visibility": "خاص", + + // "researcher.profile.public.visibility": "PUBLIC", "researcher.profile.public.visibility": "عام", + + // "researcher.profile.status": "Status:", "researcher.profile.status": "الحالة:", - "researcherprofile.claim.not-authorized": "لا غير لك هذه المادة. ", - "researcherprofile.error.claim.body": "حدث خطأ أثناء استخدام الملف الشخصي، يرجى المحاولة مرة أخرى لاحقاً", + + // "researcherprofile.claim.not-authorized": "You are not authorized to claim this item. For more details contact the administrator(s).", + "researcherprofile.claim.not-authorized": "لا يحق لك المطالبة بهذه المادة. لمزيد من التفاصيل يرجى الاتصال بالمسؤول.", + + // "researcherprofile.error.claim.body": "An error occurred while claiming the profile, please try again later", + "researcherprofile.error.claim.body": "حدث خطأ أثناء المطالبة بالملف الشخصي، يرجى المحاولة مرة أخرى لاحقاً", + + // "researcherprofile.error.claim.title": "Error", "researcherprofile.error.claim.title": "خطأ", - "researcherprofile.success.claim.body": "أكمل بالملف الكامل الفعال", + + // "researcherprofile.success.claim.body": "Profile claimed with success", + "researcherprofile.success.claim.body": "تمت المطالبة بالملف الشخصي بنجاح", + + // "researcherprofile.success.claim.title": "Success", "researcherprofile.success.claim.title": "نجاح", + + // "person.page.orcid.create": "Create an ORCID ID", "person.page.orcid.create": "إنشاء معرف أوركيد", + + // "person.page.orcid.granted-authorizations": "Granted authorizations", "person.page.orcid.granted-authorizations": "التصاريح الممنوحة", + + // "person.page.orcid.grant-authorizations": "Grant authorizations", "person.page.orcid.grant-authorizations": "منح التصاريح", - "person.page.orcid.link": "الاتصال بمعرفة أوركيد", - "person.page.orcid.link.processing": "غاري الملف الشخصي بيوركيد...", - "person.page.orcid.link.error.message": "حدث ما حدث خطأ أثناء ربط الملف الشخصي بوركيد. ", - "person.page.orcid.orcid-not-linked-message": "معرف أوركيد لهذا الملف الشخصي ({{ orcid }}) لم يتم الاتصال به بعد بحسابك في سجل أوركيد أو صلاحية الاتصال.", - "person.page.orcid.unlink": "قطعة الاتصال بأوركيد", - "person.page.orcid.unlink.processing": "جاريب...", - "person.page.orcid.missing-authorizations": "لقد فقدت التصاريح", + + // "person.page.orcid.link": "Connect to ORCID ID", + "person.page.orcid.link": "الاتصال بمعرف أوركيد", + + // "person.page.orcid.link.processing": "Linking profile to ORCID...", + "person.page.orcid.link.processing": "جاري ربط الملف الشخصي بأوركيد...", + + // "person.page.orcid.link.error.message": "Something went wrong while connecting the profile with ORCID. If the problem persists, contact the administrator.", + "person.page.orcid.link.error.message": "حدث خطأ ما أثناء ربط الملف الشخصي بأوركيد. إذا استمرت المشكلة، يرجى الاتصال بالمسؤول.", + + // "person.page.orcid.orcid-not-linked-message": "The ORCID iD of this profile ({{ orcid }}) has not yet been connected to an account on the ORCID registry or the connection is expired.", + "person.page.orcid.orcid-not-linked-message": "معرف أوركيد لهذا الملف الشخصي ({{ orcid }}) لم يتم ربطه بعد بحساب في سجل أوركيد أو انتهت صلاحية الاتصال.", + + // "person.page.orcid.unlink": "Disconnect from ORCID", + "person.page.orcid.unlink": "قطع الاتصال بأوركيد", + + // "person.page.orcid.unlink.processing": "Processing...", + "person.page.orcid.unlink.processing": "جاري المعالجة...", + + // "person.page.orcid.missing-authorizations": "Missing authorizations", + "person.page.orcid.missing-authorizations": "تصاريح مفقودة", + + // "person.page.orcid.missing-authorizations-message": "The following authorizations are missing:", "person.page.orcid.missing-authorizations-message": "التصاريح التالية مفقودة:", - "person.page.orcid.no-missing-authorizations-message": "عظيم! ", - "person.page.orcid.no-orcid-message": "لا يوجد معرف أوركيد مرتبط حتى الآن. ", + + // "person.page.orcid.no-missing-authorizations-message": "Great! This box is empty, so you have granted all access rights to use all functions offers by your institution.", + "person.page.orcid.no-missing-authorizations-message": "عظيم! هذا المربع فارغ، لذا فقد قمت بمنح جميع حقوق الوصول لاستخدام جميع الوظائف التي تقدمها مؤسستك.", + + // "person.page.orcid.no-orcid-message": "No ORCID iD associated yet. By clicking on the button below it is possible to link this profile with an ORCID account.", + "person.page.orcid.no-orcid-message": "لا يوجد معرف أوركيد مرتبط حتى الآن. بالنقر على الزر أدناه من الممكن ربط هذا الملف الشخصي بحساب أوركيد.", + + // "person.page.orcid.profile-preferences": "Profile preferences", "person.page.orcid.profile-preferences": "تفضيلات الملف الشخصي", + + // "person.page.orcid.funding-preferences": "Funding preferences", "person.page.orcid.funding-preferences": "تفضيلات التمويل", - "person.page.orcid.publications-preferences": "مفضلات النشر", + + // "person.page.orcid.publications-preferences": "Publication preferences", + "person.page.orcid.publications-preferences": "تفضيلات النشر", + + // "person.page.orcid.remove-orcid-message": "If you need to remove your ORCID, please contact the repository administrator", "person.page.orcid.remove-orcid-message": "إذا كنت بحاجة إلى إزالة أوركيد الخاص بك، يرجى الاتصال بمسؤول المستودع", + + // "person.page.orcid.save.preference.changes": "Update settings", "person.page.orcid.save.preference.changes": "تحديث الإعدادات", + + // "person.page.orcid.sync-profile.affiliation": "Affiliation", "person.page.orcid.sync-profile.affiliation": "الانتسابات", - "person.page.orcid.sync-profile.biographical": "بيانات الشخصية", + + // "person.page.orcid.sync-profile.biographical": "Biographical data", + "person.page.orcid.sync-profile.biographical": "البيانات الشخصية", + + // "person.page.orcid.sync-profile.education": "Education", "person.page.orcid.sync-profile.education": "التعليم", + + // "person.page.orcid.sync-profile.identifiers": "Identifiers", "person.page.orcid.sync-profile.identifiers": "المعرفات", - "person.page.orcid.sync-fundings.all": "كل التمويل", + + // "person.page.orcid.sync-fundings.all": "All fundings", + "person.page.orcid.sync-fundings.all": "كل التمويلات", + + // "person.page.orcid.sync-fundings.mine": "My fundings", "person.page.orcid.sync-fundings.mine": "تمويلاتي", - "person.page.orcid.sync-fundings.my_selected": "التمويل المحدد", + + // "person.page.orcid.sync-fundings.my_selected": "Selected fundings", + "person.page.orcid.sync-fundings.my_selected": "التمويلات المحددة", + + // "person.page.orcid.sync-fundings.disabled": "Disabled", "person.page.orcid.sync-fundings.disabled": "معطلة", + + // "person.page.orcid.sync-publications.all": "All publications", "person.page.orcid.sync-publications.all": "كل المنشورات", + + // "person.page.orcid.sync-publications.mine": "My publications", "person.page.orcid.sync-publications.mine": "منشوراتي", + + // "person.page.orcid.sync-publications.my_selected": "Selected publications", "person.page.orcid.sync-publications.my_selected": "المنشورات المحددة", + + // "person.page.orcid.sync-publications.disabled": "Disabled", "person.page.orcid.sync-publications.disabled": "معطلة", - "person.page.orcid.sync-queue.discard": "لا ننسى ولا ننسى مع سجل أوركيد", - "person.page.orcid.sync-queue.discard.error": "فشلت في تجاهل تسجيل قائمة انتظار أوركيد", - "person.page.orcid.sync-queue.discard.success": "تم تجاهل تسجيل قائمة انتظار أوركيد الفعالة", - "person.page.orcid.sync-queue.empty-message": "سجل قائمة انتظار أوركيد الكاملة", + + // "person.page.orcid.sync-queue.discard": "Discard the change and do not synchronize with the ORCID registry", + "person.page.orcid.sync-queue.discard": "تجاهل التغيير ولا تقم بالمزامنة مع سجل أوركيد", + + // "person.page.orcid.sync-queue.discard.error": "The discarding of the ORCID queue record failed", + "person.page.orcid.sync-queue.discard.error": "فشل تجاهل تسجيلة قائمة انتظار أوركيد", + + // "person.page.orcid.sync-queue.discard.success": "The ORCID queue record have been discarded successfully", + "person.page.orcid.sync-queue.discard.success": "تم تجاهل تسجيلة قائمة انتظار أوركيد بنجاح", + + // "person.page.orcid.sync-queue.empty-message": "The ORCID queue registry is empty", + "person.page.orcid.sync-queue.empty-message": "سجل قائمة انتظار أوركيد فارغ", + + // "person.page.orcid.sync-queue.table.header.type": "Type", "person.page.orcid.sync-queue.table.header.type": "النوع", + + // "person.page.orcid.sync-queue.table.header.description": "Description", "person.page.orcid.sync-queue.table.header.description": "الوصف", - "person.page.orcid.sync-queue.table.header.action": "صنع", + + // "person.page.orcid.sync-queue.table.header.action": "Action", + "person.page.orcid.sync-queue.table.header.action": "إجراء", + + // "person.page.orcid.sync-queue.description.affiliation": "Affiliations", "person.page.orcid.sync-queue.description.affiliation": "الانتسابات", + + // "person.page.orcid.sync-queue.description.country": "Country", "person.page.orcid.sync-queue.description.country": "البلد", + + // "person.page.orcid.sync-queue.description.education": "Educations", "person.page.orcid.sync-queue.description.education": "التعليم", + + // "person.page.orcid.sync-queue.description.external_ids": "External ids", "person.page.orcid.sync-queue.description.external_ids": "معرفات خارجية", + + // "person.page.orcid.sync-queue.description.other_names": "Other names", "person.page.orcid.sync-queue.description.other_names": "أسماء أخرى", + + // "person.page.orcid.sync-queue.description.qualification": "Qualifications", "person.page.orcid.sync-queue.description.qualification": "المؤهلات", - "person.page.orcid.sync-queue.description.researcher_urls": "عناوين URL للباحثين", - "person.page.orcid.sync-queue.description.keywords": "الكلمات الرئيسية", - "person.page.orcid.sync-queue.tooltip.insert": "إضافة حجم جديد في سجل أوركيد", + + // "person.page.orcid.sync-queue.description.researcher_urls": "Researcher urls", + "person.page.orcid.sync-queue.description.researcher_urls": "عناوين URL للباحث", + + // "person.page.orcid.sync-queue.description.keywords": "Keywords", + "person.page.orcid.sync-queue.description.keywords": "كلمات رئيسية", + + // "person.page.orcid.sync-queue.tooltip.insert": "Add a new entry in the ORCID registry", + "person.page.orcid.sync-queue.tooltip.insert": "إضافة إدخال جديد في سجل أوركيد", + + // "person.page.orcid.sync-queue.tooltip.update": "Update this entry on the ORCID registry", "person.page.orcid.sync-queue.tooltip.update": "تحديث هذا الإدخال في سجل أوركيد", + + // "person.page.orcid.sync-queue.tooltip.delete": "Remove this entry from the ORCID registry", "person.page.orcid.sync-queue.tooltip.delete": "إزالة هذا الإدخال من سجل أوركيد", + + // "person.page.orcid.sync-queue.tooltip.publication": "Publication", "person.page.orcid.sync-queue.tooltip.publication": "النشر", + + // "person.page.orcid.sync-queue.tooltip.project": "Project", "person.page.orcid.sync-queue.tooltip.project": "المشروع", + + // "person.page.orcid.sync-queue.tooltip.affiliation": "Affiliation", "person.page.orcid.sync-queue.tooltip.affiliation": "الانتسابات", + + // "person.page.orcid.sync-queue.tooltip.education": "Education", "person.page.orcid.sync-queue.tooltip.education": "التعليم", + + // "person.page.orcid.sync-queue.tooltip.qualification": "Qualification", "person.page.orcid.sync-queue.tooltip.qualification": "المؤهل", + + // "person.page.orcid.sync-queue.tooltip.other_names": "Other name", "person.page.orcid.sync-queue.tooltip.other_names": "اسم آخر", + + // "person.page.orcid.sync-queue.tooltip.country": "Country", "person.page.orcid.sync-queue.tooltip.country": "البلد", + + // "person.page.orcid.sync-queue.tooltip.keywords": "Keyword", "person.page.orcid.sync-queue.tooltip.keywords": "كلمة رئيسية", + + // "person.page.orcid.sync-queue.tooltip.external_ids": "External identifier", "person.page.orcid.sync-queue.tooltip.external_ids": "معرف خارجي", + + // "person.page.orcid.sync-queue.tooltip.researcher_urls": "Researcher url", "person.page.orcid.sync-queue.tooltip.researcher_urls": "عنوان URL للباحث", - "person.page.orcid.sync-queue.send": "النت مع سجل أوركيد", - "person.page.orcid.sync-queue.send.unauthorized-error.title": "فشل تقديم أوركيد بسبب عيوب التراخيص.", - "person.page.orcid.sync-queue.send.unauthorized-error.content": "انقر هنا لمنح الصلاحيات المطلوبة مرة أخرى. ", + + // "person.page.orcid.sync-queue.send": "Synchronize with ORCID registry", + "person.page.orcid.sync-queue.send": "المزامنة مع سجل أوركيد", + + // "person.page.orcid.sync-queue.send.unauthorized-error.title": "The submission to ORCID failed for missing authorizations.", + "person.page.orcid.sync-queue.send.unauthorized-error.title": "فشل التقديم إلى أوركيد بسبب نقص تصاريح.", + + // "person.page.orcid.sync-queue.send.unauthorized-error.content": "Click here to grant again the required permissions. If the problem persists, contact the administrator", + "person.page.orcid.sync-queue.send.unauthorized-error.content": "انقر هنا لمنح الصلاحيات المطلوبة مرة أخرى. إذا استمرت المشكلة، يرجى الاتصال بالمسؤول", + + // "person.page.orcid.sync-queue.send.bad-request-error": "The submission to ORCID failed because the resource sent to ORCID registry is not valid", "person.page.orcid.sync-queue.send.bad-request-error": "فشل التقديم إلى أوركيد لأن المورد الذي تم إرساله إلى سجل أوركيد غير صالح", + + // "person.page.orcid.sync-queue.send.error": "The submission to ORCID failed", "person.page.orcid.sync-queue.send.error": "فشل التقديم إلى أوركيد", - "person.page.orcid.sync-queue.send.conflict-error": "فشل تقديم أوركيد لأن المورد موجود بالفعل في سجل أوركيد", - "person.page.orcid.sync-queue.send.not-found-warning": "لم يعد موردًا موجودًا في سجل أوركيد.", - "person.page.orcid.sync-queue.send.success": "تم التقديم إلى أوركيد الفعال", + + // "person.page.orcid.sync-queue.send.conflict-error": "The submission to ORCID failed because the resource is already present on the ORCID registry", + "person.page.orcid.sync-queue.send.conflict-error": "فشل التقديم إلى أوركيد لأن المورد موجود بالفعل في سجل أوركيد", + + // "person.page.orcid.sync-queue.send.not-found-warning": "The resource does not exists anymore on the ORCID registry.", + "person.page.orcid.sync-queue.send.not-found-warning": "لم يعد المورد موجودًا في سجل أوركيد.", + + // "person.page.orcid.sync-queue.send.success": "The submission to ORCID was completed successfully", + "person.page.orcid.sync-queue.send.success": "تم اكتمال التقديم إلى أوركيد بنجاح", + + // "person.page.orcid.sync-queue.send.validation-error": "The data that you want to synchronize with ORCID is not valid", "person.page.orcid.sync-queue.send.validation-error": "البيانات التي تريد مزامنتها مع أوركيد غير صالحة", - "person.page.orcid.sync-queue.send.validation-error.amount-currency.required": "العملة الورقية المطلوبة", - "person.page.orcid.sync-queue.send.validation-error.external-id.required": "يلزم المورد إرساله معرفًا جديدًا على الأقل", + + // "person.page.orcid.sync-queue.send.validation-error.amount-currency.required": "The amount's currency is required", + "person.page.orcid.sync-queue.send.validation-error.amount-currency.required": "عملة المبلغ مطلوبة", + + // "person.page.orcid.sync-queue.send.validation-error.external-id.required": "The resource to be sent requires at least one identifier", + "person.page.orcid.sync-queue.send.validation-error.external-id.required": "يتطلب المورد المراد إرساله معرفًا واحدًا على الأقل", + + // "person.page.orcid.sync-queue.send.validation-error.title.required": "The title is required", "person.page.orcid.sync-queue.send.validation-error.title.required": "العنوان مطلوب", + + // "person.page.orcid.sync-queue.send.validation-error.type.required": "The dc.type is required", "person.page.orcid.sync-queue.send.validation-error.type.required": "dc.type مطلوب", - "person.page.orcid.sync-queue.send.validation-error.start-date.required": "تاريخ البدلة مطلوب", + + // "person.page.orcid.sync-queue.send.validation-error.start-date.required": "The start date is required", + "person.page.orcid.sync-queue.send.validation-error.start-date.required": "تاريخ البد مطلوب", + + // "person.page.orcid.sync-queue.send.validation-error.funder.required": "The funder is required", "person.page.orcid.sync-queue.send.validation-error.funder.required": "الممول مطلوب", + + // "person.page.orcid.sync-queue.send.validation-error.country.invalid": "Invalid 2 digits ISO 3166 country", "person.page.orcid.sync-queue.send.validation-error.country.invalid": "كود البلد المكون من رقمين ISO 3166 غير صالح", - "person.page.orcid.sync-queue.send.validation-error.organization.required": "مؤسسة مطلوبة", + + // "person.page.orcid.sync-queue.send.validation-error.organization.required": "The organization is required", + "person.page.orcid.sync-queue.send.validation-error.organization.required": "المؤسسة مطلوبة", + + // "person.page.orcid.sync-queue.send.validation-error.organization.name-required": "The organization's name is required", "person.page.orcid.sync-queue.send.validation-error.organization.name-required": "اسم المؤسسة مطلوب", + + // "person.page.orcid.sync-queue.send.validation-error.publication.date-invalid": "The publication date must be one year after 1900", "person.page.orcid.sync-queue.send.validation-error.publication.date-invalid": "يجب أن يكون تاريخ النشر بعد سنة واحدة من عام 1900", - "person.page.orcid.sync-queue.send.validation-error.organization.address-required": "الطلبات التي تقوم المؤسسة بإرسالها عنواناً", - "person.page.orcid.sync-queue.send.validation-error.organization.city-required": "مطلوب عنوان المؤسسة المراد نقلها لمدينة", - "person.page.orcid.sync-queue.send.validation-error.organization.country-required": "يلزم عنوان المؤسسة المراد إرسالها رقمين صالحين وفقًا لمعايير ISO 3166", - "person.page.orcid.sync-queue.send.validation-error.disambiguated-organization.required": "مطلوب معرف لتوضيح المنظمة. ", - "person.page.orcid.sync-queue.send.validation-error.disambiguated-organization.value-required": "المتطلبات المعرفية للهيئة", - "person.page.orcid.sync-queue.send.validation-error.disambiguation-source.required": "المتطلبات المعرفية المؤسسة مصدراً", - "person.page.orcid.sync-queue.send.validation-error.disambiguation-source.invalid": "مصدر أحد المؤسسات المعرفية غير الصالحة. ", - "person.page.orcid.synchronization-mode": "وضع النوارس", + + // "person.page.orcid.sync-queue.send.validation-error.organization.address-required": "The organization to be sent requires an address", + "person.page.orcid.sync-queue.send.validation-error.organization.address-required": "تتطلب المؤسسة التي سيتم إرسالها عنواناً", + + // "person.page.orcid.sync-queue.send.validation-error.organization.city-required": "The address of the organization to be sent requires a city", + "person.page.orcid.sync-queue.send.validation-error.organization.city-required": "يتطلب عنوان المؤسسة المراد إرسالها مدينة", + + // "person.page.orcid.sync-queue.send.validation-error.organization.country-required": "The address of the organization to be sent requires a valid 2 digits ISO 3166 country", + "person.page.orcid.sync-queue.send.validation-error.organization.country-required": "يتطلب عنوان المؤسسة المراد إرسالها رقمين صالحين وفقًا لمعايير ISO 3166", + + // "person.page.orcid.sync-queue.send.validation-error.disambiguated-organization.required": "An identifier to disambiguate organizations is required. Supported ids are GRID, Ringgold, Legal Entity identifiers (LEIs) and Crossref Funder Registry identifiers", + "person.page.orcid.sync-queue.send.validation-error.disambiguated-organization.required": "مطلوب معرف لتوضيح المؤسسات. المعرفات المدعومة هي GRID وRinggold ومعرفات الكينونات القانونية (LEIs) ومعرفات سجل Crossref Funder", + + // "person.page.orcid.sync-queue.send.validation-error.disambiguated-organization.value-required": "The organization's identifiers requires a value", + "person.page.orcid.sync-queue.send.validation-error.disambiguated-organization.value-required": "تتطلب معرفات المؤسسة قيمة", + + // "person.page.orcid.sync-queue.send.validation-error.disambiguation-source.required": "The organization's identifiers requires a source", + "person.page.orcid.sync-queue.send.validation-error.disambiguation-source.required": "تتطلب معرفات المؤسسة مصدراً", + + // "person.page.orcid.sync-queue.send.validation-error.disambiguation-source.invalid": "The source of one of the organization identifiers is invalid. Supported sources are RINGGOLD, GRID, LEI and FUNDREF", + "person.page.orcid.sync-queue.send.validation-error.disambiguation-source.invalid": "مصدر أحد معرفات المؤسسة غير صالح. المصادر المدعومة هي RINGGOLD وGRID وLEI وFUNDREF", + + // "person.page.orcid.synchronization-mode": "Synchronization mode", + "person.page.orcid.synchronization-mode": "وضع المزامنة", + + // "person.page.orcid.synchronization-mode.batch": "Batch", "person.page.orcid.synchronization-mode.batch": "دفعة", - "person.page.orcid.synchronization-mode.label": "وضع النوارس", - "person.page.orcid.synchronization-mode-message": "يرجى تحديد الطريقة التي تريد أن تتم من خلالها تشغيل النت مع أوركيد. ", - "person.page.orcid.synchronization-mode-funding-message": "حدد ما إذا كنت ترغب في استكمال الدراسة في كينونات المشروع، ثم قم بإدراج المعلومات الخاصة بالتمويل الخاص بشركة أوركيد الخاصة بك.", - "person.page.orcid.synchronization-mode-publication-message": "حدد ما إذا كنت ترغب في ترك كينونات ترغب في قائمة أعمال تسجيل أوركيد الخاصة بك.", - "person.page.orcid.synchronization-mode-profile-message": "حدد ما إذا كنت تريد إرسال بياناتك الشخصية أو معرفاتك الشخصية إلى تسجيل أوركيد الخاص بك.", - "person.page.orcid.synchronization-settings-update.success": "تم تحديث إعدادات الروبوت الفعالة", - "person.page.orcid.synchronization-settings-update.error": "فشل تحديث إعدادات الناقلات", - "person.page.orcid.synchronization-mode.manual": "يدويا", + + // "person.page.orcid.synchronization-mode.label": "Synchronization mode", + "person.page.orcid.synchronization-mode.label": "وضع المزامنة", + + // "person.page.orcid.synchronization-mode-message": "Please select how you would like synchronization to ORCID to occur. The options include \"Manual\" (you must send your data to ORCID manually), or \"Batch\" (the system will send your data to ORCID via a scheduled script).", + "person.page.orcid.synchronization-mode-message": "يرجى تحديد الطريقة التي تريد أن تتم بها المزامنة مع أوركيد. تتضمن الخيارات \"يدوي\" (يجب عليك إرسال بياناتك إلى أوركيد يدوياً)، أو \"بالدفعة\" (سيقوم النظام بإرسال بياناتك إلى أوركيد عبر برنامج نصي مجدول).", + + // "person.page.orcid.synchronization-mode-funding-message": "Select whether to send your linked Project entities to your ORCID record's list of funding information.", + "person.page.orcid.synchronization-mode-funding-message": "حدد ما إذا كنت تريد إرسال كينونات المشروع المرتبطة إلى قائمة معلومات التمويل الخاصة بتسجيلة أوركيد الخاصة بك.", + + // "person.page.orcid.synchronization-mode-publication-message": "Select whether to send your linked Publication entities to your ORCID record's list of works.", + "person.page.orcid.synchronization-mode-publication-message": "حدد ما إذا كنت تريد إرسال كينونات النشر المرتبطة إلى قائمة أعمال تسجيلة أوركيد الخاصة بك.", + + // "person.page.orcid.synchronization-mode-profile-message": "Select whether to send your biographical data or personal identifiers to your ORCID record.", + "person.page.orcid.synchronization-mode-profile-message": "حدد ما إذا كنت تريد إرسال بياناتات الشخصية أو معرفاتك الشخصية إلى تسجيلة أوركيد الخاصة بك.", + + // "person.page.orcid.synchronization-settings-update.success": "The synchronization settings have been updated successfully", + "person.page.orcid.synchronization-settings-update.success": "تم تحديث إعدادات المزامنة بنجاح", + + // "person.page.orcid.synchronization-settings-update.error": "The update of the synchronization settings failed", + "person.page.orcid.synchronization-settings-update.error": "فشل تحديث إعدادات المزامنة", + + // "person.page.orcid.synchronization-mode.manual": "Manual", + "person.page.orcid.synchronization-mode.manual": "يدوي", + + // "person.page.orcid.scope.authenticate": "Get your ORCID iD", "person.page.orcid.scope.authenticate": "احصل على معرف أوركيد الخاص بك", + + // "person.page.orcid.scope.read-limited": "Read your information with visibility set to Trusted Parties", "person.page.orcid.scope.read-limited": "اقرأ معلوماتك مع ضبط مستوى الرؤية للأطراف الموثوقة", - "person.page.orcid.scope.activities-update": "إضافة/تحديث الدراسات الخاصة بك", + + // "person.page.orcid.scope.activities-update": "Add/update your research activities", + "person.page.orcid.scope.activities-update": "إضافة/تحديث الأنشطة البحثية الخاصة بك", + + // "person.page.orcid.scope.person-update": "Add/update other information about you", "person.page.orcid.scope.person-update": "إضافة/تحديث معلومات أخرى عنك", - "person.page.orcid.unlink.success": "تم قطع الاتصال بين الملف الشخصي وأوركيد فعال", - "person.page.orcid.unlink.error": "حدث خطأ أثناء قطع الاتصال بين الملف الشخصي وأوركيد. ", - "person.orcid.sync.setting": "إعدادات نوبات أوركيد", + + // "person.page.orcid.unlink.success": "The disconnection between the profile and the ORCID registry was successful", + "person.page.orcid.unlink.success": "تم قطع الاتصال بين الملف الشخصي وسجل أوركيد بنجاح", + + // "person.page.orcid.unlink.error": "An error occurred while disconnecting between the profile and the ORCID registry. Try again", + "person.page.orcid.unlink.error": "حدث خطأ أثناء قطع الاتصال بين الملف الشخصي وسجل أوركيد. يرجى إعادة المحاولة", + + // "person.orcid.sync.setting": "ORCID Synchronization settings", + "person.orcid.sync.setting": "إعدادات مزامنة أوركيد", + + // "person.orcid.registry.queue": "ORCID Registry Queue", "person.orcid.registry.queue": "قائمة انتظار سجل أوركيد", + + // "person.orcid.registry.auth": "ORCID Authorizations", "person.orcid.registry.auth": "تصاريح أوركيد", - "home.recent-submissions.head": "أحدث العروض", - "listable-notification-object.default-message": "تعذر على تجديد هذا", - "system-wide-alert-banner.retrieval.error": "حدث خطأ أثناء حذف التنبيه على النظام", + + // "home.recent-submissions.head": "Recent Submissions", + "home.recent-submissions.head": "أحدث التقديمات", + + // "listable-notification-object.default-message": "This object couldn't be retrieved", + "listable-notification-object.default-message": "تعذر استرداد هذا الكائن", + + // "system-wide-alert-banner.retrieval.error": "Something went wrong retrieving the system-wide alert banner", + "system-wide-alert-banner.retrieval.error": "حدث خطأ أثناء استرداد شعار التنبيه على مستوى النظام", + + // "system-wide-alert-banner.countdown.prefix": "In", "system-wide-alert-banner.countdown.prefix": "خلال", - "system-wide-alert-banner.countdown.days": "{{days}} يوما,", + + // "system-wide-alert-banner.countdown.days": "{{days}} day(s),", + "system-wide-alert-banner.countdown.days": "{{days}} يوماً,", + + // "system-wide-alert-banner.countdown.hours": "{{hours}} hour(s) and", "system-wide-alert-banner.countdown.hours": "{{hours}} ساعة و", + + // "system-wide-alert-banner.countdown.minutes": "{{minutes}} minute(s):", "system-wide-alert-banner.countdown.minutes": "{{minutes}} دقيقة:", + + // "menu.section.system-wide-alert": "System-wide Alert", "menu.section.system-wide-alert": "تنبيه على مستوى النظام", + + // "system-wide-alert.form.header": "System-wide Alert", "system-wide-alert.form.header": "تنبيه على مستوى النظام", - "system-wide-alert-form.retrieval.error": "حدث ما خطأ أثناء تحديث التنبيه على النظام", + + // "system-wide-alert-form.retrieval.error": "Something went wrong retrieving the system-wide alert", + "system-wide-alert-form.retrieval.error": "حدث خطأ ما أثناء استرداد التنبيه على مستوى النظام", + + // "system-wide-alert.form.cancel": "Cancel", "system-wide-alert.form.cancel": "إلغاء", + + // "system-wide-alert.form.save": "Save", "system-wide-alert.form.save": "حفظ", + + // "system-wide-alert.form.label.active": "ACTIVE", "system-wide-alert.form.label.active": "نشط", + + // "system-wide-alert.form.label.inactive": "INACTIVE", "system-wide-alert.form.label.inactive": "غير نشط", - "system-wide-alert.form.error.message": "يجب أن يحتوي على تنبيه على النظام على رسالة", + + // "system-wide-alert.form.error.message": "The system wide alert must have a message", + "system-wide-alert.form.error.message": "يجب أن يحتوي التنبيه على مستوى النظام على رسالة", + + // "system-wide-alert.form.label.message": "Alert message", "system-wide-alert.form.label.message": "رسالة تنبيه", - "system-wide-alert.form.label.countdownTo.enable": "تفعيل تقويم التاريخ", - "system-wide-alert.form.label.countdownTo.hint": "تلميح: قم بضبط توقيت تقويم التقويم. ", + + // "system-wide-alert.form.label.countdownTo.enable": "Enable a countdown timer", + "system-wide-alert.form.label.countdownTo.enable": "تفعيل مؤقت العد التنازلي", + + // "system-wide-alert.form.label.countdownTo.hint": "Hint: Set a countdown timer. When enabled, a date can be set in the future and the system-wide alert banner will perform a countdown to the set date. When this timer ends, it will disappear from the alert. The server will NOT be automatically stopped.", + "system-wide-alert.form.label.countdownTo.hint": "تلميح: قم بضبط مؤقت العد التنازلي. عند التفعيل، يمكن تعيين تاريخ في المستقبل وسيقوم شعار التنبيه على مستوى النظام بإجراء العد التنازلي للتاريخ المحدد. عندما ينتهي هذا المؤقت، سوف يختفي من التنبيه. لن يتم إيقاف الخادم تلقائياً.", + + // "system-wide-alert-form.select-date-by-calendar": "Select date using calendar", "system-wide-alert-form.select-date-by-calendar": "حدد التاريخ باستخدام التقويم", - "system-wide-alert.form.label.preview": "معاينة التنبيه على النظام", - "system-wide-alert.form.update.success": "تم تحديث التنبيه على النظام الفعال", - "system-wide-alert.form.update.error": "حدث خطأ ما أثناء تحديث التنبيه على النظام", - "system-wide-alert.form.create.success": "تم إنشاء تنبيه على النظام الفعال", - "system-wide-alert.form.create.error": "حدث خطأ ما أثناء إنشاء تنبيه على النظام", + + // "system-wide-alert.form.label.preview": "System-wide alert preview", + "system-wide-alert.form.label.preview": "معاينة التنبيه على مستوى النظام", + + // "system-wide-alert.form.update.success": "The system-wide alert was successfully updated", + "system-wide-alert.form.update.success": "تم تحديث التنبيه على مستوى النظام بنجاح", + + // "system-wide-alert.form.update.error": "Something went wrong when updating the system-wide alert", + "system-wide-alert.form.update.error": "حدث خطأ ما أثناء تحديث التنبيه على مستوى النظام", + + // "system-wide-alert.form.create.success": "The system-wide alert was successfully created", + "system-wide-alert.form.create.success": "تم إنشاء التنبيه على مستوى النظام بنجاح", + + // "system-wide-alert.form.create.error": "Something went wrong when creating the system-wide alert", + "system-wide-alert.form.create.error": "حدث خطأ ما أثناء إنشاء التنبيه على مستوى النظام", + + // "admin.system-wide-alert.breadcrumbs": "System-wide Alerts", "admin.system-wide-alert.breadcrumbs": "تنبيهات على مستوى النظام", + + // "admin.system-wide-alert.title": "System-wide Alerts", "admin.system-wide-alert.title": "تنبيهات على مستوى النظام", - "discover.filters.head": "يكتشف", - "item-access-control-title": "يتيح لك هذا النموذج عمل التغيرات في شروط الوصول إلى مادة ميتا أو تدفقات محددة خاصة بها.", - "collection-access-control-title": "يتيح لك هذا النموذج إجراء التغيرات في شروط الوصول لكل المواد المملوكة لهذه المجموعة. ", - "community-access-control-title": "يتيح لك هذا النموذج إجراء التغيرات في شروط الوصول لكل المواد المملوكة للمجموعة ضمن هذا المجتمع. ", - "access-control-item-header-toggle": "مادة ميتاداتا", - "access-control-item-toggle.enable": "تفعيل خيار عمل الخيارات على ميتاداتا المادة", - "access-control-item-toggle.disable": "السؤال الآن هو: القدرة على إحداث تغييرات على مادة ميتابادتا", + + // "discover.filters.head": "Discover", + // TODO New key - Add a translation + "discover.filters.head": "Discover", + + // "item-access-control-title": "This form allows you to perform changes to the access conditions of the item's metadata or its bitstreams.", + "item-access-control-title": "يتيح لك هذا النموذج إجراء تغييرات على شروط الوصول إلى ميتاداتا المادة أو تدفقات البت الخاصة بها.", + + // "collection-access-control-title": "This form allows you to perform changes to the access conditions of all the items owned by this collection. Changes may be performed to either all Item metadata or all content (bitstreams).", + "collection-access-control-title": "يتيح لك هذا النموذج إجراء تغييرات على شروط الوصول لكل المواد المملوكة لهذه المجموعة. قد يتم إجراء التغييرات إما على كل ميتاداتا المادة أو على المحتوى بأكمله (تدفقات البت).", + + // "community-access-control-title": "This form allows you to perform changes to the access conditions of all the items owned by any collection under this community. Changes may be performed to either all Item metadata or all content (bitstreams).", + "community-access-control-title": "يتيح لك هذا النموذج إجراء تغييرات على شروط الوصول لكل المواد المملوكة لأي مجموعة ضمن هذا المجتمع. قد يتم إجراء التغييرات إما على كل ميتاداتا المادة أو على المحتوى بأكمله (تدفقات البت).", + + // "access-control-item-header-toggle": "Item's Metadata", + "access-control-item-header-toggle": "ميتاداتا المادة", + + // "access-control-item-toggle.enable": "Enable option to perform changes on the item's metadata", + "access-control-item-toggle.enable": "تفعيل خيار إجراء تغييرات على ميتاداتا المادة", + + // "access-control-item-toggle.disable": "Disable option to perform changes on the item's metadata", + "access-control-item-toggle.disable": "تعطيل خيار إجراء تغييرات على ميتاداتا المادة", + + // "access-control-bitstream-header-toggle": "Bitstreams", "access-control-bitstream-header-toggle": "تدفقات البت", - "access-control-bitstream-toggle.enable": "تفعيل خيار خيارات على تدفقات البت", - "access-control-bitstream-toggle.disable": "مطلوب خيار إجراء تغييرات على تدفقات البت", - "access-control-mode": "وضع", + + // "access-control-bitstream-toggle.enable": "Enable option to perform changes on the bitstreams", + "access-control-bitstream-toggle.enable": "تفعيل خيار إجراء تغييرات على تدفقات البت", + + // "access-control-bitstream-toggle.disable": "Disable option to perform changes on the bitstreams", + "access-control-bitstream-toggle.disable": "تعطيل خيار إجراء تغييرات على تدفقات البت", + + // "access-control-mode": "Mode", + "access-control-mode": "Mode", + + // "access-control-access-conditions": "Access conditions", "access-control-access-conditions": "شروط الوصول", - "access-control-no-access-conditions-warning-message": "في الوقت الحالي، لم يتم تحديد أي شروط الوصول أدناه. ", + + // "access-control-no-access-conditions-warning-message": "Currently, no access conditions are specified below. If executed, this will replace the current access conditions with the default access conditions inherited from the owning collection.", + "access-control-no-access-conditions-warning-message": "في الوقت الراهن، لم يتم تحديد أي شروط وصول أدناه. عند التنفيذ، سيتم استبدال شروط الوصول الحالية بشروط الوصول الافتراضية الموروثة من المجموعة المالكة.", + + // "access-control-replace-all": "Replace access conditions", "access-control-replace-all": "استبدل شروط الوصول", + + // "access-control-add-to-existing": "Add to existing ones", "access-control-add-to-existing": "إضافة إلى الموجود", - "access-control-limit-to-specific": "قصر التغييرات على تدفقات بتجميلة", - "access-control-process-all-bitstreams": "تحديد كل التدفقات الواضحة في المادة", + + // "access-control-limit-to-specific": "Limit the changes to specific bitstreams", + "access-control-limit-to-specific": "قصر التغييرات على تدفقات بت معينة", + + // "access-control-process-all-bitstreams": "Update all the bitstreams in the item", + "access-control-process-all-bitstreams": "تحديد كل تدفقات البت في المادة", + + // "access-control-bitstreams-selected": "bitstreams selected", "access-control-bitstreams-selected": "تم تحديد تدفقات البت", + + // "access-control-bitstreams-select": "Select bitstreams", "access-control-bitstreams-select": "حدد تدفقات البت", + + // "access-control-cancel": "Cancel", "access-control-cancel": "إلغاء", + + // "access-control-execute": "Execute", "access-control-execute": "تنفيذ", + + // "access-control-add-more": "Add more", "access-control-add-more": "إضافة المزيد", + + // "access-control-remove": "Remove access condition", "access-control-remove": "إزالة شرط الوصول", + + // "access-control-select-bitstreams-modal.title": "Select bitstreams", "access-control-select-bitstreams-modal.title": "حدد تدفقات البت", - "access-control-select-bitstreams-modal.no-items": "لا يوجد شيء.", + + // "access-control-select-bitstreams-modal.no-items": "No items to show.", + "access-control-select-bitstreams-modal.no-items": "لا توجد مواد.", + + // "access-control-select-bitstreams-modal.close": "Close", "access-control-select-bitstreams-modal.close": "إلغاء", + + // "access-control-option-label": "Access condition type", "access-control-option-label": "نوع شرط الوصول", - "access-control-option-note": "اختر شرط وصول لتطبيقه على المواد المحددة.", - "access-control-option-start-date": "أمنح من الوصول", - "access-control-option-start-date-note": "قم بتسجيل التاريخ الذي يبدأ منه تطبيق شرط ذي الوصول ذي الصلة", - "access-control-option-end-date": "أمنح حتى الوصول", - "access-control-option-end-date-note": "يجب البدء بالتاريخ الذي سيتم تطبيق شرط الوصول ذي الصلة حتى أوله", + + // "access-control-option-note": "Choose an access condition to apply to selected objects.", + "access-control-option-note": "اختر شرط وصول لتطبيقه على الكائنات المحددة.", + + // "access-control-option-start-date": "Grant access from", + "access-control-option-start-date": "منح الوصول من", + + // "access-control-option-start-date-note": "Select the date from which the related access condition is applied", + "access-control-option-start-date-note": "قم بتحديد التاريخ الذي يبدأ منه تطبيق شرط الوصول ذي الصلة", + + // "access-control-option-end-date": "Grant access until", + "access-control-option-end-date": "منح الوصول حتى", + + // "access-control-option-end-date-note": "Select the date until which the related access condition is applied", + "access-control-option-end-date-note": "قم بتحديد التاريخ الذي سيتم تطبيق شرط الوصول ذي الصلة حتى بلوغه", + + // "vocabulary-treeview.search.form.add": "Add", "vocabulary-treeview.search.form.add": "إضافة", - "admin.notifications.publicationclaim.breadcrumbs": "لكي بالنشر", - "admin.notifications.publicationclaim.page.title": "لكي بالنشر", - "filter.search.operator.placeholder": "لها", - "search.filters.filter.entityType.text": "نوع الفرن", - "search.filters.operator.equals.text": "يساوي", - "search.filters.operator.notequals.text": "لا يساوي", - "search.filters.operator.notcontains.text": "لا يحتوي على", - "search.filters.operator.contains.text": "يحتوي على", - "search.filters.filter.title.text": "عنوان العنوان", - "search.filters.applied.f.title": "عنوان العنوان", - "search.filters.filter.author.text": "المؤلف", - "coar-notify-support.title": "COAR التمهيدي", - "coar-notify-support-title.content": "هنا، نحن ندعم بشكل كامل بروتوكول COAR Notify، المصمم لتعزيز الاتصال بين المستودعات. موقع إخطار COAR.", - "coar-notify-support.ldn-inbox.title": "صندوق LDN بريد", - "coar-notify-support.ldn-inbox.content": "من أجل راحتك، يمكن الوصول بسهولة إلى صندوق الوارد الخاص بـ LDN (إشعارات البيانات المرتبطة) على {ldnInboxUrl}. ", - "coar-notify-support.message-moderation.title": "الإشراف على الرسالة", - "coar-notify-support.message-moderation.content": "ولتوفير بيئة آمنة ومنتجة، يتم مراقبة جميع الرسائل. ", - "coar-notify-support.message-moderation.feedback-form": " دفتر نموذج.", - "service.overview.delete.header": "حذف الخدمة", - "ldn-registered-services.title": "الخدمات المميزة", - "ldn-registered-services.table.name": "الاسم", - "ldn-registered-services.table.description": "الوصف", - "ldn-registered-services.table.status": "الحالة", - "ldn-registered-services.table.action": "فعل", - "ldn-registered-services.new": "جديد", - "ldn-registered-services.new.breadcrumbs": "الخدمات المميزة", - "ldn-service.overview.table.enabled": "ممكن", - "ldn-service.overview.table.disabled": "ه", - "ldn-service.overview.table.clickToEnable": "انقر للتمكين", - "ldn-service.overview.table.clickToDisable": "انقر للتعطيل", - "ldn-edit-registered-service.title": "تحرير الخدمة", - "ldn-create-service.title": "إنشاء الخدمة", - "service.overview.create.modal": "إنشاء الخدمة", - "service.overview.create.body": "الرجاء التأكيد على إنشاء هذه الخدمة.", - "ldn-service-status": "الحالة", - "service.confirm.create": "إنشاء", - "service.refuse.create": "إلغاء", - "ldn-register-new-service.title": "تسجيل خدمة جديدة", - "ldn-new-service.form.label.submit": "حفظ", - "ldn-new-service.form.label.name": "اسم", - "ldn-new-service.form.label.description": "الوصف", - "ldn-new-service.form.label.url": "عنوان URL للخدمة", - "ldn-new-service.form.label.ip-range": "لخدمة نطاق IP", - "ldn-new-service.form.label.score": "مستوى الثقة", - "ldn-new-service.form.label.ldnUrl": "عنوان URL لصندوق بريد LDN", - "ldn-new-service.form.placeholder.name": "يرجى تقديم اسم الخدمة", - "ldn-new-service.form.placeholder.description": "يرجى تقديم وصف بخصوص خدمتك", - "ldn-new-service.form.placeholder.url": "يرجى إدخال عنوان URL للمستخدمين للتحقق من مزيد من المعلومات حول الخدمة", - "ldn-new-service.form.placeholder.lowerIp": "نطاق IPv4 الحد الأدنى", - "ldn-new-service.form.placeholder.upperIp": "نطاق IPv4 الحد الأعلى", - "ldn-new-service.form.placeholder.ldnUrl": "يرجى تحديد عنوان URL لصندوق LDN الوارد", - "ldn-new-service.form.placeholder.score": "الرجاء إدخال قيمة بين 0 و1. استخدم \".\" ", - "ldn-service.form.label.placeholder.default-select": "حدد نمطًا", - "ldn-service.form.pattern.ack-accept.label": "الاعتراف والقبول", - "ldn-service.form.pattern.ack-accept.description": "يستخدم هذا النمط للإقرار بالطلب (العرض) وقبوله. ", - "ldn-service.form.pattern.ack-accept.category": "شكر وتقدير", - "ldn-service.form.pattern.ack-reject.label": "الاعتراف والرفض", - "ldn-service.form.pattern.ack-reject.description": "يستخدم هذا النمط للإقرار بالطلب (العرض) ورفضه. ", - "ldn-service.form.pattern.ack-reject.category": "شكر وتقدير", - "ldn-service.form.pattern.ack-tentative-accept.label": "الإقرار والقبول مبدئيا", - "ldn-service.form.pattern.ack-tentative-accept.description": "يُستخدم هذا النمط للإقرار بالطلب (العرض) وقبوله مبدئيًا. ", - "ldn-service.form.pattern.ack-tentative-accept.category": "شكر وتقدير", - "ldn-service.form.pattern.ack-tentative-reject.label": "الاعتراف والرفض مبدئيا", - "ldn-service.form.pattern.ack-tentative-reject.description": "يُستخدم هذا النمط للإقرار بالطلب (العرض) ورفضه مبدئيًا. ", - "ldn-service.form.pattern.ack-tentative-reject.category": "شكر وتقدير", - "ldn-service.form.pattern.announce-endorsement.label": "إعلان المصادقة", - "ldn-service.form.pattern.announce-endorsement.description": "يُستخدم هذا النمط للإعلان عن وجود تأييد، مع الإشارة إلى المورد المعتمد.", - "ldn-service.form.pattern.announce-endorsement.category": "الإعلانات", - "ldn-service.form.pattern.announce-ingest.label": "أعلن عن استيعاب", - "ldn-service.form.pattern.announce-ingest.description": "يُستخدم هذا النمط للإعلان عن استيعاب أحد الموارد.", - "ldn-service.form.pattern.announce-ingest.category": "الإعلانات", - "ldn-service.form.pattern.announce-relationship.label": "أعلن عن العلاقة", - "ldn-service.form.pattern.announce-relationship.description": "يُستخدم هذا النمط للإعلان عن وجود علاقة بين مصدرين.", - "ldn-service.form.pattern.announce-relationship.category": "الإعلانات", - "ldn-service.form.pattern.announce-review.label": "الإعلان عن المراجعة", - "ldn-service.form.pattern.announce-review.description": "يُستخدم هذا النمط للإعلان عن وجود مراجعة، مع الإشارة إلى المورد الذي تمت مراجعته.", - "ldn-service.form.pattern.announce-review.category": "الإعلانات", - "ldn-service.form.pattern.announce-service-result.label": "الإعلان عن نتيجة الخدمة", - "ldn-service.form.pattern.announce-service-result.description": "يُستخدم هذا النمط للإعلان عن وجود \"نتيجة خدمة\"، مع الإشارة إلى المورد ذي الصلة.", - "ldn-service.form.pattern.announce-service-result.category": "الإعلانات", - "ldn-service.form.pattern.request-endorsement.label": "طلب المصادقة", - "ldn-service.form.pattern.request-endorsement.description": "يُستخدم هذا النمط لطلب المصادقة على مورد مملوك للنظام الأصلي.", - "ldn-service.form.pattern.request-endorsement.category": "الطلبات", - "ldn-service.form.pattern.request-ingest.label": "طلب استيعاب", - "ldn-service.form.pattern.request-ingest.description": "يُستخدم هذا النمط لمطالبة النظام المستهدف باستيعاب أحد الموارد.", - "ldn-service.form.pattern.request-ingest.category": "الطلبات", - "ldn-service.form.pattern.request-review.label": "طلب مراجعة", - "ldn-service.form.pattern.request-review.description": "يُستخدم هذا النمط لطلب مراجعة أحد الموارد المملوكة للنظام الأصلي.", - "ldn-service.form.pattern.request-review.category": "الطلبات", - "ldn-service.form.pattern.undo-offer.label": "التراجع عن العرض", - "ldn-service.form.pattern.undo-offer.description": "يُستخدم هذا النمط للتراجع عن (سحب) عرض تم تقديمه مسبقًا.", - "ldn-service.form.pattern.undo-offer.category": "الغاء التحميل", - "ldn-new-service.form.label.placeholder.selectedItemFilter": "لم يتم تحديد أي عنصر تصفية", - "ldn-new-service.form.label.ItemFilter": "عامل تصفية العنصر", - "ldn-new-service.form.label.automatic": "تلقائي", - "ldn-new-service.form.error.name": "مطلوب اسم", - "ldn-new-service.form.error.url": "عنوان URL مطلوب", - "ldn-new-service.form.error.ipRange": "الرجاء إدخال نطاق IP صالح", - "ldn-new-service.form.hint.ipRange": "الرجاء إدخال IPV4 صالح في كلا النطاقين (ملاحظة: بالنسبة لعنوان IP واحد، يرجى إدخال نفس القيمة في كلا الحقلين)", - "ldn-new-service.form.error.ldnurl": "عنوان URL لـ LDN مطلوب", - "ldn-new-service.form.error.patterns": "مطلوب نمط على الأقل", - "ldn-new-service.form.error.score": "الرجاء إدخال نتيجة صحيحة (بين 0 و1). ", - "ldn-new-service.form.label.inboundPattern": "النمط الوارد", - "ldn-new-service.form.label.addPattern": "+ أضف المزيد", - "ldn-new-service.form.label.removeItemFilter": "يزيل", - "ldn-register-new-service.breadcrumbs": "خدمة جديدة", - "service.overview.delete.body": "هل أنت متأكد أنك تريد حذف هذه الخدمة؟", - "service.overview.edit.body": "هل تؤكد التغييرات؟", - "service.overview.edit.modal": "تحرير الخدمة", - "service.detail.update": "يتأكد", - "service.detail.return": "يلغي", - "service.overview.reset-form.body": "هل أنت متأكد أنك تريد تجاهل التغييرات والمغادرة؟", - "service.overview.reset-form.modal": "تجاهل التغييرات", - "service.overview.reset-form.reset-confirm": "ينبذ", - "admin.registries.services-formats.modify.success.head": "تحرير ناجح", - "admin.registries.services-formats.modify.success.content": "تم تعديل الخدمة", - "admin.registries.services-formats.modify.failure.head": "فشل التحرير", - "admin.registries.services-formats.modify.failure.content": "لم يتم تحرير الخدمة", - "ldn-service-notification.created.success.title": "إنشاء ناجح", - "ldn-service-notification.created.success.body": "تم إنشاء الخدمة", - "ldn-service-notification.created.failure.title": "فشل الإنشاء", - "ldn-service-notification.created.failure.body": "لم يتم إنشاء الخدمة", - "ldn-service-notification.created.warning.title": "الرجاء تحديد نمط وارد واحد على الأقل", - "ldn-enable-service.notification.success.title": "تم تحديث الحالة بنجاح", - "ldn-enable-service.notification.success.content": "تم تحديث حالة الخدمة", - "ldn-service-delete.notification.success.title": "تم الحذف بنجاح", - "ldn-service-delete.notification.success.content": "تم حذف الخدمة", - "ldn-service-delete.notification.error.title": "فشل الحذف", - "ldn-service-delete.notification.error.content": "لم يتم حذف الخدمة", - "service.overview.reset-form.reset-return": "يلغي", - "service.overview.delete": "حذف الخدمة", - "ldn-edit-service.title": "تحرير الخدمة", - "ldn-edit-service.form.label.name": "اسم", - "ldn-edit-service.form.label.description": "وصف", - "ldn-edit-service.form.label.url": "عنوان URL للخدمة", - "ldn-edit-service.form.label.ldnUrl": "عنوان URL لصندوق بريد LDN", - "ldn-edit-service.form.label.inboundPattern": "النمط الوارد", - "ldn-edit-service.form.label.noInboundPatternSelected": "لا يوجد نمط وارد", - "ldn-edit-service.form.label.selectedItemFilter": "عامل تصفية العنصر المحدد", - "ldn-edit-service.form.label.selectItemFilter": "لا يوجد عامل تصفية للعناصر", - "ldn-edit-service.form.label.automatic": "تلقائي", - "ldn-edit-service.form.label.addInboundPattern": "+ أضف المزيد", - "ldn-edit-service.form.label.submit": "يحفظ", - "ldn-edit-service.breadcrumbs": "تحرير الخدمة", - "ldn-service.control-constaint-select-none": "لا تختر شيء", - "ldn-register-new-service.notification.error.title": "خطأ", - "ldn-register-new-service.notification.error.content": "حدث خطأ أثناء إنشاء هذه العملية", - "ldn-register-new-service.notification.success.title": "نجاح", - "ldn-register-new-service.notification.success.content": "تم إنشاء العملية بنجاح", - "submission.sections.notify.info": "الخدمة المحددة متوافقة مع العنصر وفقًا لحالته الحالية. {{ service.name }}: {{ service.description }}", - "item.page.endorsement": "تَأيِيد", - "item.page.review": "مراجعة", - "item.page.dataset": "مجموعة البيانات", - "menu.section.icon.ldn_services": "نظرة عامة على خدمات LDN", - "menu.section.services": "خدمات LDN", - "menu.section.services_new": "خدمة LDN", - "quality-assurance.topics.description-with-target": "أدناه يمكنك رؤية جميع المواضيع الواردة من الاشتراكات في {{source}} فيما يتعلق ب", - "quality-assurance.events.description": "هناك أدناه القائمة التي تحتوي على كافة الاقتراحات للموضوع للبحث.", - "quality-assurance.events.description-with-topic-and-target": "أسفل القائمة التي تحتوي على كافة الاقتراحات للموضوع المحدد {{topic}}، متعلق ب {{source}} و ", - "quality-assurance.event.table.event.message.serviceUrl": "عنوان الخدمة:", - "quality-assurance.event.table.event.message.link": "وصلة:", - "service.detail.delete.cancel": "يلغي", - "service.detail.delete.button": "حذف الخدمة", - "service.detail.delete.header": "حذف الخدمة", - "service.detail.delete.body": "هل أنت متأكد أنك تريد حذف الخدمة الحالية؟", - "service.detail.delete.confirm": "حذف الخدمة", - "service.detail.delete.success": "تم حذف الخدمة بنجاح.", - "service.detail.delete.error": "حدث خطأ ما عند حذف الخدمة", - "service.overview.table.id": "معرف الخدمات", - "service.overview.table.name": "اسم", - "service.overview.table.start": "وقت البدء (التوقيت العالمي المنسق)", - "service.overview.table.status": "حالة", - "service.overview.table.user": "مستخدم", - "service.overview.title": "نظرة عامة للخدمات", - "service.overview.breadcrumbs": "نظرة عامة للخدمات", - "service.overview.table.actions": "أجراءات", - "service.overview.table.description": "وصف", - "submission.sections.submit.progressbar.coarnotify": "إخطار COAR", - "submission.section.section-coar-notify.control.request-review.label": "يمكنك طلب مراجعة لإحدى الخدمات التالية", - "submission.section.section-coar-notify.control.request-endorsement.label": "يمكنك طلب المصادقة على إحدى المجلات المتراكبة التالية", - "submission.section.section-coar-notify.control.request-ingest.label": "يمكنك طلب استيعاب نسخة من طلبك إلى إحدى الخدمات التالية", - "submission.section.section-coar-notify.dropdown.no-data": "لا تتوافر بيانات", - "submission.section.section-coar-notify.dropdown.select-none": "لا تختر شيء", - "submission.section.section-coar-notify.small.notification": "اختر خدمة ل {{ pattern }} من هذا البند", - "submission.section.section-coar-notify.selection.description": "وصف الخدمة المختارة:", - "submission.section.section-coar-notify.selection.no-description": "لا تتوفر المزيد من المعلومات", - "submission.section.section-coar-notify.notification.error": "الخدمة المحددة غير مناسبة للعنصر الحالي. ", - "submission.section.section-coar-notify.info.no-pattern": "لم يتم العثور على أنماط قابلة للتكوين.", - "error.validation.coarnotify.invalidfilter": "عامل التصفية غير صالح، حاول تحديد خدمة أخرى أو لا شيء.", - "request-status-alert-box.accepted": "المطلوب {{ offerType }} ل {{ serviceName }} وقد تم توليه المسؤولية.", - "request-status-alert-box.rejected": "المطلوب {{ offerType }} ل {{ serviceName }} وقد رفض.", - "request-status-alert-box.requested": "المطلوب {{ offerType }} ل {{ serviceName }} معلق.", - "ldn-service-button-mark-inbound-deletion": "وضع علامة على النمط الوارد للحذف", - "ldn-service-button-unmark-inbound-deletion": "قم بإلغاء تحديد النمط الوارد للحذف", - "ldn-service-input-inbound-item-filter-dropdown": "حدد عامل تصفية العنصر للنمط الوارد", - "ldn-service-input-inbound-pattern-dropdown": "حدد النمط الوارد للخدمة", - "ldn-service-overview-select-delete": "اختر الخدمة للحذف", - "ldn-service-overview-select-edit": "تحرير خدمة LDN", - "ldn-service-overview-close-modal": "إغلاق مشروط", - "a-common-or_statement.label": "نوع العنصر هو مقالة يومية أو مجموعة بيانات", - "always_true_filter.label": "دائما صحيح او صادق", - "automatic_processing_collection_filter_16.label": "المعالجة التلقائية", - "dc-identifier-uri-contains-doi_condition.label": "يحتوي URI على DOI", - "doi-filter.label": "مرشح DOI", - "driver-document-type_condition.label": "نوع المستند يساوي السائق", - "has-at-least-one-bitstream_condition.label": "يحتوي على Bitstream واحد على الأقل", - "has-bitstream_filter.label": "لديه تيار البت", - "has-one-bitstream_condition.label": "لديه Bitstream واحد", - "is-archived_condition.label": "تمت أرشفته", - "is-withdrawn_condition.label": "تم سحبه", - "item-is-public_condition.label": "العنصر عام", - "journals_ingest_suggestion_collection_filter_18.label": "استيعاب المجلات", - "title-starts-with-pattern_condition.label": "يبدأ العنوان بالنمط", - "type-equals-dataset_condition.label": "النوع يساوي مجموعة البيانات", - "type-equals-journal-article_condition.label": "النوع يساوي مقالة يومية", - "search.filters.filter.subject.text": "موضوع", - "search.advanced.filters.head": "البحث المتقدم", - "filter.search.text.placeholder": "بحث في النص", - "advancesearch.form.submit": "يضيف", - "ldn.no-filter.label": "لا أحد", - "admin.notify.dashboard": "لوحة القيادة", - "menu.section.notify_dashboard": "لوحة القيادة", - "menu.section.coar_notify": "إخطار COAR", - "admin-notify-dashboard.title": "لوحة الإخطار", - "admin-notify-dashboard.description": "تراقب لوحة معلومات Notify الاستخدام العام لبروتوكول COAR Notify عبر المستودع. ", - "admin-notify-dashboard.metrics": "المقاييس", - "admin-notify-dashboard.received-ldn": "عدد LDN المستلم", - "admin-notify-dashboard.generated-ldn": "عدد LDN الذي تم إنشاؤه", - "admin-notify-dashboard.NOTIFY.incoming.accepted": "قبلت", - "admin-notify-dashboard.NOTIFY.incoming.accepted.description": "الإخطارات الواردة المقبولة", - "admin-notify-logs.NOTIFY.incoming.accepted": "يعرض حاليا: الإخطارات المقبولة", - "admin-notify-dashboard.NOTIFY.incoming.processed": "LDN المعالجة", - "admin-notify-dashboard.NOTIFY.incoming.processed.description": "معالجة الإخطارات الواردة", - "admin-notify-logs.NOTIFY.incoming.processed": "المعروض حاليا: LDN المعالج", - "admin-notify-logs.NOTIFY.incoming.failure": "المعروض حاليًا: الإشعارات الفاشلة", - "admin-notify-dashboard.NOTIFY.incoming.failure": "فشل", - "admin-notify-dashboard.NOTIFY.incoming.failure.description": "فشل الإخطارات الواردة", - "admin-notify-logs.NOTIFY.outgoing.failure": "المعروض حاليًا: الإشعارات الفاشلة", - "admin-notify-dashboard.NOTIFY.outgoing.failure": "فشل", - "admin-notify-dashboard.NOTIFY.outgoing.failure.description": "فشل الإخطارات الصادرة", - "admin-notify-logs.NOTIFY.incoming.untrusted": "المعروض حاليًا: إشعارات غير موثوقة", - "admin-notify-dashboard.NOTIFY.incoming.untrusted": "غير موثوق به", - "admin-notify-dashboard.NOTIFY.incoming.untrusted.description": "الإخطارات الواردة غير موثوق بها", - "admin-notify-logs.NOTIFY.incoming.delivered": "المعروض حاليًا: الإخطارات التي تم تسليمها", - "admin-notify-dashboard.NOTIFY.incoming.delivered.description": "تم تسليم الإشعارات الواردة بنجاح", - "admin-notify-dashboard.NOTIFY.outgoing.delivered": "تم التوصيل", - "admin-notify-logs.NOTIFY.outgoing.delivered": "المعروض حاليًا: الإخطارات التي تم تسليمها", - "admin-notify-dashboard.NOTIFY.outgoing.delivered.description": "تم تسليم الإخطارات الصادرة بنجاح", - "admin-notify-logs.NOTIFY.outgoing.queued": "المعروض حاليًا: الإشعارات في قائمة الانتظار", - "admin-notify-dashboard.NOTIFY.outgoing.queued.description": "الإخطارات في قائمة الانتظار حاليا", - "admin-notify-dashboard.NOTIFY.outgoing.queued": "في قائمة الانتظار", - "admin-notify-logs.NOTIFY.outgoing.queued_for_retry": "يتم العرض حاليًا: في قائمة الانتظار لإعادة محاولة الإشعارات", - "admin-notify-dashboard.NOTIFY.outgoing.queued_for_retry": "في قائمة الانتظار لإعادة المحاولة", - "admin-notify-dashboard.NOTIFY.outgoing.queued_for_retry.description": "الإخطارات في قائمة الانتظار حاليا لإعادة المحاولة", - "admin-notify-dashboard.NOTIFY.incoming.involvedItems": "العناصر المعنية", - "admin-notify-dashboard.NOTIFY.incoming.involvedItems.description": "العناصر المتعلقة بالإخطارات الواردة", - "admin-notify-dashboard.NOTIFY.outgoing.involvedItems": "العناصر المعنية", - "admin-notify-dashboard.NOTIFY.outgoing.involvedItems.description": "العناصر المتعلقة بالإخطارات الصادرة", - "admin.notify.dashboard.breadcrumbs": "لوحة القيادة", - "admin.notify.dashboard.inbound": "الرسائل الواردة", - "admin.notify.dashboard.inbound-logs": "السجلات/الواردة", - "admin.notify.dashboard.filter": "منقي: ", - "search.filters.applied.f.relateditem": "الأصناف المتعلقة", - "search.filters.applied.f.ldn_service": "خدمة LDN", - "search.filters.applied.f.notifyReview": "إخطار المراجعة", - "search.filters.applied.f.notifyEndorsement": "إخطار المصادقة", - "search.filters.applied.f.notifyRelation": "إخطار العلاقة", - "search.filters.filter.queue_last_start_time.head": "آخر وقت للمعالجة ", - "search.filters.filter.queue_last_start_time.min.label": "نطاق الحد الأدنى", - "search.filters.filter.queue_last_start_time.max.label": "أقصى مدى", - "search.filters.applied.f.queue_last_start_time.min": "نطاق الحد الأدنى", - "search.filters.applied.f.queue_last_start_time.max": "أقصى مدى", - "admin.notify.dashboard.outbound": "الرسائل الصادرة", - "admin.notify.dashboard.outbound-logs": "السجلات/الصادرة", - "NOTIFY.incoming.search.results.head": "وارد", - "search.filters.filter.relateditem.head": "البند ذو الصلة", - "search.filters.filter.origin.head": "أصل", - "search.filters.filter.ldn_service.head": "خدمة LDN", - "search.filters.filter.target.head": "هدف", - "search.filters.filter.queue_status.head": "حالة قائمة الانتظار", - "search.filters.filter.activity_stream_type.head": "نوع تيار النشاط", - "search.filters.filter.coar_notify_type.head": "نوع الإخطار COAR", - "search.filters.filter.notification_type.head": "نوع إعلام", - "search.filters.filter.relateditem.label": "البحث عن العناصر ذات الصلة", - "search.filters.filter.queue_status.label": "حالة قائمة انتظار البحث", - "search.filters.filter.target.label": "هدف البحث", - "search.filters.filter.activity_stream_type.label": "نوع دفق نشاط البحث", - "search.filters.applied.f.queue_status": "حالة قائمة الانتظار", - "search.filters.queue_status.0,authority": "IP غير موثوق به", - "search.filters.queue_status.1,authority": "في قائمة الانتظار", - "search.filters.queue_status.2,authority": "يعالج", - "search.filters.queue_status.3,authority": "تمت معالجتها", - "search.filters.queue_status.4,authority": "فشل", - "search.filters.queue_status.5,authority": "غير موثوق به", - "search.filters.queue_status.6,authority": "عمل غير محدد", - "search.filters.queue_status.7,authority": "في قائمة الانتظار لإعادة المحاولة", - "search.filters.applied.f.activity_stream_type": "نوع تيار النشاط", - "search.filters.applied.f.coar_notify_type": "نوع الإخطار COAR", - "search.filters.applied.f.notification_type": "نوع إعلام", - "search.filters.filter.coar_notify_type.label": "بحث COAR نوع الإخطار", - "search.filters.filter.notification_type.label": "بحث نوع الإخطار", - "search.filters.filter.relateditem.placeholder": "الأصناف المتعلقة", - "search.filters.filter.target.placeholder": "هدف", - "search.filters.filter.origin.label": "مصدر البحث", - "search.filters.filter.origin.placeholder": "مصدر", - "search.filters.filter.ldn_service.label": "ابحث في خدمة LDN", - "search.filters.filter.ldn_service.placeholder": "خدمة LDN", - "search.filters.filter.queue_status.placeholder": "حالة قائمة الانتظار", - "search.filters.filter.activity_stream_type.placeholder": "نوع تيار النشاط", - "search.filters.filter.coar_notify_type.placeholder": "نوع الإخطار COAR", - "search.filters.filter.notification_type.placeholder": "إشعار", - "search.filters.filter.notifyRelation.head": "إخطار العلاقة", - "search.filters.filter.notifyRelation.label": "بحث إخطار العلاقة", - "search.filters.filter.notifyRelation.placeholder": "إخطار العلاقة", - "search.filters.filter.notifyReview.head": "إخطار المراجعة", - "search.filters.filter.notifyReview.label": "بحث إخطار المراجعة", - "search.filters.filter.notifyReview.placeholder": "إخطار المراجعة", - "search.filters.coar_notify_type.coar-notify:ReviewAction": "إجراء المراجعة", - "search.filters.coar_notify_type.coar-notify:ReviewAction,authority": "إجراء المراجعة", - "notify-detail-modal.coar-notify:ReviewAction": "إجراء المراجعة", - "search.filters.coar_notify_type.coar-notify:EndorsementAction": "إجراء الإقرار", - "search.filters.coar_notify_type.coar-notify:EndorsementAction,authority": "إجراء الإقرار", - "notify-detail-modal.coar-notify:EndorsementAction": "إجراء الإقرار", - "search.filters.coar_notify_type.coar-notify:IngestAction": "استيعاب العمل", - "search.filters.coar_notify_type.coar-notify:IngestAction,authority": "استيعاب العمل", - "notify-detail-modal.coar-notify:IngestAction": "استيعاب العمل", - "search.filters.coar_notify_type.coar-notify:RelationshipAction": "عمل العلاقة", - "search.filters.coar_notify_type.coar-notify:RelationshipAction,authority": "عمل العلاقة", - "notify-detail-modal.coar-notify:RelationshipAction": "عمل العلاقة", - "search.filters.queue_status.QUEUE_STATUS_QUEUED": "في قائمة الانتظار", - "notify-detail-modal.QUEUE_STATUS_QUEUED": "في قائمة الانتظار", - "search.filters.queue_status.QUEUE_STATUS_QUEUED_FOR_RETRY": "في قائمة الانتظار لإعادة المحاولة", - "notify-detail-modal.QUEUE_STATUS_QUEUED_FOR_RETRY": "في قائمة الانتظار لإعادة المحاولة", - "search.filters.queue_status.QUEUE_STATUS_PROCESSING": "يعالج", - "notify-detail-modal.QUEUE_STATUS_PROCESSING": "يعالج", - "search.filters.queue_status.QUEUE_STATUS_PROCESSED": "تمت معالجتها", - "notify-detail-modal.QUEUE_STATUS_PROCESSED": "تمت معالجتها", - "search.filters.queue_status.QUEUE_STATUS_FAILED": "فشل", - "notify-detail-modal.QUEUE_STATUS_FAILED": "فشل", - "search.filters.queue_status.QUEUE_STATUS_UNTRUSTED": "غير موثوق به", - "search.filters.queue_status.QUEUE_STATUS_UNTRUSTED_IP": "IP غير موثوق به", - "notify-detail-modal.QUEUE_STATUS_UNTRUSTED": "غير موثوق به", - "notify-detail-modal.QUEUE_STATUS_UNTRUSTED_IP": "IP غير موثوق به", - "search.filters.queue_status.QUEUE_STATUS_UNMAPPED_ACTION": "عمل غير محدد", - "notify-detail-modal.QUEUE_STATUS_UNMAPPED_ACTION": "عمل غير محدد", - "sorting.queue_last_start_time.DESC": "آخر قائمة انتظار بدأت تنازليًا", - "sorting.queue_last_start_time.ASC": "آخر قائمة انتظار بدأت تصاعديًا", - "sorting.queue_attempts.DESC": "حاولت قائمة الانتظار التنازلي", - "sorting.queue_attempts.ASC": "حاولت قائمة الانتظار التصاعدي", - "NOTIFY.incoming.involvedItems.search.results.head": "العناصر المشاركة في LDN الوارد", - "NOTIFY.outgoing.involvedItems.search.results.head": "العناصر المشاركة في LDN الصادرة", - "type.notify-detail-modal": "يكتب", - "id.notify-detail-modal": "بطاقة تعريف", - "coarNotifyType.notify-detail-modal": "نوع الإخطار COAR", - "activityStreamType.notify-detail-modal": "نوع تيار النشاط", - "inReplyTo.notify-detail-modal": "ردا على", - "object.notify-detail-modal": "عنصر المستودع", - "context.notify-detail-modal": "عنصر المستودع", - "queueAttempts.notify-detail-modal": "محاولات قائمة الانتظار", - "queueLastStartTime.notify-detail-modal": "بدأت قائمة الانتظار آخر مرة", - "origin.notify-detail-modal": "خدمة LDN", - "target.notify-detail-modal": "خدمة LDN", - "queueStatusLabel.notify-detail-modal": "حالة قائمة الانتظار", - "queueTimeout.notify-detail-modal": "مهلة قائمة الانتظار", - "notify-message-modal.title": "تفاصيل الرسالة", - "notify-message-modal.show-message": "اظهر الرسالة", - "notify-message-result.timestamp": "الطابع الزمني", - "notify-message-result.repositoryItem": "عنصر المستودع", - "notify-message-result.ldnService": "خدمة LDN", - "notify-message-result.type": "يكتب", - "notify-message-result.status": "حالة", - "notify-message-result.action": "فعل", - "notify-message-result.detail": "التفاصيل", - "notify-message-result.reprocess": "إعادة المعالجة", - "notify-queue-status.processed": "تمت معالجتها", - "notify-queue-status.failed": "فشل", - "notify-queue-status.queue_retry": "في قائمة الانتظار لإعادة المحاولة", - "notify-queue-status.unmapped_action": "عمل غير معين", - "notify-queue-status.processing": "يعالج", - "notify-queue-status.queued": "في قائمة الانتظار", - "notify-queue-status.untrusted": "غير موثوق به", - "ldnService.notify-detail-modal": "خدمة LDN", - "relatedItem.notify-detail-modal": "البند ذو الصلة", - "search.filters.filter.notifyEndorsement.head": "إخطار المصادقة", - "search.filters.filter.notifyEndorsement.placeholder": "إخطار المصادقة", - "search.filters.filter.notifyEndorsement.label": "بحث الإخطار بالمصادقة", + + // "admin.notifications.publicationclaim.breadcrumbs": "Publication Claim", + // TODO New key - Add a translation + "admin.notifications.publicationclaim.breadcrumbs": "Publication Claim", + + // "admin.notifications.publicationclaim.page.title": "Publication Claim", + // TODO New key - Add a translation + "admin.notifications.publicationclaim.page.title": "Publication Claim", + + // "filter.search.operator.placeholder": "Operator", + // TODO New key - Add a translation + "filter.search.operator.placeholder": "Operator", + + // "search.filters.filter.entityType.text": "Item Type", + // TODO New key - Add a translation + "search.filters.filter.entityType.text": "Item Type", + + // "search.filters.operator.equals.text": "Equals", + // TODO New key - Add a translation + "search.filters.operator.equals.text": "Equals", + + // "search.filters.operator.notequals.text": "Not Equals", + // TODO New key - Add a translation + "search.filters.operator.notequals.text": "Not Equals", + + // "search.filters.operator.notcontains.text": "Not Contains", + // TODO New key - Add a translation + "search.filters.operator.notcontains.text": "Not Contains", + + // "search.filters.operator.contains.text": "Contains", + // TODO New key - Add a translation + "search.filters.operator.contains.text": "Contains", + + // "search.filters.filter.title.text": "Title", + // TODO New key - Add a translation + "search.filters.filter.title.text": "Title", + + // "search.filters.applied.f.title": "Title", + // TODO New key - Add a translation + "search.filters.applied.f.title": "Title", + + // "search.filters.filter.author.text": "Author", + // TODO New key - Add a translation + "search.filters.filter.author.text": "Author", + + // "coar-notify-support.title": "COAR Notify Protocol", + // TODO New key - Add a translation + "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.", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "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.", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "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.", + // TODO New key - Add a translation + "coar-notify-support.message-moderation.feedback-form": " Feedback form.", + + // "service.overview.delete.header": "Delete Service", + // TODO New key - Add a translation + "service.overview.delete.header": "Delete Service", + + // "ldn-registered-services.title": "Registered Services", + // TODO New key - Add a translation + "ldn-registered-services.title": "Registered Services", + // "ldn-registered-services.table.name": "Name", + // TODO New key - Add a translation + "ldn-registered-services.table.name": "Name", + // "ldn-registered-services.table.description": "Description", + // TODO New key - Add a translation + "ldn-registered-services.table.description": "Description", + // "ldn-registered-services.table.status": "Status", + // TODO New key - Add a translation + "ldn-registered-services.table.status": "Status", + // "ldn-registered-services.table.action": "Action", + // TODO New key - Add a translation + "ldn-registered-services.table.action": "Action", + // "ldn-registered-services.new": "NEW", + // TODO New key - Add a translation + "ldn-registered-services.new": "NEW", + // "ldn-registered-services.new.breadcrumbs": "Registered Services", + // TODO New key - Add a translation + "ldn-registered-services.new.breadcrumbs": "Registered Services", + + // "ldn-service.overview.table.enabled": "Enabled", + // TODO New key - Add a translation + "ldn-service.overview.table.enabled": "Enabled", + // "ldn-service.overview.table.disabled": "Disabled", + // TODO New key - Add a translation + "ldn-service.overview.table.disabled": "Disabled", + // "ldn-service.overview.table.clickToEnable": "Click to enable", + // TODO New key - Add a translation + "ldn-service.overview.table.clickToEnable": "Click to enable", + // "ldn-service.overview.table.clickToDisable": "Click to disable", + // TODO New key - Add a translation + "ldn-service.overview.table.clickToDisable": "Click to disable", + + // "ldn-edit-registered-service.title": "Edit Service", + // TODO New key - Add a translation + "ldn-edit-registered-service.title": "Edit Service", + // "ldn-create-service.title": "Create service", + // TODO New key - Add a translation + "ldn-create-service.title": "Create service", + // "service.overview.create.modal": "Create Service", + // TODO New key - Add a translation + "service.overview.create.modal": "Create Service", + // "service.overview.create.body": "Please confirm the creation of this service.", + // TODO New key - Add a translation + "service.overview.create.body": "Please confirm the creation of this service.", + // "ldn-service-status": "Status", + // TODO New key - Add a translation + "ldn-service-status": "Status", + // "service.confirm.create": "Create", + // TODO New key - Add a translation + "service.confirm.create": "Create", + // "service.refuse.create": "Cancel", + // TODO New key - Add a translation + "service.refuse.create": "Cancel", + // "ldn-register-new-service.title": "Register a new service", + // TODO New key - Add a translation + "ldn-register-new-service.title": "Register a new service", + // "ldn-new-service.form.label.submit": "Save", + // TODO New key - Add a translation + "ldn-new-service.form.label.submit": "Save", + // "ldn-new-service.form.label.name": "Name", + // TODO New key - Add a translation + "ldn-new-service.form.label.name": "Name", + // "ldn-new-service.form.label.description": "Description", + // TODO New key - Add a translation + "ldn-new-service.form.label.description": "Description", + // "ldn-new-service.form.label.url": "Service URL", + // TODO New key - Add a translation + "ldn-new-service.form.label.url": "Service URL", + // "ldn-new-service.form.label.ip-range": "Service IP range", + // TODO New key - Add a translation + "ldn-new-service.form.label.ip-range": "Service IP range", + // "ldn-new-service.form.label.score": "Level of trust", + // TODO New key - Add a translation + "ldn-new-service.form.label.score": "Level of trust", + // "ldn-new-service.form.label.ldnUrl": "LDN Inbox URL", + // TODO New key - Add a translation + "ldn-new-service.form.label.ldnUrl": "LDN Inbox URL", + // "ldn-new-service.form.placeholder.name": "Please provide service name", + // TODO New key - Add a translation + "ldn-new-service.form.placeholder.name": "Please provide service name", + // "ldn-new-service.form.placeholder.description": "Please provide a description regarding your service", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "ldn-new-service.form.placeholder.lowerIp": "IPv4 range lower bound", + // "ldn-new-service.form.placeholder.upperIp": "IPv4 range upper bound", + // TODO New key - Add a translation + "ldn-new-service.form.placeholder.upperIp": "IPv4 range upper bound", + // "ldn-new-service.form.placeholder.ldnUrl": "Please specify the URL of the LDN Inbox", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "ldn-service.form.label.placeholder.default-select": "Select a pattern", + + // "ldn-service.form.pattern.ack-accept.label": "Acknowledge and Accept", + // TODO New key - Add a translation + "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.", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "ldn-service.form.pattern.ack-accept.category": "Acknowledgements", + + // "ldn-service.form.pattern.ack-reject.label": "Acknowledge and Reject", + // TODO New key - Add a translation + "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.", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "ldn-service.form.pattern.ack-reject.category": "Acknowledgements", + + // "ldn-service.form.pattern.ack-tentative-accept.label": "Acknowledge and Tentatively Accept", + // TODO New key - Add a translation + "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.", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "ldn-service.form.pattern.ack-tentative-accept.category": "Acknowledgements", + + // "ldn-service.form.pattern.ack-tentative-reject.label": "Acknowledge and Tentatively Reject", + // TODO New key - Add a translation + "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.", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "ldn-service.form.pattern.ack-tentative-reject.category": "Acknowledgements", + + // "ldn-service.form.pattern.announce-endorsement.label": "Announce Endorsement", + // TODO New key - Add a translation + "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.", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "ldn-service.form.pattern.announce-endorsement.category": "Announcements", + + // "ldn-service.form.pattern.announce-ingest.label": "Announce Ingest", + // TODO New key - Add a translation + "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.", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "ldn-service.form.pattern.announce-ingest.category": "Announcements", + + // "ldn-service.form.pattern.announce-relationship.label": "Announce Relationship", + // TODO New key - Add a translation + "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.", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "ldn-service.form.pattern.announce-relationship.category": "Announcements", + + // "ldn-service.form.pattern.announce-review.label": "Announce Review", + // TODO New key - Add a translation + "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.", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "ldn-service.form.pattern.announce-review.category": "Announcements", + + // "ldn-service.form.pattern.announce-service-result.label": "Announce Service Result", + // TODO New key - Add a translation + "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.", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "ldn-service.form.pattern.announce-service-result.category": "Announcements", + + // "ldn-service.form.pattern.request-endorsement.label": "Request Endorsement", + // TODO New key - Add a translation + "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.", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "ldn-service.form.pattern.request-endorsement.category": "Requests", + + // "ldn-service.form.pattern.request-ingest.label": "Request Ingest", + // TODO New key - Add a translation + "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.", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "ldn-service.form.pattern.request-ingest.category": "Requests", + + // "ldn-service.form.pattern.request-review.label": "Request Review", + // TODO New key - Add a translation + "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.", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "ldn-service.form.pattern.request-review.category": "Requests", + + // "ldn-service.form.pattern.undo-offer.label": "Undo Offer", + // TODO New key - Add a translation + "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.", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "ldn-service.form.pattern.undo-offer.category": "Undo", + + // "ldn-new-service.form.label.placeholder.selectedItemFilter": "No Item Filter Selected", + // TODO New key - Add a translation + "ldn-new-service.form.label.placeholder.selectedItemFilter": "No Item Filter Selected", + // "ldn-new-service.form.label.ItemFilter": "Item Filter", + // TODO New key - Add a translation + "ldn-new-service.form.label.ItemFilter": "Item Filter", + // "ldn-new-service.form.label.automatic": "Automatic", + // TODO New key - Add a translation + "ldn-new-service.form.label.automatic": "Automatic", + // "ldn-new-service.form.error.name": "Name is required", + // TODO New key - Add a translation + "ldn-new-service.form.error.name": "Name is required", + // "ldn-new-service.form.error.url": "URL is required", + // TODO New key - Add a translation + "ldn-new-service.form.error.url": "URL is required", + // "ldn-new-service.form.error.ipRange": "Please enter a valid IP range", + // TODO New key - Add a translation + "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)", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "ldn-new-service.form.error.ldnurl": "LDN URL is required", + // "ldn-new-service.form.error.patterns": "At least a pattern is required", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "ldn-new-service.form.label.inboundPattern": "Inbound Pattern", + // "ldn-new-service.form.label.addPattern": "+ Add more", + // TODO New key - Add a translation + "ldn-new-service.form.label.addPattern": "+ Add more", + // "ldn-new-service.form.label.removeItemFilter": "Remove", + // TODO New key - Add a translation + "ldn-new-service.form.label.removeItemFilter": "Remove", + // "ldn-register-new-service.breadcrumbs": "New Service", + // TODO New key - Add a translation + "ldn-register-new-service.breadcrumbs": "New Service", + // "service.overview.delete.body": "Are you sure you want to delete this service?", + // TODO New key - Add a translation + "service.overview.delete.body": "Are you sure you want to delete this service?", + // "service.overview.edit.body": "Do you confirm the changes?", + // TODO New key - Add a translation + "service.overview.edit.body": "Do you confirm the changes?", + // "service.overview.edit.modal": "Edit Service", + // TODO New key - Add a translation + "service.overview.edit.modal": "Edit Service", + // "service.detail.update": "Confirm", + // TODO New key - Add a translation + "service.detail.update": "Confirm", + // "service.detail.return": "Cancel", + // TODO New key - Add a translation + "service.detail.return": "Cancel", + // "service.overview.reset-form.body": "Are you sure you want to discard the changes and leave?", + // TODO New key - Add a translation + "service.overview.reset-form.body": "Are you sure you want to discard the changes and leave?", + // "service.overview.reset-form.modal": "Discard Changes", + // TODO New key - Add a translation + "service.overview.reset-form.modal": "Discard Changes", + // "service.overview.reset-form.reset-confirm": "Discard", + // TODO New key - Add a translation + "service.overview.reset-form.reset-confirm": "Discard", + // "admin.registries.services-formats.modify.success.head": "Successful Edit", + // TODO New key - Add a translation + "admin.registries.services-formats.modify.success.head": "Successful Edit", + // "admin.registries.services-formats.modify.success.content": "The service has been edited", + // TODO New key - Add a translation + "admin.registries.services-formats.modify.success.content": "The service has been edited", + // "admin.registries.services-formats.modify.failure.head": "Failed Edit", + // TODO New key - Add a translation + "admin.registries.services-formats.modify.failure.head": "Failed Edit", + // "admin.registries.services-formats.modify.failure.content": "The service has not been edited", + // TODO New key - Add a translation + "admin.registries.services-formats.modify.failure.content": "The service has not been edited", + // "ldn-service-notification.created.success.title": "Successful Create", + // TODO New key - Add a translation + "ldn-service-notification.created.success.title": "Successful Create", + // "ldn-service-notification.created.success.body": "The service has been created", + // TODO New key - Add a translation + "ldn-service-notification.created.success.body": "The service has been created", + // "ldn-service-notification.created.failure.title": "Failed Create", + // TODO New key - Add a translation + "ldn-service-notification.created.failure.title": "Failed Create", + // "ldn-service-notification.created.failure.body": "The service has not been created", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "ldn-service-notification.created.warning.title": "Please select at least one Inbound Pattern", + // "ldn-enable-service.notification.success.title": "Successful status updated", + // TODO New key - Add a translation + "ldn-enable-service.notification.success.title": "Successful status updated", + // "ldn-enable-service.notification.success.content": "The service status has been updated", + // TODO New key - Add a translation + "ldn-enable-service.notification.success.content": "The service status has been updated", + // "ldn-service-delete.notification.success.title": "Successful Deletion", + // TODO New key - Add a translation + "ldn-service-delete.notification.success.title": "Successful Deletion", + // "ldn-service-delete.notification.success.content": "The service has been deleted", + // TODO New key - Add a translation + "ldn-service-delete.notification.success.content": "The service has been deleted", + // "ldn-service-delete.notification.error.title": "Failed Deletion", + // TODO New key - Add a translation + "ldn-service-delete.notification.error.title": "Failed Deletion", + // "ldn-service-delete.notification.error.content": "The service has not been deleted", + // TODO New key - Add a translation + "ldn-service-delete.notification.error.content": "The service has not been deleted", + // "service.overview.reset-form.reset-return": "Cancel", + // TODO New key - Add a translation + "service.overview.reset-form.reset-return": "Cancel", + // "service.overview.delete": "Delete service", + // TODO New key - Add a translation + "service.overview.delete": "Delete service", + // "ldn-edit-service.title": "Edit service", + // TODO New key - Add a translation + "ldn-edit-service.title": "Edit service", + // "ldn-edit-service.form.label.name": "Name", + // TODO New key - Add a translation + "ldn-edit-service.form.label.name": "Name", + // "ldn-edit-service.form.label.description": "Description", + // TODO New key - Add a translation + "ldn-edit-service.form.label.description": "Description", + // "ldn-edit-service.form.label.url": "Service URL", + // TODO New key - Add a translation + "ldn-edit-service.form.label.url": "Service URL", + // "ldn-edit-service.form.label.ldnUrl": "LDN Inbox URL", + // TODO New key - Add a translation + "ldn-edit-service.form.label.ldnUrl": "LDN Inbox URL", + // "ldn-edit-service.form.label.inboundPattern": "Inbound Pattern", + // TODO New key - Add a translation + "ldn-edit-service.form.label.inboundPattern": "Inbound Pattern", + // "ldn-edit-service.form.label.noInboundPatternSelected": "No Inbound Pattern", + // TODO New key - Add a translation + "ldn-edit-service.form.label.noInboundPatternSelected": "No Inbound Pattern", + // "ldn-edit-service.form.label.selectedItemFilter": "Selected Item Filter", + // TODO New key - Add a translation + "ldn-edit-service.form.label.selectedItemFilter": "Selected Item Filter", + // "ldn-edit-service.form.label.selectItemFilter": "No Item Filter", + // TODO New key - Add a translation + "ldn-edit-service.form.label.selectItemFilter": "No Item Filter", + // "ldn-edit-service.form.label.automatic": "Automatic", + // TODO New key - Add a translation + "ldn-edit-service.form.label.automatic": "Automatic", + // "ldn-edit-service.form.label.addInboundPattern": "+ Add more", + // TODO New key - Add a translation + "ldn-edit-service.form.label.addInboundPattern": "+ Add more", + // "ldn-edit-service.form.label.submit": "Save", + // TODO New key - Add a translation + "ldn-edit-service.form.label.submit": "Save", + // "ldn-edit-service.breadcrumbs": "Edit Service", + // TODO New key - Add a translation + "ldn-edit-service.breadcrumbs": "Edit Service", + // "ldn-service.control-constaint-select-none": "Select none", + // TODO New key - Add a translation + "ldn-service.control-constaint-select-none": "Select none", + + // "ldn-register-new-service.notification.error.title": "Error", + // TODO New key - Add a translation + "ldn-register-new-service.notification.error.title": "Error", + // "ldn-register-new-service.notification.error.content": "An error occurred while creating this process", + // TODO New key - Add a translation + "ldn-register-new-service.notification.error.content": "An error occurred while creating this process", + // "ldn-register-new-service.notification.success.title": "Success", + // TODO New key - Add a translation + "ldn-register-new-service.notification.success.title": "Success", + // "ldn-register-new-service.notification.success.content": "The process was successfully created", + // TODO New key - Add a translation + "ldn-register-new-service.notification.success.content": "The process was successfully created", + + // "submission.sections.notify.info": "The selected service is compatible with the item according to its current status. {{ service.name }}: {{ service.description }}", + // TODO New key - Add a translation + "submission.sections.notify.info": "The selected service is compatible with the item according to its current status. {{ service.name }}: {{ service.description }}", + + // "item.page.endorsement": "Endorsement", + // TODO New key - Add a translation + "item.page.endorsement": "Endorsement", + + // "item.page.review": "Review", + // TODO New key - Add a translation + "item.page.review": "Review", + + // "item.page.dataset": "Dataset", + // TODO New key - Add a translation + "item.page.dataset": "Dataset", + // "menu.section.icon.ldn_services": "LDN Services overview", + // TODO New key - Add a translation + "menu.section.icon.ldn_services": "LDN Services overview", + // "menu.section.services": "LDN Services", + // TODO New key - Add a translation + "menu.section.services": "LDN Services", + + // "menu.section.services_new": "LDN Service", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "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": "توجد أدناه القائمة التي تحتوي على كافة الاقتراحات للموضوع المحدد.", + + // "quality-assurance.events.description-with-topic-and-target": "Below the list of all the suggestions for the selected topic {{topic}}, related to {{source}} and ", + // TODO New key - Add a translation + "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:", + // TODO New key - Add a translation + "quality-assurance.event.table.event.message.serviceUrl": "Service URL:", + + // "quality-assurance.event.table.event.message.link": "Link:", + // TODO New key - Add a translation + "quality-assurance.event.table.event.message.link": "Link:", + + // "service.detail.delete.cancel": "Cancel", + // TODO New key - Add a translation + "service.detail.delete.cancel": "Cancel", + + // "service.detail.delete.button": "Delete service", + // TODO New key - Add a translation + "service.detail.delete.button": "Delete service", + + // "service.detail.delete.header": "Delete service", + // TODO New key - Add a translation + "service.detail.delete.header": "Delete service", + + // "service.detail.delete.body": "Are you sure you want to delete the current service?", + // TODO New key - Add a translation + "service.detail.delete.body": "Are you sure you want to delete the current service?", + + // "service.detail.delete.confirm": "Delete service", + // TODO New key - Add a translation + "service.detail.delete.confirm": "Delete service", + + // "service.detail.delete.success": "The service was successfully deleted.", + // TODO New key - Add a translation + "service.detail.delete.success": "The service was successfully deleted.", + + // "service.detail.delete.error": "Something went wrong when deleting the service", + // TODO New key - Add a translation + "service.detail.delete.error": "Something went wrong when deleting the service", + + // "service.overview.table.id": "Services ID", + // TODO New key - Add a translation + "service.overview.table.id": "Services ID", + + // "service.overview.table.name": "Name", + // TODO New key - Add a translation + "service.overview.table.name": "Name", + + // "service.overview.table.start": "Start time (UTC)", + // TODO New key - Add a translation + "service.overview.table.start": "Start time (UTC)", + + // "service.overview.table.status": "Status", + // TODO New key - Add a translation + "service.overview.table.status": "Status", + + // "service.overview.table.user": "User", + // TODO New key - Add a translation + "service.overview.table.user": "User", + + // "service.overview.title": "Services Overview", + // TODO New key - Add a translation + "service.overview.title": "Services Overview", + + // "service.overview.breadcrumbs": "Services Overview", + // TODO New key - Add a translation + "service.overview.breadcrumbs": "Services Overview", + + // "service.overview.table.actions": "Actions", + // TODO New key - Add a translation + "service.overview.table.actions": "Actions", + + // "service.overview.table.description": "Description", + // TODO New key - Add a translation + "service.overview.table.description": "Description", + + // "submission.sections.submit.progressbar.coarnotify": "COAR Notify", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "submission.section.section-coar-notify.dropdown.no-data": "No data available", + + // "submission.section.section-coar-notify.dropdown.select-none": "Select none", + // TODO New key - Add a translation + "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", + // TODO New key - Add a translation + "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:", + // TODO New key - Add a translation + "submission.section.section-coar-notify.selection.description": "Selected service's description:", + + // "submission.section.section-coar-notify.selection.no-description": "No further information is available", + // TODO New key - Add a translation + "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.", + // TODO New key - Add a translation + "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.", + // TODO New key - Add a translation + "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.", + // TODO New key - Add a translation + "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.", + // TODO New key - Add a translation + "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.", + // TODO New key - Add a translation + "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.", + // TODO New key - Add a translation + "request-status-alert-box.requested": "The requested {{ offerType }} for {{ serviceName }} is pending.", + + // "ldn-service-button-mark-inbound-deletion": "Mark inbound pattern for deletion", + // TODO New key - Add a translation + "ldn-service-button-mark-inbound-deletion": "Mark inbound pattern for deletion", + + // "ldn-service-button-unmark-inbound-deletion": "Unmark inbound pattern for deletion", + // TODO New key - Add a translation + "ldn-service-button-unmark-inbound-deletion": "Unmark inbound pattern for deletion", + + // "ldn-service-input-inbound-item-filter-dropdown": "Select Item filter for inbound pattern", + // TODO New key - Add a translation + "ldn-service-input-inbound-item-filter-dropdown": "Select Item filter for inbound pattern", + + // "ldn-service-input-inbound-pattern-dropdown": "Select inbound pattern for service", + // TODO New key - Add a translation + "ldn-service-input-inbound-pattern-dropdown": "Select inbound pattern for service", + + // "ldn-service-overview-select-delete": "Select service for deletion", + // TODO New key - Add a translation + "ldn-service-overview-select-delete": "Select service for deletion", + + // "ldn-service-overview-select-edit": "Edit LDN service", + // TODO New key - Add a translation + "ldn-service-overview-select-edit": "Edit LDN service", + + // "ldn-service-overview-close-modal": "Close modal", + // TODO New key - Add a translation + "ldn-service-overview-close-modal": "Close modal", + + // "a-common-or_statement.label": "Item type is Journal Article or Dataset", + // TODO New key - Add a translation + "a-common-or_statement.label": "Item type is Journal Article or Dataset", + + // "always_true_filter.label": "Always true", + // TODO New key - Add a translation + "always_true_filter.label": "Always true", + + // "automatic_processing_collection_filter_16.label": "Automatic processing", + // TODO New key - Add a translation + "automatic_processing_collection_filter_16.label": "Automatic processing", + + // "dc-identifier-uri-contains-doi_condition.label": "URI contains DOI", + // TODO New key - Add a translation + "dc-identifier-uri-contains-doi_condition.label": "URI contains DOI", + + // "doi-filter.label": "DOI filter", + // TODO New key - Add a translation + "doi-filter.label": "DOI filter", + + // "driver-document-type_condition.label": "Document type equals driver", + // TODO New key - Add a translation + "driver-document-type_condition.label": "Document type equals driver", + + // "has-at-least-one-bitstream_condition.label": "Has at least one Bitstream", + // TODO New key - Add a translation + "has-at-least-one-bitstream_condition.label": "Has at least one Bitstream", + + // "has-bitstream_filter.label": "Has Bitstream", + // TODO New key - Add a translation + "has-bitstream_filter.label": "Has Bitstream", + + // "has-one-bitstream_condition.label": "Has one Bitstream", + // TODO New key - Add a translation + "has-one-bitstream_condition.label": "Has one Bitstream", + + // "is-archived_condition.label": "Is archived", + // TODO New key - Add a translation + "is-archived_condition.label": "Is archived", + + // "is-withdrawn_condition.label": "Is withdrawn", + // TODO New key - Add a translation + "is-withdrawn_condition.label": "Is withdrawn", + + // "item-is-public_condition.label": "Item is public", + // TODO New key - Add a translation + "item-is-public_condition.label": "Item is public", + + // "journals_ingest_suggestion_collection_filter_18.label": "Journals ingest", + // TODO New key - Add a translation + "journals_ingest_suggestion_collection_filter_18.label": "Journals ingest", + + // "title-starts-with-pattern_condition.label": "Title starts with pattern", + // TODO New key - Add a translation + "title-starts-with-pattern_condition.label": "Title starts with pattern", + + // "type-equals-dataset_condition.label": "Type equals Dataset", + // TODO New key - Add a translation + "type-equals-dataset_condition.label": "Type equals Dataset", + + // "type-equals-journal-article_condition.label": "Type equals Journal Article", + // TODO New key - Add a translation + "type-equals-journal-article_condition.label": "Type equals Journal Article", + + // "search.filters.filter.subject.text": "Subject", + // TODO New key - Add a translation + "search.filters.filter.subject.text": "Subject", + + // "search.advanced.filters.head": "Advanced Search", + // TODO New key - Add a translation + "search.advanced.filters.head": "Advanced Search", + + // "filter.search.text.placeholder": "Search text", + // TODO New key - Add a translation + "filter.search.text.placeholder": "Search text", + + // "advancesearch.form.submit": "Add", + // TODO New key - Add a translation + "advancesearch.form.submit": "Add", + + // "ldn.no-filter.label": "None", + // TODO New key - Add a translation + "ldn.no-filter.label": "None", + + // "admin.notify.dashboard": "Dashboard", + // TODO New key - Add a translation + "admin.notify.dashboard": "Dashboard", + + // "menu.section.notify_dashboard": "Dashboard", + // TODO New key - Add a translation + "menu.section.notify_dashboard": "Dashboard", + + // "menu.section.coar_notify": "COAR Notify", + // TODO New key - Add a translation + "menu.section.coar_notify": "COAR Notify", + + // "admin-notify-dashboard.title": "Notify Dashboard", + // TODO New key - Add a translation + "admin-notify-dashboard.title": "Notify Dashboard", + + // "admin-notify-dashboard.description": "The Notify dashboard monitor the general usage of the COAR Notify protocol across the repository. In the “Metrics” tab are statistics about usage of the COAR Notify protocol. In the “Logs/Inbound” and “Logs/Outbound” tabs it’s possible to search and check the individual status of each LDN message, either received or sent.", + // TODO New key - Add a translation + "admin-notify-dashboard.description": "The Notify dashboard monitor the general usage of the COAR Notify protocol across the repository. In the “Metrics” tab are statistics about usage of the COAR Notify protocol. In the “Logs/Inbound” and “Logs/Outbound” tabs it’s possible to search and check the individual status of each LDN message, either received or sent.", + + // "admin-notify-dashboard.metrics": "Metrics", + // TODO New key - Add a translation + "admin-notify-dashboard.metrics": "Metrics", + + // "admin-notify-dashboard.received-ldn": "Number of received LDN", + // TODO New key - Add a translation + "admin-notify-dashboard.received-ldn": "Number of received LDN", + + // "admin-notify-dashboard.generated-ldn": "Number of generated LDN", + // TODO New key - Add a translation + "admin-notify-dashboard.generated-ldn": "Number of generated LDN", + + // "admin-notify-dashboard.NOTIFY.incoming.accepted": "Accepted", + // TODO New key - Add a translation + "admin-notify-dashboard.NOTIFY.incoming.accepted": "Accepted", + + // "admin-notify-dashboard.NOTIFY.incoming.accepted.description": "Accepted inbound notifications", + // TODO New key - Add a translation + "admin-notify-dashboard.NOTIFY.incoming.accepted.description": "Accepted inbound notifications", + + // "admin-notify-logs.NOTIFY.incoming.accepted": "Currently displaying: Accepted notifications", + // TODO New key - Add a translation + "admin-notify-logs.NOTIFY.incoming.accepted": "Currently displaying: Accepted notifications", + + // "admin-notify-dashboard.NOTIFY.incoming.processed": "Processed LDN", + // TODO New key - Add a translation + "admin-notify-dashboard.NOTIFY.incoming.processed": "Processed LDN", + + // "admin-notify-dashboard.NOTIFY.incoming.processed.description": "Processed inbound notifications", + // TODO New key - Add a translation + "admin-notify-dashboard.NOTIFY.incoming.processed.description": "Processed inbound notifications", + + // "admin-notify-logs.NOTIFY.incoming.processed": "Currently displaying: Processed LDN", + // TODO New key - Add a translation + "admin-notify-logs.NOTIFY.incoming.processed": "Currently displaying: Processed LDN", + + // "admin-notify-logs.NOTIFY.incoming.failure": "Currently displaying: Failed notifications", + // TODO New key - Add a translation + "admin-notify-logs.NOTIFY.incoming.failure": "Currently displaying: Failed notifications", + + // "admin-notify-dashboard.NOTIFY.incoming.failure": "Failure", + // TODO New key - Add a translation + "admin-notify-dashboard.NOTIFY.incoming.failure": "Failure", + + // "admin-notify-dashboard.NOTIFY.incoming.failure.description": "Failed inbound notifications", + // TODO New key - Add a translation + "admin-notify-dashboard.NOTIFY.incoming.failure.description": "Failed inbound notifications", + + // "admin-notify-logs.NOTIFY.outgoing.failure": "Currently displaying: Failed notifications", + // TODO New key - Add a translation + "admin-notify-logs.NOTIFY.outgoing.failure": "Currently displaying: Failed notifications", + + // "admin-notify-dashboard.NOTIFY.outgoing.failure": "Failure", + // TODO New key - Add a translation + "admin-notify-dashboard.NOTIFY.outgoing.failure": "Failure", + + // "admin-notify-dashboard.NOTIFY.outgoing.failure.description": "Failed outbound notifications", + // TODO New key - Add a translation + "admin-notify-dashboard.NOTIFY.outgoing.failure.description": "Failed outbound notifications", + + // "admin-notify-logs.NOTIFY.incoming.untrusted": "Currently displaying: Untrusted notifications", + // TODO New key - Add a translation + "admin-notify-logs.NOTIFY.incoming.untrusted": "Currently displaying: Untrusted notifications", + + // "admin-notify-dashboard.NOTIFY.incoming.untrusted": "Untrusted", + // TODO New key - Add a translation + "admin-notify-dashboard.NOTIFY.incoming.untrusted": "Untrusted", + + // "admin-notify-dashboard.NOTIFY.incoming.untrusted.description": "Inbound notifications not trusted", + // TODO New key - Add a translation + "admin-notify-dashboard.NOTIFY.incoming.untrusted.description": "Inbound notifications not trusted", + + // "admin-notify-logs.NOTIFY.incoming.delivered": "Currently displaying: Delivered notifications", + // TODO New key - Add a translation + "admin-notify-logs.NOTIFY.incoming.delivered": "Currently displaying: Delivered notifications", + + // "admin-notify-dashboard.NOTIFY.incoming.delivered.description": "Inbound notifications successfully delivered", + // TODO New key - Add a translation + "admin-notify-dashboard.NOTIFY.incoming.delivered.description": "Inbound notifications successfully delivered", + + // "admin-notify-dashboard.NOTIFY.outgoing.delivered": "Delivered", + // TODO New key - Add a translation + "admin-notify-dashboard.NOTIFY.outgoing.delivered": "Delivered", + + // "admin-notify-logs.NOTIFY.outgoing.delivered": "Currently displaying: Delivered notifications", + // TODO New key - Add a translation + "admin-notify-logs.NOTIFY.outgoing.delivered": "Currently displaying: Delivered notifications", + + // "admin-notify-dashboard.NOTIFY.outgoing.delivered.description": "Outbound notifications successfully delivered", + // TODO New key - Add a translation + "admin-notify-dashboard.NOTIFY.outgoing.delivered.description": "Outbound notifications successfully delivered", + + // "admin-notify-logs.NOTIFY.outgoing.queued": "Currently displaying: Queued notifications", + // TODO New key - Add a translation + "admin-notify-logs.NOTIFY.outgoing.queued": "Currently displaying: Queued notifications", + + // "admin-notify-dashboard.NOTIFY.outgoing.queued.description": "Notifications currently queued", + // TODO New key - Add a translation + "admin-notify-dashboard.NOTIFY.outgoing.queued.description": "Notifications currently queued", + + // "admin-notify-dashboard.NOTIFY.outgoing.queued": "Queued", + // TODO New key - Add a translation + "admin-notify-dashboard.NOTIFY.outgoing.queued": "Queued", + + // "admin-notify-logs.NOTIFY.outgoing.queued_for_retry": "Currently displaying: Queued for retry notifications", + // TODO New key - Add a translation + "admin-notify-logs.NOTIFY.outgoing.queued_for_retry": "Currently displaying: Queued for retry notifications", + + // "admin-notify-dashboard.NOTIFY.outgoing.queued_for_retry": "Queued for retry", + // TODO New key - Add a translation + "admin-notify-dashboard.NOTIFY.outgoing.queued_for_retry": "Queued for retry", + + // "admin-notify-dashboard.NOTIFY.outgoing.queued_for_retry.description": "Notifications currently queued for retry", + // TODO New key - Add a translation + "admin-notify-dashboard.NOTIFY.outgoing.queued_for_retry.description": "Notifications currently queued for retry", + + // "admin-notify-dashboard.NOTIFY.incoming.involvedItems": "Items involved", + // TODO New key - Add a translation + "admin-notify-dashboard.NOTIFY.incoming.involvedItems": "Items involved", + + // "admin-notify-dashboard.NOTIFY.incoming.involvedItems.description": "Items related to inbound notifications", + // TODO New key - Add a translation + "admin-notify-dashboard.NOTIFY.incoming.involvedItems.description": "Items related to inbound notifications", + + // "admin-notify-dashboard.NOTIFY.outgoing.involvedItems": "Items involved", + // TODO New key - Add a translation + "admin-notify-dashboard.NOTIFY.outgoing.involvedItems": "Items involved", + + // "admin-notify-dashboard.NOTIFY.outgoing.involvedItems.description": "Items related to outbound notifications", + // TODO New key - Add a translation + "admin-notify-dashboard.NOTIFY.outgoing.involvedItems.description": "Items related to outbound notifications", + + // "admin.notify.dashboard.breadcrumbs": "Dashboard", + // TODO New key - Add a translation + "admin.notify.dashboard.breadcrumbs": "Dashboard", + + // "admin.notify.dashboard.inbound": "Inbound messages", + // TODO New key - Add a translation + "admin.notify.dashboard.inbound": "Inbound messages", + + // "admin.notify.dashboard.inbound-logs": "Logs/Inbound", + // TODO New key - Add a translation + "admin.notify.dashboard.inbound-logs": "Logs/Inbound", + + // "admin.notify.dashboard.filter": "Filter: ", + // TODO New key - Add a translation + "admin.notify.dashboard.filter": "Filter: ", + + // "search.filters.applied.f.relateditem": "Related items", + // TODO New key - Add a translation + "search.filters.applied.f.relateditem": "Related items", + + // "search.filters.applied.f.ldn_service": "LDN Service", + // TODO New key - Add a translation + "search.filters.applied.f.ldn_service": "LDN Service", + + // "search.filters.applied.f.notifyReview": "Notify Review", + // TODO New key - Add a translation + "search.filters.applied.f.notifyReview": "Notify Review", + + // "search.filters.applied.f.notifyEndorsement": "Notify Endorsement", + // TODO New key - Add a translation + "search.filters.applied.f.notifyEndorsement": "Notify Endorsement", + + // "search.filters.applied.f.notifyRelation": "Notify Relation", + // TODO New key - Add a translation + "search.filters.applied.f.notifyRelation": "Notify Relation", + + // "search.filters.filter.queue_last_start_time.head": "Last processing time ", + // TODO New key - Add a translation + "search.filters.filter.queue_last_start_time.head": "Last processing time ", + + // "search.filters.filter.queue_last_start_time.min.label": "Min range", + // TODO New key - Add a translation + "search.filters.filter.queue_last_start_time.min.label": "Min range", + + // "search.filters.filter.queue_last_start_time.max.label": "Max range", + // TODO New key - Add a translation + "search.filters.filter.queue_last_start_time.max.label": "Max range", + + // "search.filters.applied.f.queue_last_start_time.min": "Min range", + // TODO New key - Add a translation + "search.filters.applied.f.queue_last_start_time.min": "Min range", + + // "search.filters.applied.f.queue_last_start_time.max": "Max range", + // TODO New key - Add a translation + "search.filters.applied.f.queue_last_start_time.max": "Max range", + + // "admin.notify.dashboard.outbound": "Outbound messages", + // TODO New key - Add a translation + "admin.notify.dashboard.outbound": "Outbound messages", + + // "admin.notify.dashboard.outbound-logs": "Logs/Outbound", + // TODO New key - Add a translation + "admin.notify.dashboard.outbound-logs": "Logs/Outbound", + + // "NOTIFY.incoming.search.results.head": "Incoming", + // TODO New key - Add a translation + "NOTIFY.incoming.search.results.head": "Incoming", + + // "search.filters.filter.relateditem.head": "Related item", + // TODO New key - Add a translation + "search.filters.filter.relateditem.head": "Related item", + + // "search.filters.filter.origin.head": "Origin", + // TODO New key - Add a translation + "search.filters.filter.origin.head": "Origin", + + // "search.filters.filter.ldn_service.head": "LDN Service", + // TODO New key - Add a translation + "search.filters.filter.ldn_service.head": "LDN Service", + + // "search.filters.filter.target.head": "Target", + // TODO New key - Add a translation + "search.filters.filter.target.head": "Target", + + // "search.filters.filter.queue_status.head": "Queue status", + // TODO New key - Add a translation + "search.filters.filter.queue_status.head": "Queue status", + + // "search.filters.filter.activity_stream_type.head": "Activity stream type", + // TODO New key - Add a translation + "search.filters.filter.activity_stream_type.head": "Activity stream type", + + // "search.filters.filter.coar_notify_type.head": "COAR Notify type", + // TODO New key - Add a translation + "search.filters.filter.coar_notify_type.head": "COAR Notify type", + + // "search.filters.filter.notification_type.head": "Notification type", + // TODO New key - Add a translation + "search.filters.filter.notification_type.head": "Notification type", + + // "search.filters.filter.relateditem.label": "Search related items", + // TODO New key - Add a translation + "search.filters.filter.relateditem.label": "Search related items", + + // "search.filters.filter.queue_status.label": "Search queue status", + // TODO New key - Add a translation + "search.filters.filter.queue_status.label": "Search queue status", + + // "search.filters.filter.target.label": "Search target", + // TODO New key - Add a translation + "search.filters.filter.target.label": "Search target", + + // "search.filters.filter.activity_stream_type.label": "Search activity stream type", + // TODO New key - Add a translation + "search.filters.filter.activity_stream_type.label": "Search activity stream type", + + // "search.filters.applied.f.queue_status": "Queue Status", + // TODO New key - Add a translation + "search.filters.applied.f.queue_status": "Queue Status", + + // "search.filters.queue_status.0,authority": "Untrusted Ip", + // TODO New key - Add a translation + "search.filters.queue_status.0,authority": "Untrusted Ip", + + // "search.filters.queue_status.1,authority": "Queued", + // TODO New key - Add a translation + "search.filters.queue_status.1,authority": "Queued", + + // "search.filters.queue_status.2,authority": "Processing", + // TODO New key - Add a translation + "search.filters.queue_status.2,authority": "Processing", + + // "search.filters.queue_status.3,authority": "Processed", + // TODO New key - Add a translation + "search.filters.queue_status.3,authority": "Processed", + + // "search.filters.queue_status.4,authority": "Failed", + // TODO New key - Add a translation + "search.filters.queue_status.4,authority": "Failed", + + // "search.filters.queue_status.5,authority": "Untrusted", + // TODO New key - Add a translation + "search.filters.queue_status.5,authority": "Untrusted", + + // "search.filters.queue_status.6,authority": "Unmapped Action", + // TODO New key - Add a translation + "search.filters.queue_status.6,authority": "Unmapped Action", + + // "search.filters.queue_status.7,authority": "Queued for retry", + // TODO New key - Add a translation + "search.filters.queue_status.7,authority": "Queued for retry", + + // "search.filters.applied.f.activity_stream_type": "Activity stream type", + // TODO New key - Add a translation + "search.filters.applied.f.activity_stream_type": "Activity stream type", + + // "search.filters.applied.f.coar_notify_type": "COAR Notify type", + // TODO New key - Add a translation + "search.filters.applied.f.coar_notify_type": "COAR Notify type", + + // "search.filters.applied.f.notification_type": "Notification type", + // TODO New key - Add a translation + "search.filters.applied.f.notification_type": "Notification type", + + // "search.filters.filter.coar_notify_type.label": "Search COAR Notify type", + // TODO New key - Add a translation + "search.filters.filter.coar_notify_type.label": "Search COAR Notify type", + + // "search.filters.filter.notification_type.label": "Search notification type", + // TODO New key - Add a translation + "search.filters.filter.notification_type.label": "Search notification type", + + // "search.filters.filter.relateditem.placeholder": "Related items", + // TODO New key - Add a translation + "search.filters.filter.relateditem.placeholder": "Related items", + + // "search.filters.filter.target.placeholder": "Target", + // TODO New key - Add a translation + "search.filters.filter.target.placeholder": "Target", + + // "search.filters.filter.origin.label": "Search source", + // TODO New key - Add a translation + "search.filters.filter.origin.label": "Search source", + + // "search.filters.filter.origin.placeholder": "Source", + // TODO New key - Add a translation + "search.filters.filter.origin.placeholder": "Source", + + // "search.filters.filter.ldn_service.label": "Search LDN Service", + // TODO New key - Add a translation + "search.filters.filter.ldn_service.label": "Search LDN Service", + + // "search.filters.filter.ldn_service.placeholder": "LDN Service", + // TODO New key - Add a translation + "search.filters.filter.ldn_service.placeholder": "LDN Service", + + // "search.filters.filter.queue_status.placeholder": "Queue status", + // TODO New key - Add a translation + "search.filters.filter.queue_status.placeholder": "Queue status", + + // "search.filters.filter.activity_stream_type.placeholder": "Activity stream type", + // TODO New key - Add a translation + "search.filters.filter.activity_stream_type.placeholder": "Activity stream type", + + // "search.filters.filter.coar_notify_type.placeholder": "COAR Notify type", + // TODO New key - Add a translation + "search.filters.filter.coar_notify_type.placeholder": "COAR Notify type", + + // "search.filters.filter.notification_type.placeholder": "Notification", + // TODO New key - Add a translation + "search.filters.filter.notification_type.placeholder": "Notification", + + // "search.filters.filter.notifyRelation.head": "Notify Relation", + // TODO New key - Add a translation + "search.filters.filter.notifyRelation.head": "Notify Relation", + + // "search.filters.filter.notifyRelation.label": "Search Notify Relation", + // TODO New key - Add a translation + "search.filters.filter.notifyRelation.label": "Search Notify Relation", + + // "search.filters.filter.notifyRelation.placeholder": "Notify Relation", + // TODO New key - Add a translation + "search.filters.filter.notifyRelation.placeholder": "Notify Relation", + + // "search.filters.filter.notifyReview.head": "Notify Review", + // TODO New key - Add a translation + "search.filters.filter.notifyReview.head": "Notify Review", + + // "search.filters.filter.notifyReview.label": "Search Notify Review", + // TODO New key - Add a translation + "search.filters.filter.notifyReview.label": "Search Notify Review", + + // "search.filters.filter.notifyReview.placeholder": "Notify Review", + // TODO New key - Add a translation + "search.filters.filter.notifyReview.placeholder": "Notify Review", + + // "search.filters.coar_notify_type.coar-notify:ReviewAction": "Review action", + // TODO New key - Add a translation + "search.filters.coar_notify_type.coar-notify:ReviewAction": "Review action", + + // "search.filters.coar_notify_type.coar-notify:ReviewAction,authority": "Review action", + // TODO New key - Add a translation + "search.filters.coar_notify_type.coar-notify:ReviewAction,authority": "Review action", + + // "notify-detail-modal.coar-notify:ReviewAction": "Review action", + // TODO New key - Add a translation + "notify-detail-modal.coar-notify:ReviewAction": "Review action", + + // "search.filters.coar_notify_type.coar-notify:EndorsementAction": "Endorsement action", + // TODO New key - Add a translation + "search.filters.coar_notify_type.coar-notify:EndorsementAction": "Endorsement action", + + // "search.filters.coar_notify_type.coar-notify:EndorsementAction,authority": "Endorsement action", + // TODO New key - Add a translation + "search.filters.coar_notify_type.coar-notify:EndorsementAction,authority": "Endorsement action", + + // "notify-detail-modal.coar-notify:EndorsementAction": "Endorsement action", + // TODO New key - Add a translation + "notify-detail-modal.coar-notify:EndorsementAction": "Endorsement action", + + // "search.filters.coar_notify_type.coar-notify:IngestAction": "Ingest action", + // TODO New key - Add a translation + "search.filters.coar_notify_type.coar-notify:IngestAction": "Ingest action", + + // "search.filters.coar_notify_type.coar-notify:IngestAction,authority": "Ingest action", + // TODO New key - Add a translation + "search.filters.coar_notify_type.coar-notify:IngestAction,authority": "Ingest action", + + // "notify-detail-modal.coar-notify:IngestAction": "Ingest action", + // TODO New key - Add a translation + "notify-detail-modal.coar-notify:IngestAction": "Ingest action", + + // "search.filters.coar_notify_type.coar-notify:RelationshipAction": "Relationship action", + // TODO New key - Add a translation + "search.filters.coar_notify_type.coar-notify:RelationshipAction": "Relationship action", + + // "search.filters.coar_notify_type.coar-notify:RelationshipAction,authority": "Relationship action", + // TODO New key - Add a translation + "search.filters.coar_notify_type.coar-notify:RelationshipAction,authority": "Relationship action", + + // "notify-detail-modal.coar-notify:RelationshipAction": "Relationship action", + // TODO New key - Add a translation + "notify-detail-modal.coar-notify:RelationshipAction": "Relationship action", + + // "search.filters.queue_status.QUEUE_STATUS_QUEUED": "Queued", + // TODO New key - Add a translation + "search.filters.queue_status.QUEUE_STATUS_QUEUED": "Queued", + + // "notify-detail-modal.QUEUE_STATUS_QUEUED": "Queued", + // TODO New key - Add a translation + "notify-detail-modal.QUEUE_STATUS_QUEUED": "Queued", + + // "search.filters.queue_status.QUEUE_STATUS_QUEUED_FOR_RETRY": "Queued for retry", + // TODO New key - Add a translation + "search.filters.queue_status.QUEUE_STATUS_QUEUED_FOR_RETRY": "Queued for retry", + + // "notify-detail-modal.QUEUE_STATUS_QUEUED_FOR_RETRY": "Queued for retry", + // TODO New key - Add a translation + "notify-detail-modal.QUEUE_STATUS_QUEUED_FOR_RETRY": "Queued for retry", + + // "search.filters.queue_status.QUEUE_STATUS_PROCESSING": "Processing", + // TODO New key - Add a translation + "search.filters.queue_status.QUEUE_STATUS_PROCESSING": "Processing", + + // "notify-detail-modal.QUEUE_STATUS_PROCESSING": "Processing", + // TODO New key - Add a translation + "notify-detail-modal.QUEUE_STATUS_PROCESSING": "Processing", + + // "search.filters.queue_status.QUEUE_STATUS_PROCESSED": "Processed", + // TODO New key - Add a translation + "search.filters.queue_status.QUEUE_STATUS_PROCESSED": "Processed", + + // "notify-detail-modal.QUEUE_STATUS_PROCESSED": "Processed", + // TODO New key - Add a translation + "notify-detail-modal.QUEUE_STATUS_PROCESSED": "Processed", + + // "search.filters.queue_status.QUEUE_STATUS_FAILED": "Failed", + // TODO New key - Add a translation + "search.filters.queue_status.QUEUE_STATUS_FAILED": "Failed", + + // "notify-detail-modal.QUEUE_STATUS_FAILED": "Failed", + // TODO New key - Add a translation + "notify-detail-modal.QUEUE_STATUS_FAILED": "Failed", + + // "search.filters.queue_status.QUEUE_STATUS_UNTRUSTED": "Untrusted", + // TODO New key - Add a translation + "search.filters.queue_status.QUEUE_STATUS_UNTRUSTED": "Untrusted", + + // "search.filters.queue_status.QUEUE_STATUS_UNTRUSTED_IP": "Untrusted Ip", + // TODO New key - Add a translation + "search.filters.queue_status.QUEUE_STATUS_UNTRUSTED_IP": "Untrusted Ip", + + // "notify-detail-modal.QUEUE_STATUS_UNTRUSTED": "Untrusted", + // TODO New key - Add a translation + "notify-detail-modal.QUEUE_STATUS_UNTRUSTED": "Untrusted", + + // "notify-detail-modal.QUEUE_STATUS_UNTRUSTED_IP": "Untrusted Ip", + // TODO New key - Add a translation + "notify-detail-modal.QUEUE_STATUS_UNTRUSTED_IP": "Untrusted Ip", + + // "search.filters.queue_status.QUEUE_STATUS_UNMAPPED_ACTION": "Unmapped Action", + // TODO New key - Add a translation + "search.filters.queue_status.QUEUE_STATUS_UNMAPPED_ACTION": "Unmapped Action", + + // "notify-detail-modal.QUEUE_STATUS_UNMAPPED_ACTION": "Unmapped Action", + // TODO New key - Add a translation + "notify-detail-modal.QUEUE_STATUS_UNMAPPED_ACTION": "Unmapped Action", + + // "sorting.queue_last_start_time.DESC": "Last started queue Descending", + // TODO New key - Add a translation + "sorting.queue_last_start_time.DESC": "Last started queue Descending", + + // "sorting.queue_last_start_time.ASC": "Last started queue Ascending", + // TODO New key - Add a translation + "sorting.queue_last_start_time.ASC": "Last started queue Ascending", + + // "sorting.queue_attempts.DESC": "Queue attempted Descending", + // TODO New key - Add a translation + "sorting.queue_attempts.DESC": "Queue attempted Descending", + + // "sorting.queue_attempts.ASC": "Queue attempted Ascending", + // TODO New key - Add a translation + "sorting.queue_attempts.ASC": "Queue attempted Ascending", + + // "NOTIFY.incoming.involvedItems.search.results.head": "Items involved in incoming LDN", + // TODO New key - Add a translation + "NOTIFY.incoming.involvedItems.search.results.head": "Items involved in incoming LDN", + + // "NOTIFY.outgoing.involvedItems.search.results.head": "Items involved in outgoing LDN", + // TODO New key - Add a translation + "NOTIFY.outgoing.involvedItems.search.results.head": "Items involved in outgoing LDN", + + // "type.notify-detail-modal": "Type", + // TODO New key - Add a translation + "type.notify-detail-modal": "Type", + + // "id.notify-detail-modal": "Id", + // TODO New key - Add a translation + "id.notify-detail-modal": "Id", + + // "coarNotifyType.notify-detail-modal": "COAR Notify type", + // TODO New key - Add a translation + "coarNotifyType.notify-detail-modal": "COAR Notify type", + + // "activityStreamType.notify-detail-modal": "Activity stream type", + // TODO New key - Add a translation + "activityStreamType.notify-detail-modal": "Activity stream type", + + // "inReplyTo.notify-detail-modal": "In reply to", + // TODO New key - Add a translation + "inReplyTo.notify-detail-modal": "In reply to", + + // "object.notify-detail-modal": "Repository Item", + // TODO New key - Add a translation + "object.notify-detail-modal": "Repository Item", + + // "context.notify-detail-modal": "Repository Item", + // TODO New key - Add a translation + "context.notify-detail-modal": "Repository Item", + + // "queueAttempts.notify-detail-modal": "Queue attempts", + // TODO New key - Add a translation + "queueAttempts.notify-detail-modal": "Queue attempts", + + // "queueLastStartTime.notify-detail-modal": "Queue last started", + // TODO New key - Add a translation + "queueLastStartTime.notify-detail-modal": "Queue last started", + + // "origin.notify-detail-modal": "LDN Service", + // TODO New key - Add a translation + "origin.notify-detail-modal": "LDN Service", + + // "target.notify-detail-modal": "LDN Service", + // TODO New key - Add a translation + "target.notify-detail-modal": "LDN Service", + + // "queueStatusLabel.notify-detail-modal": "Queue status", + // TODO New key - Add a translation + "queueStatusLabel.notify-detail-modal": "Queue status", + + // "queueTimeout.notify-detail-modal": "Queue timeout", + // TODO New key - Add a translation + "queueTimeout.notify-detail-modal": "Queue timeout", + + // "notify-message-modal.title": "Message Detail", + // TODO New key - Add a translation + "notify-message-modal.title": "Message Detail", + + // "notify-message-modal.show-message": "Show message", + // TODO New key - Add a translation + "notify-message-modal.show-message": "Show message", + + // "notify-message-result.timestamp": "Timestamp", + // TODO New key - Add a translation + "notify-message-result.timestamp": "Timestamp", + + // "notify-message-result.repositoryItem": "Repository Item", + // TODO New key - Add a translation + "notify-message-result.repositoryItem": "Repository Item", + + // "notify-message-result.ldnService": "LDN Service", + // TODO New key - Add a translation + "notify-message-result.ldnService": "LDN Service", + + // "notify-message-result.type": "Type", + // TODO New key - Add a translation + "notify-message-result.type": "Type", + + // "notify-message-result.status": "Status", + // TODO New key - Add a translation + "notify-message-result.status": "Status", + + // "notify-message-result.action": "Action", + // TODO New key - Add a translation + "notify-message-result.action": "Action", + + // "notify-message-result.detail": "Detail", + // TODO New key - Add a translation + "notify-message-result.detail": "Detail", + + // "notify-message-result.reprocess": "Reprocess", + // TODO New key - Add a translation + "notify-message-result.reprocess": "Reprocess", + + // "notify-queue-status.processed": "Processed", + // TODO New key - Add a translation + "notify-queue-status.processed": "Processed", + + // "notify-queue-status.failed": "Failed", + // TODO New key - Add a translation + "notify-queue-status.failed": "Failed", + + // "notify-queue-status.queue_retry": "Queued for retry", + // TODO New key - Add a translation + "notify-queue-status.queue_retry": "Queued for retry", + + // "notify-queue-status.unmapped_action": "Unmapped action", + // TODO New key - Add a translation + "notify-queue-status.unmapped_action": "Unmapped action", + + // "notify-queue-status.processing": "Processing", + // TODO New key - Add a translation + "notify-queue-status.processing": "Processing", + + // "notify-queue-status.queued": "Queued", + // TODO New key - Add a translation + "notify-queue-status.queued": "Queued", + + // "notify-queue-status.untrusted": "Untrusted", + // TODO New key - Add a translation + "notify-queue-status.untrusted": "Untrusted", + + // "ldnService.notify-detail-modal": "LDN Service", + // TODO New key - Add a translation + "ldnService.notify-detail-modal": "LDN Service", + + // "relatedItem.notify-detail-modal": "Related Item", + // TODO New key - Add a translation + "relatedItem.notify-detail-modal": "Related Item", + + // "search.filters.filter.notifyEndorsement.head": "Notify Endorsement", + // TODO New key - Add a translation + "search.filters.filter.notifyEndorsement.head": "Notify Endorsement", + + // "search.filters.filter.notifyEndorsement.placeholder": "Notify Endorsement", + // TODO New key - Add a translation + "search.filters.filter.notifyEndorsement.placeholder": "Notify Endorsement", + + // "search.filters.filter.notifyEndorsement.label": "Search Notify Endorsement", + // TODO New key - Add a translation + "search.filters.filter.notifyEndorsement.label": "Search Notify Endorsement", + } From 533da6624f1140fb182505ca5b3cf69ceb1e9a67 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Tue, 9 Jul 2024 17:56:06 +0200 Subject: [PATCH 0594/1286] add missing German translations (cherry picked from commit 2af168bd5423e6917adc18990aeda8ee9f5da962) --- src/assets/i18n/de.json5 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/assets/i18n/de.json5 b/src/assets/i18n/de.json5 index 36b092178c..82420d691b 100644 --- a/src/assets/i18n/de.json5 +++ b/src/assets/i18n/de.json5 @@ -4815,6 +4815,12 @@ // "submission.sections.describe.relationship-lookup.external-source.import-button-title.Journal Volume": "Import remote journal volume", "submission.sections.describe.relationship-lookup.external-source.import-button-title.Journal Volume": "Zeitschriftenband importieren", + // "submission.sections.describe.relationship-lookup.external-source.import-button-title.none": "Import remote item", + "submission.sections.describe.relationship-lookup.external-source.import-button-title.none": "Item importieren", + + // "submission.sections.describe.relationship-lookup.external-source.import-button-title.Publication": "Import remote publication", + "submission.sections.describe.relationship-lookup.external-source.import-button-title.Publication": "Metadaten der Publikation importieren", + // "submission.sections.describe.relationship-lookup.external-source.import-modal.isAuthorOfPublication.title": "Import Remote Author", "submission.sections.describe.relationship-lookup.external-source.import-modal.isAuthorOfPublication.title": "Importiere Autor:innen-Metadaten", From 26e02639d0df25825dfe6464c41b313d6aab1e97 Mon Sep 17 00:00:00 2001 From: Sascha Szott Date: Tue, 9 Jul 2024 17:56:06 +0200 Subject: [PATCH 0595/1286] add missing German translations (cherry picked from commit 2af168bd5423e6917adc18990aeda8ee9f5da962) --- src/assets/i18n/de.json5 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/assets/i18n/de.json5 b/src/assets/i18n/de.json5 index e1ebb489cf..640352c4fa 100644 --- a/src/assets/i18n/de.json5 +++ b/src/assets/i18n/de.json5 @@ -5226,6 +5226,12 @@ // "submission.sections.describe.relationship-lookup.external-source.import-button-title.Journal Volume": "Import remote journal volume", "submission.sections.describe.relationship-lookup.external-source.import-button-title.Journal Volume": "Zeitschriftenband importieren", + // "submission.sections.describe.relationship-lookup.external-source.import-button-title.none": "Import remote item", + "submission.sections.describe.relationship-lookup.external-source.import-button-title.none": "Item importieren", + + // "submission.sections.describe.relationship-lookup.external-source.import-button-title.Publication": "Import remote publication", + "submission.sections.describe.relationship-lookup.external-source.import-button-title.Publication": "Metadaten der Publikation importieren", + // "submission.sections.describe.relationship-lookup.external-source.import-modal.isAuthorOfPublication.title": "Import Remote Author", "submission.sections.describe.relationship-lookup.external-source.import-modal.isAuthorOfPublication.title": "Importiere Autor:innen-Metadaten", From dac4d4a71321dd776d1af384535815b3ac63e53e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Oct 2024 13:57:17 +0000 Subject: [PATCH 0596/1286] Bump the angular group with 10 updates Bumps the angular group with 10 updates: | Package | From | To | | --- | --- | --- | | [@angular/localize](https://github.com/angular/angular) | `17.3.11` | `17.3.12` | | [@angular/ssr](https://github.com/angular/angular-cli) | `17.3.9` | `17.3.10` | | [@angular-devkit/build-angular](https://github.com/angular/angular-cli) | `17.3.9` | `17.3.10` | | [@angular-eslint/builder](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/builder) | `17.2.1` | `17.5.3` | | [@angular-eslint/bundled-angular-compiler](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/bundled-angular-compiler) | `17.2.1` | `17.5.3` | | [@angular-eslint/eslint-plugin](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/eslint-plugin) | `17.2.1` | `17.5.3` | | [@angular-eslint/eslint-plugin-template](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/eslint-plugin-template) | `17.2.1` | `17.5.3` | | [@angular-eslint/schematics](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/schematics) | `17.2.1` | `17.5.3` | | [@angular-eslint/template-parser](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/template-parser) | `17.2.1` | `17.5.3` | | [@angular/cli](https://github.com/angular/angular-cli) | `17.3.9` | `17.3.10` | Updates `@angular/localize` from 17.3.11 to 17.3.12 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/compare/17.3.11...17.3.12) Updates `@angular/ssr` from 17.3.9 to 17.3.10 - [Release notes](https://github.com/angular/angular-cli/releases) - [Changelog](https://github.com/angular/angular-cli/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular-cli/compare/17.3.9...17.3.10) Updates `@angular-devkit/build-angular` from 17.3.9 to 17.3.10 - [Release notes](https://github.com/angular/angular-cli/releases) - [Changelog](https://github.com/angular/angular-cli/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular-cli/compare/17.3.9...17.3.10) Updates `@angular-eslint/builder` from 17.2.1 to 17.5.3 - [Release notes](https://github.com/angular-eslint/angular-eslint/releases) - [Changelog](https://github.com/angular-eslint/angular-eslint/blob/main/packages/builder/CHANGELOG.md) - [Commits](https://github.com/angular-eslint/angular-eslint/commits/HEAD/packages/builder) Updates `@angular-eslint/bundled-angular-compiler` from 17.2.1 to 17.5.3 - [Release notes](https://github.com/angular-eslint/angular-eslint/releases) - [Changelog](https://github.com/angular-eslint/angular-eslint/blob/main/packages/bundled-angular-compiler/CHANGELOG.md) - [Commits](https://github.com/angular-eslint/angular-eslint/commits/HEAD/packages/bundled-angular-compiler) Updates `@angular-eslint/eslint-plugin` from 17.2.1 to 17.5.3 - [Release notes](https://github.com/angular-eslint/angular-eslint/releases) - [Changelog](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md) - [Commits](https://github.com/angular-eslint/angular-eslint/commits/HEAD/packages/eslint-plugin) Updates `@angular-eslint/eslint-plugin-template` from 17.2.1 to 17.5.3 - [Release notes](https://github.com/angular-eslint/angular-eslint/releases) - [Changelog](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/CHANGELOG.md) - [Commits](https://github.com/angular-eslint/angular-eslint/commits/HEAD/packages/eslint-plugin-template) Updates `@angular-eslint/schematics` from 17.2.1 to 17.5.3 - [Release notes](https://github.com/angular-eslint/angular-eslint/releases) - [Changelog](https://github.com/angular-eslint/angular-eslint/blob/main/packages/schematics/CHANGELOG.md) - [Commits](https://github.com/angular-eslint/angular-eslint/commits/HEAD/packages/schematics) Updates `@angular-eslint/template-parser` from 17.2.1 to 17.5.3 - [Release notes](https://github.com/angular-eslint/angular-eslint/releases) - [Changelog](https://github.com/angular-eslint/angular-eslint/blob/main/packages/template-parser/CHANGELOG.md) - [Commits](https://github.com/angular-eslint/angular-eslint/commits/HEAD/packages/template-parser) Updates `@angular/cli` from 17.3.9 to 17.3.10 - [Release notes](https://github.com/angular/angular-cli/releases) - [Changelog](https://github.com/angular/angular-cli/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular-cli/compare/17.3.9...17.3.10) --- updated-dependencies: - dependency-name: "@angular/localize" dependency-type: direct:production update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular/ssr" dependency-type: direct:production update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular-devkit/build-angular" dependency-type: direct:development update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular-eslint/builder" dependency-type: direct:development update-type: version-update:semver-minor dependency-group: angular - dependency-name: "@angular-eslint/bundled-angular-compiler" dependency-type: direct:development update-type: version-update:semver-minor dependency-group: angular - dependency-name: "@angular-eslint/eslint-plugin" dependency-type: direct:development update-type: version-update:semver-minor dependency-group: angular - dependency-name: "@angular-eslint/eslint-plugin-template" dependency-type: direct:development update-type: version-update:semver-minor dependency-group: angular - dependency-name: "@angular-eslint/schematics" dependency-type: direct:development update-type: version-update:semver-minor dependency-group: angular - dependency-name: "@angular-eslint/template-parser" dependency-type: direct:development update-type: version-update:semver-minor dependency-group: angular - dependency-name: "@angular/cli" dependency-type: direct:development update-type: version-update:semver-patch dependency-group: angular ... Signed-off-by: dependabot[bot] --- package.json | 20 +- yarn.lock | 678 ++++++++++++++------------------------------------- 2 files changed, 196 insertions(+), 502 deletions(-) diff --git a/package.json b/package.json index ad82a8fcd0..c67f948ed0 100644 --- a/package.json +++ b/package.json @@ -67,12 +67,12 @@ "@angular/compiler": "^17.3.11", "@angular/core": "^17.3.11", "@angular/forms": "^17.3.11", - "@angular/localize": "17.3.11", + "@angular/localize": "17.3.12", "@angular/platform-browser": "^17.3.11", "@angular/platform-browser-dynamic": "^17.3.11", "@angular/platform-server": "^17.3.11", "@angular/router": "^17.3.11", - "@angular/ssr": "^17.3.8", + "@angular/ssr": "^17.3.10", "@babel/runtime": "7.21.0", "@kolkov/ngx-gallery": "^2.0.1", "@material-ui/core": "^4.11.0", @@ -140,14 +140,14 @@ }, "devDependencies": { "@angular-builders/custom-webpack": "~17.0.2", - "@angular-devkit/build-angular": "^17.3.8", - "@angular-eslint/builder": "17.2.1", - "@angular-eslint/bundled-angular-compiler": "17.2.1", - "@angular-eslint/eslint-plugin": "17.2.1", - "@angular-eslint/eslint-plugin-template": "17.2.1", - "@angular-eslint/schematics": "17.2.1", - "@angular-eslint/template-parser": "17.2.1", - "@angular/cli": "^17.3.8", + "@angular-devkit/build-angular": "^17.3.10", + "@angular-eslint/builder": "17.5.3", + "@angular-eslint/bundled-angular-compiler": "17.5.3", + "@angular-eslint/eslint-plugin": "17.5.3", + "@angular-eslint/eslint-plugin-template": "17.5.3", + "@angular-eslint/schematics": "17.5.3", + "@angular-eslint/template-parser": "17.5.3", + "@angular/cli": "^17.3.10", "@angular/compiler-cli": "^17.3.11", "@angular/language-service": "^17.3.11", "@cypress/schematic": "^1.5.0", diff --git a/yarn.lock b/yarn.lock index 3888a2384e..0753b822a5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -31,12 +31,12 @@ lodash "^4.17.15" webpack-merge "^5.7.3" -"@angular-devkit/architect@0.1703.9", "@angular-devkit/architect@>=0.1700.0 < 0.1800.0": - version "0.1703.9" - resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1703.9.tgz#f99d01a704407c5467841c49654f5c3ac930f143" - integrity sha512-kEPfTOVnzrJxPGTvaXy8653HU9Fucxttx9gVfQR1yafs+yIEGx3fKGKe89YPmaEay32bIm7ZUpxDF1FO14nkdQ== +"@angular-devkit/architect@0.1703.10", "@angular-devkit/architect@>=0.1700.0 < 0.1800.0": + version "0.1703.10" + resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1703.10.tgz#c70a59f6dcc5228ac41713a14582253d5e348b40" + integrity sha512-wmjx5GspSPprdUGryK5+9vNawbEO7p8h9dxgX3uoeFwPAECcHC+/KK3qPhX2NiGcM6MDsyt25SrbSktJp6PRsA== dependencies: - "@angular-devkit/core" "17.3.9" + "@angular-devkit/core" "17.3.10" rxjs "7.8.1" "@angular-devkit/architect@^0.1202.10": @@ -47,15 +47,15 @@ "@angular-devkit/core" "12.2.18" rxjs "6.6.7" -"@angular-devkit/build-angular@^17.0.0", "@angular-devkit/build-angular@^17.3.8": - version "17.3.9" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-17.3.9.tgz#54d55052be3fcc9034a1a0659acd6dcd664cf034" - integrity sha512-EuAPSC4c2DSJLlL4ieviKLx1faTyY+ymWycq6KFwoxu1FgWly/dqBeWyXccYinLhPVZmoh6+A/5S4YWXlOGSnA== +"@angular-devkit/build-angular@^17.0.0", "@angular-devkit/build-angular@^17.3.10": + version "17.3.10" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-17.3.10.tgz#68c34b2922991f22369e912e080ddc5a0b112ca4" + integrity sha512-syz7xgzmp8/0tPJWwQIKZt7KNJfp9U7hkqNacXz4XTYz6YM0oyBXlqk2claSxywWBEkc0eJVSMD9e2ArusZBuA== dependencies: "@ampproject/remapping" "2.3.0" - "@angular-devkit/architect" "0.1703.9" - "@angular-devkit/build-webpack" "0.1703.9" - "@angular-devkit/core" "17.3.9" + "@angular-devkit/architect" "0.1703.10" + "@angular-devkit/build-webpack" "0.1703.10" + "@angular-devkit/core" "17.3.10" "@babel/core" "7.24.0" "@babel/generator" "7.23.6" "@babel/helper-annotate-as-pure" "7.22.5" @@ -66,7 +66,7 @@ "@babel/preset-env" "7.24.0" "@babel/runtime" "7.24.0" "@discoveryjs/json-ext" "0.5.7" - "@ngtools/webpack" "17.3.9" + "@ngtools/webpack" "17.3.10" "@vitejs/plugin-basic-ssl" "1.1.0" ansi-colors "4.1.3" autoprefixer "10.4.18" @@ -108,7 +108,7 @@ tree-kill "1.2.2" tslib "2.6.2" undici "6.11.1" - vite "5.1.7" + vite "5.1.8" watchpack "2.4.0" webpack "5.94.0" webpack-dev-middleware "6.1.2" @@ -118,12 +118,12 @@ optionalDependencies: esbuild "0.20.1" -"@angular-devkit/build-webpack@0.1703.9": - version "0.1703.9" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.1703.9.tgz#9eff5c69638d6cbb083b5c406e6dfca369e8641b" - integrity sha512-3b0LND39Nc+DwCQ0N7Tbsd7RAFWTeIc4VDwk/7RO8EMYTP5Kfgr/TK66nwTBypHsjmD69IMKHZZaZuiDfGfx2A== +"@angular-devkit/build-webpack@0.1703.10": + version "0.1703.10" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.1703.10.tgz#235760406246594b9c898eecef9e8703ad20769a" + integrity sha512-m6dDgzKLW+c3z9/TUxYmbJEtEhrdYNQ4ogdtAgEYA/FRrKueDU0WztLNr+dVbvwNP99Skovtr8sAQfN6twproQ== dependencies: - "@angular-devkit/architect" "0.1703.9" + "@angular-devkit/architect" "0.1703.10" rxjs "7.8.1" "@angular-devkit/core@12.2.18", "@angular-devkit/core@^12.2.17": @@ -138,10 +138,10 @@ rxjs "6.6.7" source-map "0.7.3" -"@angular-devkit/core@17.3.9", "@angular-devkit/core@^17.0.0", "@angular-devkit/core@^17.1.0": - version "17.3.9" - resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-17.3.9.tgz#68b72e775195f07742f84b6ebd60b241eee98a72" - integrity sha512-/iKyn5YT7NW5ylrg9yufUydS8byExeQ2HHIwFC4Ebwb/JYYCz+k4tBf2LdP+zXpemDpLznXTQGWia0/yJjG8Vg== +"@angular-devkit/core@17.3.10", "@angular-devkit/core@^17.0.0", "@angular-devkit/core@^17.1.0": + version "17.3.10" + resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-17.3.10.tgz#c259052a891ad0bd1a7708d1081571683b3fa814" + integrity sha512-czdl54yxU5DOAGy/uUPNjJruoBDTgwi/V+eOgLNybYhgrc+TsY0f7uJ11yEk/pz5sCov7xIiS7RdRv96waS7vg== dependencies: ajv "8.12.0" ajv-formats "2.1.1" @@ -159,78 +159,74 @@ ora "5.4.1" rxjs "6.6.7" -"@angular-devkit/schematics@17.3.9": - version "17.3.9" - resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-17.3.9.tgz#0fcf22d51f49fd23eeb88620134f2cb622094b7b" - integrity sha512-9qg+uWywgAtaQlvbnCQv47hcL6ZuA+d9ucgZ0upZftBllZ2vp5WIthCPb2mB0uBkj84Csmtz9MsErFjOQtTj4g== +"@angular-devkit/schematics@17.3.10": + version "17.3.10" + resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-17.3.10.tgz#a3d62b33f82fd1fa51246d00ada92efe82a00ae7" + integrity sha512-FHcNa1ktYRd0SKExCsNJpR75RffsyuPIV8kvBXzXnLHmXMqvl25G2te3yYJ9yYqy9OLy/58HZznZTxWRyUdHOg== dependencies: - "@angular-devkit/core" "17.3.9" + "@angular-devkit/core" "17.3.10" jsonc-parser "3.2.1" magic-string "0.30.8" ora "5.4.1" rxjs "7.8.1" -"@angular-eslint/builder@17.2.1": - version "17.2.1" - resolved "https://registry.yarnpkg.com/@angular-eslint/builder/-/builder-17.2.1.tgz#c7ba17e3a9de3a65d010f101b0c6cd3d5e9c26a8" - integrity sha512-O30eaR0wCPiP+zKWvXj2JM8hVq30Wok2rp7zJMFm3PurjF9nWIIyexXkE5fa538DYZYxu8N3gQRqhpv5jvTXCg== - dependencies: - "@nx/devkit" "17.2.8" - nx "17.2.8" +"@angular-eslint/builder@17.5.3": + version "17.5.3" + resolved "https://registry.yarnpkg.com/@angular-eslint/builder/-/builder-17.5.3.tgz#d04756dc2e6d70108100445aae206051d115ab1f" + integrity sha512-DoPCwt8qp5oMkfxY8V3wygf6/E7zzgXkPCwTRhIelklfpB3nYwLnbRSD8G5hueAU4eyASKiIuhR79E996AuUSw== -"@angular-eslint/bundled-angular-compiler@17.2.1": - version "17.2.1" - resolved "https://registry.yarnpkg.com/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-17.2.1.tgz#d849b0845371b41856b9f598af81ce5bf799bca0" - integrity sha512-puC0itsZv2QlrDOCcWtq1KZH+DvfrpV+mV78HHhi6+h25R5iIhr8ARKcl3EQxFjvrFq34jhG8pSupxKvFbHVfA== +"@angular-eslint/bundled-angular-compiler@17.5.3": + version "17.5.3" + resolved "https://registry.yarnpkg.com/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-17.5.3.tgz#6bdeb55881b2be796196cc3e0c684250923dd89f" + integrity sha512-x9jZ6mME9wxumErPGonWERXX/9TJ7mzEkQhOKt3BxBFm0sy9XQqLMAenp1PBSg3RF3rH7EEVdB2+jb75RtHp0g== -"@angular-eslint/eslint-plugin-template@17.2.1": - version "17.2.1" - resolved "https://registry.yarnpkg.com/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-17.2.1.tgz#226a623219375a2344112c1c896fefef0dae4df6" - integrity sha512-hl1hcHtcm90wyVL1OQGTz16oA0KHon+FFb3Qg0fLXObaXxA495Ecefd9ub5Xxg4JEOPRDi29bF1Y3YKpwflgeg== +"@angular-eslint/eslint-plugin-template@17.5.3": + version "17.5.3" + resolved "https://registry.yarnpkg.com/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-17.5.3.tgz#fa4f91cf028c64d38d0bcb5087cf8546811f5694" + integrity sha512-RkRFagxqBPV2xdNyeQQROUm6I1Izto1Z3Wy73lCk2zq1RhVgbznniH/epmOIE8PMkHmMKmZ765FV++J/90p4Ig== dependencies: - "@angular-eslint/bundled-angular-compiler" "17.2.1" - "@angular-eslint/utils" "17.2.1" - "@typescript-eslint/type-utils" "6.19.0" - "@typescript-eslint/utils" "6.19.0" + "@angular-eslint/bundled-angular-compiler" "17.5.3" + "@angular-eslint/utils" "17.5.3" + "@typescript-eslint/type-utils" "7.11.0" + "@typescript-eslint/utils" "7.11.0" aria-query "5.3.0" axobject-query "4.0.0" -"@angular-eslint/eslint-plugin@17.2.1": - version "17.2.1" - resolved "https://registry.yarnpkg.com/@angular-eslint/eslint-plugin/-/eslint-plugin-17.2.1.tgz#2be51ead1785950feb8351001e0683eae42f4c29" - integrity sha512-9yA81BHpsaCUKRBtHGN3ieAy8HpIoffzPQMu34lYqZFT4yGHGhYmhQjNSQGBRbV2LD9dVv2U35rMHNmUcozXpw== +"@angular-eslint/eslint-plugin@17.5.3": + version "17.5.3" + resolved "https://registry.yarnpkg.com/@angular-eslint/eslint-plugin/-/eslint-plugin-17.5.3.tgz#56c6bf09262089dd10a27b22ac1de979b6bc805b" + integrity sha512-2gMRZ+SkiygrPDtCJwMfjmwIFOcvxxC4NRX/MqRo6udsa0gtqPrc8acRbwrmAXlullmhzmaeUfkHpGDSzW8pFw== dependencies: - "@angular-eslint/utils" "17.2.1" - "@typescript-eslint/utils" "6.19.0" + "@angular-eslint/bundled-angular-compiler" "17.5.3" + "@angular-eslint/utils" "17.5.3" + "@typescript-eslint/utils" "7.11.0" -"@angular-eslint/schematics@17.2.1": - version "17.2.1" - resolved "https://registry.yarnpkg.com/@angular-eslint/schematics/-/schematics-17.2.1.tgz#8c0c15f106afe9fc9f89dd6573e6325afd2bf1e1" - integrity sha512-7ldtIePI4ZTp/TBpeOZkzfv30HSAn//4TgtFuqvojudI8n8batV5FqQ0VNm1e0zitl75t8Zwtr0KYT4I6vh59g== +"@angular-eslint/schematics@17.5.3": + version "17.5.3" + resolved "https://registry.yarnpkg.com/@angular-eslint/schematics/-/schematics-17.5.3.tgz#8957d5b47eb89b6c962628056d192fceb877fc81" + integrity sha512-a0MlOjNLIM18l/66S+CzhANQR3QH3jDUa1MC50E4KBf1mwjQyfqd6RdfbOTMDjgFlPrfB+5JvoWOHHGj7FFM1A== dependencies: - "@angular-eslint/eslint-plugin" "17.2.1" - "@angular-eslint/eslint-plugin-template" "17.2.1" - "@nx/devkit" "17.2.8" - ignore "5.3.0" - nx "17.2.8" + "@angular-eslint/eslint-plugin" "17.5.3" + "@angular-eslint/eslint-plugin-template" "17.5.3" + ignore "5.3.1" strip-json-comments "3.1.1" - tmp "0.2.1" + tmp "0.2.3" -"@angular-eslint/template-parser@17.2.1": - version "17.2.1" - resolved "https://registry.yarnpkg.com/@angular-eslint/template-parser/-/template-parser-17.2.1.tgz#005f997346eb17c6dbca5fffc41da51b7e755013" - integrity sha512-WPQYFvRju0tCDXQ/pwrzC911pE07JvpeDgcN2elhzV6lxDHJEZpA5O9pnW9qgNA6J6XM9Q7dBkJ22ztAzC4WFw== +"@angular-eslint/template-parser@17.5.3": + version "17.5.3" + resolved "https://registry.yarnpkg.com/@angular-eslint/template-parser/-/template-parser-17.5.3.tgz#5bfb6558a131bf54a67e3bd00bcf493d21f94e20" + integrity sha512-NYybOsMkJUtFOW2JWALicipq0kK5+jGwA1MYyRoXjdbDlXltHUb9qkXj7p0fE6uRutBGXDl4288s8g/fZCnAIA== dependencies: - "@angular-eslint/bundled-angular-compiler" "17.2.1" + "@angular-eslint/bundled-angular-compiler" "17.5.3" eslint-scope "^8.0.0" -"@angular-eslint/utils@17.2.1": - version "17.2.1" - resolved "https://registry.yarnpkg.com/@angular-eslint/utils/-/utils-17.2.1.tgz#3d4217775d86479348fdd0e1ad83014c9d8339f2" - integrity sha512-qQYTBXy90dWM7fhhpa5i9lTtqqhJisvRa+naCrQx9kBgR458JScLdkVIdcZ9D/rPiDCmKiVUfgcDISnjUeqTqg== +"@angular-eslint/utils@17.5.3": + version "17.5.3" + resolved "https://registry.yarnpkg.com/@angular-eslint/utils/-/utils-17.5.3.tgz#0b162a84e6f6af4e9ac5a3de95d95ee1df360232" + integrity sha512-0nNm1FUOLhVHrdK2PP5dZCYYVmTIkEJ4CmlwpuC4JtCLbD5XAHQpY/ZW5Ff5n1b7KfJt1Zy//jlhkkIaw3LaBQ== dependencies: - "@angular-eslint/bundled-angular-compiler" "17.2.1" - "@typescript-eslint/utils" "6.19.0" + "@angular-eslint/bundled-angular-compiler" "17.5.3" + "@typescript-eslint/utils" "7.11.0" "@angular/animations@^17.3.11": version "17.3.12" @@ -248,15 +244,15 @@ optionalDependencies: parse5 "^7.1.2" -"@angular/cli@^17.3.8": - version "17.3.9" - resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-17.3.9.tgz#cd571d288be3b3eb80acd25b54dd8a5008af417a" - integrity sha512-b5RGu5RO4VKZlMQDatwABAn1qocgD9u4IrGN2dvHDcrz5apTKYftUdGyG42vngyDNBCg1mWkSDQEWK4f2HfuGg== +"@angular/cli@^17.3.10": + version "17.3.10" + resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-17.3.10.tgz#15156dc511a6c43a798f5015e0345d7678691418" + integrity sha512-lA0kf4Cpo8Jcuennq6wGyBTP/UG1oX4xsM9uLRZ2vkPoisjHCk46rWaVP7vfAqdUH39vbATFXftpy1SiEmAI4w== dependencies: - "@angular-devkit/architect" "0.1703.9" - "@angular-devkit/core" "17.3.9" - "@angular-devkit/schematics" "17.3.9" - "@schematics/angular" "17.3.9" + "@angular-devkit/architect" "0.1703.10" + "@angular-devkit/core" "17.3.10" + "@angular-devkit/schematics" "17.3.10" + "@schematics/angular" "17.3.10" "@yarnpkg/lockfile" "1.1.0" ansi-colors "4.1.3" ini "4.1.2" @@ -319,10 +315,10 @@ resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-17.3.12.tgz#87a3d71e94ee7442eac046ca64be73a6a31a0027" integrity sha512-MVmEXonXwdhFtIpU4q8qbXHsrAsdTjZcPPuWCU0zXVQ+VaB/y6oF7BVpmBtfyBcBCums1guEncPP+AZVvulXmQ== -"@angular/localize@17.3.11": - version "17.3.11" - resolved "https://registry.yarnpkg.com/@angular/localize/-/localize-17.3.11.tgz#2eaec8c8126caaa7bad7cc7433ea91882fbe4885" - integrity sha512-uc38JfGpIEb13rDZu7wZfEvLxBpWbhfsOR+yI21M4zIiKYQxI7RGgtH9GbCKZDEZmeTUSz/idA4zwRiiX8wNvQ== +"@angular/localize@17.3.12": + version "17.3.12" + resolved "https://registry.yarnpkg.com/@angular/localize/-/localize-17.3.12.tgz#e38fbb595b6e045d49488afb0ad3e276da6721e3" + integrity sha512-b7J7zY/CgJhFVPtmu/pEjefU5SHuTy7lQgX6kTrJPaUSJ5i578R17xr4SwrWe7G4jzQwO6GXZZd17a62uNRyOA== dependencies: "@babel/core" "7.23.9" "@types/babel__core" "7.20.5" @@ -358,10 +354,10 @@ dependencies: tslib "^2.3.0" -"@angular/ssr@^17.3.8": - version "17.3.9" - resolved "https://registry.yarnpkg.com/@angular/ssr/-/ssr-17.3.9.tgz#69422608b9756c3e46f0489bc43433d8a90c4afe" - integrity sha512-AbS3tsHUVOqwC3XI4B8hQDWThfrOyv8Qhe1N9a712nJKcqmfrMO0gtvdhI//VxYz0X08/l97Yh5D61WqF7+CQw== +"@angular/ssr@^17.3.10": + version "17.3.10" + resolved "https://registry.yarnpkg.com/@angular/ssr/-/ssr-17.3.10.tgz#bf13834e3115ca7779834820dcb5b3b9659056bf" + integrity sha512-t+NX1HufU38c0u+8mDg31cqrXZo5SEUxjBuXwdu3mOvYbkanjhbtyIgIMYr9Vru8pqncasgHLJv2RVWDvAjlEw== dependencies: critters "0.0.22" tslib "^2.3.0" @@ -1922,13 +1918,6 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== -"@jest/schemas@^29.6.3": - version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" - integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== - dependencies: - "@sinclair/typebox" "^0.27.8" - "@jridgewell/gen-mapping@^0.3.2", "@jridgewell/gen-mapping@^0.3.5": version "0.3.5" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" @@ -2127,10 +2116,10 @@ dependencies: tslib "^2.0.0" -"@ngtools/webpack@17.3.9": - version "17.3.9" - resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-17.3.9.tgz#cfb27add90a1bb522ecbf869b79369145d4d9e6e" - integrity sha512-2+NvEQuYKRWdZaJbRJWEnR48tpW0uYbhwfHBHLDI9Kazb3mb0oAwYBVXdq+TtDLBypXnMsFpCewjRHTvkVx4/A== +"@ngtools/webpack@17.3.10": + version "17.3.10" + resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-17.3.10.tgz#6f077ef3d1fa4363cffcfee66f9b2e52164069b2" + integrity sha512-yPKmdbTJzxROAl2NS8P8eHB2mU0BqV2I0ZiKmX6oTetY2Ea4i2WzlTK39pPpG7atmdF2NPWYLXdJWAup+JxSyw== "@ngtools/webpack@^16.2.12": version "16.2.15" @@ -2277,84 +2266,6 @@ node-gyp "^10.0.0" which "^4.0.0" -"@nrwl/devkit@17.2.8": - version "17.2.8" - resolved "https://registry.yarnpkg.com/@nrwl/devkit/-/devkit-17.2.8.tgz#dd3467b484c4611454a45541ffb29e4de5b2ebe7" - integrity sha512-l2dFy5LkWqSA45s6pee6CoqJeluH+sjRdVnAAQfjLHRNSx6mFAKblyzq5h1f4P0EUCVVVqLs+kVqmNx5zxYqvw== - dependencies: - "@nx/devkit" "17.2.8" - -"@nrwl/tao@17.2.8": - version "17.2.8" - resolved "https://registry.yarnpkg.com/@nrwl/tao/-/tao-17.2.8.tgz#41ff3d715a0763e95cf5c35e7f79cd3be358dc5f" - integrity sha512-Qpk5YKeJ+LppPL/wtoDyNGbJs2MsTi6qyX/RdRrEc8lc4bk6Cw3Oul1qTXCI6jT0KzTz+dZtd0zYD/G7okkzvg== - dependencies: - nx "17.2.8" - tslib "^2.3.0" - -"@nx/devkit@17.2.8": - version "17.2.8" - resolved "https://registry.yarnpkg.com/@nx/devkit/-/devkit-17.2.8.tgz#49b6c94a3c12fba63eae6514fb37a468d0570e2e" - integrity sha512-6LtiQihtZwqz4hSrtT5cCG5XMCWppG6/B8c1kNksg97JuomELlWyUyVF+sxmeERkcLYFaKPTZytP0L3dmCFXaw== - dependencies: - "@nrwl/devkit" "17.2.8" - ejs "^3.1.7" - enquirer "~2.3.6" - ignore "^5.0.4" - semver "7.5.3" - tmp "~0.2.1" - tslib "^2.3.0" - -"@nx/nx-darwin-arm64@17.2.8": - version "17.2.8" - resolved "https://registry.yarnpkg.com/@nx/nx-darwin-arm64/-/nx-darwin-arm64-17.2.8.tgz#26645c9548d5e387b43c06fccfa18e2c1f08055e" - integrity sha512-dMb0uxug4hM7tusISAU1TfkDK3ixYmzc1zhHSZwpR7yKJIyKLtUpBTbryt8nyso37AS1yH+dmfh2Fj2WxfBHTg== - -"@nx/nx-darwin-x64@17.2.8": - version "17.2.8" - resolved "https://registry.yarnpkg.com/@nx/nx-darwin-x64/-/nx-darwin-x64-17.2.8.tgz#5143d6d01d24e338cb3d39076fe2af95146cb538" - integrity sha512-0cXzp1tGr7/6lJel102QiLA4NkaLCkQJj6VzwbwuvmuCDxPbpmbz7HC1tUteijKBtOcdXit1/MEoEU007To8Bw== - -"@nx/nx-freebsd-x64@17.2.8": - version "17.2.8" - resolved "https://registry.yarnpkg.com/@nx/nx-freebsd-x64/-/nx-freebsd-x64-17.2.8.tgz#82a018a1855170e0243b8fe7b0032af279c3fb83" - integrity sha512-YFMgx5Qpp2btCgvaniDGdu7Ctj56bfFvbbaHQWmOeBPK1krNDp2mqp8HK6ZKOfEuDJGOYAp7HDtCLvdZKvJxzA== - -"@nx/nx-linux-arm-gnueabihf@17.2.8": - version "17.2.8" - resolved "https://registry.yarnpkg.com/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-17.2.8.tgz#18b9c324221ff6a30589f3fc272a843aca57b70f" - integrity sha512-iN2my6MrhLRkVDtdivQHugK8YmR7URo1wU9UDuHQ55z3tEcny7LV3W9NSsY9UYPK/FrxdDfevj0r2hgSSdhnzA== - -"@nx/nx-linux-arm64-gnu@17.2.8": - version "17.2.8" - resolved "https://registry.yarnpkg.com/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-17.2.8.tgz#54a08640a2babe78bcf3283565b00eb487db595e" - integrity sha512-Iy8BjoW6mOKrSMiTGujUcNdv+xSM1DALTH6y3iLvNDkGbjGK1Re6QNnJAzqcXyDpv32Q4Fc57PmuexyysZxIGg== - -"@nx/nx-linux-arm64-musl@17.2.8": - version "17.2.8" - resolved "https://registry.yarnpkg.com/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-17.2.8.tgz#cd7b673bb9f45fec7aa1b6c880a0d23d658e927f" - integrity sha512-9wkAxWzknjpzdofL1xjtU6qPFF1PHlvKCZI3hgEYJDo4mQiatGI+7Ttko+lx/ZMP6v4+Umjtgq7+qWrApeKamQ== - -"@nx/nx-linux-x64-gnu@17.2.8": - version "17.2.8" - resolved "https://registry.yarnpkg.com/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-17.2.8.tgz#009eb75c77bf075bc9c13ec4f9caf77821eee639" - integrity sha512-sjG1bwGsjLxToasZ3lShildFsF0eyeGu+pOQZIp9+gjFbeIkd19cTlCnHrOV9hoF364GuKSXQyUlwtFYFR4VTQ== - -"@nx/nx-linux-x64-musl@17.2.8": - version "17.2.8" - resolved "https://registry.yarnpkg.com/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-17.2.8.tgz#8ee2324068732a135ca4b01081942d5956885167" - integrity sha512-QiakXZ1xBCIptmkGEouLHQbcM4klQkcr+kEaz2PlNwy/sW3gH1b/1c0Ed5J1AN9xgQxWspriAONpScYBRgxdhA== - -"@nx/nx-win32-arm64-msvc@17.2.8": - version "17.2.8" - resolved "https://registry.yarnpkg.com/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-17.2.8.tgz#9bdce5b4d1f9cec7ef326eaf43b99e68576398b0" - integrity sha512-XBWUY/F/GU3vKN9CAxeI15gM4kr3GOBqnzFZzoZC4qJt2hKSSUEWsMgeZtsMgeqEClbi4ZyCCkY7YJgU32WUGA== - -"@nx/nx-win32-x64-msvc@17.2.8": - version "17.2.8" - resolved "https://registry.yarnpkg.com/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-17.2.8.tgz#8a86ff250021ad47686b58f1840b348a209b1158" - integrity sha512-HTqDv+JThlLzbcEm/3f+LbS5/wYQWzb5YDXbP1wi7nlCTihNZOLNqGOkEmwlrR5tAdNHPRpHSmkYg4305W0CtA== - "@pkgjs/parseargs@^0.11.0": version "0.11.0" resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" @@ -2513,13 +2424,13 @@ resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8" integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g== -"@schematics/angular@17.3.9": - version "17.3.9" - resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-17.3.9.tgz#38ad60fea904592ea5d39be6581b22fb16f1baf1" - integrity sha512-q6N8mbcYC6cgPyjTrMH7ehULQoUUwEYN4g7uo4ylZ/PFklSLJvpSp4BuuxANgW449qHSBvQfdIoui9ayAUXQzA== +"@schematics/angular@17.3.10": + version "17.3.10" + resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-17.3.10.tgz#87c77ae2eb917f391d654df3c908f4a00d3d9443" + integrity sha512-cI+VB/WXlOeAMamni932lE/AZgui8o81dMyEXNXqCuYagNAMuKXliW79Mi5BwYQEABv/BUb4hB4zYtbQqHyACA== dependencies: - "@angular-devkit/core" "17.3.9" - "@angular-devkit/schematics" "17.3.9" + "@angular-devkit/core" "17.3.10" + "@angular-devkit/schematics" "17.3.10" jsonc-parser "3.2.1" "@schematics/angular@^12.2.17": @@ -2577,11 +2488,6 @@ "@sigstore/core" "^1.1.0" "@sigstore/protobuf-specs" "^0.3.2" -"@sinclair/typebox@^0.27.8": - version "0.27.8" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" - integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== - "@socket.io/component-emitter@~3.1.0": version "3.1.2" resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz#821f8442f4175d8f0467b9daf26e3a18e2d02af2" @@ -3001,14 +2907,6 @@ "@typescript-eslint/types" "5.62.0" "@typescript-eslint/visitor-keys" "5.62.0" -"@typescript-eslint/scope-manager@6.19.0": - version "6.19.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.19.0.tgz#b6d2abb825b29ab70cb542d220e40c61c1678116" - integrity sha512-dO1XMhV2ehBI6QN8Ufi7I10wmUovmLU0Oru3n5LVlM2JuzB4M+dVphCPLkVpKvGij2j/pHBWuJ9piuXx+BhzxQ== - dependencies: - "@typescript-eslint/types" "6.19.0" - "@typescript-eslint/visitor-keys" "6.19.0" - "@typescript-eslint/scope-manager@6.21.0": version "6.21.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz#ea8a9bfc8f1504a6ac5d59a6df308d3a0630a2b1" @@ -3017,6 +2915,14 @@ "@typescript-eslint/types" "6.21.0" "@typescript-eslint/visitor-keys" "6.21.0" +"@typescript-eslint/scope-manager@7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.11.0.tgz#cf5619b01de62a226a59add15a02bde457335d1d" + integrity sha512-27tGdVEiutD4POirLZX4YzT180vevUURJl4wJGmm6TrQoiYwuxTIY98PBp6L2oN+JQxzE0URvYlzJaBHIekXAw== + dependencies: + "@typescript-eslint/types" "7.11.0" + "@typescript-eslint/visitor-keys" "7.11.0" + "@typescript-eslint/scope-manager@7.18.0": version "7.18.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz#c928e7a9fc2c0b3ed92ab3112c614d6bd9951c83" @@ -3025,15 +2931,15 @@ "@typescript-eslint/types" "7.18.0" "@typescript-eslint/visitor-keys" "7.18.0" -"@typescript-eslint/type-utils@6.19.0": - version "6.19.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.19.0.tgz#522a494ef0d3e9fdc5e23a7c22c9331bbade0101" - integrity sha512-mcvS6WSWbjiSxKCwBcXtOM5pRkPQ6kcDds/juxcy/727IQr3xMEcwr/YLHW2A2+Fp5ql6khjbKBzOyjuPqGi/w== +"@typescript-eslint/type-utils@7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.11.0.tgz#ac216697d649084fedf4a910347b9642bd0ff099" + integrity sha512-WmppUEgYy+y1NTseNMJ6mCFxt03/7jTOy08bcg7bxJJdsM4nuhnchyBbE8vryveaJUf62noH7LodPSo5Z0WUCg== dependencies: - "@typescript-eslint/typescript-estree" "6.19.0" - "@typescript-eslint/utils" "6.19.0" + "@typescript-eslint/typescript-estree" "7.11.0" + "@typescript-eslint/utils" "7.11.0" debug "^4.3.4" - ts-api-utils "^1.0.1" + ts-api-utils "^1.3.0" "@typescript-eslint/type-utils@7.18.0": version "7.18.0" @@ -3050,16 +2956,16 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== -"@typescript-eslint/types@6.19.0": - version "6.19.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.19.0.tgz#689b0498c436272a6a2059b09f44bcbd90de294a" - integrity sha512-lFviGV/vYhOy3m8BJ/nAKoAyNhInTdXpftonhWle66XHAtT1ouBlkjL496b5H5hb8dWXHwtypTqgtb/DEa+j5A== - "@typescript-eslint/types@6.21.0": version "6.21.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.21.0.tgz#205724c5123a8fef7ecd195075fa6e85bac3436d" integrity sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg== +"@typescript-eslint/types@7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.11.0.tgz#5e9702a5e8b424b7fc690e338d359939257d6722" + integrity sha512-MPEsDRZTyCiXkD4vd3zywDCifi7tatc4K37KqTprCvaXptP7Xlpdw0NR2hRJTetG5TxbWDB79Ys4kLmHliEo/w== + "@typescript-eslint/types@7.18.0": version "7.18.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.18.0.tgz#b90a57ccdea71797ffffa0321e744f379ec838c9" @@ -3078,20 +2984,6 @@ semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/typescript-estree@6.19.0": - version "6.19.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.0.tgz#0813ba364a409afb4d62348aec0202600cb468fa" - integrity sha512-o/zefXIbbLBZ8YJ51NlkSAt2BamrK6XOmuxSR3hynMIzzyMY33KuJ9vuMdFSXW+H0tVvdF9qBPTHA91HDb4BIQ== - dependencies: - "@typescript-eslint/types" "6.19.0" - "@typescript-eslint/visitor-keys" "6.19.0" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - minimatch "9.0.3" - semver "^7.5.4" - ts-api-utils "^1.0.1" - "@typescript-eslint/typescript-estree@6.21.0": version "6.21.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz#c47ae7901db3b8bddc3ecd73daff2d0895688c46" @@ -3106,6 +2998,20 @@ semver "^7.5.4" ts-api-utils "^1.0.1" +"@typescript-eslint/typescript-estree@7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.11.0.tgz#7cbc569bc7336c3a494ceaf8204fdee5d5dbb7fa" + integrity sha512-cxkhZ2C/iyi3/6U9EPc5y+a6csqHItndvN/CzbNXTNrsC3/ASoYQZEt9uMaEp+xFNjasqQyszp5TumAVKKvJeQ== + dependencies: + "@typescript-eslint/types" "7.11.0" + "@typescript-eslint/visitor-keys" "7.11.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + minimatch "^9.0.4" + semver "^7.6.0" + ts-api-utils "^1.3.0" + "@typescript-eslint/typescript-estree@7.18.0": version "7.18.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz#b5868d486c51ce8f312309ba79bdb9f331b37931" @@ -3134,18 +3040,15 @@ eslint-scope "^5.1.1" semver "^7.3.7" -"@typescript-eslint/utils@6.19.0": - version "6.19.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.19.0.tgz#557b72c3eeb4f73bef8037c85dae57b21beb1a4b" - integrity sha512-QR41YXySiuN++/dC9UArYOg4X86OAYP83OWTewpVx5ct1IZhjjgTLocj7QNxGhWoTqknsgpl7L+hGygCO+sdYw== +"@typescript-eslint/utils@7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.11.0.tgz#524f047f2209959424c3ef689b0d83b3bc09919c" + integrity sha512-xlAWwPleNRHwF37AhrZurOxA1wyXowW4PqVXZVUNCLjB48CqdPJoJWkrpH2nij9Q3Lb7rtWindtoXwxjxlKKCA== dependencies: "@eslint-community/eslint-utils" "^4.4.0" - "@types/json-schema" "^7.0.12" - "@types/semver" "^7.5.0" - "@typescript-eslint/scope-manager" "6.19.0" - "@typescript-eslint/types" "6.19.0" - "@typescript-eslint/typescript-estree" "6.19.0" - semver "^7.5.4" + "@typescript-eslint/scope-manager" "7.11.0" + "@typescript-eslint/types" "7.11.0" + "@typescript-eslint/typescript-estree" "7.11.0" "@typescript-eslint/utils@7.18.0", "@typescript-eslint/utils@^7.2.0": version "7.18.0" @@ -3178,14 +3081,6 @@ "@typescript-eslint/types" "5.62.0" eslint-visitor-keys "^3.3.0" -"@typescript-eslint/visitor-keys@6.19.0": - version "6.19.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.0.tgz#4565e0ecd63ca1f81b96f1dd76e49f746c6b2b49" - integrity sha512-hZaUCORLgubBvtGpp1JEFEazcuEdfxta9j4iUwdSAr7mEsYYAp3EAUyCZk3VEEqGj6W+AV4uWyrDGtrlawAsgQ== - dependencies: - "@typescript-eslint/types" "6.19.0" - eslint-visitor-keys "^3.4.1" - "@typescript-eslint/visitor-keys@6.21.0": version "6.21.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz#87a99d077aa507e20e238b11d56cc26ade45fe47" @@ -3194,6 +3089,14 @@ "@typescript-eslint/types" "6.21.0" eslint-visitor-keys "^3.4.1" +"@typescript-eslint/visitor-keys@7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.11.0.tgz#2c50cd292e67645eec05ac0830757071b4a4d597" + integrity sha512-7syYk4MzjxTEk0g/w3iqtgxnFQspDJfn6QKD36xMuuhTzjcxY7F8EmBLnALjVyaOF1/bVocu3bS/2/F7rXrveQ== + dependencies: + "@typescript-eslint/types" "7.11.0" + eslint-visitor-keys "^3.4.3" + "@typescript-eslint/visitor-keys@7.18.0": version "7.18.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz#0564629b6124d67607378d0f0332a0495b25e7d7" @@ -3358,26 +3261,11 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== -"@yarnpkg/lockfile@1.1.0", "@yarnpkg/lockfile@^1.1.0": +"@yarnpkg/lockfile@1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== -"@yarnpkg/parsers@3.0.0-rc.46": - version "3.0.0-rc.46" - resolved "https://registry.yarnpkg.com/@yarnpkg/parsers/-/parsers-3.0.0-rc.46.tgz#03f8363111efc0ea670e53b0282cd3ef62de4e01" - integrity sha512-aiATs7pSutzda/rq8fnuPwTglyVwjM22bNnK2ZgjrpAjQHSSl3lztd2f9evst1W/qnC58DRz7T7QndUDumAR4Q== - dependencies: - js-yaml "^3.10.0" - tslib "^2.4.0" - -"@zkochan/js-yaml@0.0.6": - version "0.0.6" - resolved "https://registry.yarnpkg.com/@zkochan/js-yaml/-/js-yaml-0.0.6.tgz#975f0b306e705e28b8068a07737fa46d3fc04826" - integrity sha512-nzvgl3VfhcELQ8LyVrYOru+UtAy1nrygk2+AGbTm8a5YcO6o8lSjAT+pfg3vJWxIoZKOUhrK6UU7xW/+00kQrg== - dependencies: - argparse "^2.0.1" - abbrev@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-2.0.0.tgz#cf59829b8b4f03f89dda2771cb7f3653828c89bf" @@ -3575,11 +3463,6 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" -ansi-styles@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" - integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== - ansi-styles@^6.1.0: version "6.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" @@ -3810,7 +3693,7 @@ axe-core@^4.7.2: resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.10.0.tgz#d9e56ab0147278272739a000880196cdfe113b59" integrity sha512-Mr2ZakwQ7XUAjp7pAwQWRhhK8mQQ6JAaNWSjmjxil0R8BPioMtQsTLOolGYkji1rcL++3dCqZA3zWqpT+9Ew6g== -axios@^1.5.1, axios@^1.7.4: +axios@^1.7.4: version "1.7.7" resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f" integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q== @@ -3927,7 +3810,7 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== -bl@^4.0.3, bl@^4.1.0: +bl@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== @@ -4291,7 +4174,7 @@ clean-stack@^2.0.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== -cli-cursor@3.1.0, cli-cursor@^3.1.0: +cli-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== @@ -4305,11 +4188,6 @@ cli-progress@^3.12.0: dependencies: string-width "^4.2.3" -cli-spinners@2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.6.1.tgz#adc954ebe281c37a6319bfa401e6dd2488ffb70d" - integrity sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g== - cli-spinners@^2.5.0: version "2.9.2" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" @@ -5035,11 +4913,6 @@ di@^0.0.1: resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" integrity sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA== -diff-sequences@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" - integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== - diff@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" @@ -5140,17 +5013,7 @@ domutils@^3.0.1: domelementtype "^2.3.0" domhandler "^5.0.3" -dotenv-expand@~10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-10.0.0.tgz#12605d00fb0af6d0a592e6558585784032e4ef37" - integrity sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A== - -dotenv@~16.3.1: - version "16.3.2" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.2.tgz#3cb611ce5a63002dbabf7c281bc331f69d28f03f" - integrity sha512-HTlk5nmhkm8F6JcdXvHIzaorzCoziNQT9mGxLPVXW8wJF1TiGSL60ZGB4gHWabHOaMmWmhvk2/lPHfnBiT78AQ== - -duplexer@^0.1.1, duplexer@^0.1.2: +duplexer@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== @@ -5187,7 +5050,7 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -ejs@^3.1.10, ejs@^3.1.7: +ejs@^3.1.10: version "3.1.10" resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.10.tgz#69ab8358b14e896f80cc39e62087b88500c3ac3b" integrity sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA== @@ -5238,7 +5101,7 @@ encoding@^0.1.13: dependencies: iconv-lite "^0.6.2" -end-of-stream@^1.1.0, end-of-stream@^1.4.1: +end-of-stream@^1.1.0: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== @@ -5293,13 +5156,6 @@ enquirer@^2.3.6: ansi-colors "^4.1.1" strip-ansi "^6.0.1" -enquirer@~2.3.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" - integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== - dependencies: - ansi-colors "^4.1.1" - ent@~2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.1.tgz#68dc99a002f115792c26239baedaaea9e70c0ca2" @@ -6020,7 +5876,7 @@ fd-slicer@~1.1.0: dependencies: pend "~1.2.0" -figures@3.2.0, figures@^3.2.0: +figures@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== @@ -6210,11 +6066,6 @@ fresh@0.5.2, fresh@^0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== -fs-constants@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" - integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== - fs-extra@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-3.0.1.tgz#3794f378c58b342ea7dbbb23095109c4b3b62291" @@ -6224,15 +6075,6 @@ fs-extra@3.0.1: jsonfile "^3.0.0" universalify "^0.1.0" -fs-extra@^11.1.0: - version "11.2.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b" - integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - fs-extra@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" @@ -6386,18 +6228,6 @@ glob-to-regexp@^0.4.1: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== -glob@7.1.4: - version "7.1.4" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" - integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - glob@^10.2.2, glob@^10.3.10: version "10.4.5" resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" @@ -6814,12 +6644,12 @@ ignore-walk@^6.0.4: dependencies: minimatch "^9.0.0" -ignore@5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.0.tgz#67418ae40d34d6999c95ff56016759c718c82f78" - integrity sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg== +ignore@5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" + integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== -ignore@^5.0.4, ignore@^5.2.0, ignore@^5.2.4, ignore@^5.3.1: +ignore@^5.2.0, ignore@^5.2.4, ignore@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== @@ -7372,21 +7202,6 @@ jasmine@^3.8.0: glob "^7.1.6" jasmine-core "~3.99.0" -jest-diff@^29.4.1: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" - integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== - dependencies: - chalk "^4.0.0" - diff-sequences "^29.6.3" - jest-get-type "^29.6.3" - pretty-format "^29.7.0" - -jest-get-type@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" - integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== - jest-worker@^27.4.5: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" @@ -7411,14 +7226,7 @@ js-cookie@2.2.1: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@4.1.0, js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -js-yaml@^3.10.0, js-yaml@^3.13.1: +js-yaml@^3.13.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== @@ -7426,6 +7234,13 @@ js-yaml@^3.10.0, js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + jsbn@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-1.1.0.tgz#b01307cb29b618a1ed26ec79e911f803c4da0040" @@ -7518,11 +7333,6 @@ jsonc-parser@3.0.0: resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.0.0.tgz#abdd785701c7e7eaca8a9ec8cf070ca51a745a22" integrity sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA== -jsonc-parser@3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" - integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w== - jsonc-parser@3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.1.tgz#031904571ccf929d7670ee8c547545081cb37f1a" @@ -7837,11 +7647,6 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== -lines-and-columns@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-2.0.4.tgz#d00318855905d2660d8c0822e3f5a4715855fc42" - integrity sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A== - linkify-it@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-4.0.1.tgz#01f1d5e508190d06669982ba31a7d9f56a5751ec" @@ -8179,13 +7984,6 @@ minimalistic-assert@^1.0.0: resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== -minimatch@3.0.5: - version "3.0.5" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.5.tgz#4da8f1290ee0f0f8e83d60ca69f8f134068604a3" - integrity sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw== - dependencies: - brace-expansion "^1.1.7" - minimatch@9.0.3: version "9.0.3" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" @@ -8534,11 +8332,6 @@ node-gyp@^10.0.0: tar "^6.2.1" which "^4.0.0" -node-machine-id@1.1.12: - version "1.1.12" - resolved "https://registry.yarnpkg.com/node-machine-id/-/node-machine-id-1.1.12.tgz#37904eee1e59b320bb9c5d6c0a59f3b469cb6267" - integrity sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ== - node-releases@^2.0.18: version "2.0.18" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f" @@ -8690,57 +8483,6 @@ nth-check@^2.0.1: dependencies: boolbase "^1.0.0" -nx@17.2.8: - version "17.2.8" - resolved "https://registry.yarnpkg.com/nx/-/nx-17.2.8.tgz#09482acd5d9b64c115d5ccf12417f1af2787d4d1" - integrity sha512-rM5zXbuXLEuqQqcjVjClyvHwRJwt+NVImR2A6KFNG40Z60HP6X12wAxxeLHF5kXXTDRU0PFhf/yACibrpbPrAw== - dependencies: - "@nrwl/tao" "17.2.8" - "@yarnpkg/lockfile" "^1.1.0" - "@yarnpkg/parsers" "3.0.0-rc.46" - "@zkochan/js-yaml" "0.0.6" - axios "^1.5.1" - chalk "^4.1.0" - cli-cursor "3.1.0" - cli-spinners "2.6.1" - cliui "^8.0.1" - dotenv "~16.3.1" - dotenv-expand "~10.0.0" - enquirer "~2.3.6" - figures "3.2.0" - flat "^5.0.2" - fs-extra "^11.1.0" - glob "7.1.4" - ignore "^5.0.4" - jest-diff "^29.4.1" - js-yaml "4.1.0" - jsonc-parser "3.2.0" - lines-and-columns "~2.0.3" - minimatch "3.0.5" - node-machine-id "1.1.12" - npm-run-path "^4.0.1" - open "^8.4.0" - semver "7.5.3" - string-width "^4.2.3" - strong-log-transformer "^2.1.0" - tar-stream "~2.2.0" - tmp "~0.2.1" - tsconfig-paths "^4.1.2" - tslib "^2.3.0" - yargs "^17.6.2" - yargs-parser "21.1.1" - optionalDependencies: - "@nx/nx-darwin-arm64" "17.2.8" - "@nx/nx-darwin-x64" "17.2.8" - "@nx/nx-freebsd-x64" "17.2.8" - "@nx/nx-linux-arm-gnueabihf" "17.2.8" - "@nx/nx-linux-arm64-gnu" "17.2.8" - "@nx/nx-linux-arm64-musl" "17.2.8" - "@nx/nx-linux-x64-gnu" "17.2.8" - "@nx/nx-linux-x64-musl" "17.2.8" - "@nx/nx-win32-arm64-msvc" "17.2.8" - "@nx/nx-win32-x64-msvc" "17.2.8" - oauth-sign@~0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" @@ -8837,7 +8579,7 @@ onetime@^5.1.0, onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" -open@8.4.2, open@^8.0.9, open@^8.4.0: +open@8.4.2, open@^8.0.9: version "8.4.2" resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== @@ -9587,15 +9329,6 @@ pretty-bytes@^5.6.0: resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg== -pretty-format@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" - integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== - dependencies: - "@jest/schemas" "^29.6.3" - ansi-styles "^5.0.0" - react-is "^18.0.0" - proc-log@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-3.0.0.tgz#fb05ef83ccd64fd7b20bbe9c8c1070fc08338dd8" @@ -9884,11 +9617,6 @@ react-is@^16.13.1, react-is@^16.7.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== -react-is@^18.0.0: - version "18.3.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" - integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== - react-mosaic-component@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/react-mosaic-component/-/react-mosaic-component-4.1.1.tgz#48a34e5e5c16654075212666c2aebeb488bab9f2" @@ -10010,7 +9738,7 @@ readable-stream@^2.0.1: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0: +readable-stream@^3.0.6, readable-stream@^3.4.0: version "3.6.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== @@ -10268,7 +9996,7 @@ rimraf@^2.2.8, rimraf@^2.5.2, rimraf@^2.6.3: dependencies: glob "^7.1.3" -rimraf@^3.0.0, rimraf@^3.0.2: +rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== @@ -10525,13 +10253,6 @@ semver-compare@^1.0.0: resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" integrity sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow== -semver@7.5.3: - version "7.5.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" - integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== - dependencies: - lru-cache "^6.0.0" - semver@7.6.0: version "7.6.0" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" @@ -11140,15 +10861,6 @@ strip-json-comments@3.1.1, strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -strong-log-transformer@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz#0f5ed78d325e0421ac6f90f7f10e691d6ae3ae10" - integrity sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA== - dependencies: - duplexer "^0.1.1" - minimist "^1.2.0" - through "^2.3.4" - supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" @@ -11197,17 +10909,6 @@ tapable@^2.1.1, tapable@^2.2.0, tapable@^2.2.1: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== -tar-stream@~2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" - integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== - dependencies: - bl "^4.0.3" - end-of-stream "^1.4.1" - fs-constants "^1.0.0" - inherits "^2.0.3" - readable-stream "^3.1.1" - tar@^6.0.2, tar@^6.1.11, tar@^6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a" @@ -11275,7 +10976,7 @@ throttleit@^1.0.0: resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.1.tgz#304ec51631c3b770c65c6c6f76938b384000f4d5" integrity sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ== -through@^2.3.4, through@^2.3.8: +through@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== @@ -11295,12 +10996,10 @@ tiny-warning@^1.0.2: resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== -tmp@0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" - integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== - dependencies: - rimraf "^3.0.0" +tmp@0.2.3, tmp@^0.2.1, tmp@~0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae" + integrity sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w== tmp@^0.0.33: version "0.0.33" @@ -11309,11 +11008,6 @@ tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" -tmp@^0.2.1, tmp@~0.2.1, tmp@~0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae" - integrity sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w== - to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -11418,7 +11112,7 @@ tsconfig-paths@^3.15.0: minimist "^1.2.6" strip-bom "^3.0.0" -tsconfig-paths@^4.1.0, tsconfig-paths@^4.1.2: +tsconfig-paths@^4.1.0: version "4.2.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c" integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg== @@ -11437,7 +11131,7 @@ tslib@^1.8.1, tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.0, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.3.1, tslib@^2.4.0: +tslib@^2.0.0, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.3.1: version "2.7.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== @@ -11782,10 +11476,10 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -vite@5.1.7: - version "5.1.7" - resolved "https://registry.yarnpkg.com/vite/-/vite-5.1.7.tgz#9f685a2c4c70707fef6d37341b0e809c366da619" - integrity sha512-sgnEEFTZYMui/sTlH1/XEnVNHMujOahPLGMxn1+5sIT45Xjng1Ec1K78jRP15dSmVgg5WBin9yO81j3o9OxofA== +vite@5.1.8: + version "5.1.8" + resolved "https://registry.yarnpkg.com/vite/-/vite-5.1.8.tgz#f728feda90c3f30b0ab530c0981e5aa7745b8aee" + integrity sha512-mB8ToUuSmzODSpENgvpFk2fTiU/YQ1tmcVJJ4WZbq4fPdGJkFNVcmVL5k7iDug6xzWjjuGDKAuSievIsD6H7Xw== dependencies: esbuild "^0.19.3" postcss "^8.4.35" @@ -12223,17 +11917,17 @@ yaml@^1.10.0: resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== -yargs-parser@21.1.1, yargs-parser@^21.1.1: - version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" - integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== - yargs-parser@^20.2.2: version "20.2.9" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== -yargs@17.7.2, yargs@^17.0.0, yargs@^17.2.1, yargs@^17.3.1, yargs@^17.6.2: +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@17.7.2, yargs@^17.0.0, yargs@^17.2.1, yargs@^17.3.1: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== From e6ce7512790384d7f737061c66f32ad9c6b15160 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Oct 2024 13:57:36 +0000 Subject: [PATCH 0597/1286] Bump @types/lodash from 4.17.7 to 4.17.10 Bumps [@types/lodash](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/lodash) from 4.17.7 to 4.17.10. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/lodash) --- updated-dependencies: - dependency-name: "@types/lodash" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index ad82a8fcd0..c848a14e2e 100644 --- a/package.json +++ b/package.json @@ -159,7 +159,7 @@ "@types/express": "^4.17.17", "@types/jasmine": "~3.6.0", "@types/js-cookie": "2.2.6", - "@types/lodash": "^4.14.194", + "@types/lodash": "^4.17.10", "@types/node": "^14.14.9", "@types/sanitize-html": "^2.9.0", "@typescript-eslint/eslint-plugin": "^7.2.0", diff --git a/yarn.lock b/yarn.lock index 3888a2384e..87236afd2c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2785,10 +2785,10 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== -"@types/lodash@^4.14.194": - version "4.17.7" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.7.tgz#2f776bcb53adc9e13b2c0dfd493dfcbd7de43612" - integrity sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA== +"@types/lodash@^4.17.10": + version "4.17.10" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.10.tgz#64f3edf656af2fe59e7278b73d3e62404144a6e6" + integrity sha512-YpS0zzoduEhuOWjAotS6A5AVCva7X4lVlYLF0FYHAY9sdraBfnatttHItlWeZdGhuEkf+OzMNg2ZYAx8t+52uQ== "@types/mime@^1": version "1.3.5" From 3352a966f3c6d727ed250259c0c78d32d05659e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Oct 2024 13:57:49 +0000 Subject: [PATCH 0598/1286] Bump @types/deep-freeze from 0.1.2 to 0.1.5 Bumps [@types/deep-freeze](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/deep-freeze) from 0.1.2 to 0.1.5. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/deep-freeze) --- updated-dependencies: - dependency-name: "@types/deep-freeze" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index ad82a8fcd0..279cab3fc2 100644 --- a/package.json +++ b/package.json @@ -154,7 +154,7 @@ "@fortawesome/fontawesome-free": "^6.4.0", "@ngrx/store-devtools": "^17.1.1", "@ngtools/webpack": "^16.2.12", - "@types/deep-freeze": "0.1.2", + "@types/deep-freeze": "0.1.5", "@types/ejs": "^3.1.2", "@types/express": "^4.17.17", "@types/jasmine": "~3.6.0", diff --git a/yarn.lock b/yarn.lock index 3888a2384e..926db0ca4b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2700,10 +2700,10 @@ dependencies: "@types/node" "*" -"@types/deep-freeze@0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@types/deep-freeze/-/deep-freeze-0.1.2.tgz#68e5379291910e82c2f0d1629732163c2aa662cc" - integrity sha512-M6x29Vk4681dght4IMnPIcF1SNmeEm0c4uatlTFhp+++H1oDK1THEIzuCC2WeCBVhX+gU0NndsseDS3zaCtlcQ== +"@types/deep-freeze@0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@types/deep-freeze/-/deep-freeze-0.1.5.tgz#ae94f37ca134b4e34facb55f52ed90921192f764" + integrity sha512-KZtR+jtmgkCpgE0f+We/QEI2Fi0towBV/tTkvHVhMzx+qhUVGXMx7pWvAtDp6vEWIjdKLTKpqbI/sORRCo8TKg== "@types/ejs@^3.1.2": version "3.1.5" From 1321b7b8a950340f1aa2edbd30d3229d784bf2d9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Oct 2024 13:59:10 +0000 Subject: [PATCH 0599/1286] Bump reflect-metadata from 0.1.14 to 0.2.2 Bumps [reflect-metadata](https://github.com/rbuckton/reflect-metadata) from 0.1.14 to 0.2.2. - [Release notes](https://github.com/rbuckton/reflect-metadata/releases) - [Changelog](https://github.com/rbuckton/reflect-metadata/blob/main/tsconfig-release.json) - [Commits](https://github.com/rbuckton/reflect-metadata/commits) --- updated-dependencies: - dependency-name: reflect-metadata dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package.json | 2 +- yarn.lock | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index ad82a8fcd0..1460ec17f3 100644 --- a/package.json +++ b/package.json @@ -130,7 +130,7 @@ "pem": "1.14.7", "prop-types": "^15.8.1", "react-copy-to-clipboard": "^5.1.0", - "reflect-metadata": "^0.1.13", + "reflect-metadata": "^0.2.2", "rxjs": "^7.8.0", "sanitize-html": "^2.12.1", "sortablejs": "1.15.0", diff --git a/yarn.lock b/yarn.lock index 3888a2384e..9a55237ed5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10057,12 +10057,7 @@ redux@^4.0.0, redux@^4.0.4, redux@^4.0.5: dependencies: "@babel/runtime" "^7.9.2" -reflect-metadata@^0.1.13: - version "0.1.14" - resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.14.tgz#24cf721fe60677146bb77eeb0e1f9dece3d65859" - integrity sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A== - -reflect-metadata@^0.2.0: +reflect-metadata@^0.2.0, reflect-metadata@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.2.2.tgz#400c845b6cba87a21f2c65c4aeb158f4fa4d9c5b" integrity sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q== From 2044f7b2d547079f837a975243470d9e04ee9e1d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:03:00 +0000 Subject: [PATCH 0600/1286] Bump axe-core from 4.9.1 to 4.10.0 Bumps [axe-core](https://github.com/dequelabs/axe-core) from 4.9.1 to 4.10.0. - [Release notes](https://github.com/dequelabs/axe-core/releases) - [Changelog](https://github.com/dequelabs/axe-core/blob/develop/CHANGELOG.md) - [Commits](https://github.com/dequelabs/axe-core/compare/v4.9.1...v4.10.0) --- updated-dependencies: - dependency-name: axe-core dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1f806222aa..96f5301bcf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -110,7 +110,7 @@ "@typescript-eslint/parser": "^7.2.0", "@typescript-eslint/rule-tester": "^7.2.0", "@typescript-eslint/utils": "^7.2.0", - "axe-core": "^4.7.2", + "axe-core": "^4.10.0", "browser-sync": "^3.0.3", "compression-webpack-plugin": "^9.2.0", "copy-webpack-plugin": "^6.4.1", @@ -8206,9 +8206,9 @@ "dev": true }, "node_modules/axe-core": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.9.1.tgz", - "integrity": "sha512-QbUdXJVTpvUTHU7871ppZkdOLBeGUKBQWHkHrvN2V9IQWGMt61zf3B45BtzjxEJzYuj0JBjBZP/hmYS/R9pmAw==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.0.tgz", + "integrity": "sha512-Mr2ZakwQ7XUAjp7pAwQWRhhK8mQQ6JAaNWSjmjxil0R8BPioMtQsTLOolGYkji1rcL++3dCqZA3zWqpT+9Ew6g==", "dev": true, "engines": { "node": ">=4" diff --git a/package.json b/package.json index 59dce033db..1bd7cd2350 100644 --- a/package.json +++ b/package.json @@ -197,7 +197,7 @@ "@typescript-eslint/parser": "^7.2.0", "@typescript-eslint/rule-tester": "^7.2.0", "@typescript-eslint/utils": "^7.2.0", - "axe-core": "^4.7.2", + "axe-core": "^4.10.0", "browser-sync": "^3.0.3", "compression-webpack-plugin": "^9.2.0", "copy-webpack-plugin": "^6.4.1", From 68d27e59bbe4bce85b7bf7159596a2d6173ac7d7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:03:34 +0000 Subject: [PATCH 0601/1286] Bump eslint-plugin-import from 2.29.1 to 2.31.0 Bumps [eslint-plugin-import](https://github.com/import-js/eslint-plugin-import) from 2.29.1 to 2.31.0. - [Release notes](https://github.com/import-js/eslint-plugin-import/releases) - [Changelog](https://github.com/import-js/eslint-plugin-import/blob/main/CHANGELOG.md) - [Commits](https://github.com/import-js/eslint-plugin-import/compare/v2.29.1...v2.31.0) --- updated-dependencies: - dependency-name: eslint-plugin-import dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 46 +++++++++++++++++++++++++++------------------- package.json | 2 +- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1f806222aa..b8ae748b34 100644 --- a/package-lock.json +++ b/package-lock.json @@ -122,7 +122,7 @@ "eslint-plugin-deprecation": "^1.4.1", "eslint-plugin-dspace-angular-html": "file:./lint/dist/src/rules/html", "eslint-plugin-dspace-angular-ts": "file:./lint/dist/src/rules/ts", - "eslint-plugin-import": "^2.27.5", + "eslint-plugin-import": "^2.31.0", "eslint-plugin-import-newlines": "^1.3.1", "eslint-plugin-jsdoc": "^45.0.0", "eslint-plugin-jsonc": "^2.6.0", @@ -6256,6 +6256,12 @@ "win32" ] }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true + }, "node_modules/@schematics/angular": { "version": "17.3.8", "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-17.3.8.tgz", @@ -11448,9 +11454,9 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", - "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", "dev": true, "dependencies": { "debug": "^3.2.7" @@ -11619,34 +11625,36 @@ "link": true }, "node_modules/eslint-plugin-import": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", - "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", "dev": true, "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", "array.prototype.flat": "^1.3.2", "array.prototype.flatmap": "^1.3.2", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", + "eslint-module-utils": "^2.12.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.8", "tsconfig-paths": "^3.15.0" }, "engines": { "node": ">=4" }, "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, "node_modules/eslint-plugin-import-newlines": { @@ -13884,9 +13892,9 @@ } }, "node_modules/is-core-module": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", - "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", "dev": true, "dependencies": { "hasown": "^2.0.2" diff --git a/package.json b/package.json index 59dce033db..12ebf2524e 100644 --- a/package.json +++ b/package.json @@ -209,7 +209,7 @@ "eslint-plugin-deprecation": "^1.4.1", "eslint-plugin-dspace-angular-html": "file:./lint/dist/src/rules/html", "eslint-plugin-dspace-angular-ts": "file:./lint/dist/src/rules/ts", - "eslint-plugin-import": "^2.27.5", + "eslint-plugin-import": "^2.31.0", "eslint-plugin-import-newlines": "^1.3.1", "eslint-plugin-jsdoc": "^45.0.0", "eslint-plugin-jsonc": "^2.6.0", From 9033e020ee5b0c544279b91121a9932df5598bac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:04:47 +0000 Subject: [PATCH 0602/1286] Bump @typescript-eslint/eslint-plugin from 7.15.0 to 7.18.0 Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 7.15.0 to 7.18.0. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v7.18.0/packages/eslint-plugin) --- updated-dependencies: - dependency-name: "@typescript-eslint/eslint-plugin" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 125 ++++++++++++++++++++++++++++++++++++++++------ package.json | 2 +- 2 files changed, 112 insertions(+), 15 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1f806222aa..4d48d5fffa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -106,7 +106,7 @@ "@types/lodash": "^4.14.194", "@types/node": "^14.14.9", "@types/sanitize-html": "^2.9.0", - "@typescript-eslint/eslint-plugin": "^7.2.0", + "@typescript-eslint/eslint-plugin": "^7.18.0", "@typescript-eslint/parser": "^7.2.0", "@typescript-eslint/rule-tester": "^7.2.0", "@typescript-eslint/utils": "^7.2.0", @@ -6828,16 +6828,16 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.15.0.tgz", - "integrity": "sha512-uiNHpyjZtFrLwLDpHnzaDlP3Tt6sGMqTCiqmxaN4n4RP0EfYZDODJyddiFDF44Hjwxr5xAcaYxVKm9QKQFJFLA==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", + "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.15.0", - "@typescript-eslint/type-utils": "7.15.0", - "@typescript-eslint/utils": "7.15.0", - "@typescript-eslint/visitor-keys": "7.15.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/type-utils": "7.18.0", + "@typescript-eslint/utils": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -6860,14 +6860,31 @@ } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.15.0.tgz", - "integrity": "sha512-SkgriaeV6PDvpA6253PDVep0qCqgbO1IOBiycjnXsszNTVQe5flN5wR5jiczoEoDEnAqYFSFFc9al9BSGVltkg==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", + "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.15.0", - "@typescript-eslint/utils": "7.15.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", + "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/utils": "7.18.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -6887,6 +6904,86 @@ } } }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", + "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", + "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", + "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", + "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.18.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", diff --git a/package.json b/package.json index 59dce033db..75b62d3986 100644 --- a/package.json +++ b/package.json @@ -193,7 +193,7 @@ "@types/lodash": "^4.14.194", "@types/node": "^14.14.9", "@types/sanitize-html": "^2.9.0", - "@typescript-eslint/eslint-plugin": "^7.2.0", + "@typescript-eslint/eslint-plugin": "^7.18.0", "@typescript-eslint/parser": "^7.2.0", "@typescript-eslint/rule-tester": "^7.2.0", "@typescript-eslint/utils": "^7.2.0", From 4bb1baf638816cbb41460c334ba45ff8f5319ba4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:05:24 +0000 Subject: [PATCH 0603/1286] Bump ng-mocks from 14.13.0 to 14.13.1 Bumps [ng-mocks](https://github.com/help-me-mom/ng-mocks) from 14.13.0 to 14.13.1. - [Release notes](https://github.com/help-me-mom/ng-mocks/releases) - [Changelog](https://github.com/help-me-mom/ng-mocks/blob/master/CHANGELOG.md) - [Commits](https://github.com/help-me-mom/ng-mocks/compare/v14.13.0...v14.13.1) --- updated-dependencies: - dependency-name: ng-mocks dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1f806222aa..60ffa84a93 100644 --- a/package-lock.json +++ b/package-lock.json @@ -66,7 +66,7 @@ "mirador-dl-plugin": "^0.13.0", "mirador-share-plugin": "^0.11.0", "morgan": "^1.10.0", - "ng-mocks": "^14.10.0", + "ng-mocks": "^14.13.1", "ng2-file-upload": "5.0.0", "ng2-nouislider": "^2.0.0", "ngx-infinite-scroll": "^16.0.0", @@ -16717,9 +16717,9 @@ "dev": true }, "node_modules/ng-mocks": { - "version": "14.13.0", - "resolved": "https://registry.npmjs.org/ng-mocks/-/ng-mocks-14.13.0.tgz", - "integrity": "sha512-cQ6nUj/P+v7X52gYU6bAj/03iDKl2pzbPy2V0tx/d5lxME063Vxc190p6UPlJkbRIxcB+OqSALPgQvy83efzjw==", + "version": "14.13.1", + "resolved": "https://registry.npmjs.org/ng-mocks/-/ng-mocks-14.13.1.tgz", + "integrity": "sha512-eyfnjXeC108SqVD09i/cBwCpKkK0JjBoAg8jp7oQS2HS081K3WJTttFpgLGeLDYKmZsZ6nYpI+HHNQ3OksaJ7A==", "funding": { "url": "https://github.com/sponsors/help-me-mom" }, diff --git a/package.json b/package.json index 59dce033db..6c55eafd00 100644 --- a/package.json +++ b/package.json @@ -153,7 +153,7 @@ "mirador-dl-plugin": "^0.13.0", "mirador-share-plugin": "^0.11.0", "morgan": "^1.10.0", - "ng-mocks": "^14.10.0", + "ng-mocks": "^14.13.1", "ng2-file-upload": "5.0.0", "ng2-nouislider": "^2.0.0", "ngx-infinite-scroll": "^16.0.0", From 3ad1f6e69c2e06c1180a887a2f1079c5bca8e7f1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:05:44 +0000 Subject: [PATCH 0604/1286] Bump reflect-metadata from 0.1.14 to 0.2.2 Bumps [reflect-metadata](https://github.com/rbuckton/reflect-metadata) from 0.1.14 to 0.2.2. - [Release notes](https://github.com/rbuckton/reflect-metadata/releases) - [Changelog](https://github.com/rbuckton/reflect-metadata/blob/main/tsconfig-release.json) - [Commits](https://github.com/rbuckton/reflect-metadata/commits) --- updated-dependencies: - dependency-name: reflect-metadata dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 13 ++++--------- package.json | 2 +- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1f806222aa..a4878ed18f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -74,7 +74,7 @@ "ngx-ui-switch": "^14.1.0", "nouislider": "^15.7.1", "pem": "1.14.7", - "reflect-metadata": "^0.1.13", + "reflect-metadata": "^0.2.2", "rxjs": "^7.8.0", "sanitize-html": "^2.12.1", "sortablejs": "1.15.0", @@ -1595,11 +1595,6 @@ "semver": "bin/semver.js" } }, - "node_modules/@angular/compiler-cli/node_modules/reflect-metadata": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", - "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==" - }, "node_modules/@angular/core": { "version": "17.3.11", "resolved": "https://registry.npmjs.org/@angular/core/-/core-17.3.11.tgz", @@ -20047,9 +20042,9 @@ } }, "node_modules/reflect-metadata": { - "version": "0.1.14", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.14.tgz", - "integrity": "sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==" + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==" }, "node_modules/regenerate": { "version": "1.4.2", diff --git a/package.json b/package.json index 59dce033db..b2fbccc4a4 100644 --- a/package.json +++ b/package.json @@ -161,7 +161,7 @@ "ngx-ui-switch": "^14.1.0", "nouislider": "^15.7.1", "pem": "1.14.7", - "reflect-metadata": "^0.1.13", + "reflect-metadata": "^0.2.2", "rxjs": "^7.8.0", "sanitize-html": "^2.12.1", "sortablejs": "1.15.0", From 9a2b794c8e0005aab7fddf44ee2a7f8d2d45f765 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 15 Oct 2024 16:41:11 -0500 Subject: [PATCH 0605/1286] Update all @typescript-eslint dependencies to 7.18.0 --- package-lock.json | 173 ++++++++++------------------------------------ package.json | 6 +- 2 files changed, 41 insertions(+), 138 deletions(-) diff --git a/package-lock.json b/package-lock.json index 237f8b010f..f464086afe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -107,9 +107,9 @@ "@types/node": "^14.14.9", "@types/sanitize-html": "^2.9.0", "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.2.0", - "@typescript-eslint/rule-tester": "^7.2.0", - "@typescript-eslint/utils": "^7.2.0", + "@typescript-eslint/parser": "^7.18.0", + "@typescript-eslint/rule-tester": "^7.18.0", + "@typescript-eslint/utils": "^7.18.0", "axe-core": "^4.10.0", "browser-sync": "^3.0.3", "compression-webpack-plugin": "^9.2.0", @@ -6860,23 +6860,6 @@ } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", - "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { "version": "7.18.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", @@ -6904,86 +6887,6 @@ } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", - "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", - "dev": true, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", - "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", - "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", - "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.18.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", @@ -7135,15 +7038,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.15.0.tgz", - "integrity": "sha512-k9fYuQNnypLFcqORNClRykkGOMOj+pV6V91R4GO/l1FDGwpqmSwoOQrOHo3cGaH63e+D3ZiCAOsuS/D2c99j/A==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", + "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.15.0", - "@typescript-eslint/types": "7.15.0", - "@typescript-eslint/typescript-estree": "7.15.0", - "@typescript-eslint/visitor-keys": "7.15.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", "debug": "^4.3.4" }, "engines": { @@ -7163,13 +7066,13 @@ } }, "node_modules/@typescript-eslint/rule-tester": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/rule-tester/-/rule-tester-7.15.0.tgz", - "integrity": "sha512-QyBNG3gTpUJKb+Kx0hMbfZk9K7a3VnWEcWygZyKbw6ihTt/pf7c7AaR7JNbdnrFYc0q3JOgCXdKq8JM4RsAeaA==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/rule-tester/-/rule-tester-7.18.0.tgz", + "integrity": "sha512-ClrFQlwen9pJcYPIBLuarzBpONQAwjmJ0+YUjAo1TGzoZFJPyUK/A7bb4Mps0u+SMJJnFXbfMN8I9feQDf0O5A==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.15.0", - "@typescript-eslint/utils": "7.15.0", + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/utils": "7.18.0", "ajv": "^6.12.6", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "4.6.2", @@ -7210,13 +7113,13 @@ "dev": true }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.15.0.tgz", - "integrity": "sha512-Q/1yrF/XbxOTvttNVPihxh1b9fxamjEoz2Os/Pe38OHwxC24CyCqXxGTOdpb4lt6HYtqw9HetA/Rf6gDGaMPlw==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", + "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.15.0", - "@typescript-eslint/visitor-keys": "7.15.0" + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -7369,9 +7272,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.15.0.tgz", - "integrity": "sha512-aV1+B1+ySXbQH0pLK0rx66I3IkiZNidYobyfn0WFsdGhSXw+P3YOqeTq5GED458SfB24tg+ux3S+9g118hjlTw==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", + "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -7382,13 +7285,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.15.0.tgz", - "integrity": "sha512-gjyB/rHAopL/XxfmYThQbXbzRMGhZzGw6KpcMbfe8Q3nNQKStpxnUKeXb0KiN/fFDR42Z43szs6rY7eHk0zdGQ==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", + "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.15.0", - "@typescript-eslint/visitor-keys": "7.15.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7410,15 +7313,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.15.0.tgz", - "integrity": "sha512-hfDMDqaqOqsUVGiEPSMLR/AjTSCsmJwjpKkYQRo1FNbmW4tBwBspYDwO9eh7sKSTwMQgBw9/T4DHudPaqshRWA==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", + "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.15.0", - "@typescript-eslint/types": "7.15.0", - "@typescript-eslint/typescript-estree": "7.15.0" + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -7432,12 +7335,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.15.0.tgz", - "integrity": "sha512-Hqgy/ETgpt2L5xueA/zHHIl4fJI2O4XUE9l4+OIfbJIRSnTJb/QscncdqqZzofQegIJugRIF57OJea1khw2SDw==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", + "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.15.0", + "@typescript-eslint/types": "7.18.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { diff --git a/package.json b/package.json index e0ed12a497..5ff97dec31 100644 --- a/package.json +++ b/package.json @@ -194,9 +194,9 @@ "@types/node": "^14.14.9", "@types/sanitize-html": "^2.9.0", "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.2.0", - "@typescript-eslint/rule-tester": "^7.2.0", - "@typescript-eslint/utils": "^7.2.0", + "@typescript-eslint/parser": "^7.18.0", + "@typescript-eslint/rule-tester": "^7.18.0", + "@typescript-eslint/utils": "^7.18.0", "axe-core": "^4.10.0", "browser-sync": "^3.0.3", "compression-webpack-plugin": "^9.2.0", From 77c245ae5366f1d2507c928d3da88b13c35e0a7c Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 15 Oct 2024 16:44:50 -0500 Subject: [PATCH 0606/1286] Ensure @typescript-eslint dependency updates are grouped by dependabot --- .github/dependabot.yml | 48 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index f9e32a0190..fc964ee3cf 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -45,6 +45,22 @@ updates: update-types: - "minor" - "patch" + # Group together all patch version updates for @typescript-eslint in a single PR + typescript-eslint: + applies-to: version-updates + patterns: + - "@typescript-eslint*" + update-types: + - "minor" + - "patch" + # Group together all security updates for @typescript-eslint. + typescript-eslint-security: + applies-to: security-updates + patterns: + - "@typescript-eslint*" + update-types: + - "minor" + - "patch" ignore: # Ignore all major version updates for all dependencies. We'll only automate minor/patch updates. - dependency-name: "*" @@ -93,6 +109,22 @@ updates: update-types: - "minor" - "patch" + # Group together all patch version updates for @typescript-eslint in a single PR + typescript-eslint: + applies-to: version-updates + patterns: + - "@typescript-eslint*" + update-types: + - "minor" + - "patch" + # Group together all security updates for @typescript-eslint. + typescript-eslint-security: + applies-to: security-updates + patterns: + - "@typescript-eslint*" + update-types: + - "minor" + - "patch" ignore: # Ignore all major version updates for all dependencies. We'll only automate minor/patch updates. - dependency-name: "*" @@ -141,6 +173,22 @@ updates: update-types: - "minor" - "patch" + # Group together all patch version updates for @typescript-eslint in a single PR + typescript-eslint: + applies-to: version-updates + patterns: + - "@typescript-eslint*" + update-types: + - "minor" + - "patch" + # Group together all security updates for @typescript-eslint. + typescript-eslint-security: + applies-to: security-updates + patterns: + - "@typescript-eslint*" + update-types: + - "minor" + - "patch" ignore: # Ignore all major version updates for all dependencies. We'll only automate minor/patch updates. - dependency-name: "*" From 63a5217f6b171014733522b30826836418ce8d39 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Oct 2024 22:31:55 +0000 Subject: [PATCH 0607/1286] Bump express-static-gzip from 2.1.7 to 2.1.8 Bumps [express-static-gzip](https://github.com/tkoenig89/express-static-gzip) from 2.1.7 to 2.1.8. - [Release notes](https://github.com/tkoenig89/express-static-gzip/releases) - [Commits](https://github.com/tkoenig89/express-static-gzip/compare/v2.1.7...v2.1.8) --- updated-dependencies: - dependency-name: express-static-gzip dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package-lock.json | 10 +++++----- package.json | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index f464086afe..2504202104 100644 --- a/package-lock.json +++ b/package-lock.json @@ -130,7 +130,7 @@ "eslint-plugin-rxjs": "^5.0.3", "eslint-plugin-simple-import-sort": "^10.0.0", "eslint-plugin-unused-imports": "^3.2.0", - "express-static-gzip": "^2.1.7", + "express-static-gzip": "^2.1.8", "jasmine": "^3.8.0", "jasmine-core": "^3.8.0", "jasmine-marbles": "0.9.2", @@ -12293,12 +12293,12 @@ "integrity": "sha512-MTjE2eIbHv5DyfuFz4zLYWxpqVhEhkTiwFGuB74Q9CSou2WHO52nlE5y3Zlg6SIsiYUIPj6ifFxnkPz6O3sIUg==" }, "node_modules/express-static-gzip": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/express-static-gzip/-/express-static-gzip-2.1.7.tgz", - "integrity": "sha512-QOCZUC+lhPPCjIJKpQGu1Oa61Axg9Mq09Qvit8Of7kzpMuwDeMSqjjQteQS3OVw/GkENBoSBheuQDWPlngImvw==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/express-static-gzip/-/express-static-gzip-2.1.8.tgz", + "integrity": "sha512-g8tiJuI9Y9Ffy59ehVXvqb0hhP83JwZiLxzanobPaMbkB5qBWA8nuVgd+rcd5qzH3GkgogTALlc0BaADYwnMbQ==", "dev": true, "dependencies": { - "serve-static": "^1.14.1" + "serve-static": "^1.16.2" } }, "node_modules/express/node_modules/cookie": { diff --git a/package.json b/package.json index 5ff97dec31..ee44c74372 100644 --- a/package.json +++ b/package.json @@ -217,7 +217,7 @@ "eslint-plugin-rxjs": "^5.0.3", "eslint-plugin-simple-import-sort": "^10.0.0", "eslint-plugin-unused-imports": "^3.2.0", - "express-static-gzip": "^2.1.7", + "express-static-gzip": "^2.1.8", "jasmine": "^3.8.0", "jasmine-core": "^3.8.0", "jasmine-marbles": "0.9.2", From 696ce32ab4f536233602caf23d4a71c8bd076b32 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Oct 2024 22:37:54 +0000 Subject: [PATCH 0608/1286] Bump the angular group with 21 updates Bumps the angular group with 21 updates: | Package | From | To | | --- | --- | --- | | [@angular/animations](https://github.com/angular/angular/tree/HEAD/packages/animations) | `17.3.11` | `17.3.12` | | [@angular/common](https://github.com/angular/angular/tree/HEAD/packages/common) | `17.3.11` | `17.3.12` | | [@angular/compiler](https://github.com/angular/angular/tree/HEAD/packages/compiler) | `17.3.11` | `17.3.12` | | [@angular/core](https://github.com/angular/angular/tree/HEAD/packages/core) | `17.3.11` | `17.3.12` | | [@angular/forms](https://github.com/angular/angular/tree/HEAD/packages/forms) | `17.3.11` | `17.3.12` | | [@angular/localize](https://github.com/angular/angular) | `17.3.11` | `17.3.12` | | [@angular/platform-browser](https://github.com/angular/angular/tree/HEAD/packages/platform-browser) | `17.3.11` | `17.3.12` | | [@angular/platform-browser-dynamic](https://github.com/angular/angular/tree/HEAD/packages/platform-browser-dynamic) | `17.3.11` | `17.3.12` | | [@angular/platform-server](https://github.com/angular/angular/tree/HEAD/packages/platform-server) | `17.3.11` | `17.3.12` | | [@angular/router](https://github.com/angular/angular/tree/HEAD/packages/router) | `17.3.11` | `17.3.12` | | [@angular/ssr](https://github.com/angular/angular-cli) | `17.3.8` | `17.3.10` | | [@angular-devkit/build-angular](https://github.com/angular/angular-cli) | `17.3.8` | `17.3.10` | | [@angular-eslint/builder](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/builder) | `17.2.1` | `17.5.3` | | [@angular-eslint/bundled-angular-compiler](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/bundled-angular-compiler) | `17.2.1` | `17.5.3` | | [@angular-eslint/eslint-plugin](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/eslint-plugin) | `17.2.1` | `17.5.3` | | [@angular-eslint/eslint-plugin-template](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/eslint-plugin-template) | `17.2.1` | `17.5.3` | | [@angular-eslint/schematics](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/schematics) | `17.2.1` | `17.5.3` | | [@angular-eslint/template-parser](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/template-parser) | `17.2.1` | `17.5.3` | | [@angular/cli](https://github.com/angular/angular-cli) | `17.3.8` | `17.3.10` | | [@angular/compiler-cli](https://github.com/angular/angular/tree/HEAD/packages/compiler-cli) | `17.3.11` | `17.3.12` | | [@angular/language-service](https://github.com/angular/angular/tree/HEAD/packages/language-service) | `17.3.11` | `17.3.12` | Updates `@angular/animations` from 17.3.11 to 17.3.12 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/17.3.12/packages/animations) Updates `@angular/common` from 17.3.11 to 17.3.12 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/17.3.12/packages/common) Updates `@angular/compiler` from 17.3.11 to 17.3.12 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/17.3.12/packages/compiler) Updates `@angular/core` from 17.3.11 to 17.3.12 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/17.3.12/packages/core) Updates `@angular/forms` from 17.3.11 to 17.3.12 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/17.3.12/packages/forms) Updates `@angular/localize` from 17.3.11 to 17.3.12 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/compare/17.3.11...17.3.12) Updates `@angular/platform-browser` from 17.3.11 to 17.3.12 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/17.3.12/packages/platform-browser) Updates `@angular/platform-browser-dynamic` from 17.3.11 to 17.3.12 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/17.3.12/packages/platform-browser-dynamic) Updates `@angular/platform-server` from 17.3.11 to 17.3.12 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/17.3.12/packages/platform-server) Updates `@angular/router` from 17.3.11 to 17.3.12 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/17.3.12/packages/router) Updates `@angular/ssr` from 17.3.8 to 17.3.10 - [Release notes](https://github.com/angular/angular-cli/releases) - [Changelog](https://github.com/angular/angular-cli/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular-cli/compare/17.3.8...17.3.10) Updates `@angular-devkit/build-angular` from 17.3.8 to 17.3.10 - [Release notes](https://github.com/angular/angular-cli/releases) - [Changelog](https://github.com/angular/angular-cli/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular-cli/compare/17.3.8...17.3.10) Updates `@angular-eslint/builder` from 17.2.1 to 17.5.3 - [Release notes](https://github.com/angular-eslint/angular-eslint/releases) - [Changelog](https://github.com/angular-eslint/angular-eslint/blob/main/packages/builder/CHANGELOG.md) - [Commits](https://github.com/angular-eslint/angular-eslint/commits/HEAD/packages/builder) Updates `@angular-eslint/bundled-angular-compiler` from 17.2.1 to 17.5.3 - [Release notes](https://github.com/angular-eslint/angular-eslint/releases) - [Changelog](https://github.com/angular-eslint/angular-eslint/blob/main/packages/bundled-angular-compiler/CHANGELOG.md) - [Commits](https://github.com/angular-eslint/angular-eslint/commits/HEAD/packages/bundled-angular-compiler) Updates `@angular-eslint/eslint-plugin` from 17.2.1 to 17.5.3 - [Release notes](https://github.com/angular-eslint/angular-eslint/releases) - [Changelog](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md) - [Commits](https://github.com/angular-eslint/angular-eslint/commits/HEAD/packages/eslint-plugin) Updates `@angular-eslint/eslint-plugin-template` from 17.2.1 to 17.5.3 - [Release notes](https://github.com/angular-eslint/angular-eslint/releases) - [Changelog](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/CHANGELOG.md) - [Commits](https://github.com/angular-eslint/angular-eslint/commits/HEAD/packages/eslint-plugin-template) Updates `@angular-eslint/schematics` from 17.2.1 to 17.5.3 - [Release notes](https://github.com/angular-eslint/angular-eslint/releases) - [Changelog](https://github.com/angular-eslint/angular-eslint/blob/main/packages/schematics/CHANGELOG.md) - [Commits](https://github.com/angular-eslint/angular-eslint/commits/HEAD/packages/schematics) Updates `@angular-eslint/template-parser` from 17.2.1 to 17.5.3 - [Release notes](https://github.com/angular-eslint/angular-eslint/releases) - [Changelog](https://github.com/angular-eslint/angular-eslint/blob/main/packages/template-parser/CHANGELOG.md) - [Commits](https://github.com/angular-eslint/angular-eslint/commits/HEAD/packages/template-parser) Updates `@angular/cli` from 17.3.8 to 17.3.10 - [Release notes](https://github.com/angular/angular-cli/releases) - [Changelog](https://github.com/angular/angular-cli/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular-cli/compare/17.3.8...17.3.10) Updates `@angular/compiler-cli` from 17.3.11 to 17.3.12 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/17.3.12/packages/compiler-cli) Updates `@angular/language-service` from 17.3.11 to 17.3.12 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/17.3.12/packages/language-service) --- updated-dependencies: - dependency-name: "@angular/animations" dependency-type: direct:production update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular/common" dependency-type: direct:production update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular/compiler" dependency-type: direct:production update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular/core" dependency-type: direct:production update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular/forms" dependency-type: direct:production update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular/localize" dependency-type: direct:production update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular/platform-browser" dependency-type: direct:production update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular/platform-browser-dynamic" dependency-type: direct:production update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular/platform-server" dependency-type: direct:production update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular/router" dependency-type: direct:production update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular/ssr" dependency-type: direct:production update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular-devkit/build-angular" dependency-type: direct:development update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular-eslint/builder" dependency-type: direct:development update-type: version-update:semver-minor dependency-group: angular - dependency-name: "@angular-eslint/bundled-angular-compiler" dependency-type: direct:development update-type: version-update:semver-minor dependency-group: angular - dependency-name: "@angular-eslint/eslint-plugin" dependency-type: direct:development update-type: version-update:semver-minor dependency-group: angular - dependency-name: "@angular-eslint/eslint-plugin-template" dependency-type: direct:development update-type: version-update:semver-minor dependency-group: angular - dependency-name: "@angular-eslint/schematics" dependency-type: direct:development update-type: version-update:semver-minor dependency-group: angular - dependency-name: "@angular-eslint/template-parser" dependency-type: direct:development update-type: version-update:semver-minor dependency-group: angular - dependency-name: "@angular/cli" dependency-type: direct:development update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular/compiler-cli" dependency-type: direct:development update-type: version-update:semver-patch dependency-group: angular - dependency-name: "@angular/language-service" dependency-type: direct:development update-type: version-update:semver-patch dependency-group: angular ... Signed-off-by: dependabot[bot] --- package-lock.json | 3582 +++++++++++++++------------------------------ package.json | 38 +- 2 files changed, 1228 insertions(+), 2392 deletions(-) diff --git a/package-lock.json b/package-lock.json index f464086afe..1d0f3ee08c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,18 +9,18 @@ "version": "9.0.0-next", "hasInstallScript": true, "dependencies": { - "@angular/animations": "^17.3.11", + "@angular/animations": "^17.3.12", "@angular/cdk": "^17.3.10", - "@angular/common": "^17.3.11", - "@angular/compiler": "^17.3.11", - "@angular/core": "^17.3.11", - "@angular/forms": "^17.3.11", - "@angular/localize": "^17.3.11", - "@angular/platform-browser": "^17.3.11", - "@angular/platform-browser-dynamic": "^17.3.11", - "@angular/platform-server": "^17.3.11", - "@angular/router": "^17.3.11", - "@angular/ssr": "^17.3.8", + "@angular/common": "^17.3.12", + "@angular/compiler": "^17.3.12", + "@angular/core": "^17.3.12", + "@angular/forms": "^17.3.12", + "@angular/localize": "^17.3.12", + "@angular/platform-browser": "^17.3.12", + "@angular/platform-browser-dynamic": "^17.3.12", + "@angular/platform-server": "^17.3.12", + "@angular/router": "^17.3.12", + "@angular/ssr": "^17.3.10", "@babel/runtime": "7.21.0", "@kolkov/ngx-gallery": "^2.0.1", "@ng-bootstrap/ng-bootstrap": "^11.0.0", @@ -85,15 +85,15 @@ "devDependencies": { "@angular-builders/custom-webpack": "~17.0.2", "@angular-devkit/build-angular": "^17.3.8", - "@angular-eslint/builder": "17.2.1", - "@angular-eslint/bundled-angular-compiler": "17.2.1", - "@angular-eslint/eslint-plugin": "17.2.1", - "@angular-eslint/eslint-plugin-template": "17.2.1", - "@angular-eslint/schematics": "17.2.1", - "@angular-eslint/template-parser": "17.2.1", - "@angular/cli": "^17.3.8", + "@angular-eslint/builder": "17.5.3", + "@angular-eslint/bundled-angular-compiler": "17.5.3", + "@angular-eslint/eslint-plugin": "17.5.3", + "@angular-eslint/eslint-plugin-template": "17.5.3", + "@angular-eslint/schematics": "17.5.3", + "@angular-eslint/template-parser": "17.5.3", + "@angular/cli": "^17.3.10", "@angular/compiler-cli": "^17.3.11", - "@angular/language-service": "^17.3.11", + "@angular/language-service": "^17.3.12", "@cypress/schematic": "^1.5.0", "@fortawesome/fontawesome-free": "^6.4.0", "@ngrx/store-devtools": "^17.1.1", @@ -263,12 +263,12 @@ } }, "node_modules/@angular-devkit/architect": { - "version": "0.1703.8", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1703.8.tgz", - "integrity": "sha512-lKxwG4/QABXZvJpqeSIn/kAwnY6MM9HdHZUV+o5o3UiTi+vO8rZApG4CCaITH3Bxebm7Nam7Xbk8RuukC5rq6g==", + "version": "0.1703.10", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1703.10.tgz", + "integrity": "sha512-wmjx5GspSPprdUGryK5+9vNawbEO7p8h9dxgX3uoeFwPAECcHC+/KK3qPhX2NiGcM6MDsyt25SrbSktJp6PRsA==", "dev": true, "dependencies": { - "@angular-devkit/core": "17.3.8", + "@angular-devkit/core": "17.3.10", "rxjs": "7.8.1" }, "engines": { @@ -278,15 +278,15 @@ } }, "node_modules/@angular-devkit/build-angular": { - "version": "17.3.8", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-17.3.8.tgz", - "integrity": "sha512-ixsdXggWaFRP7Jvxd0AMukImnePuGflT9Yy7NJ9/y0cL/k//S/3RnkQv5i411KzN+7D4RIbNkRGGTYeqH24zlg==", + "version": "17.3.10", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-17.3.10.tgz", + "integrity": "sha512-syz7xgzmp8/0tPJWwQIKZt7KNJfp9U7hkqNacXz4XTYz6YM0oyBXlqk2claSxywWBEkc0eJVSMD9e2ArusZBuA==", "dev": true, "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1703.8", - "@angular-devkit/build-webpack": "0.1703.8", - "@angular-devkit/core": "17.3.8", + "@angular-devkit/architect": "0.1703.10", + "@angular-devkit/build-webpack": "0.1703.10", + "@angular-devkit/core": "17.3.10", "@babel/core": "7.24.0", "@babel/generator": "7.23.6", "@babel/helper-annotate-as-pure": "7.22.5", @@ -297,7 +297,7 @@ "@babel/preset-env": "7.24.0", "@babel/runtime": "7.24.0", "@discoveryjs/json-ext": "0.5.7", - "@ngtools/webpack": "17.3.8", + "@ngtools/webpack": "17.3.10", "@vitejs/plugin-basic-ssl": "1.1.0", "ansi-colors": "4.1.3", "autoprefixer": "10.4.18", @@ -339,9 +339,9 @@ "tree-kill": "1.2.2", "tslib": "2.6.2", "undici": "6.11.1", - "vite": "5.1.7", + "vite": "5.1.8", "watchpack": "2.4.0", - "webpack": "5.90.3", + "webpack": "5.94.0", "webpack-dev-middleware": "6.1.2", "webpack-dev-server": "4.15.1", "webpack-merge": "5.10.0", @@ -418,10 +418,378 @@ "node": ">=6.9.0" } }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/aix-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", + "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/android-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", + "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/android-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", + "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/android-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", + "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/darwin-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", + "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/darwin-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", + "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", + "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/freebsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", + "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", + "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", + "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", + "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-loong64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", + "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-mips64el": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", + "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", + "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-riscv64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", + "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-s390x": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", + "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", + "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/netbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", + "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/openbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", + "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/sunos-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", + "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/win32-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", + "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/win32-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", + "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/win32-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", + "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@angular-devkit/build-angular/node_modules/@ngtools/webpack": { - "version": "17.3.8", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-17.3.8.tgz", - "integrity": "sha512-CjSVVa/9fzMpEDQP01SC4colKCbZwj7vUq0H2bivp8jVsmd21x9Fu0gDBH0Y9NdfAIm4eGZvmiZKMII3vIOaYQ==", + "version": "17.3.10", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-17.3.10.tgz", + "integrity": "sha512-yPKmdbTJzxROAl2NS8P8eHB2mU0BqV2I0ZiKmX6oTetY2Ea4i2WzlTK39pPpG7atmdF2NPWYLXdJWAup+JxSyw==", "dev": true, "engines": { "node": "^18.13.0 || >=20.9.0", @@ -434,31 +802,27 @@ "webpack": "^5.54.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/@angular-devkit/build-angular/node_modules/@types/node": { + "version": "22.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", + "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", "dev": true, - "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "undici-types": "~6.19.2" } }, - "node_modules/@angular-devkit/build-angular/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "node_modules/@angular-devkit/build-angular/node_modules/@vitejs/plugin-basic-ssl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-1.1.0.tgz", + "integrity": "sha512-wO4Dk/rm8u7RNhOf95ZzcEmC9rYOncYgvq4z3duaJrCgjN8BxAnDVyndanfcJZ0O6XZzHz6Q0hTimxTg8Y9g/A==", "dev": true, - "license": "MIT", + "engines": { + "node": ">=14.6.0" + }, "peerDependencies": { - "ajv": "^6.9.1" + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0" } }, "node_modules/@angular-devkit/build-angular/node_modules/connect-history-api-fallback": { @@ -520,30 +884,6 @@ } } }, - "node_modules/@angular-devkit/build-angular/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, "node_modules/@angular-devkit/build-angular/node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -600,9 +940,9 @@ } }, "node_modules/@angular-devkit/build-angular/node_modules/immutable": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.6.tgz", - "integrity": "sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz", + "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==", "dev": true }, "node_modules/@angular-devkit/build-angular/node_modules/ipaddr.js": { @@ -614,20 +954,6 @@ "node": ">= 10" } }, - "node_modules/@angular-devkit/build-angular/node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@angular-devkit/build-angular/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, "node_modules/@angular-devkit/build-angular/node_modules/postcss": { "version": "8.4.35", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", @@ -762,54 +1088,99 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@angular-devkit/build-angular/node_modules/webpack": { - "version": "5.90.3", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.3.tgz", - "integrity": "sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA==", + "node_modules/@angular-devkit/build-angular/node_modules/vite": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.8.tgz", + "integrity": "sha512-mB8ToUuSmzODSpENgvpFk2fTiU/YQ1tmcVJJ4WZbq4fPdGJkFNVcmVL5k7iDug6xzWjjuGDKAuSievIsD6H7Xw==", "dev": true, - "license": "MIT", "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.5", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.21.10", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.15.0", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" + "esbuild": "^0.19.3", + "postcss": "^8.4.35", + "rollup": "^4.2.0" }, "bin": { - "webpack": "bin/webpack.js" + "vite": "bin/vite.js" }, "engines": { - "node": ">=10.13.0" + "node": "^18.0.0 || >=20.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" }, "peerDependenciesMeta": { - "webpack-cli": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { "optional": true } } }, + "node_modules/@angular-devkit/build-angular/node_modules/vite/node_modules/esbuild": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", + "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.19.12", + "@esbuild/android-arm": "0.19.12", + "@esbuild/android-arm64": "0.19.12", + "@esbuild/android-x64": "0.19.12", + "@esbuild/darwin-arm64": "0.19.12", + "@esbuild/darwin-x64": "0.19.12", + "@esbuild/freebsd-arm64": "0.19.12", + "@esbuild/freebsd-x64": "0.19.12", + "@esbuild/linux-arm": "0.19.12", + "@esbuild/linux-arm64": "0.19.12", + "@esbuild/linux-ia32": "0.19.12", + "@esbuild/linux-loong64": "0.19.12", + "@esbuild/linux-mips64el": "0.19.12", + "@esbuild/linux-ppc64": "0.19.12", + "@esbuild/linux-riscv64": "0.19.12", + "@esbuild/linux-s390x": "0.19.12", + "@esbuild/linux-x64": "0.19.12", + "@esbuild/netbsd-x64": "0.19.12", + "@esbuild/openbsd-x64": "0.19.12", + "@esbuild/sunos-x64": "0.19.12", + "@esbuild/win32-arm64": "0.19.12", + "@esbuild/win32-ia32": "0.19.12", + "@esbuild/win32-x64": "0.19.12" + } + }, "node_modules/@angular-devkit/build-angular/node_modules/webpack-dev-server": { "version": "4.15.1", "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", @@ -892,42 +1263,13 @@ "webpack": "^4.0.0 || ^5.0.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/webpack/node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/@angular-devkit/build-webpack": { - "version": "0.1703.8", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1703.8.tgz", - "integrity": "sha512-9u6fl8VVOxcLOEMzrUeaybSvi9hSLSRucHnybneYrabsgreDo32tuy/4G8p6YAHQjpWEj9jvF9Um13ertdni5Q==", + "version": "0.1703.10", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1703.10.tgz", + "integrity": "sha512-m6dDgzKLW+c3z9/TUxYmbJEtEhrdYNQ4ogdtAgEYA/FRrKueDU0WztLNr+dVbvwNP99Skovtr8sAQfN6twproQ==", "dev": true, "dependencies": { - "@angular-devkit/architect": "0.1703.8", + "@angular-devkit/architect": "0.1703.10", "rxjs": "7.8.1" }, "engines": { @@ -941,9 +1283,9 @@ } }, "node_modules/@angular-devkit/core": { - "version": "17.3.8", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-17.3.8.tgz", - "integrity": "sha512-Q8q0voCGudbdCgJ7lXdnyaxKHbNQBARH68zPQV72WT8NWy+Gw/tys870i6L58NWbBaCJEUcIj/kb6KoakSRu+Q==", + "version": "17.3.10", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-17.3.10.tgz", + "integrity": "sha512-czdl54yxU5DOAGy/uUPNjJruoBDTgwi/V+eOgLNybYhgrc+TsY0f7uJ11yEk/pz5sCov7xIiS7RdRv96waS7vg==", "dev": true, "dependencies": { "ajv": "8.12.0", @@ -968,12 +1310,12 @@ } }, "node_modules/@angular-devkit/schematics": { - "version": "17.3.8", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-17.3.8.tgz", - "integrity": "sha512-QRVEYpIfgkprNHc916JlPuNbLzOgrm9DZalHasnLUz4P6g7pR21olb8YCyM2OTJjombNhya9ZpckcADU5Qyvlg==", + "version": "17.3.10", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-17.3.10.tgz", + "integrity": "sha512-FHcNa1ktYRd0SKExCsNJpR75RffsyuPIV8kvBXzXnLHmXMqvl25G2te3yYJ9yYqy9OLy/58HZznZTxWRyUdHOg==", "dev": true, "dependencies": { - "@angular-devkit/core": "17.3.8", + "@angular-devkit/core": "17.3.10", "jsonc-parser": "3.2.1", "magic-string": "0.30.8", "ora": "5.4.1", @@ -986,33 +1328,30 @@ } }, "node_modules/@angular-eslint/builder": { - "version": "17.2.1", - "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-17.2.1.tgz", - "integrity": "sha512-O30eaR0wCPiP+zKWvXj2JM8hVq30Wok2rp7zJMFm3PurjF9nWIIyexXkE5fa538DYZYxu8N3gQRqhpv5jvTXCg==", + "version": "17.5.3", + "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-17.5.3.tgz", + "integrity": "sha512-DoPCwt8qp5oMkfxY8V3wygf6/E7zzgXkPCwTRhIelklfpB3nYwLnbRSD8G5hueAU4eyASKiIuhR79E996AuUSw==", "dev": true, - "dependencies": { - "@nx/devkit": "17.2.8", - "nx": "17.2.8" - }, "peerDependencies": { "eslint": "^7.20.0 || ^8.0.0", "typescript": "*" } }, "node_modules/@angular-eslint/bundled-angular-compiler": { - "version": "17.2.1", - "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-17.2.1.tgz", - "integrity": "sha512-puC0itsZv2QlrDOCcWtq1KZH+DvfrpV+mV78HHhi6+h25R5iIhr8ARKcl3EQxFjvrFq34jhG8pSupxKvFbHVfA==", + "version": "17.5.3", + "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-17.5.3.tgz", + "integrity": "sha512-x9jZ6mME9wxumErPGonWERXX/9TJ7mzEkQhOKt3BxBFm0sy9XQqLMAenp1PBSg3RF3rH7EEVdB2+jb75RtHp0g==", "dev": true }, "node_modules/@angular-eslint/eslint-plugin": { - "version": "17.2.1", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-17.2.1.tgz", - "integrity": "sha512-9yA81BHpsaCUKRBtHGN3ieAy8HpIoffzPQMu34lYqZFT4yGHGhYmhQjNSQGBRbV2LD9dVv2U35rMHNmUcozXpw==", + "version": "17.5.3", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-17.5.3.tgz", + "integrity": "sha512-2gMRZ+SkiygrPDtCJwMfjmwIFOcvxxC4NRX/MqRo6udsa0gtqPrc8acRbwrmAXlullmhzmaeUfkHpGDSzW8pFw==", "dev": true, "dependencies": { - "@angular-eslint/utils": "17.2.1", - "@typescript-eslint/utils": "6.19.0" + "@angular-eslint/bundled-angular-compiler": "17.5.3", + "@angular-eslint/utils": "17.5.3", + "@typescript-eslint/utils": "7.11.0" }, "peerDependencies": { "eslint": "^7.20.0 || ^8.0.0", @@ -1020,15 +1359,15 @@ } }, "node_modules/@angular-eslint/eslint-plugin-template": { - "version": "17.2.1", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-17.2.1.tgz", - "integrity": "sha512-hl1hcHtcm90wyVL1OQGTz16oA0KHon+FFb3Qg0fLXObaXxA495Ecefd9ub5Xxg4JEOPRDi29bF1Y3YKpwflgeg==", + "version": "17.5.3", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-17.5.3.tgz", + "integrity": "sha512-RkRFagxqBPV2xdNyeQQROUm6I1Izto1Z3Wy73lCk2zq1RhVgbznniH/epmOIE8PMkHmMKmZ765FV++J/90p4Ig==", "dev": true, "dependencies": { - "@angular-eslint/bundled-angular-compiler": "17.2.1", - "@angular-eslint/utils": "17.2.1", - "@typescript-eslint/type-utils": "6.19.0", - "@typescript-eslint/utils": "6.19.0", + "@angular-eslint/bundled-angular-compiler": "17.5.3", + "@angular-eslint/utils": "17.5.3", + "@typescript-eslint/type-utils": "7.11.0", + "@typescript-eslint/utils": "7.11.0", "aria-query": "5.3.0", "axobject-query": "4.0.0" }, @@ -1037,17 +1376,31 @@ "typescript": "*" } }, - "node_modules/@angular-eslint/eslint-plugin-template/node_modules/@typescript-eslint/scope-manager": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.0.tgz", - "integrity": "sha512-dO1XMhV2ehBI6QN8Ufi7I10wmUovmLU0Oru3n5LVlM2JuzB4M+dVphCPLkVpKvGij2j/pHBWuJ9piuXx+BhzxQ==", + "node_modules/@angular-eslint/eslint-plugin-template/node_modules/@angular-eslint/utils": { + "version": "17.5.3", + "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-17.5.3.tgz", + "integrity": "sha512-0nNm1FUOLhVHrdK2PP5dZCYYVmTIkEJ4CmlwpuC4JtCLbD5XAHQpY/ZW5Ff5n1b7KfJt1Zy//jlhkkIaw3LaBQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.0", - "@typescript-eslint/visitor-keys": "6.19.0" + "@angular-eslint/bundled-angular-compiler": "17.5.3", + "@typescript-eslint/utils": "7.11.0" + }, + "peerDependencies": { + "eslint": "^7.20.0 || ^8.0.0", + "typescript": "*" + } + }, + "node_modules/@angular-eslint/eslint-plugin-template/node_modules/@typescript-eslint/scope-manager": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.11.0.tgz", + "integrity": "sha512-27tGdVEiutD4POirLZX4YzT180vevUURJl4wJGmm6TrQoiYwuxTIY98PBp6L2oN+JQxzE0URvYlzJaBHIekXAw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.11.0", + "@typescript-eslint/visitor-keys": "7.11.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -1055,12 +1408,12 @@ } }, "node_modules/@angular-eslint/eslint-plugin-template/node_modules/@typescript-eslint/types": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.0.tgz", - "integrity": "sha512-lFviGV/vYhOy3m8BJ/nAKoAyNhInTdXpftonhWle66XHAtT1ouBlkjL496b5H5hb8dWXHwtypTqgtb/DEa+j5A==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.11.0.tgz", + "integrity": "sha512-MPEsDRZTyCiXkD4vd3zywDCifi7tatc4K37KqTprCvaXptP7Xlpdw0NR2hRJTetG5TxbWDB79Ys4kLmHliEo/w==", "dev": true, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -1068,22 +1421,22 @@ } }, "node_modules/@angular-eslint/eslint-plugin-template/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.0.tgz", - "integrity": "sha512-o/zefXIbbLBZ8YJ51NlkSAt2BamrK6XOmuxSR3hynMIzzyMY33KuJ9vuMdFSXW+H0tVvdF9qBPTHA91HDb4BIQ==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.11.0.tgz", + "integrity": "sha512-cxkhZ2C/iyi3/6U9EPc5y+a6csqHItndvN/CzbNXTNrsC3/ASoYQZEt9uMaEp+xFNjasqQyszp5TumAVKKvJeQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.0", - "@typescript-eslint/visitor-keys": "6.19.0", + "@typescript-eslint/types": "7.11.0", + "@typescript-eslint/visitor-keys": "7.11.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -1096,73 +1449,69 @@ } }, "node_modules/@angular-eslint/eslint-plugin-template/node_modules/@typescript-eslint/utils": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.0.tgz", - "integrity": "sha512-QR41YXySiuN++/dC9UArYOg4X86OAYP83OWTewpVx5ct1IZhjjgTLocj7QNxGhWoTqknsgpl7L+hGygCO+sdYw==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.11.0.tgz", + "integrity": "sha512-xlAWwPleNRHwF37AhrZurOxA1wyXowW4PqVXZVUNCLjB48CqdPJoJWkrpH2nij9Q3Lb7rtWindtoXwxjxlKKCA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.19.0", - "@typescript-eslint/types": "6.19.0", - "@typescript-eslint/typescript-estree": "6.19.0", - "semver": "^7.5.4" + "@typescript-eslint/scope-manager": "7.11.0", + "@typescript-eslint/types": "7.11.0", + "@typescript-eslint/typescript-estree": "7.11.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" } }, "node_modules/@angular-eslint/eslint-plugin-template/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.0.tgz", - "integrity": "sha512-hZaUCORLgubBvtGpp1JEFEazcuEdfxta9j4iUwdSAr7mEsYYAp3EAUyCZk3VEEqGj6W+AV4uWyrDGtrlawAsgQ==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.11.0.tgz", + "integrity": "sha512-7syYk4MzjxTEk0g/w3iqtgxnFQspDJfn6QKD36xMuuhTzjcxY7F8EmBLnALjVyaOF1/bVocu3bS/2/F7rXrveQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.0", - "eslint-visitor-keys": "^3.4.1" + "@typescript-eslint/types": "7.11.0", + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@angular-eslint/eslint-plugin-template/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "node_modules/@angular-eslint/eslint-plugin/node_modules/@angular-eslint/utils": { + "version": "17.5.3", + "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-17.5.3.tgz", + "integrity": "sha512-0nNm1FUOLhVHrdK2PP5dZCYYVmTIkEJ4CmlwpuC4JtCLbD5XAHQpY/ZW5Ff5n1b7KfJt1Zy//jlhkkIaw3LaBQ==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "@angular-eslint/bundled-angular-compiler": "17.5.3", + "@typescript-eslint/utils": "7.11.0" }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "peerDependencies": { + "eslint": "^7.20.0 || ^8.0.0", + "typescript": "*" } }, "node_modules/@angular-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.0.tgz", - "integrity": "sha512-dO1XMhV2ehBI6QN8Ufi7I10wmUovmLU0Oru3n5LVlM2JuzB4M+dVphCPLkVpKvGij2j/pHBWuJ9piuXx+BhzxQ==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.11.0.tgz", + "integrity": "sha512-27tGdVEiutD4POirLZX4YzT180vevUURJl4wJGmm6TrQoiYwuxTIY98PBp6L2oN+JQxzE0URvYlzJaBHIekXAw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.0", - "@typescript-eslint/visitor-keys": "6.19.0" + "@typescript-eslint/types": "7.11.0", + "@typescript-eslint/visitor-keys": "7.11.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -1170,12 +1519,12 @@ } }, "node_modules/@angular-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.0.tgz", - "integrity": "sha512-lFviGV/vYhOy3m8BJ/nAKoAyNhInTdXpftonhWle66XHAtT1ouBlkjL496b5H5hb8dWXHwtypTqgtb/DEa+j5A==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.11.0.tgz", + "integrity": "sha512-MPEsDRZTyCiXkD4vd3zywDCifi7tatc4K37KqTprCvaXptP7Xlpdw0NR2hRJTetG5TxbWDB79Ys4kLmHliEo/w==", "dev": true, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -1183,22 +1532,22 @@ } }, "node_modules/@angular-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.0.tgz", - "integrity": "sha512-o/zefXIbbLBZ8YJ51NlkSAt2BamrK6XOmuxSR3hynMIzzyMY33KuJ9vuMdFSXW+H0tVvdF9qBPTHA91HDb4BIQ==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.11.0.tgz", + "integrity": "sha512-cxkhZ2C/iyi3/6U9EPc5y+a6csqHItndvN/CzbNXTNrsC3/ASoYQZEt9uMaEp+xFNjasqQyszp5TumAVKKvJeQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.0", - "@typescript-eslint/visitor-keys": "6.19.0", + "@typescript-eslint/types": "7.11.0", + "@typescript-eslint/visitor-keys": "7.11.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -1211,87 +1560,67 @@ } }, "node_modules/@angular-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.0.tgz", - "integrity": "sha512-QR41YXySiuN++/dC9UArYOg4X86OAYP83OWTewpVx5ct1IZhjjgTLocj7QNxGhWoTqknsgpl7L+hGygCO+sdYw==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.11.0.tgz", + "integrity": "sha512-xlAWwPleNRHwF37AhrZurOxA1wyXowW4PqVXZVUNCLjB48CqdPJoJWkrpH2nij9Q3Lb7rtWindtoXwxjxlKKCA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.19.0", - "@typescript-eslint/types": "6.19.0", - "@typescript-eslint/typescript-estree": "6.19.0", - "semver": "^7.5.4" + "@typescript-eslint/scope-manager": "7.11.0", + "@typescript-eslint/types": "7.11.0", + "@typescript-eslint/typescript-estree": "7.11.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" } }, "node_modules/@angular-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.0.tgz", - "integrity": "sha512-hZaUCORLgubBvtGpp1JEFEazcuEdfxta9j4iUwdSAr7mEsYYAp3EAUyCZk3VEEqGj6W+AV4uWyrDGtrlawAsgQ==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.11.0.tgz", + "integrity": "sha512-7syYk4MzjxTEk0g/w3iqtgxnFQspDJfn6QKD36xMuuhTzjcxY7F8EmBLnALjVyaOF1/bVocu3bS/2/F7rXrveQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.0", - "eslint-visitor-keys": "^3.4.1" + "@typescript-eslint/types": "7.11.0", + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@angular-eslint/eslint-plugin/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@angular-eslint/schematics": { - "version": "17.2.1", - "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-17.2.1.tgz", - "integrity": "sha512-7ldtIePI4ZTp/TBpeOZkzfv30HSAn//4TgtFuqvojudI8n8batV5FqQ0VNm1e0zitl75t8Zwtr0KYT4I6vh59g==", + "version": "17.5.3", + "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-17.5.3.tgz", + "integrity": "sha512-a0MlOjNLIM18l/66S+CzhANQR3QH3jDUa1MC50E4KBf1mwjQyfqd6RdfbOTMDjgFlPrfB+5JvoWOHHGj7FFM1A==", "dev": true, "dependencies": { - "@angular-eslint/eslint-plugin": "17.2.1", - "@angular-eslint/eslint-plugin-template": "17.2.1", - "@nx/devkit": "17.2.8", - "ignore": "5.3.0", - "nx": "17.2.8", + "@angular-eslint/eslint-plugin": "17.5.3", + "@angular-eslint/eslint-plugin-template": "17.5.3", + "ignore": "5.3.1", "strip-json-comments": "3.1.1", - "tmp": "0.2.1" + "tmp": "0.2.3" }, "peerDependencies": { "@angular/cli": ">= 17.0.0 < 18.0.0" } }, "node_modules/@angular-eslint/template-parser": { - "version": "17.2.1", - "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-17.2.1.tgz", - "integrity": "sha512-WPQYFvRju0tCDXQ/pwrzC911pE07JvpeDgcN2elhzV6lxDHJEZpA5O9pnW9qgNA6J6XM9Q7dBkJ22ztAzC4WFw==", + "version": "17.5.3", + "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-17.5.3.tgz", + "integrity": "sha512-NYybOsMkJUtFOW2JWALicipq0kK5+jGwA1MYyRoXjdbDlXltHUb9qkXj7p0fE6uRutBGXDl4288s8g/fZCnAIA==", "dev": true, "dependencies": { - "@angular-eslint/bundled-angular-compiler": "17.2.1", + "@angular-eslint/bundled-angular-compiler": "17.5.3", "eslint-scope": "^8.0.0" }, "peerDependencies": { @@ -1299,139 +1628,10 @@ "typescript": "*" } }, - "node_modules/@angular-eslint/utils": { - "version": "17.2.1", - "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-17.2.1.tgz", - "integrity": "sha512-qQYTBXy90dWM7fhhpa5i9lTtqqhJisvRa+naCrQx9kBgR458JScLdkVIdcZ9D/rPiDCmKiVUfgcDISnjUeqTqg==", - "dev": true, - "dependencies": { - "@angular-eslint/bundled-angular-compiler": "17.2.1", - "@typescript-eslint/utils": "6.19.0" - }, - "peerDependencies": { - "eslint": "^7.20.0 || ^8.0.0", - "typescript": "*" - } - }, - "node_modules/@angular-eslint/utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.0.tgz", - "integrity": "sha512-dO1XMhV2ehBI6QN8Ufi7I10wmUovmLU0Oru3n5LVlM2JuzB4M+dVphCPLkVpKvGij2j/pHBWuJ9piuXx+BhzxQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.19.0", - "@typescript-eslint/visitor-keys": "6.19.0" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@angular-eslint/utils/node_modules/@typescript-eslint/types": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.0.tgz", - "integrity": "sha512-lFviGV/vYhOy3m8BJ/nAKoAyNhInTdXpftonhWle66XHAtT1ouBlkjL496b5H5hb8dWXHwtypTqgtb/DEa+j5A==", - "dev": true, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@angular-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.0.tgz", - "integrity": "sha512-o/zefXIbbLBZ8YJ51NlkSAt2BamrK6XOmuxSR3hynMIzzyMY33KuJ9vuMdFSXW+H0tVvdF9qBPTHA91HDb4BIQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.19.0", - "@typescript-eslint/visitor-keys": "6.19.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@angular-eslint/utils/node_modules/@typescript-eslint/utils": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.0.tgz", - "integrity": "sha512-QR41YXySiuN++/dC9UArYOg4X86OAYP83OWTewpVx5ct1IZhjjgTLocj7QNxGhWoTqknsgpl7L+hGygCO+sdYw==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.19.0", - "@typescript-eslint/types": "6.19.0", - "@typescript-eslint/typescript-estree": "6.19.0", - "semver": "^7.5.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - } - }, - "node_modules/@angular-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.0.tgz", - "integrity": "sha512-hZaUCORLgubBvtGpp1JEFEazcuEdfxta9j4iUwdSAr7mEsYYAp3EAUyCZk3VEEqGj6W+AV4uWyrDGtrlawAsgQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.19.0", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@angular-eslint/utils/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@angular/animations": { - "version": "17.3.11", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-17.3.11.tgz", - "integrity": "sha512-1y1Egag5jbdUSUWVK+KA39N9VFDrzq9ObjbAhrXFlXKa0npBRw5bprEEeLFQMETMP9Mpjbmj2PoASfl4vqj/Iw==", + "version": "17.3.12", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-17.3.12.tgz", + "integrity": "sha512-9hsdWF4gRRcVJtPcCcYLaX1CIyM9wUu6r+xRl6zU5hq8qhl35hig6ounz7CXFAzLf0WDBdM16bPHouVGaG76lg==", "dependencies": { "tslib": "^2.3.0" }, @@ -1439,7 +1639,7 @@ "node": "^18.13.0 || >=20.9.0" }, "peerDependencies": { - "@angular/core": "17.3.11" + "@angular/core": "17.3.12" } }, "node_modules/@angular/cdk": { @@ -1459,15 +1659,15 @@ } }, "node_modules/@angular/cli": { - "version": "17.3.8", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-17.3.8.tgz", - "integrity": "sha512-X5ZOQ6ZTKVHjhIsfl32ZRqbs+FUoeHLbT7x4fh2Os/8ObDDwrUcCJPqxe2b2RB5E2d0vepYigknHeLE7gwzlNQ==", + "version": "17.3.10", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-17.3.10.tgz", + "integrity": "sha512-lA0kf4Cpo8Jcuennq6wGyBTP/UG1oX4xsM9uLRZ2vkPoisjHCk46rWaVP7vfAqdUH39vbATFXftpy1SiEmAI4w==", "dev": true, "dependencies": { - "@angular-devkit/architect": "0.1703.8", - "@angular-devkit/core": "17.3.8", - "@angular-devkit/schematics": "17.3.8", - "@schematics/angular": "17.3.8", + "@angular-devkit/architect": "0.1703.10", + "@angular-devkit/core": "17.3.10", + "@angular-devkit/schematics": "17.3.10", + "@schematics/angular": "17.3.10", "@yarnpkg/lockfile": "1.1.0", "ansi-colors": "4.1.3", "ini": "4.1.2", @@ -1493,9 +1693,9 @@ } }, "node_modules/@angular/common": { - "version": "17.3.11", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-17.3.11.tgz", - "integrity": "sha512-WG+HQjUaQziYLGdbcv2aW+G73uroN5VF9yk4qWYcolW+VB8SV/DOAol8uFVgCF21cIOl5+wfJZvA4r5oG3dYaw==", + "version": "17.3.12", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-17.3.12.tgz", + "integrity": "sha512-vabJzvrx76XXFrm1RJZ6o/CyG32piTB/1sfFfKHdlH1QrmArb8It4gyk9oEjZ1IkAD0HvBWlfWmn+T6Vx3pdUw==", "dependencies": { "tslib": "^2.3.0" }, @@ -1503,14 +1703,14 @@ "node": "^18.13.0 || >=20.9.0" }, "peerDependencies": { - "@angular/core": "17.3.11", + "@angular/core": "17.3.12", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/compiler": { - "version": "17.3.11", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-17.3.11.tgz", - "integrity": "sha512-ingRoREDPkeZGSa13DlztSjZgGArNcmsAWjj+f+vQgQekTjkfQD/N+Bix/LSt5ZdbSjHMtrkDMyRPwbNyk5Keg==", + "version": "17.3.12", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-17.3.12.tgz", + "integrity": "sha512-vwI8oOL/gM+wPnptOVeBbMfZYwzRxQsovojZf+Zol9szl0k3SZ3FycWlxxXZGFu3VIEfrP6pXplTmyODS/Lt1w==", "dependencies": { "tslib": "^2.3.0" }, @@ -1518,7 +1718,7 @@ "node": "^18.13.0 || >=20.9.0" }, "peerDependencies": { - "@angular/core": "17.3.11" + "@angular/core": "17.3.12" }, "peerDependenciesMeta": { "@angular/core": { @@ -1527,9 +1727,9 @@ } }, "node_modules/@angular/compiler-cli": { - "version": "17.3.11", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-17.3.11.tgz", - "integrity": "sha512-O44H/BKGw0TYq0aNTOKYZfQiTrfjbmcTl8y4UX6C9Xey8hXvijzZOAsjA0TGvvDJxeLR+sxaRF4i9Ihoatnd8g==", + "version": "17.3.12", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-17.3.12.tgz", + "integrity": "sha512-1F8M7nWfChzurb7obbvuE7mJXlHtY1UG58pcwcomVtpPb+kPavgAO8OEvJHYBMV+bzSxkXt5UIwL9lt9jHUxZA==", "dependencies": { "@babel/core": "7.23.9", "@jridgewell/sourcemap-codec": "^1.4.14", @@ -1549,7 +1749,7 @@ "node": "^18.13.0 || >=20.9.0" }, "peerDependencies": { - "@angular/compiler": "17.3.11", + "@angular/compiler": "17.3.12", "typescript": ">=5.2 <5.5" } }, @@ -1601,9 +1801,9 @@ "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==" }, "node_modules/@angular/core": { - "version": "17.3.11", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-17.3.11.tgz", - "integrity": "sha512-2wPZwXFei3kVxK2ylIH6CdGebrC4kvooFx7qoX+250OITAEFMODJGdh/e3x0DpFUjlRvQtIFQ+YpQlfC5JnL4g==", + "version": "17.3.12", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-17.3.12.tgz", + "integrity": "sha512-MuFt5yKi161JmauUta4Dh0m8ofwoq6Ino+KoOtkYMBGsSx+A7dSm+DUxxNwdj7+DNyg3LjVGCFgBFnq4g8z06A==", "dependencies": { "tslib": "^2.3.0" }, @@ -1616,9 +1816,9 @@ } }, "node_modules/@angular/forms": { - "version": "17.3.11", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-17.3.11.tgz", - "integrity": "sha512-719flo/1L64YOAxL3pzszTK+7bczVVOQDXT1khnjb48GVZdBUBwW2D+cFbqSW1VMuWWr2Amwy1lL4YM5S7qPJQ==", + "version": "17.3.12", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-17.3.12.tgz", + "integrity": "sha512-tV6r12Q3yEUlXwpVko4E+XscunTIpPkLbaiDn/MTL3Vxi2LZnsLgHyd/i38HaHN+e/H3B0a1ToSOhV5wf3ay4Q==", "dependencies": { "tslib": "^2.3.0" }, @@ -1626,25 +1826,25 @@ "node": "^18.13.0 || >=20.9.0" }, "peerDependencies": { - "@angular/common": "17.3.11", - "@angular/core": "17.3.11", - "@angular/platform-browser": "17.3.11", + "@angular/common": "17.3.12", + "@angular/core": "17.3.12", + "@angular/platform-browser": "17.3.12", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/language-service": { - "version": "17.3.11", - "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-17.3.11.tgz", - "integrity": "sha512-C93TH34vG6Un8G0C75TU0aeTppJWUUbRcnR/3I6/ZmTirjIspXEAcmUr2LssFnULTYqA0npNn8cfDtsoLeoGog==", + "version": "17.3.12", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-17.3.12.tgz", + "integrity": "sha512-MVmEXonXwdhFtIpU4q8qbXHsrAsdTjZcPPuWCU0zXVQ+VaB/y6oF7BVpmBtfyBcBCums1guEncPP+AZVvulXmQ==", "dev": true, "engines": { "node": "^18.13.0 || >=20.9.0" } }, "node_modules/@angular/localize": { - "version": "17.3.11", - "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-17.3.11.tgz", - "integrity": "sha512-uc38JfGpIEb13rDZu7wZfEvLxBpWbhfsOR+yI21M4zIiKYQxI7RGgtH9GbCKZDEZmeTUSz/idA4zwRiiX8wNvQ==", + "version": "17.3.12", + "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-17.3.12.tgz", + "integrity": "sha512-b7J7zY/CgJhFVPtmu/pEjefU5SHuTy7lQgX6kTrJPaUSJ5i578R17xr4SwrWe7G4jzQwO6GXZZd17a62uNRyOA==", "dependencies": { "@babel/core": "7.23.9", "@types/babel__core": "7.20.5", @@ -1660,8 +1860,8 @@ "node": "^18.13.0 || >=20.9.0" }, "peerDependencies": { - "@angular/compiler": "17.3.11", - "@angular/compiler-cli": "17.3.11" + "@angular/compiler": "17.3.12", + "@angular/compiler-cli": "17.3.12" } }, "node_modules/@angular/localize/node_modules/@babel/core": { @@ -1707,9 +1907,9 @@ } }, "node_modules/@angular/platform-browser": { - "version": "17.3.11", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-17.3.11.tgz", - "integrity": "sha512-sWjMy8qKH6AOt5YV4OMoPhExCbGdRIPjNSwUrxCm8a8Zz5DamoX3Sib9yRk1etjBuRj+oJySSxISJim2OYXJQQ==", + "version": "17.3.12", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-17.3.12.tgz", + "integrity": "sha512-DYY04ptWh/ulMHzd+y52WCE8QnEYGeIiW3hEIFjCN8z0kbIdFdUtEB0IK5vjNL3ejyhUmphcpeT5PYf3YXtqWQ==", "dependencies": { "tslib": "^2.3.0" }, @@ -1717,9 +1917,9 @@ "node": "^18.13.0 || >=20.9.0" }, "peerDependencies": { - "@angular/animations": "17.3.11", - "@angular/common": "17.3.11", - "@angular/core": "17.3.11" + "@angular/animations": "17.3.12", + "@angular/common": "17.3.12", + "@angular/core": "17.3.12" }, "peerDependenciesMeta": { "@angular/animations": { @@ -1728,9 +1928,9 @@ } }, "node_modules/@angular/platform-browser-dynamic": { - "version": "17.3.11", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-17.3.11.tgz", - "integrity": "sha512-JPA0enJyJQ5H340WQ2wfXbCCHzjBiAljEDMr/Siw/CzSe0XI8aQYDqKMLUMtRyCdYhNCEYjnBWgXBi9Za9blZg==", + "version": "17.3.12", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-17.3.12.tgz", + "integrity": "sha512-DQwV7B2x/DRLRDSisngZRdLqHdYbbrqZv2Hmu4ZbnNYaWPC8qvzgE/0CvY+UkDat3nCcsfwsMnlDeB6TL7/IaA==", "dependencies": { "tslib": "^2.3.0" }, @@ -1738,16 +1938,16 @@ "node": "^18.13.0 || >=20.9.0" }, "peerDependencies": { - "@angular/common": "17.3.11", - "@angular/compiler": "17.3.11", - "@angular/core": "17.3.11", - "@angular/platform-browser": "17.3.11" + "@angular/common": "17.3.12", + "@angular/compiler": "17.3.12", + "@angular/core": "17.3.12", + "@angular/platform-browser": "17.3.12" } }, "node_modules/@angular/platform-server": { - "version": "17.3.11", - "resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-17.3.11.tgz", - "integrity": "sha512-xytV4+5gTCECUORniXBTE1lvJ3qf3IWlawmm3eZylvJMqH2W3ApZrrwLM7umL8BOU9ISEhjolbwfGXornKL+5A==", + "version": "17.3.12", + "resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-17.3.12.tgz", + "integrity": "sha512-P3xBzyeT2w/iiGsqGUNuLRYdqs2e+5nRnVYU9tc/TjhYDAgwEgq946U7Nie1xq5Ts/8b7bhxcK9maPKWG237Kw==", "dependencies": { "tslib": "^2.3.0", "xhr2": "^0.2.0" @@ -1756,17 +1956,17 @@ "node": "^18.13.0 || >=20.9.0" }, "peerDependencies": { - "@angular/animations": "17.3.11", - "@angular/common": "17.3.11", - "@angular/compiler": "17.3.11", - "@angular/core": "17.3.11", - "@angular/platform-browser": "17.3.11" + "@angular/animations": "17.3.12", + "@angular/common": "17.3.12", + "@angular/compiler": "17.3.12", + "@angular/core": "17.3.12", + "@angular/platform-browser": "17.3.12" } }, "node_modules/@angular/router": { - "version": "17.3.11", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-17.3.11.tgz", - "integrity": "sha512-A3aU6uHAeJfsfCw1dgNXHn2Kjw/UieRMnFwENkzz96YFCvFPCEZjy/mODuE3zHludMuqVsJhM/uUxWu8ATRTcA==", + "version": "17.3.12", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-17.3.12.tgz", + "integrity": "sha512-dg7PHBSW9fmPKTVzwvHEeHZPZdpnUqW/U7kj8D29HTP9ur8zZnx9QcnbplwPeYb8yYa62JMnZSEel2X4PxdYBg==", "dependencies": { "tslib": "^2.3.0" }, @@ -1774,16 +1974,16 @@ "node": "^18.13.0 || >=20.9.0" }, "peerDependencies": { - "@angular/common": "17.3.11", - "@angular/core": "17.3.11", - "@angular/platform-browser": "17.3.11", + "@angular/common": "17.3.12", + "@angular/core": "17.3.12", + "@angular/platform-browser": "17.3.12", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/ssr": { - "version": "17.3.8", - "resolved": "https://registry.npmjs.org/@angular/ssr/-/ssr-17.3.8.tgz", - "integrity": "sha512-qsCMMR7wEOlbPbqTOrcr/1hEoQjIQOGqq6stbK9J52IebTyzC+rZNzDjJcL9e39nSmvbIeCUaN1XquebQ12/pw==", + "version": "17.3.10", + "resolved": "https://registry.npmjs.org/@angular/ssr/-/ssr-17.3.10.tgz", + "integrity": "sha512-t+NX1HufU38c0u+8mDg31cqrXZo5SEUxjBuXwdu3mOvYbkanjhbtyIgIMYr9Vru8pqncasgHLJv2RVWDvAjlEw==", "dependencies": { "critters": "0.0.22", "tslib": "^2.3.0" @@ -1794,11 +1994,11 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz", + "integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==", "dependencies": { - "@babel/highlight": "^7.24.7", + "@babel/highlight": "^7.25.7", "picocolors": "^1.0.0" }, "engines": { @@ -1806,9 +2006,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.7.tgz", - "integrity": "sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.8.tgz", + "integrity": "sha512-ZsysZyXY4Tlx+Q53XdnOFmqwfB9QDTHYxaZYajWRoBLuLEAwI2UIbtxOjWh/cFaa9IKUlcB+DDuoskLuKu56JA==", "engines": { "node": ">=6.9.0" } @@ -1915,26 +2115,26 @@ } }, "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", - "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.7.tgz", + "integrity": "sha512-12xfNeKNH7jubQNm7PAkzlLwEmCs1tfuX3UjIw6vP6QXi+leKh6+LyC/+Ed4EIQermwd58wsyh070yjDHFlNGg==", "dev": true, "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz", - "integrity": "sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.7.tgz", + "integrity": "sha512-DniTEax0sv6isaw6qSQSfV4gVRNtw2rte8HHM45t9ZR0xILaufBRNkpMifCRiAPyvL4ACD6v0gfCwCmtOQaV4A==", "dependencies": { - "@babel/compat-data": "^7.24.7", - "@babel/helper-validator-option": "^7.24.7", - "browserslist": "^4.22.2", + "@babel/compat-data": "^7.25.7", + "@babel/helper-validator-option": "^7.25.7", + "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -1964,19 +2164,17 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.7.tgz", - "integrity": "sha512-kTkaDl7c9vO80zeX1rJxnuRpEsD5tA81yh11X1gQo+PhSti3JS+7qeZo9U4RHobKRiFPKaGK3svUAeb8D0Q7eg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.7.tgz", + "integrity": "sha512-bD4WQhbkx80mAyj/WCm4ZHcF4rDxkoLFO6ph8/5/mQ3z4vAzltQXAmbc7GvVJx5H+lk5Mi5EmbTeox5nMGCsbw==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-member-expression-to-functions": "^7.24.7", - "@babel/helper-optimise-call-expression": "^7.24.7", - "@babel/helper-replace-supers": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-member-expression-to-functions": "^7.25.7", + "@babel/helper-optimise-call-expression": "^7.25.7", + "@babel/helper-replace-supers": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", + "@babel/traverse": "^7.25.7", "semver": "^6.3.1" }, "engines": { @@ -1987,24 +2185,12 @@ } }, "node_modules/@babel/helper-create-class-features-plugin/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.7.tgz", + "integrity": "sha512-4xwU8StnqnlIhhioZf1tqnVWeQ9pvH/ujS8hRfw/WOza+/a+1qv69BWNy+oY231maTCWgKWhfBU7kDpsds6zAA==", "dev": true, "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-create-class-features-plugin/node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", - "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.7" + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2020,13 +2206,13 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.7.tgz", - "integrity": "sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.7.tgz", + "integrity": "sha512-byHhumTj/X47wJ6C6eLpK7wW/WBEcnUeb7D0FNc/jFQnQVw7DOso3Zz5u9x/zLrFVkHa89ZGDbkAa1D54NdrCQ==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "regexpu-core": "^5.3.1", + "@babel/helper-annotate-as-pure": "^7.25.7", + "regexpu-core": "^6.1.1", "semver": "^6.3.1" }, "engines": { @@ -2037,12 +2223,12 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.7.tgz", + "integrity": "sha512-4xwU8StnqnlIhhioZf1tqnVWeQ9pvH/ujS8hRfw/WOza+/a+1qv69BWNy+oY231maTCWgKWhfBU7kDpsds6zAA==", "dev": true, "dependencies": { - "@babel/types": "^7.24.7" + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2077,29 +2263,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", - "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", - "dependencies": { - "@babel/template": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", - "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", + "dev": true, "dependencies": { "@babel/types": "^7.24.7" }, @@ -2108,40 +2272,39 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.7.tgz", - "integrity": "sha512-LGeMaf5JN4hAT471eJdBs/GK1DoYIJ5GCtZN/EsL6KUiiDZOvO/eKE11AMZJa2zP4zk4qe9V2O/hxAmkRc8p6w==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.7.tgz", + "integrity": "sha512-O31Ssjd5K6lPbTX9AAYpSKrZmLeagt9uwschJd+Ixo6QiRyfpvgtVQp8qrDR9UNFjZ8+DO34ZkdrN+BnPXemeA==", "dev": true, "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", - "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.7.tgz", + "integrity": "sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw==", "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz", - "integrity": "sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.7.tgz", + "integrity": "sha512-k/6f8dKG3yDz/qCwSM+RKovjMix563SLxQFo0UhRNo239SP6n9u5/eLtKD6EAjwta2JHJ49CsD8pms2HdNiMMQ==", "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7" + "@babel/helper-module-imports": "^7.25.7", + "@babel/helper-simple-access": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2150,47 +2313,36 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-module-transforms/node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", - "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", - "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.7.tgz", + "integrity": "sha512-VAwcwuYhv/AT+Vfr28c9y6SHzTan1ryqrydSTFGjU0uDJHw3uZ+PduI8plCLkRsDnqK2DMEDmwrOQRsK/Ykjng==", "dev": true, "dependencies": { - "@babel/types": "^7.24.7" + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz", - "integrity": "sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.7.tgz", + "integrity": "sha512-eaPZai0PiqCi09pPs3pAFfl/zYgGaE6IdXtYvmf0qlcDTd3WCtO7JWCcRd64e0EQrcYgiHibEZnOGsSY4QSgaw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.7.tgz", - "integrity": "sha512-9pKLcTlZ92hNZMQfGCHImUpDOlAgkkpqalWEeftW5FBya75k8Li2ilerxkM/uBEj01iBZXcCIB/bwvDYgWyibA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.7.tgz", + "integrity": "sha512-kRGE89hLnPfcz6fTrlNU+uhgcwv0mBE4Gv3P9Ke9kLVJYpi4AMVVEElXvB5CabrPZW4nCM8P8UyyjrzCM0O2sw==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-wrap-function": "^7.24.7" + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-wrap-function": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2200,26 +2352,26 @@ } }, "node_modules/@babel/helper-remap-async-to-generator/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.7.tgz", + "integrity": "sha512-4xwU8StnqnlIhhioZf1tqnVWeQ9pvH/ujS8hRfw/WOza+/a+1qv69BWNy+oY231maTCWgKWhfBU7kDpsds6zAA==", "dev": true, "dependencies": { - "@babel/types": "^7.24.7" + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz", - "integrity": "sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.7.tgz", + "integrity": "sha512-iy8JhqlUW9PtZkd4pHM96v6BdJ66Ba9yWSE4z0W4TvSZwLBPkyDsiIU3ENe4SmrzRBs76F7rQXTy1lYC49n6Lw==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-member-expression-to-functions": "^7.24.7", - "@babel/helper-optimise-call-expression": "^7.24.7" + "@babel/helper-member-expression-to-functions": "^7.25.7", + "@babel/helper-optimise-call-expression": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2229,25 +2381,25 @@ } }, "node_modules/@babel/helper-simple-access": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", - "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.7.tgz", + "integrity": "sha512-FPGAkJmyoChQeM+ruBGIDyrT2tKfZJO8NcxdC+CWNJi7N8/rZpSxK7yvBJ5O/nF1gfu5KzN7VKG3YVSLFfRSxQ==", "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", - "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.7.tgz", + "integrity": "sha512-pPbNbchZBkPMD50K0p3JGcFMNLVUCuU/ABybm/PGNj4JiHrpmNyqqCphBk4i19xXtNV0JhldQJJtbSW5aUvbyA==", "dev": true, "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2266,39 +2418,38 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz", - "integrity": "sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz", + "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", + "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz", - "integrity": "sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.7.tgz", + "integrity": "sha512-ytbPLsm+GjArDYXJ8Ydr1c/KJuutjF2besPNbIZnZ6MKUxi/uTA22t2ymmA4WFjZFpjiAMO0xuuJPqK2nvDVfQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.24.7.tgz", - "integrity": "sha512-N9JIYk3TD+1vq/wn77YnJOqMtfWhNewNE+DJV4puD2X7Ew9J4JvrzrFDfTfyv5EgEXVy9/Wt8QiOErzEmv5Ifw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.7.tgz", + "integrity": "sha512-MA0roW3JF2bD1ptAaJnvcabsVlNQShUaThyJbCDD4bCp8NEgiFvpoqRI2YS22hHlc2thjO/fTg2ShLMC3jygAg==", "dev": true, "dependencies": { - "@babel/helper-function-name": "^7.24.7", - "@babel/template": "^7.24.7", - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/template": "^7.25.7", + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2317,11 +2468,11 @@ } }, "node_modules/@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.7.tgz", + "integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==", "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", + "@babel/helper-validator-identifier": "^7.25.7", "chalk": "^2.4.2", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" @@ -2331,9 +2482,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.7.tgz", - "integrity": "sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.8.tgz", + "integrity": "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ==", + "dependencies": { + "@babel/types": "^7.25.8" + }, "bin": { "parser": "bin/babel-parser.js" }, @@ -2342,12 +2496,12 @@ } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.7.tgz", - "integrity": "sha512-unaQgZ/iRu/By6tsjMZzpeBZjChYfLYry6HrEXPoz3KmfF0sVBQ1l8zKMQ4xRGLWVsjuvB8nQfjNP/DcfEOCsg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.7.tgz", + "integrity": "sha512-wxyWg2RYaSUYgmd9MR0FyRGyeOMQE/Uzr1wzd/g5cf5bwi9A4v6HFdDm7y1MgDtod/fLOSTZY6jDgV0xU9d5bA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2357,14 +2511,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", - "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.7.tgz", + "integrity": "sha512-Xwg6tZpLxc4iQjorYsyGMyfJE7nP5MV8t/Ka58BgiA7Jw0fRqQNcANlLfdJ/yvBt9z9LD2We+BEkT7vLqZRWng==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/plugin-transform-optional-chaining": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", + "@babel/plugin-transform-optional-chaining": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2374,13 +2528,13 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.7.tgz", - "integrity": "sha512-utA4HuR6F4Vvcr+o4DnjL8fCOlgRFGbeeBEGNg3ZTrLFw6VWG5XmUrvcQ0FjIYMU2ST4XcR2Wsp7t9qOAPnxMg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.7.tgz", + "integrity": "sha512-UVATLMidXrnH+GMUIuxq55nejlj02HP7F5ETyBONzP6G87fPBogG4CH6kxrSrdIuAjdwNO9VzyaYsrZPscWUrw==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2465,12 +2619,12 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz", - "integrity": "sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.7.tgz", + "integrity": "sha512-ZvZQRmME0zfJnDQnVBKYzHxXT7lYBB3Revz1GuS7oLXWMgqUPX4G+DDbT30ICClht9WKV34QVrZhSw6WdklwZQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2480,12 +2634,12 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", - "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.7.tgz", + "integrity": "sha512-AqVo+dguCgmpi/3mYBdu9lkngOBlQ2w2vnNpa6gfiCxQZLzV4ZbhsXitJ2Yblkoe1VQwtHSaNmIaGll/26YWRw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2637,12 +2791,12 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", - "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.7.tgz", + "integrity": "sha512-EJN2mKxDwfOUCPxMO6MUI58RN3ganiRAG/MS/S3HfB6QFNjroAMelQo/gybyYq97WerCBAZoyrAoW8Tzdq2jWg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2687,12 +2841,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", - "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.7.tgz", + "integrity": "sha512-xHttvIM9fvqW+0a3tZlYcZYSBpSWzGBFIt/sYG3tcdSzBB8ZeVgz2gBP7Df+sM0N1850jrviYSSeUuc+135dmQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2702,12 +2856,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.7.tgz", - "integrity": "sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.7.tgz", + "integrity": "sha512-ZEPJSkVZaeTFG/m2PARwLZQ+OG0vFIhPlKHK/JdIMy8DbRJ/htz6LRrTFtdzxi9EHmcwbNPAKDnadpNSIW+Aow==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2717,13 +2871,13 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz", - "integrity": "sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.7.tgz", + "integrity": "sha512-mhyfEW4gufjIqYFo9krXHJ3ElbFLIze5IDp+wQTxoPd+mwFb1NxatNAwmv8Q8Iuxv7Zc+q8EkiMQwc9IhyGf4g==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2733,14 +2887,13 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", - "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.25.8.tgz", + "integrity": "sha512-e82gl3TCorath6YLf9xUwFehVvjvfqFhdOo4+0iVIVju+6XOi5XHkqB3P2AXnSwoeTX0HBoXq5gJFtvotJzFnQ==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-class-static-block": "^7.14.5" + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2750,18 +2903,16 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.7.tgz", - "integrity": "sha512-CFbbBigp8ln4FU6Bpy6g7sE8B/WmCmzvivzUC6xDAdWVsjYTXijpuuGJmYkAaoWAzcItGKT3IOAbxRItZ5HTjw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.7.tgz", + "integrity": "sha512-9j9rnl+YCQY0IGoeipXvnk3niWicIB6kCsWRGLwX241qSXpbA4MKxtp/EdvFxsc4zI5vqfLxzOd0twIJ7I99zg==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-compilation-targets": "^7.24.7", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-replace-supers": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-replace-supers": "^7.25.7", + "@babel/traverse": "^7.25.7", "globals": "^11.1.0" }, "engines": { @@ -2772,37 +2923,25 @@ } }, "node_modules/@babel/plugin-transform-classes/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.7.tgz", + "integrity": "sha512-4xwU8StnqnlIhhioZf1tqnVWeQ9pvH/ujS8hRfw/WOza+/a+1qv69BWNy+oY231maTCWgKWhfBU7kDpsds6zAA==", "dev": true, "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/plugin-transform-classes/node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", - "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.7" + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", - "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.7.tgz", + "integrity": "sha512-QIv+imtM+EtNxg/XBKL3hiWjgdLjMOmZ+XzQwSgmBfKbfxUjBzGgVPklUuE55eq5/uVoh8gg3dqlrwR/jw3ZeA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/template": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/template": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2812,12 +2951,12 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.7.tgz", - "integrity": "sha512-19eJO/8kdCQ9zISOf+SEUJM/bAUIsvY3YDnXZTupUCQ8LgrWnsG/gFB9dvXqdXnRXMAM8fvt7b0CBKQHNGy1mw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.7.tgz", + "integrity": "sha512-xKcfLTlJYUczdaM1+epcdh1UGewJqr9zATgrNHcLBcV2QmfvPPEixo/sK/syql9cEmbr7ulu5HMFG5vbbt/sEA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2827,13 +2966,13 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", - "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.7.tgz", + "integrity": "sha512-kXzXMMRzAtJdDEgQBLF4oaiT6ZCU3oWHgpARnTKDAqPkDJ+bs3NrZb310YYevR5QlRo3Kn7dzzIdHbZm1VzJdQ==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2843,12 +2982,12 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", - "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.7.tgz", + "integrity": "sha512-by+v2CjoL3aMnWDOyCIg+yxU9KXSRa9tN6MbqggH5xvymmr9p4AMjYkNlQy4brMceBnUyHZ9G8RnpvT8wP7Cfg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2858,13 +2997,12 @@ } }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", - "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.8.tgz", + "integrity": "sha512-gznWY+mr4ZQL/EWPcbBQUP3BXS5FwZp8RUOw06BaRn8tQLzN4XLIxXejpHN9Qo8x8jjBmAAKp6FoS51AgkSA/A==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2874,13 +3012,13 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", - "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.7.tgz", + "integrity": "sha512-yjqtpstPfZ0h/y40fAXRv2snciYr0OAoMXY/0ClC7tm4C/nG5NJKmIItlaYlLbIVAWNfrYuy9dq1bE0SbX0PEg==", "dev": true, "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2890,13 +3028,12 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", - "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.8.tgz", + "integrity": "sha512-sPtYrduWINTQTW7FtOy99VCTWp4H23UX7vYcut7S4CIMEXU+54zKX9uCoGkLsWXteyaMXzVHgzWbLfQ1w4GZgw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2906,13 +3043,13 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", - "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.7.tgz", + "integrity": "sha512-n/TaiBGJxYFWvpJDfsxSj9lEEE44BFM1EPGz4KEiTipTgkoFVVcCmzAL3qA7fdQU96dpo4gGf5HBx/KnDvqiHw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2922,14 +3059,14 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.7.tgz", - "integrity": "sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.7.tgz", + "integrity": "sha512-5MCTNcjCMxQ63Tdu9rxyN6cAWurqfrDZ76qvVPrGYdBxIj+EawuuxTu/+dgJlhK5eRz3v1gLwp6XwS8XaX2NiQ==", "dev": true, "dependencies": { - "@babel/helper-compilation-targets": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2939,13 +3076,12 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", - "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.8.tgz", + "integrity": "sha512-4OMNv7eHTmJ2YXs3tvxAfa/I43di+VcF+M4Wt66c88EAED1RoGaf1D64cL5FkRpNL+Vx9Hds84lksWvd/wMIdA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-json-strings": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2955,12 +3091,12 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.7.tgz", - "integrity": "sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.7.tgz", + "integrity": "sha512-fwzkLrSu2fESR/cm4t6vqd7ebNIopz2QHGtjoU+dswQo/P6lwAG04Q98lliE3jkz/XqnbGFLnUcE0q0CVUf92w==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2970,13 +3106,12 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", - "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.8.tgz", + "integrity": "sha512-f5W0AhSbbI+yY6VakT04jmxdxz+WsID0neG7+kQZbCOjuyJNdL5Nn4WIBm4hRpKnUcO9lP0eipUhFN12JpoH8g==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2986,12 +3121,12 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", - "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.7.tgz", + "integrity": "sha512-Std3kXwpXfRV0QtQy5JJcRpkqP8/wG4XL7hSKZmGlxPlDqmpXtEPRmhF7ztnlTCtUN3eXRUJp+sBEZjaIBVYaw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3001,13 +3136,13 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", - "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.7.tgz", + "integrity": "sha512-CgselSGCGzjQvKzghCvDTxKHP3iooenLpJDO842ehn5D2G5fJB222ptnDwQho0WjEvg7zyoxb9P+wiYxiJX5yA==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3017,14 +3152,14 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.7.tgz", - "integrity": "sha512-iFI8GDxtevHJ/Z22J5xQpVqFLlMNstcLXh994xifFwxxGslr2ZXXLWgtBeLctOD63UFDArdvN6Tg8RFw+aEmjQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.7.tgz", + "integrity": "sha512-L9Gcahi0kKFYXvweO6n0wc3ZG1ChpSFdgG+eV1WYZ3/dGbJK7vvk91FgGgak8YwRgrCuihF8tE/Xg07EkL5COg==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-simple-access": "^7.24.7" + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-simple-access": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3034,15 +3169,15 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.7.tgz", - "integrity": "sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.7.tgz", + "integrity": "sha512-t9jZIvBmOXJsiuyOwhrIGs8dVcD6jDyg2icw1VL4A/g+FnWyJKwUfSSU2nwJuMV2Zqui856El9u+ElB+j9fV1g==", "dev": true, "dependencies": { - "@babel/helper-hoist-variables": "^7.24.7", - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7" + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3052,13 +3187,13 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", - "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.7.tgz", + "integrity": "sha512-p88Jg6QqsaPh+EB7I9GJrIqi1Zt4ZBHUQtjw3z1bzEXcLh6GfPqzZJ6G+G1HBGKUNukT58MnKG7EN7zXQBCODw==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3068,13 +3203,13 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", - "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.7.tgz", + "integrity": "sha512-BtAT9LzCISKG3Dsdw5uso4oV1+v2NlVXIIomKJgQybotJY3OwCwJmkongjHgwGKoZXd0qG5UZ12JUlDQ07W6Ow==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3084,12 +3219,12 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", - "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.7.tgz", + "integrity": "sha512-CfCS2jDsbcZaVYxRFo2qtavW8SpdzmBXC2LOI4oO0rP+JSRDxxF3inF4GcPsLgfb5FjkhXG5/yR/lxuRs2pySA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3099,13 +3234,12 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", - "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.8.tgz", + "integrity": "sha512-Z7WJJWdQc8yCWgAmjI3hyC+5PXIubH9yRKzkl9ZEG647O9szl9zvmKLzpbItlijBnVhTUf1cpyWBsZ3+2wjWPQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3115,13 +3249,12 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", - "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.8.tgz", + "integrity": "sha512-rm9a5iEFPS4iMIy+/A/PiS0QN0UyjPIeVvbU5EMZFKJZHt8vQnasbpo3T3EFcxzCeYO0BHfc4RqooCZc51J86Q==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3131,15 +3264,14 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", - "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.8.tgz", + "integrity": "sha512-LkUu0O2hnUKHKE7/zYOIjByMa4VRaV2CD/cdGz0AxU9we+VA3kDDggKEzI0Oz1IroG+6gUP6UmWEHBMWZU316g==", "dev": true, "dependencies": { - "@babel/helper-compilation-targets": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.24.7" + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-transform-parameters": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3149,13 +3281,13 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", - "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.7.tgz", + "integrity": "sha512-pWT6UXCEW3u1t2tcAGtE15ornCBvopHj9Bps9D2DsH15APgNVOTwwczGckX+WkAvBmuoYKRCFa4DK+jM8vh5AA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-replace-supers": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-replace-supers": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3165,13 +3297,12 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", - "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.8.tgz", + "integrity": "sha512-EbQYweoMAHOn7iJ9GgZo14ghhb9tTjgOc88xFgYngifx7Z9u580cENCV159M4xDh3q/irbhSjZVpuhpC2gKBbg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3181,14 +3312,13 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.7.tgz", - "integrity": "sha512-tK+0N9yd4j+x/4hxF3F0e0fu/VdcxU18y5SevtyM/PCFlQvXbR0Zmlo2eBrKtVipGNFzpq56o8WsIIKcJFUCRQ==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.8.tgz", + "integrity": "sha512-q05Bk7gXOxpTHoQ8RSzGSh/LHVB9JEIkKnk3myAWwZHnYiTGYtbdrYkIsS8Xyh4ltKf7GNUSgzs/6P2bJtBAQg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3198,12 +3328,12 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", - "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.7.tgz", + "integrity": "sha512-FYiTvku63me9+1Nz7TOx4YMtW3tWXzfANZtrzHhUZrz4d47EEtMQhzFoZWESfXuAMMT5mwzD4+y1N8ONAX6lMQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3213,13 +3343,13 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz", - "integrity": "sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.7.tgz", + "integrity": "sha512-KY0hh2FluNxMLwOCHbxVOKfdB5sjWG4M183885FmaqWWiGMhRZq4DQRKH6mHdEucbJnyDyYiZNwNG424RymJjA==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3229,15 +3359,14 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", - "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.8.tgz", + "integrity": "sha512-8Uh966svuB4V8RHHg0QJOB32QK287NBksJOByoKmHMp1TAobNniNalIkI2i5IPj5+S9NYCG4VIjbEuiSN8r+ow==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-create-class-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3247,24 +3376,24 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.7.tgz", + "integrity": "sha512-4xwU8StnqnlIhhioZf1tqnVWeQ9pvH/ujS8hRfw/WOza+/a+1qv69BWNy+oY231maTCWgKWhfBU7kDpsds6zAA==", "dev": true, "dependencies": { - "@babel/types": "^7.24.7" + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", - "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.7.tgz", + "integrity": "sha512-lQEeetGKfFi0wHbt8ClQrUSUMfEeI3MMm74Z73T9/kuz990yYVtfofjf3NuA42Jy3auFOpbjDyCSiIkTs1VIYw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3274,12 +3403,12 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", - "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.7.tgz", + "integrity": "sha512-mgDoQCRjrY3XK95UuV60tZlFCQGXEtMg8H+IsW72ldw1ih1jZhzYXbJvghmAEpg5UVhhnCeia1CkGttUvCkiMQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-plugin-utils": "^7.25.7", "regenerator-transform": "^0.15.2" }, "engines": { @@ -3290,12 +3419,12 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", - "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.7.tgz", + "integrity": "sha512-3OfyfRRqiGeOvIWSagcwUTVk2hXBsr/ww7bLn6TRTuXnexA+Udov2icFOxFX9abaj4l96ooYkcNN1qi2Zvqwng==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3334,12 +3463,12 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", - "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.7.tgz", + "integrity": "sha512-uBbxNwimHi5Bv3hUccmOFlUy3ATO6WagTApenHz9KzoIdn0XeACdB12ZJ4cjhuB2WSi80Ez2FWzJnarccriJeA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3349,13 +3478,13 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", - "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.7.tgz", + "integrity": "sha512-Mm6aeymI0PBh44xNIv/qvo8nmbkpZze1KvR8MkEqbIREDxoiWTi18Zr2jryfRMwDfVZF9foKh060fWgni44luw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3365,12 +3494,12 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", - "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.7.tgz", + "integrity": "sha512-ZFAeNkpGuLnAQ/NCsXJ6xik7Id+tHuS+NT+ue/2+rn/31zcdnupCdmunOizEaP0JsUmTFSTOPoQY7PkK2pttXw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3380,12 +3509,12 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", - "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.7.tgz", + "integrity": "sha512-SI274k0nUsFFmyQupiO7+wKATAmMFf8iFgq2O+vVFXZ0SV9lNfT1NGzBEhjquFmD8I9sqHLguH+gZVN3vww2AA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3395,12 +3524,12 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.7.tgz", - "integrity": "sha512-VtR8hDy7YLB7+Pet9IarXjg/zgCMSF+1mNS/EQEiEaUPoFXCVsHG64SIxcaaI2zJgRiv+YmgaQESUfWAdbjzgg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.7.tgz", + "integrity": "sha512-OmWmQtTHnO8RSUbL0NTdtpbZHeNTnm68Gj5pA4Y2blFNh+V4iZR68V1qL9cI37J21ZN7AaCnkfdHtLExQPf2uA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3410,12 +3539,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", - "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.7.tgz", + "integrity": "sha512-BN87D7KpbdiABA+t3HbVqHzKWUDN3dymLaTnPFAMyc8lV+KN3+YzNhVRNdinaCPA4AUqx7ubXbQ9shRjYBl3SQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3425,13 +3554,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", - "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.7.tgz", + "integrity": "sha512-IWfR89zcEPQGB/iB408uGtSPlQd3Jpq11Im86vUgcmSTcoWAiQMCTOa2K2yNNqFJEBVICKhayctee65Ka8OB0w==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3441,13 +3570,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", - "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.7.tgz", + "integrity": "sha512-8JKfg/hiuA3qXnlLx8qtv5HWRbgyFx2hMMtpDDuU2rTckpKkGu4ycK5yYHwuEa16/quXfoxHBIApEsNyMWnt0g==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3457,13 +3586,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz", - "integrity": "sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.7.tgz", + "integrity": "sha512-YRW8o9vzImwmh4Q3Rffd09bH5/hvY0pxg+1H1i0f7APoUeg12G7+HhLj9ZFNIrYkgBXhIijPJ+IXypN0hLTIbw==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -3589,12 +3718,6 @@ "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/@babel/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", - "dev": true - }, "node_modules/@babel/runtime": { "version": "7.21.0", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", @@ -3607,31 +3730,28 @@ } }, "node_modules/@babel/template": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", - "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.7.tgz", + "integrity": "sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==", "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/code-frame": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.7.tgz", - "integrity": "sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.7.tgz", + "integrity": "sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg==", "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.7", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-hoist-variables": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/types": "^7.24.7", + "@babel/code-frame": "^7.25.7", + "@babel/generator": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/template": "^7.25.7", + "@babel/types": "^7.25.7", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -3640,37 +3760,37 @@ } }, "node_modules/@babel/traverse/node_modules/@babel/generator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz", - "integrity": "sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.7.tgz", + "integrity": "sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA==", "dependencies": { - "@babel/types": "^7.24.7", + "@babel/types": "^7.25.7", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/traverse/node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", - "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", - "dependencies": { - "@babel/types": "^7.24.7" + "node_modules/@babel/traverse/node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "bin": { + "jsesc": "bin/jsesc" }, "engines": { - "node": ">=6.9.0" + "node": ">=6" } }, "node_modules/@babel/types": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.7.tgz", - "integrity": "sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.8.tgz", + "integrity": "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==", "dependencies": { - "@babel/helper-string-parser": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7", + "@babel/helper-string-parser": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", "to-fast-properties": "^2.0.0" }, "engines": { @@ -4949,18 +5069,6 @@ "node": ">=8" } }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", @@ -5728,233 +5836,6 @@ "node": "^16.13.0 || >=18.0.0" } }, - "node_modules/@nrwl/devkit": { - "version": "17.2.8", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-17.2.8.tgz", - "integrity": "sha512-l2dFy5LkWqSA45s6pee6CoqJeluH+sjRdVnAAQfjLHRNSx6mFAKblyzq5h1f4P0EUCVVVqLs+kVqmNx5zxYqvw==", - "dev": true, - "dependencies": { - "@nx/devkit": "17.2.8" - } - }, - "node_modules/@nrwl/tao": { - "version": "17.2.8", - "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-17.2.8.tgz", - "integrity": "sha512-Qpk5YKeJ+LppPL/wtoDyNGbJs2MsTi6qyX/RdRrEc8lc4bk6Cw3Oul1qTXCI6jT0KzTz+dZtd0zYD/G7okkzvg==", - "dev": true, - "dependencies": { - "nx": "17.2.8", - "tslib": "^2.3.0" - }, - "bin": { - "tao": "index.js" - } - }, - "node_modules/@nx/devkit": { - "version": "17.2.8", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-17.2.8.tgz", - "integrity": "sha512-6LtiQihtZwqz4hSrtT5cCG5XMCWppG6/B8c1kNksg97JuomELlWyUyVF+sxmeERkcLYFaKPTZytP0L3dmCFXaw==", - "dev": true, - "dependencies": { - "@nrwl/devkit": "17.2.8", - "ejs": "^3.1.7", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "semver": "7.5.3", - "tmp": "~0.2.1", - "tslib": "^2.3.0" - }, - "peerDependencies": { - "nx": ">= 16 <= 18" - } - }, - "node_modules/@nx/devkit/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nx/devkit/node_modules/semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nx/nx-darwin-arm64": { - "version": "17.2.8", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-17.2.8.tgz", - "integrity": "sha512-dMb0uxug4hM7tusISAU1TfkDK3ixYmzc1zhHSZwpR7yKJIyKLtUpBTbryt8nyso37AS1yH+dmfh2Fj2WxfBHTg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/nx-darwin-x64": { - "version": "17.2.8", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-17.2.8.tgz", - "integrity": "sha512-0cXzp1tGr7/6lJel102QiLA4NkaLCkQJj6VzwbwuvmuCDxPbpmbz7HC1tUteijKBtOcdXit1/MEoEU007To8Bw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/nx-freebsd-x64": { - "version": "17.2.8", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-17.2.8.tgz", - "integrity": "sha512-YFMgx5Qpp2btCgvaniDGdu7Ctj56bfFvbbaHQWmOeBPK1krNDp2mqp8HK6ZKOfEuDJGOYAp7HDtCLvdZKvJxzA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "17.2.8", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-17.2.8.tgz", - "integrity": "sha512-iN2my6MrhLRkVDtdivQHugK8YmR7URo1wU9UDuHQ55z3tEcny7LV3W9NSsY9UYPK/FrxdDfevj0r2hgSSdhnzA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/nx-linux-arm64-gnu": { - "version": "17.2.8", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-17.2.8.tgz", - "integrity": "sha512-Iy8BjoW6mOKrSMiTGujUcNdv+xSM1DALTH6y3iLvNDkGbjGK1Re6QNnJAzqcXyDpv32Q4Fc57PmuexyysZxIGg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/nx-linux-arm64-musl": { - "version": "17.2.8", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-17.2.8.tgz", - "integrity": "sha512-9wkAxWzknjpzdofL1xjtU6qPFF1PHlvKCZI3hgEYJDo4mQiatGI+7Ttko+lx/ZMP6v4+Umjtgq7+qWrApeKamQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/nx-linux-x64-gnu": { - "version": "17.2.8", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-17.2.8.tgz", - "integrity": "sha512-sjG1bwGsjLxToasZ3lShildFsF0eyeGu+pOQZIp9+gjFbeIkd19cTlCnHrOV9hoF364GuKSXQyUlwtFYFR4VTQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/nx-linux-x64-musl": { - "version": "17.2.8", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-17.2.8.tgz", - "integrity": "sha512-QiakXZ1xBCIptmkGEouLHQbcM4klQkcr+kEaz2PlNwy/sW3gH1b/1c0Ed5J1AN9xgQxWspriAONpScYBRgxdhA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/nx-win32-arm64-msvc": { - "version": "17.2.8", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-17.2.8.tgz", - "integrity": "sha512-XBWUY/F/GU3vKN9CAxeI15gM4kr3GOBqnzFZzoZC4qJt2hKSSUEWsMgeZtsMgeqEClbi4ZyCCkY7YJgU32WUGA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/nx-win32-x64-msvc": { - "version": "17.2.8", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-17.2.8.tgz", - "integrity": "sha512-HTqDv+JThlLzbcEm/3f+LbS5/wYQWzb5YDXbP1wi7nlCTihNZOLNqGOkEmwlrR5tAdNHPRpHSmkYg4305W0CtA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -6257,13 +6138,13 @@ ] }, "node_modules/@schematics/angular": { - "version": "17.3.8", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-17.3.8.tgz", - "integrity": "sha512-2g4OmSyE9YGq50Uj7fNI26P/TSAFJ7ZuirwTF2O7Xc4XRQ29/tYIIqhezpNlTb6rlYblcQuMcUZBrMfWJHcqJw==", + "version": "17.3.10", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-17.3.10.tgz", + "integrity": "sha512-cI+VB/WXlOeAMamni932lE/AZgui8o81dMyEXNXqCuYagNAMuKXliW79Mi5BwYQEABv/BUb4hB4zYtbQqHyACA==", "dev": true, "dependencies": { - "@angular-devkit/core": "17.3.8", - "@angular-devkit/schematics": "17.3.8", + "@angular-devkit/core": "17.3.10", + "@angular-devkit/schematics": "17.3.10", "jsonc-parser": "3.2.1" }, "engines": { @@ -6355,12 +6236,6 @@ "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, "node_modules/@socket.io/component-emitter": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", @@ -6521,28 +6396,6 @@ "integrity": "sha512-nv+GSx77ZtXiJzwKdsASqi+YQ5Z7vwHsTP0JY2SiQgjGckkBRKZnk8nIM+7oUZ1VCtuTz0+By4qVR7fqzp/Dfg==", "dev": true }, - "node_modules/@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", @@ -6887,15 +6740,6 @@ } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, "node_modules/@typescript-eslint/experimental-utils": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.62.0.tgz", @@ -7130,25 +6974,25 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.19.0.tgz", - "integrity": "sha512-mcvS6WSWbjiSxKCwBcXtOM5pRkPQ6kcDds/juxcy/727IQr3xMEcwr/YLHW2A2+Fp5ql6khjbKBzOyjuPqGi/w==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.11.0.tgz", + "integrity": "sha512-WmppUEgYy+y1NTseNMJ6mCFxt03/7jTOy08bcg7bxJJdsM4nuhnchyBbE8vryveaJUf62noH7LodPSo5Z0WUCg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.19.0", - "@typescript-eslint/utils": "6.19.0", + "@typescript-eslint/typescript-estree": "7.11.0", + "@typescript-eslint/utils": "7.11.0", "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -7157,16 +7001,16 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.0.tgz", - "integrity": "sha512-dO1XMhV2ehBI6QN8Ufi7I10wmUovmLU0Oru3n5LVlM2JuzB4M+dVphCPLkVpKvGij2j/pHBWuJ9piuXx+BhzxQ==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.11.0.tgz", + "integrity": "sha512-27tGdVEiutD4POirLZX4YzT180vevUURJl4wJGmm6TrQoiYwuxTIY98PBp6L2oN+JQxzE0URvYlzJaBHIekXAw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.0", - "@typescript-eslint/visitor-keys": "6.19.0" + "@typescript-eslint/types": "7.11.0", + "@typescript-eslint/visitor-keys": "7.11.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -7174,12 +7018,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.0.tgz", - "integrity": "sha512-lFviGV/vYhOy3m8BJ/nAKoAyNhInTdXpftonhWle66XHAtT1ouBlkjL496b5H5hb8dWXHwtypTqgtb/DEa+j5A==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.11.0.tgz", + "integrity": "sha512-MPEsDRZTyCiXkD4vd3zywDCifi7tatc4K37KqTprCvaXptP7Xlpdw0NR2hRJTetG5TxbWDB79Ys4kLmHliEo/w==", "dev": true, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -7187,22 +7031,22 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.0.tgz", - "integrity": "sha512-o/zefXIbbLBZ8YJ51NlkSAt2BamrK6XOmuxSR3hynMIzzyMY33KuJ9vuMdFSXW+H0tVvdF9qBPTHA91HDb4BIQ==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.11.0.tgz", + "integrity": "sha512-cxkhZ2C/iyi3/6U9EPc5y+a6csqHItndvN/CzbNXTNrsC3/ASoYQZEt9uMaEp+xFNjasqQyszp5TumAVKKvJeQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.0", - "@typescript-eslint/visitor-keys": "6.19.0", + "@typescript-eslint/types": "7.11.0", + "@typescript-eslint/visitor-keys": "7.11.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -7215,62 +7059,44 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.0.tgz", - "integrity": "sha512-QR41YXySiuN++/dC9UArYOg4X86OAYP83OWTewpVx5ct1IZhjjgTLocj7QNxGhWoTqknsgpl7L+hGygCO+sdYw==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.11.0.tgz", + "integrity": "sha512-xlAWwPleNRHwF37AhrZurOxA1wyXowW4PqVXZVUNCLjB48CqdPJoJWkrpH2nij9Q3Lb7rtWindtoXwxjxlKKCA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.19.0", - "@typescript-eslint/types": "6.19.0", - "@typescript-eslint/typescript-estree": "6.19.0", - "semver": "^7.5.4" + "@typescript-eslint/scope-manager": "7.11.0", + "@typescript-eslint/types": "7.11.0", + "@typescript-eslint/typescript-estree": "7.11.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.0.tgz", - "integrity": "sha512-hZaUCORLgubBvtGpp1JEFEazcuEdfxta9j4iUwdSAr7mEsYYAp3EAUyCZk3VEEqGj6W+AV4uWyrDGtrlawAsgQ==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.11.0.tgz", + "integrity": "sha512-7syYk4MzjxTEk0g/w3iqtgxnFQspDJfn6QKD36xMuuhTzjcxY7F8EmBLnALjVyaOF1/bVocu3bS/2/F7rXrveQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.0", - "eslint-visitor-keys": "^3.4.1" + "@typescript-eslint/types": "7.11.0", + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@typescript-eslint/types": { "version": "7.18.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", @@ -7356,18 +7182,6 @@ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" }, - "node_modules/@vitejs/plugin-basic-ssl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-1.1.0.tgz", - "integrity": "sha512-wO4Dk/rm8u7RNhOf95ZzcEmC9rYOncYgvq4z3duaJrCgjN8BxAnDVyndanfcJZ0O6XZzHz6Q0hTimxTg8Y9g/A==", - "dev": true, - "engines": { - "node": ">=14.6.0" - }, - "peerDependencies": { - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0" - } - }, "node_modules/@webassemblyjs/ast": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", @@ -7576,59 +7390,6 @@ "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", "dev": true }, - "node_modules/@yarnpkg/parsers": { - "version": "3.0.0-rc.46", - "resolved": "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.0-rc.46.tgz", - "integrity": "sha512-aiATs7pSutzda/rq8fnuPwTglyVwjM22bNnK2ZgjrpAjQHSSl3lztd2f9evst1W/qnC58DRz7T7QndUDumAR4Q==", - "dev": true, - "dependencies": { - "js-yaml": "^3.10.0", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=14.15.0" - } - }, - "node_modules/@yarnpkg/parsers/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@yarnpkg/parsers/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@yarnpkg/parsers/node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "node_modules/@zkochan/js-yaml": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.6.tgz", - "integrity": "sha512-nzvgl3VfhcELQ8LyVrYOru+UtAy1nrygk2+AGbTm8a5YcO6o8lSjAT+pfg3vJWxIoZKOUhrK6UU7xW/+00kQrg==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/abbrev": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", @@ -7661,16 +7422,6 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^8" - } - }, "node_modules/acorn-import-attributes": { "version": "1.9.5", "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", @@ -8780,9 +8531,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.1.tgz", - "integrity": "sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz", + "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==", "funding": [ { "type": "opencollective", @@ -8798,10 +8549,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001629", - "electron-to-chromium": "^1.4.796", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.16" + "caniuse-lite": "^1.0.30001663", + "electron-to-chromium": "^1.5.28", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" }, "bin": { "browserslist": "cli.js" @@ -8955,9 +8706,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001640", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001640.tgz", - "integrity": "sha512-lA4VMpW0PSUrFnkmVuEKBUovSWKhj7puyCg8StBChgu298N1AtuF1sKWEvfDuimSEDbhlb/KqPKC3fs1HbuQUA==", + "version": "1.0.30001668", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001668.tgz", + "integrity": "sha512-nWLrdxqCdblixUO+27JtGJJE/txpJlyUy5YN1u53wLZkP0emYCo5zgS6QYft7VUYR42LGgi/S5hdLZTrnyIddw==", "funding": [ { "type": "opencollective", @@ -9722,12 +9473,12 @@ } }, "node_modules/core-js-compat": { - "version": "3.37.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", - "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", + "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==", "dev": true, "dependencies": { - "browserslist": "^4.23.0" + "browserslist": "^4.23.3" }, "funding": { "type": "opencollective", @@ -10248,15 +9999,6 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/cypress/node_modules/tmp": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", - "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", - "dev": true, - "engines": { - "node": ">=14.14" - } - }, "node_modules/cypress/node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -10608,15 +10350,6 @@ "node": ">=0.3.1" } }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -10749,27 +10482,6 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/dotenv": { - "version": "16.3.2", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.2.tgz", - "integrity": "sha512-HTlk5nmhkm8F6JcdXvHIzaorzCoziNQT9mGxLPVXW8wJF1TiGSL60ZGB4gHWabHOaMmWmhvk2/lPHfnBiT78AQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/motdotla/dotenv?sponsor=1" - } - }, - "node_modules/dotenv-expand": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", - "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", @@ -10912,9 +10624,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.818", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.818.tgz", - "integrity": "sha512-eGvIk2V0dGImV9gWLq8fDfTTsCAeMDwZqEPMr+jMInxZdnp9Us8UpovYpRCf9NQ7VOFgrN2doNSgvISbsbNpxA==" + "version": "1.5.38", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.38.tgz", + "integrity": "sha512-VbeVexmZ1IFh+5EfrYz1I0HTzHVIlJa112UEWhciPyeOcKJGeTv6N8WnG4wsQB81DGCaVEGhpSb6o6a8WYFXXg==" }, "node_modules/element-resize-detector": { "version": "1.2.4", @@ -12791,12 +12503,6 @@ "node": ">= 0.6" } }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true - }, "node_modules/fs-extra": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz", @@ -13545,9 +13251,9 @@ ] }, "node_modules/ignore": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", - "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "engines": { "node": ">= 4" } @@ -14577,100 +14283,6 @@ "rxjs": "^7.0.0" } }, - "node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-diff/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-diff/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-diff/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-diff/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-diff/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-diff/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/jest-worker": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", @@ -15600,15 +15212,6 @@ "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==", "dev": true }, - "node_modules/lines-and-columns": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz", - "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, "node_modules/linkify-it": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", @@ -16882,9 +16485,9 @@ } }, "node_modules/node-gyp-build": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz", - "integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==", + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.2.tgz", + "integrity": "sha512-IRUxE4BVsHWXkV/SFOut4qTlagw2aM8T5/vnTsmrHJvVoKueJHRc/JaFND7QDDc61kLYUJ6qlZM3sqTSyx2dTw==", "dev": true, "optional": true, "bin": { @@ -16949,16 +16552,10 @@ "node": "^16.13.0 || >=18.0.0" } }, - "node_modules/node-machine-id": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/node-machine-id/-/node-machine-id-1.1.12.tgz", - "integrity": "sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==", - "dev": true - }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" }, "node_modules/nodemon": { "version": "2.0.22", @@ -17222,255 +16819,6 @@ "url": "https://github.com/fb55/nth-check?sponsor=1" } }, - "node_modules/nx": { - "version": "17.2.8", - "resolved": "https://registry.npmjs.org/nx/-/nx-17.2.8.tgz", - "integrity": "sha512-rM5zXbuXLEuqQqcjVjClyvHwRJwt+NVImR2A6KFNG40Z60HP6X12wAxxeLHF5kXXTDRU0PFhf/yACibrpbPrAw==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@nrwl/tao": "17.2.8", - "@yarnpkg/lockfile": "^1.1.0", - "@yarnpkg/parsers": "3.0.0-rc.46", - "@zkochan/js-yaml": "0.0.6", - "axios": "^1.5.1", - "chalk": "^4.1.0", - "cli-cursor": "3.1.0", - "cli-spinners": "2.6.1", - "cliui": "^8.0.1", - "dotenv": "~16.3.1", - "dotenv-expand": "~10.0.0", - "enquirer": "~2.3.6", - "figures": "3.2.0", - "flat": "^5.0.2", - "fs-extra": "^11.1.0", - "glob": "7.1.4", - "ignore": "^5.0.4", - "jest-diff": "^29.4.1", - "js-yaml": "4.1.0", - "jsonc-parser": "3.2.0", - "lines-and-columns": "~2.0.3", - "minimatch": "3.0.5", - "node-machine-id": "1.1.12", - "npm-run-path": "^4.0.1", - "open": "^8.4.0", - "semver": "7.5.3", - "string-width": "^4.2.3", - "strong-log-transformer": "^2.1.0", - "tar-stream": "~2.2.0", - "tmp": "~0.2.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0", - "yargs": "^17.6.2", - "yargs-parser": "21.1.1" - }, - "bin": { - "nx": "bin/nx.js", - "nx-cloud": "bin/nx-cloud.js" - }, - "optionalDependencies": { - "@nx/nx-darwin-arm64": "17.2.8", - "@nx/nx-darwin-x64": "17.2.8", - "@nx/nx-freebsd-x64": "17.2.8", - "@nx/nx-linux-arm-gnueabihf": "17.2.8", - "@nx/nx-linux-arm64-gnu": "17.2.8", - "@nx/nx-linux-arm64-musl": "17.2.8", - "@nx/nx-linux-x64-gnu": "17.2.8", - "@nx/nx-linux-x64-musl": "17.2.8", - "@nx/nx-win32-arm64-msvc": "17.2.8", - "@nx/nx-win32-x64-msvc": "17.2.8" - }, - "peerDependencies": { - "@swc-node/register": "^1.6.7", - "@swc/core": "^1.3.85" - }, - "peerDependenciesMeta": { - "@swc-node/register": { - "optional": true - }, - "@swc/core": { - "optional": true - } - } - }, - "node_modules/nx/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/nx/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/nx/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/nx/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/nx/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/nx/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/nx/node_modules/glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/nx/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/nx/node_modules/jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", - "dev": true - }, - "node_modules/nx/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/nx/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/nx/node_modules/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/nx/node_modules/semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/nx/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nx/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -19304,38 +18652,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/pretty-format/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true - }, "node_modules/proc-log": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", @@ -20058,9 +19374,9 @@ "dev": true }, "node_modules/regenerate-unicode-properties": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", - "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", + "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", "dev": true, "dependencies": { "regenerate": "^1.4.2" @@ -20108,15 +19424,15 @@ } }, "node_modules/regexpu-core": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", - "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.1.1.tgz", + "integrity": "sha512-k67Nb9jvwJcJmVpw0jPttR1/zVfnKf8Km0IPatrU/zJ5XeG3+Slx0xLXs9HByJSzXzrlz5EDvN6yLNMDc2qdnw==", "dev": true, "dependencies": { - "@babel/regjsgen": "^0.8.0", "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsparser": "^0.9.1", + "regenerate-unicode-properties": "^10.2.0", + "regjsgen": "^0.8.0", + "regjsparser": "^0.11.0", "unicode-match-property-ecmascript": "^2.0.0", "unicode-match-property-value-ecmascript": "^2.1.0" }, @@ -20124,25 +19440,34 @@ "node": ">=4" } }, + "node_modules/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", + "dev": true + }, "node_modules/regjsparser": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.11.1.tgz", + "integrity": "sha512-1DHODs4B8p/mQHU9kr+jv8+wIC9mtG4eBHxWxIq5mhjE3D5oORhCc6deRKzTjs9DcfRFmj9BHSDguZklqCGFWQ==", "dev": true, "dependencies": { - "jsesc": "~0.5.0" + "jsesc": "~3.0.2" }, "bin": { "regjsparser": "bin/parser" } }, "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", "dev": true, "bin": { "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" } }, "node_modules/request-progress": { @@ -21828,23 +21153,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strong-log-transformer": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz", - "integrity": "sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==", - "dev": true, - "dependencies": { - "duplexer": "^0.1.1", - "minimist": "^1.2.0", - "through": "^2.3.4" - }, - "bin": { - "sl-log-transformer": "bin/sl-log-transformer.js" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -21915,22 +21223,6 @@ "node": ">=10" } }, - "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dev": true, - "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/tar/node_modules/minipass": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", @@ -22128,15 +21420,12 @@ "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" }, "node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", "dev": true, - "dependencies": { - "rimraf": "^3.0.0" - }, "engines": { - "node": ">=8.17.0" + "node": ">=14.14" } }, "node_modules/to-fast-properties": { @@ -22567,15 +21856,23 @@ "node": ">=18.0" } }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true, + "optional": true, + "peer": true + }, "node_modules/unfetch": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/unfetch/-/unfetch-4.2.0.tgz", "integrity": "sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==" }, "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", "dev": true, "engines": { "node": ">=4" @@ -22595,9 +21892,9 @@ } }, "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", - "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", + "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", "dev": true, "engines": { "node": ">=4" @@ -22788,467 +22085,6 @@ "extsprintf": "^1.2.0" } }, - "node_modules/vite": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.7.tgz", - "integrity": "sha512-sgnEEFTZYMui/sTlH1/XEnVNHMujOahPLGMxn1+5sIT45Xjng1Ec1K78jRP15dSmVgg5WBin9yO81j3o9OxofA==", - "dev": true, - "dependencies": { - "esbuild": "^0.19.3", - "postcss": "^8.4.35", - "rollup": "^4.2.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "node_modules/vite/node_modules/@esbuild/aix-ppc64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", - "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", - "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", - "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", - "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", - "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", - "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", - "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", - "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", - "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", - "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", - "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", - "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", - "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", - "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", - "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", - "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", - "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", - "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", - "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", - "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", - "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", - "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", - "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/esbuild": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", - "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.19.12", - "@esbuild/android-arm": "0.19.12", - "@esbuild/android-arm64": "0.19.12", - "@esbuild/android-x64": "0.19.12", - "@esbuild/darwin-arm64": "0.19.12", - "@esbuild/darwin-x64": "0.19.12", - "@esbuild/freebsd-arm64": "0.19.12", - "@esbuild/freebsd-x64": "0.19.12", - "@esbuild/linux-arm": "0.19.12", - "@esbuild/linux-arm64": "0.19.12", - "@esbuild/linux-ia32": "0.19.12", - "@esbuild/linux-loong64": "0.19.12", - "@esbuild/linux-mips64el": "0.19.12", - "@esbuild/linux-ppc64": "0.19.12", - "@esbuild/linux-riscv64": "0.19.12", - "@esbuild/linux-s390x": "0.19.12", - "@esbuild/linux-x64": "0.19.12", - "@esbuild/netbsd-x64": "0.19.12", - "@esbuild/openbsd-x64": "0.19.12", - "@esbuild/sunos-x64": "0.19.12", - "@esbuild/win32-arm64": "0.19.12", - "@esbuild/win32-ia32": "0.19.12", - "@esbuild/win32-x64": "0.19.12" - } - }, "node_modules/void-elements": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", diff --git a/package.json b/package.json index 5ff97dec31..4d0c6d3813 100644 --- a/package.json +++ b/package.json @@ -96,18 +96,18 @@ } }, "dependencies": { - "@angular/animations": "^17.3.11", + "@angular/animations": "^17.3.12", "@angular/cdk": "^17.3.10", - "@angular/common": "^17.3.11", - "@angular/compiler": "^17.3.11", - "@angular/core": "^17.3.11", - "@angular/forms": "^17.3.11", - "@angular/localize": "^17.3.11", - "@angular/platform-browser": "^17.3.11", - "@angular/platform-browser-dynamic": "^17.3.11", - "@angular/platform-server": "^17.3.11", - "@angular/router": "^17.3.11", - "@angular/ssr": "^17.3.8", + "@angular/common": "^17.3.12", + "@angular/compiler": "^17.3.12", + "@angular/core": "^17.3.12", + "@angular/forms": "^17.3.12", + "@angular/localize": "^17.3.12", + "@angular/platform-browser": "^17.3.12", + "@angular/platform-browser-dynamic": "^17.3.12", + "@angular/platform-server": "^17.3.12", + "@angular/router": "^17.3.12", + "@angular/ssr": "^17.3.10", "@babel/runtime": "7.21.0", "@kolkov/ngx-gallery": "^2.0.1", "@ng-bootstrap/ng-bootstrap": "^11.0.0", @@ -172,15 +172,15 @@ "devDependencies": { "@angular-builders/custom-webpack": "~17.0.2", "@angular-devkit/build-angular": "^17.3.8", - "@angular-eslint/builder": "17.2.1", - "@angular-eslint/bundled-angular-compiler": "17.2.1", - "@angular-eslint/eslint-plugin": "17.2.1", - "@angular-eslint/eslint-plugin-template": "17.2.1", - "@angular-eslint/schematics": "17.2.1", - "@angular-eslint/template-parser": "17.2.1", - "@angular/cli": "^17.3.8", + "@angular-eslint/builder": "17.5.3", + "@angular-eslint/bundled-angular-compiler": "17.5.3", + "@angular-eslint/eslint-plugin": "17.5.3", + "@angular-eslint/eslint-plugin-template": "17.5.3", + "@angular-eslint/schematics": "17.5.3", + "@angular-eslint/template-parser": "17.5.3", + "@angular/cli": "^17.3.10", "@angular/compiler-cli": "^17.3.11", - "@angular/language-service": "^17.3.11", + "@angular/language-service": "^17.3.12", "@cypress/schematic": "^1.5.0", "@fortawesome/fontawesome-free": "^6.4.0", "@ngrx/store-devtools": "^17.1.1", From 479e1be216b3511f3bc8288e789a4028bbf8a7e6 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 16 Oct 2024 10:18:55 -0500 Subject: [PATCH 0609/1286] Add missing @angular-eslint/utils dependency. Update all @angular-eslint deps to use caret versioning --- package-lock.json | 152 +++++++++++++++++++++++++++++++++++----------- package.json | 13 ++-- 2 files changed, 125 insertions(+), 40 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1d0f3ee08c..6e6422a140 100644 --- a/package-lock.json +++ b/package-lock.json @@ -85,12 +85,13 @@ "devDependencies": { "@angular-builders/custom-webpack": "~17.0.2", "@angular-devkit/build-angular": "^17.3.8", - "@angular-eslint/builder": "17.5.3", - "@angular-eslint/bundled-angular-compiler": "17.5.3", - "@angular-eslint/eslint-plugin": "17.5.3", - "@angular-eslint/eslint-plugin-template": "17.5.3", - "@angular-eslint/schematics": "17.5.3", - "@angular-eslint/template-parser": "17.5.3", + "@angular-eslint/builder": "^17.5.3", + "@angular-eslint/bundled-angular-compiler": "^17.5.3", + "@angular-eslint/eslint-plugin": "^17.5.3", + "@angular-eslint/eslint-plugin-template": "^17.5.3", + "@angular-eslint/schematics": "^17.5.3", + "@angular-eslint/template-parser": "^17.5.3", + "@angular-eslint/utils": "^17.5.3", "@angular/cli": "^17.3.10", "@angular/compiler-cli": "^17.3.11", "@angular/language-service": "^17.3.12", @@ -1376,20 +1377,6 @@ "typescript": "*" } }, - "node_modules/@angular-eslint/eslint-plugin-template/node_modules/@angular-eslint/utils": { - "version": "17.5.3", - "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-17.5.3.tgz", - "integrity": "sha512-0nNm1FUOLhVHrdK2PP5dZCYYVmTIkEJ4CmlwpuC4JtCLbD5XAHQpY/ZW5Ff5n1b7KfJt1Zy//jlhkkIaw3LaBQ==", - "dev": true, - "dependencies": { - "@angular-eslint/bundled-angular-compiler": "17.5.3", - "@typescript-eslint/utils": "7.11.0" - }, - "peerDependencies": { - "eslint": "^7.20.0 || ^8.0.0", - "typescript": "*" - } - }, "node_modules/@angular-eslint/eslint-plugin-template/node_modules/@typescript-eslint/scope-manager": { "version": "7.11.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.11.0.tgz", @@ -1487,20 +1474,6 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@angular-eslint/eslint-plugin/node_modules/@angular-eslint/utils": { - "version": "17.5.3", - "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-17.5.3.tgz", - "integrity": "sha512-0nNm1FUOLhVHrdK2PP5dZCYYVmTIkEJ4CmlwpuC4JtCLbD5XAHQpY/ZW5Ff5n1b7KfJt1Zy//jlhkkIaw3LaBQ==", - "dev": true, - "dependencies": { - "@angular-eslint/bundled-angular-compiler": "17.5.3", - "@typescript-eslint/utils": "7.11.0" - }, - "peerDependencies": { - "eslint": "^7.20.0 || ^8.0.0", - "typescript": "*" - } - }, "node_modules/@angular-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { "version": "7.11.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.11.0.tgz", @@ -1628,6 +1601,117 @@ "typescript": "*" } }, + "node_modules/@angular-eslint/utils": { + "version": "17.5.3", + "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-17.5.3.tgz", + "integrity": "sha512-0nNm1FUOLhVHrdK2PP5dZCYYVmTIkEJ4CmlwpuC4JtCLbD5XAHQpY/ZW5Ff5n1b7KfJt1Zy//jlhkkIaw3LaBQ==", + "dev": true, + "dependencies": { + "@angular-eslint/bundled-angular-compiler": "17.5.3", + "@typescript-eslint/utils": "7.11.0" + }, + "peerDependencies": { + "eslint": "^7.20.0 || ^8.0.0", + "typescript": "*" + } + }, + "node_modules/@angular-eslint/utils/node_modules/@typescript-eslint/scope-manager": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.11.0.tgz", + "integrity": "sha512-27tGdVEiutD4POirLZX4YzT180vevUURJl4wJGmm6TrQoiYwuxTIY98PBp6L2oN+JQxzE0URvYlzJaBHIekXAw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.11.0", + "@typescript-eslint/visitor-keys": "7.11.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@angular-eslint/utils/node_modules/@typescript-eslint/types": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.11.0.tgz", + "integrity": "sha512-MPEsDRZTyCiXkD4vd3zywDCifi7tatc4K37KqTprCvaXptP7Xlpdw0NR2hRJTetG5TxbWDB79Ys4kLmHliEo/w==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@angular-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.11.0.tgz", + "integrity": "sha512-cxkhZ2C/iyi3/6U9EPc5y+a6csqHItndvN/CzbNXTNrsC3/ASoYQZEt9uMaEp+xFNjasqQyszp5TumAVKKvJeQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.11.0", + "@typescript-eslint/visitor-keys": "7.11.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@angular-eslint/utils/node_modules/@typescript-eslint/utils": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.11.0.tgz", + "integrity": "sha512-xlAWwPleNRHwF37AhrZurOxA1wyXowW4PqVXZVUNCLjB48CqdPJoJWkrpH2nij9Q3Lb7rtWindtoXwxjxlKKCA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.11.0", + "@typescript-eslint/types": "7.11.0", + "@typescript-eslint/typescript-estree": "7.11.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@angular-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.11.0.tgz", + "integrity": "sha512-7syYk4MzjxTEk0g/w3iqtgxnFQspDJfn6QKD36xMuuhTzjcxY7F8EmBLnALjVyaOF1/bVocu3bS/2/F7rXrveQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.11.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@angular/animations": { "version": "17.3.12", "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-17.3.12.tgz", diff --git a/package.json b/package.json index 4d0c6d3813..0834316052 100644 --- a/package.json +++ b/package.json @@ -172,12 +172,13 @@ "devDependencies": { "@angular-builders/custom-webpack": "~17.0.2", "@angular-devkit/build-angular": "^17.3.8", - "@angular-eslint/builder": "17.5.3", - "@angular-eslint/bundled-angular-compiler": "17.5.3", - "@angular-eslint/eslint-plugin": "17.5.3", - "@angular-eslint/eslint-plugin-template": "17.5.3", - "@angular-eslint/schematics": "17.5.3", - "@angular-eslint/template-parser": "17.5.3", + "@angular-eslint/builder": "^17.5.3", + "@angular-eslint/bundled-angular-compiler": "^17.5.3", + "@angular-eslint/eslint-plugin": "^17.5.3", + "@angular-eslint/eslint-plugin-template": "^17.5.3", + "@angular-eslint/schematics": "^17.5.3", + "@angular-eslint/template-parser": "^17.5.3", + "@angular-eslint/utils": "^17.5.3", "@angular/cli": "^17.3.10", "@angular/compiler-cli": "^17.3.11", "@angular/language-service": "^17.3.12", From 9c2b12ead822aa2e25b7848b0e87731774780c6f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 16 Oct 2024 16:03:14 +0000 Subject: [PATCH 0610/1286] Bump @babel/runtime from 7.21.0 to 7.25.7 Bumps [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) from 7.21.0 to 7.25.7. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.25.7/packages/babel-runtime) --- updated-dependencies: - dependency-name: "@babel/runtime" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 22 ++++++++-------------- package.json | 2 +- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6e6422a140..48d4ddad6f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "@angular/platform-server": "^17.3.12", "@angular/router": "^17.3.12", "@angular/ssr": "^17.3.10", - "@babel/runtime": "7.21.0", + "@babel/runtime": "7.25.7", "@kolkov/ngx-gallery": "^2.0.1", "@ng-bootstrap/ng-bootstrap": "^11.0.0", "@ng-dynamic-forms/core": "^16.0.0", @@ -1014,12 +1014,6 @@ } } }, - "node_modules/@angular-devkit/build-angular/node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true - }, "node_modules/@angular-devkit/build-angular/node_modules/sass": { "version": "1.71.1", "resolved": "https://registry.npmjs.org/sass/-/sass-1.71.1.tgz", @@ -3803,11 +3797,11 @@ } }, "node_modules/@babel/runtime": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", - "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.7.tgz", + "integrity": "sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w==", "dependencies": { - "regenerator-runtime": "^0.13.11" + "regenerator-runtime": "^0.14.0" }, "engines": { "node": ">=6.9.0" @@ -19470,9 +19464,9 @@ } }, "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, "node_modules/regenerator-transform": { "version": "0.15.2", diff --git a/package.json b/package.json index 0834316052..c058d5cbe7 100644 --- a/package.json +++ b/package.json @@ -108,7 +108,7 @@ "@angular/platform-server": "^17.3.12", "@angular/router": "^17.3.12", "@angular/ssr": "^17.3.10", - "@babel/runtime": "7.21.0", + "@babel/runtime": "7.25.7", "@kolkov/ngx-gallery": "^2.0.1", "@ng-bootstrap/ng-bootstrap": "^11.0.0", "@ng-dynamic-forms/core": "^16.0.0", From 72246bdc60cc4e8a22142809c8c1ef34f5153bb4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 16 Oct 2024 16:03:28 +0000 Subject: [PATCH 0611/1286] Bump @fortawesome/fontawesome-free from 6.5.2 to 6.6.0 Bumps [@fortawesome/fontawesome-free](https://github.com/FortAwesome/Font-Awesome) from 6.5.2 to 6.6.0. - [Release notes](https://github.com/FortAwesome/Font-Awesome/releases) - [Changelog](https://github.com/FortAwesome/Font-Awesome/blob/6.x/CHANGELOG.md) - [Commits](https://github.com/FortAwesome/Font-Awesome/compare/6.5.2...6.6.0) --- updated-dependencies: - dependency-name: "@fortawesome/fontawesome-free" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 9 ++++----- package.json | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6e6422a140..f46fbd813f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -96,7 +96,7 @@ "@angular/compiler-cli": "^17.3.11", "@angular/language-service": "^17.3.12", "@cypress/schematic": "^1.5.0", - "@fortawesome/fontawesome-free": "^6.4.0", + "@fortawesome/fontawesome-free": "^6.6.0", "@ngrx/store-devtools": "^17.1.1", "@ngtools/webpack": "^16.2.12", "@types/deep-freeze": "0.1.2", @@ -4932,11 +4932,10 @@ } }, "node_modules/@fortawesome/fontawesome-free": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.5.2.tgz", - "integrity": "sha512-hRILoInAx8GNT5IMkrtIt9blOdrqHOnPBH+k70aWUAqPZPgopb9G5EQJFpaBx/S8zp2fC+mPW349Bziuk1o28Q==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.6.0.tgz", + "integrity": "sha512-60G28ke/sXdtS9KZCpZSHHkCbdsOGEhIUGlwq6yhY74UpTiToIh8np7A8yphhM4BWsvNFtIvLpi4co+h9Mr9Ow==", "dev": true, - "hasInstallScript": true, "engines": { "node": ">=6" } diff --git a/package.json b/package.json index 0834316052..9e0b579ad1 100644 --- a/package.json +++ b/package.json @@ -183,7 +183,7 @@ "@angular/compiler-cli": "^17.3.11", "@angular/language-service": "^17.3.12", "@cypress/schematic": "^1.5.0", - "@fortawesome/fontawesome-free": "^6.4.0", + "@fortawesome/fontawesome-free": "^6.6.0", "@ngrx/store-devtools": "^17.1.1", "@ngtools/webpack": "^16.2.12", "@types/deep-freeze": "0.1.2", From a8115b7201ad41765a9a1795c3241fe16c946b7a Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 16 Oct 2024 13:37:32 -0500 Subject: [PATCH 0612/1286] Move ng-mocks to dev dependencies. It's only for testing --- package-lock.json | 3 ++- package.json | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 60ffa84a93..7740e49e6b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -66,7 +66,6 @@ "mirador-dl-plugin": "^0.13.0", "mirador-share-plugin": "^0.11.0", "morgan": "^1.10.0", - "ng-mocks": "^14.13.1", "ng2-file-upload": "5.0.0", "ng2-nouislider": "^2.0.0", "ngx-infinite-scroll": "^16.0.0", @@ -140,6 +139,7 @@ "karma-jasmine": "~4.0.0", "karma-jasmine-html-reporter": "^1.5.0", "karma-mocha-reporter": "2.2.5", + "ng-mocks": "^14.13.1", "ngx-mask": "14.2.4", "nodemon": "^2.0.22", "postcss": "^8.4", @@ -16720,6 +16720,7 @@ "version": "14.13.1", "resolved": "https://registry.npmjs.org/ng-mocks/-/ng-mocks-14.13.1.tgz", "integrity": "sha512-eyfnjXeC108SqVD09i/cBwCpKkK0JjBoAg8jp7oQS2HS081K3WJTttFpgLGeLDYKmZsZ6nYpI+HHNQ3OksaJ7A==", + "dev": true, "funding": { "url": "https://github.com/sponsors/help-me-mom" }, diff --git a/package.json b/package.json index 6c55eafd00..9e8562f383 100644 --- a/package.json +++ b/package.json @@ -153,7 +153,6 @@ "mirador-dl-plugin": "^0.13.0", "mirador-share-plugin": "^0.11.0", "morgan": "^1.10.0", - "ng-mocks": "^14.13.1", "ng2-file-upload": "5.0.0", "ng2-nouislider": "^2.0.0", "ngx-infinite-scroll": "^16.0.0", @@ -227,6 +226,7 @@ "karma-jasmine": "~4.0.0", "karma-jasmine-html-reporter": "^1.5.0", "karma-mocha-reporter": "2.2.5", + "ng-mocks": "^14.13.1", "ngx-mask": "14.2.4", "nodemon": "^2.0.22", "postcss": "^8.4", From 8c88f7052a65bbabde3a19223e967feddb186008 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 16 Oct 2024 14:15:11 -0500 Subject: [PATCH 0613/1286] Wait on viewevent to trigger before checking Collection Page in e2e tests. This ensures Collection page is fully loaded because viewevent triggers upon loading. --- cypress/e2e/collection-page.cy.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cypress/e2e/collection-page.cy.ts b/cypress/e2e/collection-page.cy.ts index d12536d332..373da07888 100644 --- a/cypress/e2e/collection-page.cy.ts +++ b/cypress/e2e/collection-page.cy.ts @@ -3,8 +3,15 @@ import { testA11y } from 'cypress/support/utils'; describe('Collection Page', () => { it('should pass accessibility tests', () => { + cy.intercept('POST', '/server/api/statistics/viewevents').as('viewevent'); + + // Visit Collections page cy.visit('/collections/'.concat(Cypress.env('DSPACE_TEST_COLLECTION'))); + // Wait for the "viewevent" to trigger on the Collection page. + // This ensures our tag is fully loaded, as the tag is contained within it. + cy.wait('@viewevent'); + // tag must be loaded cy.get('ds-collection-page').should('be.visible'); From dfe2d4580ebcd305080a67cd44283286b5dda0ec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 16 Oct 2024 21:43:58 +0000 Subject: [PATCH 0614/1286] Bump nouislider from 15.7.1 to 15.8.1 Bumps [nouislider](https://github.com/leongersen/noUiSlider) from 15.7.1 to 15.8.1. - [Release notes](https://github.com/leongersen/noUiSlider/releases) - [Changelog](https://github.com/leongersen/noUiSlider/blob/master/CHANGELOG.MD) - [Commits](https://github.com/leongersen/noUiSlider/compare/15.7.1...15.8.1) --- updated-dependencies: - dependency-name: nouislider dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index cb8456501a..ba2dbd1c62 100644 --- a/package.json +++ b/package.json @@ -122,7 +122,7 @@ "ngx-pagination": "6.0.3", "ngx-sortablejs": "^11.1.0", "ngx-ui-switch": "^14.1.0", - "nouislider": "^15.7.1", + "nouislider": "^15.8.1", "pem": "1.14.7", "prop-types": "^15.8.1", "react-copy-to-clipboard": "^5.1.0", diff --git a/yarn.lock b/yarn.lock index 26f50cb912..b584dd5181 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8644,10 +8644,10 @@ normalize-url@^4.5.0: resolved "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz" integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== -nouislider@^15.7.1: - version "15.7.1" - resolved "https://registry.yarnpkg.com/nouislider/-/nouislider-15.7.1.tgz#77d55e47d9b4cd771728515713df43b489db9705" - integrity sha512-5N7C1ru/i8y3dg9+Z6ilj6+m1EfabvOoaRa7ztpxBSKKRZso4vA52DGSbBJjw5XLtFr/LZ9SgGAXqyVtlVHO5w== +nouislider@^15.8.1: + version "15.8.1" + resolved "https://registry.yarnpkg.com/nouislider/-/nouislider-15.8.1.tgz#18729ed29738d2d328a1b5e0429d38eb8be8a696" + integrity sha512-93TweAi8kqntHJSPiSWQ1o/uZ29VWOmal9YKb6KKGGlCkugaNfAupT7o1qTHqdJvNQ7S0su5rO6qRFCjP8fxtw== npm-bundled@^3.0.0: version "3.0.0" From a74cd848feeabe380026f504f0e70f6de134fd65 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 16 Oct 2024 16:33:20 -0500 Subject: [PATCH 0615/1286] Add basic e2e testing for i18n --- cypress/e2e/header.cy.ts | 25 +++++++++++++++++++ .../lang-switch/lang-switch.component.html | 1 + 2 files changed, 26 insertions(+) diff --git a/cypress/e2e/header.cy.ts b/cypress/e2e/header.cy.ts index 043d67dd2b..1471e5ae6c 100644 --- a/cypress/e2e/header.cy.ts +++ b/cypress/e2e/header.cy.ts @@ -10,4 +10,29 @@ describe('Header', () => { // Analyze for accessibility testA11y('ds-header'); }); + + it('should allow for changing language to German (for example)', () => { + cy.visit('/'); + + // Click the language switcher (globe) in header + cy.get('a[data-test="lang-switch"]').click(); + // Click on the "Deusch" language in dropdown + cy.get('#language-menu-list li').contains('Deutsch').click(); + + // HTML "lang" attribute should switch to "de" + cy.get('html').invoke('attr', 'lang').should('eq', 'de'); + + // Login menu should now be in German + cy.get('a[data-test="login-menu"]').contains('Anmelden'); + + // Change back to English from language switcher + cy.get('a[data-test="lang-switch"]').click(); + cy.get('#language-menu-list li').contains('English').click(); + + // HTML "lang" attribute should switch to "en" + cy.get('html').invoke('attr', 'lang').should('eq', 'en'); + + // Login menu should now be in English + cy.get('a[data-test="login-menu"]').contains('Log In'); + }); }); diff --git a/src/app/shared/lang-switch/lang-switch.component.html b/src/app/shared/lang-switch/lang-switch.component.html index 9be622099b..6d1727cfe7 100644 --- a/src/app/shared/lang-switch/lang-switch.component.html +++ b/src/app/shared/lang-switch/lang-switch.component.html @@ -5,6 +5,7 @@ aria-haspopup="menu" [title]="'nav.language' | translate" (click)="$event.preventDefault()" data-toggle="dropdown" ngbDropdownToggle + data-test="lang-switch" tabindex="0"> From ad8dd8b648d3cdbb3d3ce61f652051ce3d6c4a3e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 16 Oct 2024 21:45:45 +0000 Subject: [PATCH 0616/1286] Bump core-js from 3.30.1 to 3.38.1 Bumps [core-js](https://github.com/zloirock/core-js/tree/HEAD/packages/core-js) from 3.30.1 to 3.38.1. - [Release notes](https://github.com/zloirock/core-js/releases) - [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md) - [Commits](https://github.com/zloirock/core-js/commits/v3.38.1/packages/core-js) --- updated-dependencies: - dependency-name: core-js dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index cb8456501a..1a866c2909 100644 --- a/package.json +++ b/package.json @@ -89,7 +89,7 @@ "colors": "^1.4.0", "compression": "^1.7.4", "cookie-parser": "1.4.7", - "core-js": "^3.30.1", + "core-js": "^3.38.1", "date-fns": "^2.29.3", "date-fns-tz": "^1.3.7", "deepmerge": "^4.3.1", diff --git a/yarn.lock b/yarn.lock index 26f50cb912..c12d67a67f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4413,10 +4413,10 @@ core-js-compat@^3.25.1: dependencies: browserslist "^4.21.5" -core-js@^3.30.1: - version "3.30.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.30.1.tgz#fc9c5adcc541d8e9fa3e381179433cbf795628ba" - integrity sha512-ZNS5nbiSwDTq4hFosEDqm65izl2CWmLz0hARJMyNQBgkUZMIF51cQiMvIQKA6hvuaeWxQDP3hEedM1JZIgTldQ== +core-js@^3.38.1: + version "3.38.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.38.1.tgz#aa375b79a286a670388a1a363363d53677c0383e" + integrity sha512-OP35aUorbU3Zvlx7pjsFdu1rGNnD4pgw/CWoYzRY3t2EzoVT7shKHY1dlAy3f41cGIO7ZDPQimhGFTlEYkG/Hw== core-util-is@1.0.2: version "1.0.2" From e181e854cc6d911021500fac7c8321592077a212 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 16 Oct 2024 21:47:00 +0000 Subject: [PATCH 0617/1286] Bump @types/node from 14.18.42 to 14.18.63 Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 14.18.42 to 14.18.63. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) --- updated-dependencies: - dependency-name: "@types/node" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index cb8456501a..8418678f90 100644 --- a/package.json +++ b/package.json @@ -156,7 +156,7 @@ "@types/jasmine": "~3.6.0", "@types/js-cookie": "2.2.6", "@types/lodash": "^4.14.194", - "@types/node": "^14.14.9", + "@types/node": "^14.18.63", "@types/sanitize-html": "^2.9.0", "@typescript-eslint/eslint-plugin": "^5.59.1", "@typescript-eslint/parser": "^5.59.1", diff --git a/yarn.lock b/yarn.lock index 26f50cb912..0883a4816f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2593,10 +2593,10 @@ resolved "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz" integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA== -"@types/node@*", "@types/node@>=10.0.0", "@types/node@^14.14.9": - version "14.18.42" - resolved "https://registry.npmjs.org/@types/node/-/node-14.18.42.tgz" - integrity sha512-xefu+RBie4xWlK8hwAzGh3npDz/4VhF6icY/shU+zv/1fNn+ZVG7T7CRwe9LId9sAYRPxI+59QBPuKL3WpyGRg== +"@types/node@*", "@types/node@>=10.0.0", "@types/node@^14.18.63": + version "14.18.63" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.63.tgz#1788fa8da838dbb5f9ea994b834278205db6ca2b" + integrity sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ== "@types/parse-json@^4.0.0": version "4.0.0" From d674bcc3908c4cf8469853778fc167295320a51c Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Mon, 16 Sep 2024 15:47:42 +0200 Subject: [PATCH 0618/1286] 118220: Integrate live-region component into item-edit-bitsream page --- .../item-edit-bitstream-bundle.component.html | 2 +- .../item-edit-bitstream-bundle.component.ts | 21 ++++++++++++------- src/assets/i18n/en.json5 | 4 ++++ 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html index 0338055df5..d530fb38d1 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html @@ -68,7 +68,7 @@
diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts index bd99fc1a09..24319f4a83 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts @@ -30,6 +30,8 @@ import { RequestService } from '../../../../core/data/request.service'; import { ItemBitstreamsService } from '../item-bitstreams.service'; import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop'; import { hasValue } from '../../../../shared/empty.util'; +import { LiveRegionService } from '../../../../shared/live-region/live-region.service'; +import { TranslateService } from '@ngx-translate/core'; /** * Interface storing all the information necessary to create a row in the bitstream edit table @@ -166,11 +168,6 @@ export class ItemEditBitstreamBundleComponent implements OnInit { */ pageSize$: BehaviorSubject; - /** - * Whether the table has multiple pages - */ - hasMultiplePages = false; - /** * The self url of the bundle, also used when retrieving fieldUpdates */ @@ -190,6 +187,8 @@ export class ItemEditBitstreamBundleComponent implements OnInit { protected paginationService: PaginationService, protected requestService: RequestService, protected itemBitstreamsService: ItemBitstreamsService, + protected liveRegionService: LiveRegionService, + protected translateService: TranslateService, ) { } @@ -301,7 +300,7 @@ export class ItemEditBitstreamBundleComponent implements OnInit { this.paginationComponent.doPageSizeChange(pageSize); } - dragStart() { + dragStart(bitstreamName: string) { // Only open the drag tooltip when there are multiple pages this.paginationComponent.shouldShowBottomPager.pipe( take(1), @@ -309,10 +308,18 @@ export class ItemEditBitstreamBundleComponent implements OnInit { ).subscribe(() => { this.dragTooltip.open(); }); + + const message = this.translateService.instant('item.edit.bitstreams.edit.live.drag', + { bitstream: bitstreamName }); + this.liveRegionService.addMessage(message); } - dragEnd() { + dragEnd(bitstreamName: string) { this.dragTooltip.close(); + + const message = this.translateService.instant('item.edit.bitstreams.edit.live.drop', + { bitstream: bitstreamName }); + this.liveRegionService.addMessage(message); } diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index f2dbf9b2d1..48fd581bdf 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1950,6 +1950,10 @@ "item.edit.bitstreams.edit.buttons.undo": "Undo changes", + "item.edit.bitstreams.edit.live.drag": "{{ bitstream }} grabbed", + + "item.edit.bitstreams.edit.live.drop": "{{ bitstream }} dropped", + "item.edit.bitstreams.empty": "This item doesn't contain any bitstreams. Click the upload button to create one.", "item.edit.bitstreams.headers.actions": "Actions", From 1f909dc6ea0d84859fbeef690c9bd212417c7a99 Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Tue, 17 Sep 2024 13:34:08 +0200 Subject: [PATCH 0619/1286] 118223: Add instructive alert to item-bitstreams edit page --- .../item-bitstreams/item-bitstreams.component.html | 7 ++++++- .../item-bitstreams/item-bitstreams.component.ts | 4 ++++ src/assets/i18n/en.json5 | 2 ++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html index 3527f2f5b8..1c13154bfa 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html @@ -1,4 +1,8 @@
+
+ +
+
Date: Wed, 18 Sep 2024 11:57:41 +0200 Subject: [PATCH 0620/1286] 118223: Implement bitstream reordering with keyboard --- .../item-bitstreams.component.html | 1 - .../item-bitstreams.component.spec.ts | 43 +- .../item-bitstreams.component.ts | 87 ++-- .../item-bitstreams.service.spec.ts | 19 + .../item-bitstreams.service.ts | 303 ++++++++++++- .../item-edit-bitstream-bundle.component.html | 33 +- ...em-edit-bitstream-bundle.component.spec.ts | 1 + .../item-edit-bitstream-bundle.component.ts | 405 ++++++++++++------ .../live-region/live-region.service.stub.ts | 30 ++ src/assets/i18n/en.json5 | 8 +- 10 files changed, 727 insertions(+), 203 deletions(-) create mode 100644 src/app/shared/live-region/live-region.service.stub.ts diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html index 1c13154bfa..b9af2a7d18 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html @@ -33,7 +33,6 @@ [item]="item" [columnSizes]="columnSizes" [isFirstTable]="isFirst" - (dropObject)="dropBitstream(bundle, $event)" aria-describedby="reorder-description">
diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.spec.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.spec.ts index 6ce7394473..a5549a6ba0 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.spec.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.spec.ts @@ -25,6 +25,10 @@ import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } f import { createPaginatedList } from '../../../shared/testing/utils.test'; import { FieldChangeType } from '../../../core/data/object-updates/field-change-type.model'; import { BitstreamDataServiceStub } from '../../../shared/testing/bitstream-data-service.stub'; +import { ItemBitstreamsService } from './item-bitstreams.service'; +import { ResponsiveTableSizes } from '../../../shared/responsive-table-sizes/responsive-table-sizes'; +import { ResponsiveColumnSizes } from '../../../shared/responsive-table-sizes/responsive-column-sizes'; +import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; let comp: ItemBitstreamsComponent; let fixture: ComponentFixture; @@ -76,6 +80,7 @@ let objectCache: ObjectCacheService; let requestService: RequestService; let searchConfig: SearchConfigurationService; let bundleService: BundleDataService; +let itemBitstreamsService: ItemBitstreamsService; describe('ItemBitstreamsComponent', () => { beforeEach(waitForAsync(() => { @@ -147,6 +152,19 @@ describe('ItemBitstreamsComponent', () => { patch: createSuccessfulRemoteDataObject$({}), }); + itemBitstreamsService = jasmine.createSpyObj('itemBitstreamsService', { + getColumnSizes: new ResponsiveTableSizes([ + new ResponsiveColumnSizes(2, 2, 3, 4, 4), + new ResponsiveColumnSizes(2, 3, 3, 3, 3), + new ResponsiveColumnSizes(2, 2, 2, 2, 2), + new ResponsiveColumnSizes(6, 5, 4, 3, 3) + ]), + getSelectedBitstream$: observableOf({}), + getInitialBundlesPaginationOptions: new PaginationComponentOptions(), + removeMarkedBitstreams: createSuccessfulRemoteDataObject$({}), + displayNotifications: undefined, + }); + TestBed.configureTestingModule({ imports: [TranslateModule.forRoot()], declarations: [ItemBitstreamsComponent, ObjectValuesPipe, VarDirective], @@ -161,6 +179,7 @@ describe('ItemBitstreamsComponent', () => { { provide: RequestService, useValue: requestService }, { provide: SearchConfigurationService, useValue: searchConfig }, { provide: BundleDataService, useValue: bundleService }, + { provide: ItemBitstreamsService, useValue: itemBitstreamsService }, ChangeDetectorRef ], schemas: [ NO_ERRORS_SCHEMA @@ -181,28 +200,8 @@ describe('ItemBitstreamsComponent', () => { comp.submit(); }); - it('should call removeMultiple on the bitstreamService for the marked field', () => { - expect(bitstreamService.removeMultiple).toHaveBeenCalledWith([bitstream2]); - }); - - it('should not call removeMultiple on the bitstreamService for the unmarked field', () => { - expect(bitstreamService.removeMultiple).not.toHaveBeenCalledWith([bitstream1]); - }); - }); - - describe('when dropBitstream is called', () => { - beforeEach((done) => { - comp.dropBitstream(bundle, { - fromIndex: 0, - toIndex: 50, - finish: () => { - done(); - } - }); - }); - - it('should send out a patch for the move operation', () => { - expect(bundleService.patch).toHaveBeenCalled(); + it('should call removeMarkedBitstreams on the itemBitstreamsService', () => { + expect(itemBitstreamsService.removeMarkedBitstreams).toHaveBeenCalled(); }); }); diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts index 7757170f4e..4ced3dd649 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectorRef, Component, NgZone, OnDestroy } from '@angular/core'; +import { ChangeDetectorRef, Component, NgZone, OnDestroy, HostListener } from '@angular/core'; import { AbstractItemUpdateComponent } from '../abstract-item-update/abstract-item-update.component'; import { map, switchMap, take } from 'rxjs/operators'; import { Observable, Subscription, zip as observableZip } from 'rxjs'; @@ -8,13 +8,11 @@ import { ActivatedRoute, Router } from '@angular/router'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; import { BitstreamDataService } from '../../../core/data/bitstream-data.service'; -import { hasValue } from '../../../shared/empty.util'; import { ObjectCacheService } from '../../../core/cache/object-cache.service'; import { RequestService } from '../../../core/data/request.service'; import { getFirstSucceededRemoteData, getRemoteDataPayload, - getFirstCompletedRemoteData } from '../../../core/shared/operators'; import { RemoteData } from '../../../core/data/remote-data'; import { PaginatedList } from '../../../core/data/paginated-list.model'; @@ -23,7 +21,6 @@ import { BundleDataService } from '../../../core/data/bundle-data.service'; import { PaginatedSearchOptions } from '../../../shared/search/models/paginated-search-options.model'; import { ResponsiveTableSizes } from '../../../shared/responsive-table-sizes/responsive-table-sizes'; import { NoContent } from '../../../core/shared/NoContent.model'; -import { Operation } from 'fast-json-patch'; import { ItemBitstreamsService } from './item-bitstreams.service'; import { AlertType } from '../../../shared/alert/aletr-type'; @@ -88,13 +85,63 @@ export class ItemBitstreamsComponent extends AbstractItemUpdateComponent impleme postItemInit(): void { const bundlesOptions = this.itemBitstreamsService.getInitialBundlesPaginationOptions(); - this. bundles$ = this.itemService.getBundles(this.item.id, new PaginatedSearchOptions({pagination: bundlesOptions})).pipe( + this.bundles$ = this.itemService.getBundles(this.item.id, new PaginatedSearchOptions({pagination: bundlesOptions})).pipe( getFirstSucceededRemoteData(), getRemoteDataPayload(), map((bundlePage: PaginatedList) => bundlePage.page) ); } + /** + * Handles keyboard events that should move the currently selected bitstream up + */ + @HostListener('document:keydown.arrowUp', ['$event']) + moveUp(event: KeyboardEvent) { + if (this.itemBitstreamsService.hasSelectedBitstream()) { + event.preventDefault(); + this.itemBitstreamsService.moveSelectedBitstreamUp(); + } + } + + /** + * Handles keyboard events that should move the currently selected bitstream down + */ + @HostListener('document:keydown.arrowDown', ['$event']) + moveDown(event: KeyboardEvent) { + if (this.itemBitstreamsService.hasSelectedBitstream()) { + event.preventDefault(); + this.itemBitstreamsService.moveSelectedBitstreamDown(); + } + } + + /** + * Handles keyboard events that should cancel the currently selected bitstream. + * A cancel means that the selected bitstream is returned to its original position and is no longer selected. + * @param event + */ + @HostListener('document:keyup.escape', ['$event']) + cancelSelection(event: KeyboardEvent) { + if (this.itemBitstreamsService.hasSelectedBitstream()) { + event.preventDefault(); + this.itemBitstreamsService.cancelSelection(); + } + } + + /** + * Handles keyboard events that should clear the currently selected bitstream. + * A clear means that the selected bitstream remains in its current position but is no longer selected. + */ + @HostListener('document:keydown.enter', ['$event']) + @HostListener('document:keydown.space', ['$event']) + clearSelection(event: KeyboardEvent) { + // Only when no specific element is in focus do we want to clear the currently selected bitstream + // Otherwise we might clear the selection when a different action was intended, e.g. clicking a button or selecting + // a different bitstream. + if (event.target instanceof Element && event.target.tagName === 'BODY') { + this.itemBitstreamsService.clearSelection(); + } + } + /** * Initialize the notification messages prefix */ @@ -120,36 +167,6 @@ export class ItemBitstreamsComponent extends AbstractItemUpdateComponent impleme }); } - /** - * A bitstream was dropped in a new location. Send out a Move Patch request to the REST API, display notifications, - * refresh the bundle's cache (so the lists can properly reload) and call the event's callback function (which will - * navigate the user to the correct page) - * @param bundle The bundle to send patch requests to - * @param event The event containing the index the bitstream came from and was dropped to - */ - dropBitstream(bundle: Bundle, event: any) { - this.zone.runOutsideAngular(() => { - if (hasValue(event) && hasValue(event.fromIndex) && hasValue(event.toIndex) && hasValue(event.finish)) { - const moveOperation = { - op: 'move', - from: `/_links/bitstreams/${event.fromIndex}/href`, - path: `/_links/bitstreams/${event.toIndex}/href` - } as Operation; - this.bundleService.patch(bundle, [moveOperation]).pipe( - getFirstCompletedRemoteData(), - ).subscribe((response: RemoteData) => { - this.zone.run(() => { - this.itemBitstreamsService.displayNotifications('item.edit.bitstreams.notifications.move', [response]); - // Remove all cached requests from this bundle and call the event's callback when the requests are cleared - this.requestService.setStaleByHrefSubstring(bundle.self).pipe( - take(1) - ).subscribe(() => event.finish()); - }); - }); - } - }); - } - /** * Request the object updates service to discard all current changes to this item * Shows a notification to remind the user that they can undo this diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.spec.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.spec.ts index 89ecfb518f..e144e81ec7 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.spec.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.spec.ts @@ -16,6 +16,12 @@ import { createFailedRemoteDataObject, createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils'; +import { BundleDataService } from '../../../core/data/bundle-data.service'; +import { RequestService } from '../../../core/data/request.service'; +import { LiveRegionService } from '../../../shared/live-region/live-region.service'; +import { Bundle } from '../../../core/shared/bundle.model'; +import { of } from 'rxjs'; +import { getLiveRegionServiceStub } from '../../../shared/live-region/live-region.service.stub'; describe('ItemBitstreamsService', () => { let service: ItemBitstreamsService; @@ -23,21 +29,34 @@ describe('ItemBitstreamsService', () => { let translateService: TranslateService; let objectUpdatesService: ObjectUpdatesService; let bitstreamDataService: BitstreamDataService; + let bundleDataService: BundleDataService; let dsoNameService: DSONameService; + let requestService: RequestService; + let liveRegionService: LiveRegionService; beforeEach(() => { notificationsService = new NotificationsServiceStub() as any; translateService = getMockTranslateService(); objectUpdatesService = new ObjectUpdatesServiceStub() as any; bitstreamDataService = new BitstreamDataServiceStub() as any; + bundleDataService = jasmine.createSpyObj('bundleDataService', { + patch: createSuccessfulRemoteDataObject$(new Bundle()), + }); dsoNameService = new DSONameServiceMock() as any; + requestService = jasmine.createSpyObj('requestService', { + setStaleByHrefSubstring: of(true), + }); + liveRegionService = getLiveRegionServiceStub(); service = new ItemBitstreamsService( notificationsService, translateService, objectUpdatesService, bitstreamDataService, + bundleDataService, dsoNameService, + requestService, + liveRegionService, ); }); diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.ts index 487df77b28..21dc415198 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.ts @@ -3,38 +3,277 @@ import { PaginationComponentOptions } from '../../../shared/pagination/paginatio import { ResponsiveTableSizes } from '../../../shared/responsive-table-sizes/responsive-table-sizes'; import { ResponsiveColumnSizes } from '../../../shared/responsive-table-sizes/responsive-column-sizes'; import { RemoteData } from '../../../core/data/remote-data'; -import { isNotEmpty, hasValue } from '../../../shared/empty.util'; +import { isNotEmpty, hasValue, hasNoValue } from '../../../shared/empty.util'; import { Bundle } from '../../../core/shared/bundle.model'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; -import { Observable, zip as observableZip } from 'rxjs'; +import { Observable, zip as observableZip, BehaviorSubject } from 'rxjs'; import { NoContent } from '../../../core/shared/NoContent.model'; -import { take, switchMap, map } from 'rxjs/operators'; +import { take, switchMap, map, tap } from 'rxjs/operators'; import { FieldUpdates } from '../../../core/data/object-updates/field-updates.model'; import { FieldUpdate } from '../../../core/data/object-updates/field-update.model'; import { FieldChangeType } from '../../../core/data/object-updates/field-change-type.model'; import { Bitstream } from '../../../core/shared/bitstream.model'; import { ObjectUpdatesService } from '../../../core/data/object-updates/object-updates.service'; import { BitstreamDataService } from '../../../core/data/bitstream-data.service'; -import { BitstreamTableEntry } from './item-edit-bitstream-bundle/item-edit-bitstream-bundle.component'; -import { getFirstSucceededRemoteDataPayload } from '../../../core/shared/operators'; +import { getFirstSucceededRemoteDataPayload, getFirstCompletedRemoteData } from '../../../core/shared/operators'; import { getBitstreamDownloadRoute } from '../../../app-routing-paths'; import { DSONameService } from '../../../core/breadcrumbs/dso-name.service'; +import { BitstreamFormat } from '../../../core/shared/bitstream-format.model'; +import { MoveOperation } from 'fast-json-patch'; +import { BundleDataService } from '../../../core/data/bundle-data.service'; +import { RequestService } from '../../../core/data/request.service'; +import { LiveRegionService } from '../../../shared/live-region/live-region.service'; +/** + * Interface storing all the information necessary to create a row in the bitstream edit table + */ +export interface BitstreamTableEntry { + /** + * The bitstream + */ + bitstream: Bitstream, + /** + * The uuid of the Bitstream + */ + id: string, + /** + * The name of the Bitstream + */ + name: string, + /** + * The name of the Bitstream with all whitespace removed + */ + nameStripped: string, + /** + * The description of the Bitstream + */ + description: string, + /** + * Observable emitting the Format of the Bitstream + */ + format: Observable, + /** + * The download url of the Bitstream + */ + downloadUrl: string, +} + +/** + * Interface storing information necessary to highlight and reorder the selected bitstream entry + */ +export interface SelectedBitstreamTableEntry { + /** + * The selected entry + */ + bitstream: BitstreamTableEntry, + /** + * The bundle the bitstream belongs to + */ + bundle: Bundle, + /** + * The total number of bitstreams in the bundle + */ + bundleSize: number, + /** + * The original position of the bitstream within the bundle. + */ + originalPosition: number, + /** + * The current position of the bitstream within the bundle. + */ + currentPosition: number, +} + +/** + * This service handles the selection and updating of the bitstreams and their order on the + * 'Edit Item' -> 'Bitstreams' page. + */ @Injectable( { providedIn: 'root' }, ) export class ItemBitstreamsService { + /** + * BehaviorSubject which emits every time the selected bitstream changes. + */ + protected selectedBitstream$: BehaviorSubject = new BehaviorSubject(null); + + protected isPerformingMoveRequest = false; + constructor( protected notificationsService: NotificationsService, protected translateService: TranslateService, protected objectUpdatesService: ObjectUpdatesService, protected bitstreamService: BitstreamDataService, + protected bundleService: BundleDataService, protected dsoNameService: DSONameService, + protected requestService: RequestService, + protected liveRegionService: LiveRegionService, ) { } + /** + * Returns the observable emitting the currently selected bitstream + */ + getSelectedBitstream$(): Observable { + return this.selectedBitstream$; + } + + /** + * Returns a copy of the currently selected bitstream + */ + getSelectedBitstream(): SelectedBitstreamTableEntry { + const selected = this.selectedBitstream$.getValue(); + + if (hasNoValue(selected)) { + return selected; + } + + return Object.assign({}, selected); + } + + hasSelectedBitstream(): boolean { + return hasValue(this.getSelectedBitstream()); + } + + /** + * Select the provided entry + */ + selectBitstreamEntry(entry: SelectedBitstreamTableEntry) { + if (entry !== this.selectedBitstream$.getValue()) { + this.announceSelect(entry.bitstream.name); + this.updateSelectedBitstream(entry); + } + } + + /** + * Makes the {@link selectedBitstream$} observable emit the provided {@link SelectedBitstreamTableEntry}. + * @protected + */ + protected updateSelectedBitstream(entry: SelectedBitstreamTableEntry) { + this.selectedBitstream$.next(entry); + } + + /** + * Unselects the selected bitstream. Does nothing if no bitstream is selected. + */ + clearSelection() { + const selected = this.getSelectedBitstream(); + + if (hasValue(selected)) { + this.updateSelectedBitstream(null); + this.announceClear(selected.bitstream.name); + } + } + + /** + * Returns the currently selected bitstream to its original position and unselects the bitstream. + * Does nothing if no bitstream is selected. + */ + cancelSelection() { + const selected = this.getSelectedBitstream(); + + if (hasNoValue(selected) || this.isPerformingMoveRequest) { + return; + } + + this.selectedBitstream$.next(null); + + const originalPosition = selected.originalPosition; + const currentPosition = selected.currentPosition; + + // If the selected bitstream has not moved, there is no need to return it to its original position + if (currentPosition === originalPosition) { + this.announceClear(selected.bitstream.name); + } else { + this.announceCancel(selected.bitstream.name, originalPosition); + this.performBitstreamMoveRequest(selected.bundle, currentPosition, originalPosition); + } + } + + /** + * Moves the selected bitstream one position up in the bundle. Does nothing if no bitstream is selected or the + * selected bitstream already is at the beginning of the bundle. + */ + moveSelectedBitstreamUp() { + const selected = this.getSelectedBitstream(); + + if (hasNoValue(selected) || this.isPerformingMoveRequest) { + return; + } + + const originalPosition = selected.currentPosition; + if (originalPosition > 0) { + const newPosition = originalPosition - 1; + selected.currentPosition = newPosition; + + const onRequestCompleted = () => { + this.announceMove(selected.bitstream.name, newPosition); + }; + + this.performBitstreamMoveRequest(selected.bundle, originalPosition, newPosition, onRequestCompleted); + this.updateSelectedBitstream(selected); + } + } + + /** + * Moves the selected bitstream one position down in the bundle. Does nothing if no bitstream is selected or the + * selected bitstream already is at the end of the bundle. + */ + moveSelectedBitstreamDown() { + const selected = this.getSelectedBitstream(); + + if (hasNoValue(selected) || this.isPerformingMoveRequest) { + return; + } + + const originalPosition = selected.currentPosition; + if (originalPosition < selected.bundleSize - 1) { + const newPosition = originalPosition + 1; + selected.currentPosition = newPosition; + + const onRequestCompleted = () => { + this.announceMove(selected.bitstream.name, newPosition); + }; + + this.performBitstreamMoveRequest(selected.bundle, originalPosition, newPosition, onRequestCompleted); + this.updateSelectedBitstream(selected); + } + } + + /** + * Sends out a Move Patch request to the REST API, display notifications, + * refresh the bundle's cache (so the lists can properly reload) + * @param bundle The bundle to send patch requests to + * @param fromIndex The index to move from + * @param toIndex The index to move to + * @param finish Optional: Function to execute once the response has been received + */ + performBitstreamMoveRequest(bundle: Bundle, fromIndex: number, toIndex: number, finish?: () => void) { + if (this.isPerformingMoveRequest) { + console.warn('Attempted to perform move request while previous request has not completed yet'); + return; + } + + const moveOperation: MoveOperation = { + op: 'move', + from: `/_links/bitstreams/${fromIndex}/href`, + path: `/_links/bitstreams/${toIndex}/href`, + }; + + this.isPerformingMoveRequest = true; + this.bundleService.patch(bundle, [moveOperation]).pipe( + getFirstCompletedRemoteData(), + tap((response: RemoteData) => this.displayNotifications('item.edit.bitstreams.notifications.move', [response])), + switchMap(() => this.requestService.setStaleByHrefSubstring(bundle.self)), + take(1), + ).subscribe(() => { + this.isPerformingMoveRequest = false; + finish?.(); + }); + } + /** * Returns the pagination options to use when fetching the bundles */ @@ -46,6 +285,10 @@ export class ItemBitstreamsService { }); } + /** + * Returns the initial pagination options to use when fetching the bitstreams + * @param bundleName The name of the bundle, will be as pagination id. + */ getInitialBitstreamsPaginationOptions(bundleName: string): PaginationComponentOptions { return Object.assign(new PaginationComponentOptions(),{ id: bundleName, // This might behave unexpectedly if the item contains two bundles with the same name @@ -118,6 +361,10 @@ export class ItemBitstreamsService { ); } + /** + * Creates an array of {@link BitstreamTableEntry}s from an array of {@link Bitstream}s + * @param bitstreams The bitstreams array to map to table entries + */ mapBitstreamsToTableEntries(bitstreams: Bitstream[]): BitstreamTableEntry[] { return bitstreams.map((bitstream) => { const name = this.dsoNameService.getName(bitstream); @@ -143,7 +390,7 @@ export class ItemBitstreamsService { // To make it clear which headers are relevant for a specific field in the table, the 'headers' attribute is used to // refer to specific headers. The Bitstream's name is used as header ID for the row containing information regarding // that bitstream. As the 'headers' attribute contains a space-separated string of header IDs, the Bitstream's header - // ID can not contain strings itself. + // ID can not contain spaces itself. return this.stripWhiteSpace(name); } @@ -155,4 +402,48 @@ export class ItemBitstreamsService { // '/\s+/g' matches all occurrences of any amount of whitespace characters return str.replace(/\s+/g, ''); } + + /** + * Adds a message to the live region mentioning that the bitstream with the provided name was selected. + * @param bitstreamName The name of the bitstream that was selected. + */ + announceSelect(bitstreamName: string) { + const message = this.translateService.instant('item.edit.bitstreams.edit.live.select', + { bitstream: bitstreamName }); + this.liveRegionService.addMessage(message); + } + + /** + * Adds a message to the live region mentioning that the bitstream with the provided name was moved to the provided + * position. + * @param bitstreamName The name of the bitstream that moved. + * @param toPosition The zero-indexed position that the bitstream moved to. + */ + announceMove(bitstreamName: string, toPosition: number) { + const message = this.translateService.instant('item.edit.bitstreams.edit.live.move', + { bitstream: bitstreamName, toIndex: toPosition + 1 }); + this.liveRegionService.addMessage(message); + } + + /** + * Adds a message to the live region mentioning that the bitstream with the provided name is no longer selected and + * was returned to the provided position. + * @param bitstreamName The name of the bitstream that is no longer selected + * @param toPosition The zero-indexed position the bitstream returned to. + */ + announceCancel(bitstreamName: string, toPosition: number) { + const message = this.translateService.instant('item.edit.bitstreams.edit.live.cancel', + { bitstream: bitstreamName, toIndex: toPosition + 1 }); + this.liveRegionService.addMessage(message); + } + + /** + * Adds a message to the live region mentioning that the bitstream with the provided name is no longer selected. + * @param bitstreamName The name of the bitstream that is no longer selected. + */ + announceClear(bitstreamName: string) { + const message = this.translateService.instant('item.edit.bitstreams.edit.live.clear', + { bitstream: bitstreamName }); + this.liveRegionService.addMessage(message); + } } diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html index d530fb38d1..06fb571ce4 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html @@ -5,7 +5,8 @@ [hidePagerWhenSinglePage]="true" [hidePaginationDetail]="true" [paginationOptions]="paginationOptions" - [collectionSize]="bitstreamsList.totalElements"> + [collectionSize]="bitstreamsList.totalElements" + [retainScrollPosition]="true"> -
- -
+ diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.spec.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.spec.ts index 1502ad2311..25274b8941 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.spec.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.spec.ts @@ -58,6 +58,7 @@ describe('ItemEditBitstreamBundleComponent', () => { currentPage: 1, pageSize: 9999 }), + getSelectedBitstream$: observableOf({}), }); beforeEach(waitForAsync(() => { diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts index 24319f4a83..7d2a519baf 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts @@ -1,4 +1,10 @@ -import { Component, EventEmitter, Input, OnInit, Output, ViewChild, ViewContainerRef } from '@angular/core'; +import { + Component, + Input, + OnInit, + ViewChild, + ViewContainerRef, OnDestroy, +} from '@angular/core'; import { Bundle } from '../../../../core/shared/bundle.model'; import { Item } from '../../../../core/shared/item.model'; import { ResponsiveColumnSizes } from '../../../../shared/responsive-table-sizes/responsive-column-sizes'; @@ -8,7 +14,7 @@ import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; import { RemoteData } from 'src/app/core/data/remote-data'; import { PaginatedList } from 'src/app/core/data/paginated-list.model'; import { Bitstream } from 'src/app/core/shared/bitstream.model'; -import { Observable, BehaviorSubject, switchMap } from 'rxjs'; +import { Observable, BehaviorSubject, switchMap, shareReplay, Subscription } from 'rxjs'; import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model'; import { FieldUpdates } from '../../../../core/data/object-updates/field-updates.model'; import { PaginatedSearchOptions } from '../../../../shared/search/models/paginated-search-options.model'; @@ -17,55 +23,17 @@ import { followLink } from '../../../../shared/utils/follow-link-config.model'; import { getAllSucceededRemoteData, paginatedListToArray, - getFirstSucceededRemoteData } from '../../../../core/shared/operators'; import { ObjectUpdatesService } from '../../../../core/data/object-updates/object-updates.service'; -import { BitstreamFormat } from '../../../../core/shared/bitstream-format.model'; -import { map, take, filter } from 'rxjs/operators'; +import { map, take, filter, tap, pairwise } from 'rxjs/operators'; import { FieldChangeType } from '../../../../core/data/object-updates/field-change-type.model'; import { FieldUpdate } from '../../../../core/data/object-updates/field-update.model'; import { PaginationService } from '../../../../core/pagination/pagination.service'; import { PaginationComponent } from '../../../../shared/pagination/pagination.component'; import { RequestService } from '../../../../core/data/request.service'; -import { ItemBitstreamsService } from '../item-bitstreams.service'; -import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop'; -import { hasValue } from '../../../../shared/empty.util'; -import { LiveRegionService } from '../../../../shared/live-region/live-region.service'; -import { TranslateService } from '@ngx-translate/core'; - -/** - * Interface storing all the information necessary to create a row in the bitstream edit table - */ -export interface BitstreamTableEntry { - /** - * The bitstream - */ - bitstream: Bitstream, - /** - * The uuid of the Bitstream - */ - id: string, - /** - * The name of the Bitstream - */ - name: string, - /** - * The name of the Bitstream with all whitespace removed - */ - nameStripped: string, - /** - * The description of the Bitstream - */ - description: string, - /** - * Observable emitting the Format of the Bitstream - */ - format: Observable, - /** - * The download url of the Bitstream - */ - downloadUrl: string, -} +import { ItemBitstreamsService, BitstreamTableEntry, SelectedBitstreamTableEntry } from '../item-bitstreams.service'; +import { CdkDragDrop } from '@angular/cdk/drag-drop'; +import { hasValue, hasNoValue } from '../../../../shared/empty.util'; @Component({ selector: 'ds-item-edit-bitstream-bundle', @@ -77,7 +45,7 @@ export interface BitstreamTableEntry { * Creates an embedded view of the contents. This is to ensure the table structure won't break. * (which means it'll be added to the parents html without a wrapping ds-item-edit-bitstream-bundle element) */ -export class ItemEditBitstreamBundleComponent implements OnInit { +export class ItemEditBitstreamBundleComponent implements OnInit, OnDestroy { protected readonly FieldChangeType = FieldChangeType; /** @@ -115,13 +83,6 @@ export class ItemEditBitstreamBundleComponent implements OnInit { */ @Input() isFirstTable = false; - /** - * Send an event when the user drops an object on the pagination - * The event contains details about the index the object came from and is dropped to (across the entirety of the list, - * not just within a single page) - */ - @Output() dropObject: EventEmitter = new EventEmitter(); - /** * The bootstrap sizes used for the Bundle Name column * This column stretches over the first 3 columns and thus is a combination of their sizes processed in ngOnInit @@ -138,6 +99,11 @@ export class ItemEditBitstreamBundleComponent implements OnInit { */ bundleName: string; + /** + * The number of bitstreams in the bundle + */ + bundleSize: number; + /** * The bitstreams to show in the table */ @@ -146,7 +112,7 @@ export class ItemEditBitstreamBundleComponent implements OnInit { /** * The data to show in the table */ - tableEntries$: BehaviorSubject = new BehaviorSubject(null); + tableEntries$: BehaviorSubject = new BehaviorSubject([]); /** * The initial page options to use for fetching the bitstreams @@ -158,11 +124,6 @@ export class ItemEditBitstreamBundleComponent implements OnInit { */ currentPaginationOptions$: BehaviorSubject; - /** - * The available page size options - */ - pageSizeOptions: number[]; - /** * The currently selected page size */ @@ -178,6 +139,11 @@ export class ItemEditBitstreamBundleComponent implements OnInit { */ updates$: BehaviorSubject = new BehaviorSubject(null); + /** + * Array containing all subscriptions created by this component + */ + subscriptions: Subscription[] = []; + constructor( protected viewContainerRef: ViewContainerRef, @@ -187,8 +153,6 @@ export class ItemEditBitstreamBundleComponent implements OnInit { protected paginationService: PaginationService, protected requestService: RequestService, protected itemBitstreamsService: ItemBitstreamsService, - protected liveRegionService: LiveRegionService, - protected translateService: TranslateService, ) { } @@ -201,23 +165,27 @@ export class ItemEditBitstreamBundleComponent implements OnInit { this.initializePagination(); this.initializeBitstreams(); + this.initializeSelectionActions(); + } - // this.bitstreamsRD = this. + ngOnDestroy() { + this.subscriptions.forEach(sub => sub?.unsubscribe()); } protected initializePagination() { this.paginationOptions = this.itemBitstreamsService.getInitialBitstreamsPaginationOptions(this.bundleName); - this.pageSizeOptions = this.paginationOptions.pageSizeOptions; - this.currentPaginationOptions$ = new BehaviorSubject(this.paginationOptions); this.pageSize$ = new BehaviorSubject(this.paginationOptions.pageSize); - this.paginationService.getCurrentPagination(this.paginationOptions.id, this.paginationOptions) - .subscribe((pagination) => { - this.currentPaginationOptions$.next(pagination); - this.pageSize$.next(pagination.pageSize); - }); + this.subscriptions.push( + this.paginationService.getCurrentPagination(this.paginationOptions.id, this.paginationOptions) + .subscribe((pagination) => { + this.currentPaginationOptions$.next(pagination); + this.pageSize$.next(pagination.pageSize); + }) + ); + } protected initializeBitstreams() { @@ -233,26 +201,88 @@ export class ItemEditBitstreamBundleComponent implements OnInit { )) ); }), + getAllSucceededRemoteData(), + shareReplay(1), ); - this.bitstreamsRD$.pipe( - getFirstSucceededRemoteData(), - paginatedListToArray(), - ).subscribe((bitstreams) => { - this.objectUpdatesService.initialize(this.bundleUrl, bitstreams, new Date()); - }); + this.subscriptions.push( + this.bitstreamsRD$.pipe( + take(1), + tap(bitstreamsRD => this.bundleSize = bitstreamsRD.payload.totalElements), + paginatedListToArray(), + ).subscribe((bitstreams) => { + this.objectUpdatesService.initialize(this.bundleUrl, bitstreams, new Date()); + }), - this.bitstreamsRD$.pipe( - getAllSucceededRemoteData(), - paginatedListToArray(), - switchMap((bitstreams) => this.objectUpdatesService.getFieldUpdatesExclusive(this.bundleUrl, bitstreams)) - ).subscribe((updates) => this.updates$.next(updates)); + this.bitstreamsRD$.pipe( + paginatedListToArray(), + switchMap((bitstreams) => this.objectUpdatesService.getFieldUpdatesExclusive(this.bundleUrl, bitstreams)) + ).subscribe((updates) => this.updates$.next(updates)), - this.bitstreamsRD$.pipe( - getAllSucceededRemoteData(), - paginatedListToArray(), - map((bitstreams) => this.itemBitstreamsService.mapBitstreamsToTableEntries(bitstreams)), - ).subscribe((tableEntries) => this.tableEntries$.next(tableEntries)); + this.bitstreamsRD$.pipe( + paginatedListToArray(), + map((bitstreams) => this.itemBitstreamsService.mapBitstreamsToTableEntries(bitstreams)), + ).subscribe((tableEntries) => this.tableEntries$.next(tableEntries)), + ); + } + + protected initializeSelectionActions() { + this.subscriptions.push( + this.itemBitstreamsService.getSelectedBitstream$().pipe(pairwise()).subscribe( + ([previousSelection, currentSelection]) => + this.handleSelectedEntryChange(previousSelection, currentSelection)) + ); + } + + /** + * Handles a change in selected bitstream by changing the pagination if the change happened on a different page + * @param previousSelectedEntry The previously selected entry + * @param currentSelectedEntry The currently selected entry + * @protected + */ + protected handleSelectedEntryChange( + previousSelectedEntry: SelectedBitstreamTableEntry, + currentSelectedEntry: SelectedBitstreamTableEntry + ) { + if (hasValue(currentSelectedEntry) && currentSelectedEntry.bundle === this.bundle) { + // If the currently selected bitstream belongs to this bundle, it has possibly moved to a different page. + // In that case we want to change the pagination to the new page. + this.redirectToCurrentPage(currentSelectedEntry); + } + + // If the selection is cancelled or cleared, it is possible the selected bitstream is currently on a different page + // In that case we want to change the pagination to the place where the bitstream was returned to + if (hasNoValue(currentSelectedEntry) && hasValue(previousSelectedEntry) && previousSelectedEntry.bundle === this.bundle) { + this.redirectToOriginalPage(previousSelectedEntry); + } + } + + /** + * Redirect the user to the current page of the provided bitstream if it is on a different page. + * @param bitstreamEntry The entry that the current position will be taken from to determine the page to move to + * @protected + */ + protected redirectToCurrentPage(bitstreamEntry: SelectedBitstreamTableEntry) { + const currentPage = this.getCurrentPage(); + const selectedEntryPage = this.bundleIndexToPage(bitstreamEntry.currentPosition); + + if (currentPage !== selectedEntryPage) { + this.changeToPage(selectedEntryPage); + } + } + + /** + * Redirect the user to the original page of the provided bitstream if it is on a different page. + * @param bitstreamEntry The entry that the original position will be taken from to determine the page to move to + * @protected + */ + protected redirectToOriginalPage(bitstreamEntry: SelectedBitstreamTableEntry) { + const currentPage = this.getCurrentPage(); + const originPage = this.bundleIndexToPage(bitstreamEntry.originalPosition); + + if (currentPage !== originPage) { + this.changeToPage(originPage); + } } /** @@ -283,7 +313,18 @@ export class ItemEditBitstreamBundleComponent implements OnInit { this.objectUpdatesService.removeSingleFieldUpdate(this.bundleUrl, bitstream.uuid); } - getRowClass(update: FieldUpdate): string { + /** + * Returns the css class for a table row depending on the state of the table entry. + * @param update + * @param bitstream + */ + getRowClass(update: FieldUpdate, bitstream: BitstreamTableEntry): string { + const selected = this.itemBitstreamsService.getSelectedBitstream(); + + if (hasValue(selected) && bitstream.id === selected.bitstream.id) { + return 'table-info'; + } + switch (update.changeType) { case FieldChangeType.UPDATE: return 'table-warning'; @@ -296,11 +337,19 @@ export class ItemEditBitstreamBundleComponent implements OnInit { } } + /** + * Changes the page size to the provided page size. + * @param pageSize + */ public doPageSizeChange(pageSize: number) { this.paginationComponent.doPageSizeChange(pageSize); } - dragStart(bitstreamName: string) { + /** + * Handles start of dragging by opening the tooltip mentioning that it is possible to drag a bitstream to a different + * page by dropping it on the page number, only if there are multiple pages. + */ + dragStart() { // Only open the drag tooltip when there are multiple pages this.paginationComponent.shouldShowBottomPager.pipe( take(1), @@ -308,66 +357,170 @@ export class ItemEditBitstreamBundleComponent implements OnInit { ).subscribe(() => { this.dragTooltip.open(); }); - - const message = this.translateService.instant('item.edit.bitstreams.edit.live.drag', - { bitstream: bitstreamName }); - this.liveRegionService.addMessage(message); } - dragEnd(bitstreamName: string) { + /** + * Handles end of dragging by closing the tooltip. + */ + dragEnd() { this.dragTooltip.close(); - - const message = this.translateService.instant('item.edit.bitstreams.edit.live.drop', - { bitstream: bitstreamName }); - this.liveRegionService.addMessage(message); } - + /** + * Handles dropping by calculation the target position, and changing the page if the bitstream was dropped on a + * different page. + * @param event + */ drop(event: CdkDragDrop) { const dragIndex = event.previousIndex; let dropIndex = event.currentIndex; - const dragPage = this.currentPaginationOptions$.value.currentPage - 1; - let dropPage = this.currentPaginationOptions$.value.currentPage - 1; + const dragPage = this.getCurrentPage(); + let dropPage = this.getCurrentPage(); // Check if the user is hovering over any of the pagination's pages at the time of dropping the object const droppedOnElement = document.elementFromPoint(event.dropPoint.x, event.dropPoint.y); if (hasValue(droppedOnElement) && hasValue(droppedOnElement.textContent) && droppedOnElement.classList.contains('page-link')) { // The user is hovering over a page, fetch the page's number from the element - const droppedPage = Number(droppedOnElement.textContent); + let droppedPage = Number(droppedOnElement.textContent); if (hasValue(droppedPage) && !Number.isNaN(droppedPage)) { - dropPage = droppedPage - 1; - dropIndex = 0; + droppedPage -= 1; + + if (droppedPage !== dragPage) { + dropPage = droppedPage; + + if (dropPage > dragPage) { + // When moving to later page, place bitstream at the top + dropIndex = 0; + } else { + // When moving to earlier page, place bitstream at the bottom + dropIndex = this.getCurrentPageSize() - 1; + } + } } } - const isNewPage = dragPage !== dropPage; - // Move the object in the custom order array if the drop happened within the same page - // This allows us to instantly display a change in the order, instead of waiting for the REST API's response first - if (!isNewPage && dragIndex !== dropIndex) { - const currentEntries = [...this.tableEntries$.value]; - moveItemInArray(currentEntries, dragIndex, dropIndex); - this.tableEntries$.next(currentEntries); + const fromIndex = this.pageIndexToBundleIndex(dragIndex, dragPage); + const toIndex = this.pageIndexToBundleIndex(dropIndex, dropPage); + + if (fromIndex === toIndex) { + return; } - const pageSize = this.currentPaginationOptions$.value.pageSize; - const redirectPage = dropPage + 1; - const fromIndex = (dragPage * pageSize) + dragIndex; - const toIndex = (dropPage * pageSize) + dropIndex; - // Send out a drop event (and navigate to the new page) when the "from" and "to" indexes are different from each other - if (fromIndex !== toIndex) { - // if (isNewPage) { - // this.loading$.next(true); - // } - this.dropObject.emit(Object.assign({ - fromIndex, - toIndex, - finish: () => { - if (isNewPage) { - this.paginationComponent.doPageChange(redirectPage); - } - } - })); + const selectedBitstream = this.tableEntries$.value[dragIndex]; + + const finish = () => { + this.itemBitstreamsService.announceMove(selectedBitstream.name, toIndex); + + if (dropPage !== this.getCurrentPage()) { + this.changeToPage(dropPage); + } + }; + + this.itemBitstreamsService.performBitstreamMoveRequest(this.bundle, fromIndex, toIndex, finish); + } + + /** + * Handles a select action for the provided bitstream entry. + * If the selected bitstream is currently selected, the selection is cleared. + * If no, or a different bitstream, is selected, the provided bitstream becomes the selected bitstream. + * @param bitstream + */ + select(bitstream: BitstreamTableEntry) { + const selectedBitstream = this.itemBitstreamsService.getSelectedBitstream(); + + if (hasValue(selectedBitstream) && selectedBitstream.bitstream === bitstream) { + this.itemBitstreamsService.cancelSelection(); + } else { + const selectionObject = this.createBitstreamSelectionObject(bitstream); + + if (hasNoValue(selectionObject)) { + console.warn('Failed to create selection object'); + return; + } + + this.itemBitstreamsService.selectBitstreamEntry(selectionObject); } } + /** + * Creates a {@link SelectedBitstreamTableEntry} from the provided {@link BitstreamTableEntry} so it can be given + * to the {@link ItemBitstreamsService} to select the table entry. + * @param bitstream The table entry to create the selection object from. + * @protected + */ + protected createBitstreamSelectionObject(bitstream: BitstreamTableEntry): SelectedBitstreamTableEntry { + const pageIndex = this.findBitstreamPageIndex(bitstream); + + if (pageIndex === -1) { + return null; + } + + const position = this.pageIndexToBundleIndex(pageIndex, this.getCurrentPage()); + + return { + bitstream: bitstream, + bundle: this.bundle, + bundleSize: this.bundleSize, + currentPosition: position, + originalPosition: position, + }; + } + + /** + * Returns the index of the provided {@link BitstreamTableEntry} relative to the current page + * If the current page size is 10, it will return a value from 0 to 9 (inclusive) + * Returns -1 if the provided bitstream could not be found + * @protected + */ + protected findBitstreamPageIndex(bitstream: BitstreamTableEntry): number { + const entries = this.tableEntries$.value; + return entries.findIndex(entry => entry === bitstream); + } + + /** + * Returns the current zero-indexed page + * @protected + */ + protected getCurrentPage(): number { + // The pagination component uses one-based numbering while zero-based numbering is more convenient for calculations + return this.currentPaginationOptions$.value.currentPage - 1; + } + + /** + * Returns the current page size + * @protected + */ + protected getCurrentPageSize(): number { + return this.currentPaginationOptions$.value.pageSize; + } + + /** + * Converts an index relative to the page to an index relative to the bundle + * @param index The index relative to the page + * @param page The zero-indexed page number + * @protected + */ + protected pageIndexToBundleIndex(index: number, page: number) { + return page * this.getCurrentPageSize() + index; + } + + /** + * Calculates the zero-indexed page number from the index relative to the bundle + * @param index The index relative to the bundle + * @protected + */ + protected bundleIndexToPage(index: number) { + return Math.floor(index / this.getCurrentPageSize()); + } + + /** + * Change the pagination for this bundle to the provided zero-indexed page + * @param page The zero-indexed page to change to + * @protected + */ + protected changeToPage(page: number) { + // Increments page by one because zero-indexing is way easier for calculations but the pagination component + // uses one-indexing. + this.paginationComponent.doPageChange(page + 1); + } } diff --git a/src/app/shared/live-region/live-region.service.stub.ts b/src/app/shared/live-region/live-region.service.stub.ts new file mode 100644 index 0000000000..4f10b46a4c --- /dev/null +++ b/src/app/shared/live-region/live-region.service.stub.ts @@ -0,0 +1,30 @@ +import { of } from 'rxjs'; +import { LiveRegionService } from './live-region.service'; + +export function getLiveRegionServiceStub(): LiveRegionService { + return new LiveRegionServiceStub() as unknown as LiveRegionService; +} + +export class LiveRegionServiceStub { + getMessages = jasmine.createSpy('getMessages').and.returnValue( + ['Message One', 'Message Two'] + ); + + getMessages$ = jasmine.createSpy('getMessages$').and.returnValue( + of(['Message One', 'Message Two']) + ); + + addMessage = jasmine.createSpy('addMessage').and.returnValue('messageId'); + + clear = jasmine.createSpy('clear'); + + clearMessageByUUID = jasmine.createSpy('clearMessageByUUID'); + + getLiveRegionVisibility = jasmine.createSpy('getLiveRegionVisibility').and.returnValue(false); + + setLiveRegionVisibility = jasmine.createSpy('setLiveRegionVisibility'); + + getMessageTimeOutMs = jasmine.createSpy('getMessageTimeOutMs').and.returnValue(30000); + + setMessageTimeOutMs = jasmine.createSpy('setMessageTimeOutMs'); +} diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index ab6f3792ca..519189ed69 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1950,9 +1950,13 @@ "item.edit.bitstreams.edit.buttons.undo": "Undo changes", - "item.edit.bitstreams.edit.live.drag": "{{ bitstream }} grabbed", + "item.edit.bitstreams.edit.live.cancel": "{{ bitstream }} was returned to position {{ toIndex }} and is no longer selected.", - "item.edit.bitstreams.edit.live.drop": "{{ bitstream }} dropped", + "item.edit.bitstreams.edit.live.clear": "{{ bitstream }} is no longer selected.", + + "item.edit.bitstreams.edit.live.select": "{{ bitstream }} is selected.", + + "item.edit.bitstreams.edit.live.move": "{{ bitstream }} is now in position {{ toIndex }}.", "item.edit.bitstreams.empty": "This item doesn't contain any bitstreams. Click the upload button to create one.", From 2e1b1489b65c6c6715774ef482242e8f14d990f0 Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Fri, 4 Oct 2024 09:40:20 +0200 Subject: [PATCH 0621/1286] 118223: Stop space from scrolling down page --- .../item-bitstreams/item-bitstreams.component.ts | 1 + .../item-edit-bitstream-bundle.component.html | 2 +- .../item-edit-bitstream-bundle.component.ts | 12 ++++++++++-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts index 4ced3dd649..f77eda02fb 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts @@ -138,6 +138,7 @@ export class ItemBitstreamsComponent extends AbstractItemUpdateComponent impleme // Otherwise we might clear the selection when a different action was intended, e.g. clicking a button or selecting // a different bitstream. if (event.target instanceof Element && event.target.tagName === 'BODY') { + event.preventDefault(); this.itemBitstreamsService.clearSelection(); } } diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html index 06fb571ce4..9afdd2d41c 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html @@ -82,7 +82,7 @@
-
- +
+
{{ entry.name }}
+ (keydown.enter)="select($event, entry)" (keydown.space)="select($event, entry)" (click)="select($event, entry)">
diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts index 7d2a519baf..e2dff2f018 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts @@ -423,9 +423,17 @@ export class ItemEditBitstreamBundleComponent implements OnInit, OnDestroy { * Handles a select action for the provided bitstream entry. * If the selected bitstream is currently selected, the selection is cleared. * If no, or a different bitstream, is selected, the provided bitstream becomes the selected bitstream. - * @param bitstream + * @param event The event that triggered the select action + * @param bitstream The bitstream that is the target of the select action */ - select(bitstream: BitstreamTableEntry) { + select(event: UIEvent, bitstream: BitstreamTableEntry) { + event.preventDefault(); + + if (event instanceof KeyboardEvent && event.repeat) { + // Don't handle hold events, otherwise it would change rapidly between being selected and unselected + return; + } + const selectedBitstream = this.itemBitstreamsService.getSelectedBitstream(); if (hasValue(selectedBitstream) && selectedBitstream.bitstream === bitstream) { From 0920a218762a4aa547c8b9bf72e795e8321e73ff Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Fri, 4 Oct 2024 10:53:42 +0200 Subject: [PATCH 0622/1286] 118223: Stop sending success notificiations on every move --- .../item-bitstreams.service.ts | 60 +++++++++++++++---- .../item-edit-bitstream-bundle.component.ts | 9 ++- 2 files changed, 57 insertions(+), 12 deletions(-) diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.ts index 21dc415198..f8091d616a 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.ts @@ -3,7 +3,7 @@ import { PaginationComponentOptions } from '../../../shared/pagination/paginatio import { ResponsiveTableSizes } from '../../../shared/responsive-table-sizes/responsive-table-sizes'; import { ResponsiveColumnSizes } from '../../../shared/responsive-table-sizes/responsive-column-sizes'; import { RemoteData } from '../../../core/data/remote-data'; -import { isNotEmpty, hasValue, hasNoValue } from '../../../shared/empty.util'; +import { hasValue, hasNoValue } from '../../../shared/empty.util'; import { Bundle } from '../../../core/shared/bundle.model'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; @@ -25,6 +25,8 @@ import { BundleDataService } from '../../../core/data/bundle-data.service'; import { RequestService } from '../../../core/data/request.service'; import { LiveRegionService } from '../../../shared/live-region/live-region.service'; +export const MOVE_KEY = 'item.edit.bitstreams.notifications.move'; + /** * Interface storing all the information necessary to create a row in the bitstream edit table */ @@ -164,6 +166,10 @@ export class ItemBitstreamsService { if (hasValue(selected)) { this.updateSelectedBitstream(null); this.announceClear(selected.bitstream.name); + + if (selected.currentPosition !== selected.originalPosition) { + this.displaySuccessNotification(MOVE_KEY); + } } } @@ -265,7 +271,7 @@ export class ItemBitstreamsService { this.isPerformingMoveRequest = true; this.bundleService.patch(bundle, [moveOperation]).pipe( getFirstCompletedRemoteData(), - tap((response: RemoteData) => this.displayNotifications('item.edit.bitstreams.notifications.move', [response])), + tap((response: RemoteData) => this.displayFailedResponseNotifications(MOVE_KEY, [response])), switchMap(() => this.requestService.setStaleByHrefSubstring(bundle.self)), take(1), ).subscribe(() => { @@ -321,19 +327,51 @@ export class ItemBitstreamsService { * @param responses The returned responses to display notifications for */ displayNotifications(key: string, responses: RemoteData[]) { - if (isNotEmpty(responses)) { - const failedResponses = responses.filter((response: RemoteData) => hasValue(response) && response.hasFailed); - const successfulResponses = responses.filter((response: RemoteData) => hasValue(response) && response.hasSucceeded); + this.displayFailedResponseNotifications(key, responses); + this.displaySuccessFulResponseNotifications(key, responses); + } - failedResponses.forEach((response: RemoteData) => { - this.notificationsService.error(this.translateService.instant(`${key}.failed.title`), response.errorMessage); - }); - if (successfulResponses.length > 0) { - this.notificationsService.success(this.translateService.instant(`${key}.saved.title`), this.translateService.instant(`${key}.saved.content`)); - } + /** + * Display an error notification for each failed response with their message + * @param key The i18n key for the notification messages + * @param responses The returned responses to display notifications for + */ + displayFailedResponseNotifications(key: string, responses: RemoteData[]) { + const failedResponses = responses.filter((response: RemoteData) => hasValue(response) && response.hasFailed); + failedResponses.forEach((response: RemoteData) => { + this.displayErrorNotification(key, response.errorMessage); + }); + } + + /** + * Display an error notification with the provided key and message + * @param key The i18n key for the notification messages + * @param errorMessage The error message to display + */ + displayErrorNotification(key: string, errorMessage: string) { + this.notificationsService.error(this.translateService.instant(`${key}.failed.title`), errorMessage); + } + + /** + * Display a success notification in case there's at least one successful response + * @param key The i18n key for the notification messages + * @param responses The returned responses to display notifications for + */ + displaySuccessFulResponseNotifications(key: string, responses: RemoteData[]) { + const successfulResponses = responses.filter((response: RemoteData) => hasValue(response) && response.hasSucceeded); + if (successfulResponses.length > 0) { + this.displaySuccessNotification(key); } } + /** + * Display a success notification with the provided key + * @param key The i18n key for the notification messages + */ + displaySuccessNotification(key: string) { + this.notificationsService.success(this.translateService.instant(`${key}.saved.title`), this.translateService.instant(`${key}.saved.content`)); + } + /** * Removes the bitstreams marked for deletion from the Bundles emitted by the provided observable. * @param bundles$ diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts index e2dff2f018..4079ad225b 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts @@ -31,7 +31,12 @@ import { FieldUpdate } from '../../../../core/data/object-updates/field-update.m import { PaginationService } from '../../../../core/pagination/pagination.service'; import { PaginationComponent } from '../../../../shared/pagination/pagination.component'; import { RequestService } from '../../../../core/data/request.service'; -import { ItemBitstreamsService, BitstreamTableEntry, SelectedBitstreamTableEntry } from '../item-bitstreams.service'; +import { + ItemBitstreamsService, + BitstreamTableEntry, + SelectedBitstreamTableEntry, + MOVE_KEY +} from '../item-bitstreams.service'; import { CdkDragDrop } from '@angular/cdk/drag-drop'; import { hasValue, hasNoValue } from '../../../../shared/empty.util'; @@ -414,6 +419,8 @@ export class ItemEditBitstreamBundleComponent implements OnInit, OnDestroy { if (dropPage !== this.getCurrentPage()) { this.changeToPage(dropPage); } + + this.itemBitstreamsService.displaySuccessNotification(MOVE_KEY); }; this.itemBitstreamsService.performBitstreamMoveRequest(this.bundle, fromIndex, toIndex, finish); From b158c5c2a275ff64108229c37083da7e7f78720e Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Fri, 4 Oct 2024 10:58:52 +0200 Subject: [PATCH 0623/1286] 118223: Move drag tooltip to center of pagination numbers --- .../item-edit-bitstream-bundle.component.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html index 9afdd2d41c..efbdd8c69b 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html @@ -6,7 +6,9 @@ [hidePaginationDetail]="true" [paginationOptions]="paginationOptions" [collectionSize]="bitstreamsList.totalElements" - [retainScrollPosition]="true"> + [retainScrollPosition]="true" + [ngbTooltip]="'item.edit.bitstreams.bundle.tooltip' | translate" placement="bottom" + [autoClose]="false" triggers="manual" #dragTooltip="ngbTooltip"> - + +
{{'item.edit.bitstreams.bundle.name' | translate:{ name: bundleName } }} From 1dcc5d1ec5a21667e90322fb2a6dc4528d8f5c0b Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Fri, 4 Oct 2024 15:16:16 +0200 Subject: [PATCH 0624/1286] 118223: Add ItemBitstreams service tests --- .../item-bitstreams.service.spec.ts | 443 +++++++++++++++++- .../item-bitstreams.service.ts | 4 +- 2 files changed, 444 insertions(+), 3 deletions(-) diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.spec.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.spec.ts index e144e81ec7..94adb5f23a 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.spec.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.spec.ts @@ -1,4 +1,4 @@ -import { ItemBitstreamsService } from './item-bitstreams.service'; +import { ItemBitstreamsService, SelectedBitstreamTableEntry } from './item-bitstreams.service'; import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub'; import { getMockTranslateService } from '../../../shared/mocks/translate.service.mock'; import { ObjectUpdatesServiceStub } from '../../../core/data/object-updates/object-updates.service.stub'; @@ -22,6 +22,9 @@ import { LiveRegionService } from '../../../shared/live-region/live-region.servi import { Bundle } from '../../../core/shared/bundle.model'; import { of } from 'rxjs'; import { getLiveRegionServiceStub } from '../../../shared/live-region/live-region.service.stub'; +import { fakeAsync, tick } from '@angular/core/testing'; +import createSpy = jasmine.createSpy; +import { MoveOperation } from 'fast-json-patch'; describe('ItemBitstreamsService', () => { let service: ItemBitstreamsService; @@ -60,6 +63,444 @@ describe('ItemBitstreamsService', () => { ); }); + const defaultEntry: SelectedBitstreamTableEntry = { + bitstream: { + name: 'bitstream name', + } as any, + bundle: Object.assign(new Bundle(), { + _links: { self: { href: 'self_link' }}, + }), + bundleSize: 10, + currentPosition: 0, + originalPosition: 0, + }; + + describe('selectBitstreamEntry', () => { + it('should correctly make getSelectedBitstream$ emit', fakeAsync(() => { + const emittedEntries = []; + + service.getSelectedBitstream$().subscribe(selected => emittedEntries.push(selected)); + + expect(emittedEntries.length).toBe(1); + expect(emittedEntries[0]).toBeNull(); + + const entry = Object.assign({}, defaultEntry); + + service.selectBitstreamEntry(entry); + tick(); + + expect(emittedEntries.length).toBe(2); + expect(emittedEntries[1]).toEqual(entry); + })); + + it('should correctly make getSelectedBitstream return the bitstream', () => { + expect(service.getSelectedBitstream()).toBeNull(); + + const entry = Object.assign({}, defaultEntry); + + service.selectBitstreamEntry(entry); + expect(service.getSelectedBitstream()).toEqual(entry); + }); + + it('should correctly make hasSelectedBitstream return', () => { + expect(service.hasSelectedBitstream()).toBeFalse(); + + const entry = Object.assign({}, defaultEntry); + + service.selectBitstreamEntry(entry); + expect(service.hasSelectedBitstream()).toBeTrue(); + }); + + it('should do nothing if no entry was provided', fakeAsync(() => { + const emittedEntries = []; + + service.getSelectedBitstream$().subscribe(selected => emittedEntries.push(selected)); + + expect(emittedEntries.length).toBe(1); + expect(emittedEntries[0]).toBeNull(); + + const entry = Object.assign({}, defaultEntry); + + service.selectBitstreamEntry(entry); + tick(); + + expect(emittedEntries.length).toBe(2); + expect(emittedEntries[1]).toEqual(entry); + + service.selectBitstreamEntry(null); + tick(); + + expect(emittedEntries.length).toBe(2); + expect(emittedEntries[1]).toEqual(entry); + })); + + it('should announce the selected bitstream', () => { + const entry = Object.assign({}, defaultEntry); + + spyOn(service, 'announceSelect'); + + service.selectBitstreamEntry(entry); + expect(service.announceSelect).toHaveBeenCalledWith(entry.bitstream.name); + }); + }); + + describe('clearSelection', () => { + it('should clear the selected bitstream', fakeAsync(() => { + const emittedEntries = []; + + service.getSelectedBitstream$().subscribe(selected => emittedEntries.push(selected)); + + expect(emittedEntries.length).toBe(1); + expect(emittedEntries[0]).toBeNull(); + + const entry = Object.assign({}, defaultEntry); + + service.selectBitstreamEntry(entry); + tick(); + + expect(emittedEntries.length).toBe(2); + expect(emittedEntries[1]).toEqual(entry); + + service.clearSelection(); + tick(); + + expect(emittedEntries.length).toBe(3); + expect(emittedEntries[2]).toBeNull(); + })); + + it('should not do anything if there is no selected bitstream', fakeAsync(() => { + const emittedEntries = []; + + service.getSelectedBitstream$().subscribe(selected => emittedEntries.push(selected)); + + expect(emittedEntries.length).toBe(1); + expect(emittedEntries[0]).toBeNull(); + + service.clearSelection(); + tick(); + + expect(emittedEntries.length).toBe(1); + expect(emittedEntries[0]).toBeNull(); + })); + + it('should announce the cleared bitstream', () => { + const entry = Object.assign({}, defaultEntry); + + spyOn(service, 'announceClear'); + service.selectBitstreamEntry(entry); + service.clearSelection(); + + expect(service.announceClear).toHaveBeenCalledWith(entry.bitstream.name); + }); + + it('should display a notification if the selected bitstream was moved', () => { + const entry = Object.assign({}, defaultEntry, + { + originalPosition: 5, + currentPosition: 7, + } + ); + + spyOn(service, 'displaySuccessNotification'); + service.selectBitstreamEntry(entry); + service.clearSelection(); + + expect(service.displaySuccessNotification).toHaveBeenCalled(); + }); + + it('should not display a notification if the selected bitstream is in its original position', () => { + const entry = Object.assign({}, defaultEntry, + { + originalPosition: 7, + currentPosition: 7, + } + ); + + spyOn(service, 'displaySuccessNotification'); + service.selectBitstreamEntry(entry); + service.clearSelection(); + + expect(service.displaySuccessNotification).not.toHaveBeenCalled(); + }); + }); + + describe('cancelSelection', () => { + it('should clear the selected bitstream', fakeAsync(() => { + const emittedEntries = []; + + service.getSelectedBitstream$().subscribe(selected => emittedEntries.push(selected)); + + expect(emittedEntries.length).toBe(1); + expect(emittedEntries[0]).toBeNull(); + + const entry = Object.assign({}, defaultEntry); + + service.selectBitstreamEntry(entry); + tick(); + + expect(emittedEntries.length).toBe(2); + expect(emittedEntries[1]).toEqual(entry); + + service.cancelSelection(); + tick(); + + expect(emittedEntries.length).toBe(3); + expect(emittedEntries[2]).toBeNull(); + })); + + it('should announce a clear if the bitstream has not moved', () => { + const entry = Object.assign({}, defaultEntry, + { + originalPosition: 7, + currentPosition: 7, + } + ); + + spyOn(service, 'announceClear'); + spyOn(service, 'announceCancel'); + + service.selectBitstreamEntry(entry); + service.cancelSelection(); + + expect(service.announceClear).toHaveBeenCalledWith(entry.bitstream.name); + expect(service.announceCancel).not.toHaveBeenCalled(); + }); + + it('should announce a cancel if the bitstream has moved', () => { + const entry = Object.assign({}, defaultEntry, + { + originalPosition: 5, + currentPosition: 7, + } + ); + + spyOn(service, 'announceClear'); + spyOn(service, 'announceCancel'); + + service.selectBitstreamEntry(entry); + service.cancelSelection(); + + expect(service.announceClear).not.toHaveBeenCalled(); + expect(service.announceCancel).toHaveBeenCalledWith(entry.bitstream.name, entry.originalPosition); + }); + + it('should return the bitstream to its original position if it has moved', () => { + const entry = Object.assign({}, defaultEntry, + { + originalPosition: 5, + currentPosition: 7, + } + ); + + spyOn(service, 'performBitstreamMoveRequest'); + + service.selectBitstreamEntry(entry); + service.cancelSelection(); + + expect(service.performBitstreamMoveRequest).toHaveBeenCalledWith(entry.bundle, entry.currentPosition, entry.originalPosition); + }); + + it('should not move the bitstream if it has not moved', () => { + const entry = Object.assign({}, defaultEntry, + { + originalPosition: 7, + currentPosition: 7, + } + ); + + spyOn(service, 'performBitstreamMoveRequest'); + + service.selectBitstreamEntry(entry); + service.cancelSelection(); + + expect(service.performBitstreamMoveRequest).not.toHaveBeenCalled(); + }); + + it('should not do anything if there is no selected bitstream', () => { + spyOn(service, 'announceClear'); + spyOn(service, 'announceCancel'); + spyOn(service, 'performBitstreamMoveRequest'); + + service.cancelSelection(); + + expect(service.announceClear).not.toHaveBeenCalled(); + expect(service.announceCancel).not.toHaveBeenCalled(); + expect(service.performBitstreamMoveRequest).not.toHaveBeenCalled(); + }); + }); + + describe('moveSelectedBitstream', () => { + beforeEach(() => { + spyOn(service, 'performBitstreamMoveRequest').and.callThrough(); + }); + + describe('up', () => { + it('should move the selected bitstream one position up', () => { + const startPosition = 7; + const endPosition = startPosition - 1; + + const entry = Object.assign({}, defaultEntry, + { + originalPosition: 5, + currentPosition: startPosition, + } + ); + + const movedEntry = Object.assign({}, defaultEntry, + { + originalPosition: 5, + currentPosition: endPosition, + } + ); + + service.selectBitstreamEntry(entry); + service.moveSelectedBitstreamUp(); + expect(service.performBitstreamMoveRequest).toHaveBeenCalledWith(entry.bundle, startPosition, endPosition, jasmine.any(Function)); + expect(service.getSelectedBitstream()).toEqual(movedEntry); + }); + + it('should announce the move', () => { + const startPosition = 7; + const endPosition = startPosition - 1; + + spyOn(service, 'announceMove'); + + const entry = Object.assign({}, defaultEntry, + { + originalPosition: 5, + currentPosition: startPosition, + } + ); + + service.selectBitstreamEntry(entry); + service.moveSelectedBitstreamUp(); + + expect(service.announceMove).toHaveBeenCalledWith(entry.bitstream.name, endPosition); + }); + + it('should not do anything if the bitstream is already at the top', () => { + const entry = Object.assign({}, defaultEntry, + { + originalPosition: 5, + currentPosition: 0, + } + ); + + service.selectBitstreamEntry(entry); + service.moveSelectedBitstreamUp(); + + expect(service.performBitstreamMoveRequest).not.toHaveBeenCalled(); + }); + + it('should not do anything if there is no selected bitstream', () => { + service.moveSelectedBitstreamUp(); + + expect(service.performBitstreamMoveRequest).not.toHaveBeenCalled(); + }); + }); + + describe('down', () => { + it('should move the selected bitstream one position down', () => { + const startPosition = 7; + const endPosition = startPosition + 1; + + const entry = Object.assign({}, defaultEntry, + { + originalPosition: 5, + currentPosition: startPosition, + } + ); + + const movedEntry = Object.assign({}, defaultEntry, + { + originalPosition: 5, + currentPosition: endPosition, + } + ); + + service.selectBitstreamEntry(entry); + service.moveSelectedBitstreamDown(); + expect(service.performBitstreamMoveRequest).toHaveBeenCalledWith(entry.bundle, startPosition, endPosition, jasmine.any(Function)); + expect(service.getSelectedBitstream()).toEqual(movedEntry); + }); + + it('should announce the move', () => { + const startPosition = 7; + const endPosition = startPosition + 1; + + spyOn(service, 'announceMove'); + + const entry = Object.assign({}, defaultEntry, + { + originalPosition: 5, + currentPosition: startPosition, + } + ); + + service.selectBitstreamEntry(entry); + service.moveSelectedBitstreamDown(); + + expect(service.announceMove).toHaveBeenCalledWith(entry.bitstream.name, endPosition); + }); + + it('should not do anything if the bitstream is already at the bottom of the bundle', () => { + const entry = Object.assign({}, defaultEntry, + { + originalPosition: 5, + currentPosition: 9, + } + ); + + service.selectBitstreamEntry(entry); + service.moveSelectedBitstreamDown(); + + expect(service.performBitstreamMoveRequest).not.toHaveBeenCalled(); + }); + + it('should not do anything if there is no selected bitstream', () => { + service.moveSelectedBitstreamDown(); + + expect(service.performBitstreamMoveRequest).not.toHaveBeenCalled(); + }); + }); + }); + + describe('performBitstreamMoveRequest', () => { + const bundle: Bundle = defaultEntry.bundle; + const from = 5; + const to = 7; + const callback = createSpy('callbackFunction'); + + console.log('bundle:', bundle); + + it('should correctly create the Move request', () => { + const expectedOperation: MoveOperation = { + op: 'move', + from: `/_links/bitstreams/${from}/href`, + path: `/_links/bitstreams/${to}/href`, + }; + + service.performBitstreamMoveRequest(bundle, from, to, callback); + expect(bundleDataService.patch).toHaveBeenCalledWith(bundle, [expectedOperation]); + }); + + it('should correctly make the bundle\'s self link stale', () => { + service.performBitstreamMoveRequest(bundle, from, to, callback); + expect(requestService.setStaleByHrefSubstring).toHaveBeenCalledWith(bundle._links.self.href); + }); + + it('should attempt to show a message should the request have failed', () => { + spyOn(service, 'displayFailedResponseNotifications'); + service.performBitstreamMoveRequest(bundle, from, to, callback); + expect(service.displayFailedResponseNotifications).toHaveBeenCalled(); + }); + + it('should correctly call the provided function once the request has finished', () => { + service.performBitstreamMoveRequest(bundle, from, to, callback); + expect(callback).toHaveBeenCalled(); + }); + }); + describe('displayNotifications', () => { it('should display an error notification if a response failed', () => { const responses = [ diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.ts index f8091d616a..5b5fb7d63c 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.ts @@ -143,7 +143,7 @@ export class ItemBitstreamsService { * Select the provided entry */ selectBitstreamEntry(entry: SelectedBitstreamTableEntry) { - if (entry !== this.selectedBitstream$.getValue()) { + if (hasValue(entry) && entry !== this.selectedBitstream$.getValue()) { this.announceSelect(entry.bitstream.name); this.updateSelectedBitstream(entry); } @@ -184,7 +184,7 @@ export class ItemBitstreamsService { return; } - this.selectedBitstream$.next(null); + this.updateSelectedBitstream(null); const originalPosition = selected.originalPosition; const currentPosition = selected.currentPosition; From 0bdb5742e064ca35325aa03530506012e36b1dc4 Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Fri, 4 Oct 2024 15:22:43 +0200 Subject: [PATCH 0625/1286] 118223: Remove unused item-edit-bitstream component --- .../edit-item-page/edit-item-page.module.ts | 2 - .../item-edit-bitstream.component.html | 51 ------ .../item-edit-bitstream.component.spec.ts | 145 ------------------ .../item-edit-bitstream.component.ts | 117 -------------- 4 files changed, 315 deletions(-) delete mode 100644 src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream/item-edit-bitstream.component.html delete mode 100644 src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream/item-edit-bitstream.component.spec.ts delete mode 100644 src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream/item-edit-bitstream.component.ts diff --git a/src/app/item-page/edit-item-page/edit-item-page.module.ts b/src/app/item-page/edit-item-page/edit-item-page.module.ts index 4ae5ebe666..c38b480622 100644 --- a/src/app/item-page/edit-item-page/edit-item-page.module.ts +++ b/src/app/item-page/edit-item-page/edit-item-page.module.ts @@ -15,7 +15,6 @@ import { ItemPrivateComponent } from './item-private/item-private.component'; import { ItemPublicComponent } from './item-public/item-public.component'; import { ItemDeleteComponent } from './item-delete/item-delete.component'; import { ItemBitstreamsComponent } from './item-bitstreams/item-bitstreams.component'; -import { ItemEditBitstreamComponent } from './item-bitstreams/item-edit-bitstream/item-edit-bitstream.component'; import { SearchPageModule } from '../../search-page/search-page.module'; import { ItemCollectionMapperComponent } from './item-collection-mapper/item-collection-mapper.component'; import { ItemRelationshipsComponent } from './item-relationships/item-relationships.component'; @@ -78,7 +77,6 @@ import { ItemRelationshipsComponent, ItemBitstreamsComponent, ItemVersionHistoryComponent, - ItemEditBitstreamComponent, ItemEditBitstreamBundleComponent, EditRelationshipComponent, EditRelationshipListComponent, diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream/item-edit-bitstream.component.html b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream/item-edit-bitstream.component.html deleted file mode 100644 index 0f0fad2199..0000000000 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream/item-edit-bitstream.component.html +++ /dev/null @@ -1,51 +0,0 @@ - -
- -
- - {{ bitstreamName }} - -
-
-
-
-
- {{ bitstream?.firstMetadataValue('dc.description') }} -
-
-
-
-
- - {{ (format$ | async)?.shortDescription }} - -
-
-
-
-
- - - - - - -
-
-
-
diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream/item-edit-bitstream.component.spec.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream/item-edit-bitstream.component.spec.ts deleted file mode 100644 index aafa5a4fe4..0000000000 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream/item-edit-bitstream.component.spec.ts +++ /dev/null @@ -1,145 +0,0 @@ -import { ItemEditBitstreamComponent } from './item-edit-bitstream.component'; -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; -import { ObjectUpdatesService } from '../../../../core/data/object-updates/object-updates.service'; -import { of as observableOf } from 'rxjs'; -import { Bitstream } from '../../../../core/shared/bitstream.model'; -import { TranslateModule } from '@ngx-translate/core'; -import { VarDirective } from '../../../../shared/utils/var.directive'; -import { NO_ERRORS_SCHEMA } from '@angular/core'; -import { BitstreamFormat } from '../../../../core/shared/bitstream-format.model'; -import { ResponsiveTableSizes } from '../../../../shared/responsive-table-sizes/responsive-table-sizes'; -import { ResponsiveColumnSizes } from '../../../../shared/responsive-table-sizes/responsive-column-sizes'; -import { createSuccessfulRemoteDataObject$ } from '../../../../shared/remote-data.utils'; -import { getBitstreamDownloadRoute } from '../../../../app-routing-paths'; -import { By } from '@angular/platform-browser'; -import { BrowserOnlyMockPipe } from '../../../../shared/testing/browser-only-mock.pipe'; - -let comp: ItemEditBitstreamComponent; -let fixture: ComponentFixture; - -const columnSizes = new ResponsiveTableSizes([ - new ResponsiveColumnSizes(2, 2, 3, 4, 4), - new ResponsiveColumnSizes(2, 3, 3, 3, 3), - new ResponsiveColumnSizes(2, 2, 2, 2, 2), - new ResponsiveColumnSizes(6, 5, 4, 3, 3) -]); - -const format = Object.assign(new BitstreamFormat(), { - shortDescription: 'PDF' -}); -const bitstream = Object.assign(new Bitstream(), { - uuid: 'bitstreamUUID', - name: 'Fake Bitstream', - bundleName: 'ORIGINAL', - description: 'Description', - _links: { - content: { href: 'content-link' } - }, - - format: createSuccessfulRemoteDataObject$(format) -}); -const fieldUpdate = { - field: bitstream, - changeType: undefined -}; -const date = new Date(); -const url = 'thisUrl'; - -let objectUpdatesService: ObjectUpdatesService; - -describe('ItemEditBitstreamComponent', () => { - beforeEach(waitForAsync(() => { - objectUpdatesService = jasmine.createSpyObj('objectUpdatesService', - { - getFieldUpdates: observableOf({ - [bitstream.uuid]: fieldUpdate, - }), - getFieldUpdatesExclusive: observableOf({ - [bitstream.uuid]: fieldUpdate, - }), - saveRemoveFieldUpdate: {}, - removeSingleFieldUpdate: {}, - saveAddFieldUpdate: {}, - discardFieldUpdates: {}, - reinstateFieldUpdates: observableOf(true), - initialize: {}, - getUpdatedFields: observableOf([bitstream]), - getLastModified: observableOf(date), - hasUpdates: observableOf(true), - isReinstatable: observableOf(false), - isValidPage: observableOf(true) - } - ); - - TestBed.configureTestingModule({ - imports: [TranslateModule.forRoot()], - declarations: [ - ItemEditBitstreamComponent, - VarDirective, - BrowserOnlyMockPipe, - ], - providers: [ - { provide: ObjectUpdatesService, useValue: objectUpdatesService } - ], schemas: [ - NO_ERRORS_SCHEMA - ] - }).compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(ItemEditBitstreamComponent); - comp = fixture.componentInstance; - comp.fieldUpdate = fieldUpdate; - comp.bundleUrl = url; - comp.columnSizes = columnSizes; - comp.ngOnChanges(undefined); - fixture.detectChanges(); - }); - - describe('when remove is called', () => { - beforeEach(() => { - comp.remove(); - }); - - it('should call saveRemoveFieldUpdate on objectUpdatesService', () => { - expect(objectUpdatesService.saveRemoveFieldUpdate).toHaveBeenCalledWith(url, bitstream); - }); - }); - - describe('when undo is called', () => { - beforeEach(() => { - comp.undo(); - }); - - it('should call removeSingleFieldUpdate on objectUpdatesService', () => { - expect(objectUpdatesService.removeSingleFieldUpdate).toHaveBeenCalledWith(url, bitstream.uuid); - }); - }); - - describe('when canRemove is called', () => { - it('should return true', () => { - expect(comp.canRemove()).toEqual(true); - }); - }); - - describe('when canUndo is called', () => { - it('should return false', () => { - expect(comp.canUndo()).toEqual(false); - }); - }); - - describe('when the component loads', () => { - it('should contain download button with a valid link to the bitstreams download page', () => { - fixture.detectChanges(); - const downloadBtnHref = fixture.debugElement.query(By.css('[data-test="download-button"]')).nativeElement.getAttribute('href'); - expect(downloadBtnHref).toEqual(comp.bitstreamDownloadUrl); - }); - }); - - describe('when the bitstreamDownloadUrl property gets populated', () => { - it('should contain the bitstream download page route', () => { - expect(comp.bitstreamDownloadUrl).not.toEqual(bitstream._links.content.href); - expect(comp.bitstreamDownloadUrl).toEqual(getBitstreamDownloadRoute(bitstream)); - }); - }); -}); diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream/item-edit-bitstream.component.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream/item-edit-bitstream.component.ts deleted file mode 100644 index fcb5c706ac..0000000000 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream/item-edit-bitstream.component.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { Component, Input, OnChanges, OnInit, SimpleChanges, ViewChild, ViewContainerRef } from '@angular/core'; -import { Bitstream } from '../../../../core/shared/bitstream.model'; -import cloneDeep from 'lodash/cloneDeep'; -import { ObjectUpdatesService } from '../../../../core/data/object-updates/object-updates.service'; -import { Observable } from 'rxjs'; -import { BitstreamFormat } from '../../../../core/shared/bitstream-format.model'; -import { getRemoteDataPayload, getFirstSucceededRemoteData } from '../../../../core/shared/operators'; -import { ResponsiveTableSizes } from '../../../../shared/responsive-table-sizes/responsive-table-sizes'; -import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; -import { FieldUpdate } from '../../../../core/data/object-updates/field-update.model'; -import { FieldChangeType } from '../../../../core/data/object-updates/field-change-type.model'; -import { getBitstreamDownloadRoute } from '../../../../app-routing-paths'; - -@Component({ - selector: 'ds-item-edit-bitstream', - styleUrls: ['../item-bitstreams.component.scss'], - templateUrl: './item-edit-bitstream.component.html', -}) -/** - * Component that displays a single bitstream of an item on the edit page - * Creates an embedded view of the contents - * (which means it'll be added to the parents html without a wrapping ds-item-edit-bitstream element) - */ -export class ItemEditBitstreamComponent implements OnChanges, OnInit { - - /** - * The view on the bitstream - */ - @ViewChild('bitstreamView', {static: true}) bitstreamView; - - /** - * The current field, value and state of the bitstream - */ - @Input() fieldUpdate: FieldUpdate; - - /** - * The url of the bundle - */ - @Input() bundleUrl: string; - - /** - * The bootstrap sizes used for the columns within this table - */ - @Input() columnSizes: ResponsiveTableSizes; - - /** - * The bitstream of this field - */ - bitstream: Bitstream; - - /** - * The bitstream's name - */ - bitstreamName: string; - - /** - * The bitstream's download url - */ - bitstreamDownloadUrl: string; - - /** - * The format of the bitstream - */ - format$: Observable; - - constructor(private objectUpdatesService: ObjectUpdatesService, - private dsoNameService: DSONameService, - private viewContainerRef: ViewContainerRef) { - } - - ngOnInit(): void { - this.viewContainerRef.createEmbeddedView(this.bitstreamView); - } - - /** - * Update the current bitstream and its format on changes - * @param changes - */ - ngOnChanges(changes: SimpleChanges): void { - this.bitstream = cloneDeep(this.fieldUpdate.field) as Bitstream; - this.bitstreamName = this.dsoNameService.getName(this.bitstream); - this.bitstreamDownloadUrl = getBitstreamDownloadRoute(this.bitstream); - this.format$ = this.bitstream.format.pipe( - getFirstSucceededRemoteData(), - getRemoteDataPayload() - ); - } - - /** - * Sends a new remove update for this field to the object updates service - */ - remove(): void { - this.objectUpdatesService.saveRemoveFieldUpdate(this.bundleUrl, this.bitstream); - } - - /** - * Cancels the current update for this field in the object updates service - */ - undo(): void { - this.objectUpdatesService.removeSingleFieldUpdate(this.bundleUrl, this.bitstream.uuid); - } - - /** - * Check if a user should be allowed to remove this field - */ - canRemove(): boolean { - return this.fieldUpdate.changeType !== FieldChangeType.REMOVE; - } - - /** - * Check if a user should be allowed to cancel the update to this field - */ - canUndo(): boolean { - return this.fieldUpdate.changeType >= 0; - } - -} From e8379db987317c5cb892989a21297ab5edce8669 Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Mon, 7 Oct 2024 11:49:54 +0200 Subject: [PATCH 0626/1286] 118223: Add item-bitstreams component tests --- .../item-bitstreams.component.spec.ts | 129 +++++++++++++++--- .../item-bitstreams.component.ts | 6 +- .../item-bitstreams.service.stub.ts | 74 ++++++++++ 3 files changed, 192 insertions(+), 17 deletions(-) create mode 100644 src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.stub.ts diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.spec.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.spec.ts index a5549a6ba0..d26f815316 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.spec.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.spec.ts @@ -26,9 +26,7 @@ import { createPaginatedList } from '../../../shared/testing/utils.test'; import { FieldChangeType } from '../../../core/data/object-updates/field-change-type.model'; import { BitstreamDataServiceStub } from '../../../shared/testing/bitstream-data-service.stub'; import { ItemBitstreamsService } from './item-bitstreams.service'; -import { ResponsiveTableSizes } from '../../../shared/responsive-table-sizes/responsive-table-sizes'; -import { ResponsiveColumnSizes } from '../../../shared/responsive-table-sizes/responsive-column-sizes'; -import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; +import { getItemBitstreamsServiceStub, ItemBitstreamsServiceStub } from './item-bitstreams.service.stub'; let comp: ItemBitstreamsComponent; let fixture: ComponentFixture; @@ -80,7 +78,7 @@ let objectCache: ObjectCacheService; let requestService: RequestService; let searchConfig: SearchConfigurationService; let bundleService: BundleDataService; -let itemBitstreamsService: ItemBitstreamsService; +let itemBitstreamsService: ItemBitstreamsServiceStub; describe('ItemBitstreamsComponent', () => { beforeEach(waitForAsync(() => { @@ -152,18 +150,7 @@ describe('ItemBitstreamsComponent', () => { patch: createSuccessfulRemoteDataObject$({}), }); - itemBitstreamsService = jasmine.createSpyObj('itemBitstreamsService', { - getColumnSizes: new ResponsiveTableSizes([ - new ResponsiveColumnSizes(2, 2, 3, 4, 4), - new ResponsiveColumnSizes(2, 3, 3, 3, 3), - new ResponsiveColumnSizes(2, 2, 2, 2, 2), - new ResponsiveColumnSizes(6, 5, 4, 3, 3) - ]), - getSelectedBitstream$: observableOf({}), - getInitialBundlesPaginationOptions: new PaginationComponentOptions(), - removeMarkedBitstreams: createSuccessfulRemoteDataObject$({}), - displayNotifications: undefined, - }); + itemBitstreamsService = getItemBitstreamsServiceStub(); TestBed.configureTestingModule({ imports: [TranslateModule.forRoot()], @@ -218,4 +205,114 @@ describe('ItemBitstreamsComponent', () => { expect(objectUpdatesService.reinstateFieldUpdates).toHaveBeenCalledWith(bundle.self); }); }); + + describe('moveUp', () => { + it('should move the selected bitstream up', () => { + itemBitstreamsService.hasSelectedBitstream.and.returnValue(true); + + const event = { + preventDefault: () => {/* Intentionally empty */}, + } as KeyboardEvent; + comp.moveUp(event); + + expect(itemBitstreamsService.moveSelectedBitstreamUp).toHaveBeenCalled(); + }); + + it('should not do anything if no bitstream is selected', () => { + itemBitstreamsService.hasSelectedBitstream.and.returnValue(false); + + const event = { + preventDefault: () => {/* Intentionally empty */}, + } as KeyboardEvent; + comp.moveUp(event); + + expect(itemBitstreamsService.moveSelectedBitstreamUp).not.toHaveBeenCalled(); + }); + }); + + describe('moveDown', () => { + it('should move the selected bitstream down', () => { + itemBitstreamsService.hasSelectedBitstream.and.returnValue(true); + + const event = { + preventDefault: () => {/* Intentionally empty */}, + } as KeyboardEvent; + comp.moveDown(event); + + expect(itemBitstreamsService.moveSelectedBitstreamDown).toHaveBeenCalled(); + }); + + it('should not do anything if no bitstream is selected', () => { + itemBitstreamsService.hasSelectedBitstream.and.returnValue(false); + + const event = { + preventDefault: () => {/* Intentionally empty */}, + } as KeyboardEvent; + comp.moveDown(event); + + expect(itemBitstreamsService.moveSelectedBitstreamDown).not.toHaveBeenCalled(); + }); + }); + + describe('cancelSelection', () => { + it('should cancel the selection', () => { + itemBitstreamsService.hasSelectedBitstream.and.returnValue(true); + + const event = { + preventDefault: () => {/* Intentionally empty */}, + } as KeyboardEvent; + comp.cancelSelection(event); + + expect(itemBitstreamsService.cancelSelection).toHaveBeenCalled(); + }); + + it('should not do anything if no bitstream is selected', () => { + itemBitstreamsService.hasSelectedBitstream.and.returnValue(false); + + const event = { + preventDefault: () => {/* Intentionally empty */}, + } as KeyboardEvent; + comp.cancelSelection(event); + + expect(itemBitstreamsService.cancelSelection).not.toHaveBeenCalled(); + }); + }); + + describe('clearSelection', () => { + it('should clear the selection', () => { + itemBitstreamsService.hasSelectedBitstream.and.returnValue(true); + + const event = { + target: document.createElement('BODY'), + preventDefault: () => {/* Intentionally empty */}, + } as unknown as KeyboardEvent; + comp.clearSelection(event); + + expect(itemBitstreamsService.clearSelection).toHaveBeenCalled(); + }); + + it('should not do anything if no bitstream is selected', () => { + itemBitstreamsService.hasSelectedBitstream.and.returnValue(false); + + const event = { + target: document.createElement('BODY'), + preventDefault: () => {/* Intentionally empty */}, + } as unknown as KeyboardEvent; + comp.clearSelection(event); + + expect(itemBitstreamsService.clearSelection).not.toHaveBeenCalled(); + }); + + it('should not do anything if the event target is not \'BODY\'', () => { + itemBitstreamsService.hasSelectedBitstream.and.returnValue(true); + + const event = { + target: document.createElement('NOT-BODY'), + preventDefault: () => {/* Intentionally empty */}, + } as unknown as KeyboardEvent; + comp.clearSelection(event); + + expect(itemBitstreamsService.clearSelection).not.toHaveBeenCalled(); + }); + }); }); diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts index f77eda02fb..6ee5dcb545 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts @@ -137,7 +137,11 @@ export class ItemBitstreamsComponent extends AbstractItemUpdateComponent impleme // Only when no specific element is in focus do we want to clear the currently selected bitstream // Otherwise we might clear the selection when a different action was intended, e.g. clicking a button or selecting // a different bitstream. - if (event.target instanceof Element && event.target.tagName === 'BODY') { + if ( + this.itemBitstreamsService.hasSelectedBitstream() && + event.target instanceof Element && + event.target.tagName === 'BODY' + ) { event.preventDefault(); this.itemBitstreamsService.clearSelection(); } diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.stub.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.stub.ts new file mode 100644 index 0000000000..0521bf47f6 --- /dev/null +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.stub.ts @@ -0,0 +1,74 @@ +import { of } from 'rxjs'; +import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; +import { ResponsiveTableSizes } from '../../../shared/responsive-table-sizes/responsive-table-sizes'; +import { ResponsiveColumnSizes } from '../../../shared/responsive-table-sizes/responsive-column-sizes'; +import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; + +export function getItemBitstreamsServiceStub(): ItemBitstreamsServiceStub { + return new ItemBitstreamsServiceStub(); +} + +export class ItemBitstreamsServiceStub { + getSelectedBitstream$ = jasmine.createSpy('getSelectedBitstream$').and + .returnValue(of(null)); + + getSelectedBitstream = jasmine.createSpy('getSelectedBitstream').and + .returnValue(null); + + hasSelectedBitstream = jasmine.createSpy('hasSelectedBitstream').and + .returnValue(false); + + selectBitstreamEntry = jasmine.createSpy('selectBitstreamEntry'); + + clearSelection = jasmine.createSpy('clearSelection'); + + cancelSelection = jasmine.createSpy('cancelSelection'); + + moveSelectedBitstreamUp = jasmine.createSpy('moveSelectedBitstreamUp'); + + moveSelectedBitstreamDown = jasmine.createSpy('moveSelectedBitstreamDown'); + + performBitstreamMoveRequest = jasmine.createSpy('performBitstreamMoveRequest'); + + getInitialBundlesPaginationOptions = jasmine.createSpy('getInitialBundlesPaginationOptions').and + .returnValue(new PaginationComponentOptions()); + + getInitialBitstreamsPaginationOptions = jasmine.createSpy('getInitialBitstreamsPaginationOptions').and + .returnValue(new PaginationComponentOptions()); + + getColumnSizes = jasmine.createSpy('getColumnSizes').and + .returnValue( + new ResponsiveTableSizes([ + new ResponsiveColumnSizes(2, 2, 3, 4, 4), + new ResponsiveColumnSizes(2, 3, 3, 3, 3), + new ResponsiveColumnSizes(2, 2, 2, 2, 2), + new ResponsiveColumnSizes(6, 5, 4, 3, 3) + ]) + ); + + displayNotifications = jasmine.createSpy('displayNotifications'); + + displayFailedResponseNotifications = jasmine.createSpy('displayFailedResponseNotifications'); + + displayErrorNotification = jasmine.createSpy('displayErrorNotification'); + + displaySuccessFulResponseNotifications = jasmine.createSpy('displaySuccessFulResponseNotifications'); + + displaySuccessNotification = jasmine.createSpy('displaySuccessNotification'); + + removeMarkedBitstreams = jasmine.createSpy('removeMarkedBitstreams').and + .returnValue(createSuccessfulRemoteDataObject$({})); + + mapBitstreamsToTableEntries = jasmine.createSpy('mapBitstreamsToTableEntries').and + .returnValue([]); + + nameToHeader = jasmine.createSpy('nameToHeader').and.returnValue('header'); + + stripWhiteSpace = jasmine.createSpy('stripWhiteSpace').and.returnValue('string'); + + announceSelect = jasmine.createSpy('announceSelect'); + + announceMove = jasmine.createSpy('announceMove'); + + announceCancel = jasmine.createSpy('announceCancel'); +} From 7fb4755abaa1759f175ea2d2cff6d93af00d946e Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Tue, 8 Oct 2024 15:51:00 +0200 Subject: [PATCH 0627/1286] 118223: Add item-edit-bitstream-bundle component tests --- ...em-edit-bitstream-bundle.component.spec.ts | 302 ++++++++++++++++-- .../item-edit-bitstream-bundle.component.ts | 3 +- 2 files changed, 285 insertions(+), 20 deletions(-) diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.spec.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.spec.ts index 25274b8941..6008b5431f 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.spec.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.spec.ts @@ -7,14 +7,19 @@ import { Bundle } from '../../../../core/shared/bundle.model'; import { ResponsiveTableSizes } from '../../../../shared/responsive-table-sizes/responsive-table-sizes'; import { ResponsiveColumnSizes } from '../../../../shared/responsive-table-sizes/responsive-column-sizes'; import { BundleDataService } from '../../../../core/data/bundle-data.service'; -import { of as observableOf } from 'rxjs'; +import { of as observableOf, of, Subject } from 'rxjs'; import { ObjectUpdatesService } from '../../../../core/data/object-updates/object-updates.service'; import { PaginationServiceStub } from '../../../../shared/testing/pagination-service.stub'; import { RequestService } from '../../../../core/data/request.service'; import { getMockRequestService } from '../../../../shared/mocks/request.service.mock'; -import { ItemBitstreamsService } from '../item-bitstreams.service'; +import { ItemBitstreamsService, BitstreamTableEntry, SelectedBitstreamTableEntry } from '../item-bitstreams.service'; import { PaginationService } from '../../../../core/pagination/pagination.service'; -import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model'; +import { getItemBitstreamsServiceStub, ItemBitstreamsServiceStub } from '../item-bitstreams.service.stub'; +import { FieldUpdate } from '../../../../core/data/object-updates/field-update.model'; +import { FieldChangeType } from '../../../../core/data/object-updates/field-change-type.model'; +import { createSuccessfulRemoteDataObject$ } from '../../../../shared/remote-data.utils'; +import { createPaginatedList } from '../../../../shared/testing/utils.test'; +import { CdkDragDrop } from '@angular/cdk/drag-drop'; describe('ItemEditBitstreamBundleComponent', () => { let comp: ItemEditBitstreamBundleComponent; @@ -43,25 +48,20 @@ describe('ItemEditBitstreamBundleComponent', () => { const restEndpoint = 'fake-rest-endpoint'; const bundleService = jasmine.createSpyObj('bundleService', { getBitstreamsEndpoint: observableOf(restEndpoint), - getBitstreams: null, + getBitstreams: createSuccessfulRemoteDataObject$(createPaginatedList([])), }); - const objectUpdatesService = { - initialize: () => { - // do nothing - }, - }; - - const itemBitstreamsService = jasmine.createSpyObj('itemBitstreamsService', { - getInitialBitstreamsPaginationOptions: Object.assign(new PaginationComponentOptions(), { - id: 'bundles-pagination-options', - currentPage: 1, - pageSize: 9999 - }), - getSelectedBitstream$: observableOf({}), - }); + let objectUpdatesService: any; + let itemBitstreamsService: ItemBitstreamsServiceStub; beforeEach(waitForAsync(() => { + objectUpdatesService = jasmine.createSpyObj('objectUpdatesService', { + initialize: undefined, + getFieldUpdatesExclusive: of(null), + }); + + itemBitstreamsService = getItemBitstreamsServiceStub(); + TestBed.configureTestingModule({ imports: [TranslateModule.forRoot()], declarations: [ItemEditBitstreamBundleComponent], @@ -92,4 +92,270 @@ describe('ItemEditBitstreamBundleComponent', () => { it('should create an embedded view of the component', () => { expect(viewContainerRef.createEmbeddedView).toHaveBeenCalled(); }); + + describe('on selected entry change', () => { + let paginationComponent: any; + let testSubject: Subject = new Subject(); + + beforeEach(() => { + paginationComponent = jasmine.createSpyObj('paginationComponent', { + doPageChange: undefined, + }); + comp.paginationComponent = paginationComponent; + + spyOn(comp, 'getCurrentPageSize').and.returnValue(2); + }); + + it('should move to the page the selected entry is on if were not on that page', () => { + const selectedA: SelectedBitstreamTableEntry = { + bitstream: null, + bundle: bundle, + bundleSize: 5, + originalPosition: 1, + currentPosition: 1, + }; + + const selectedB: SelectedBitstreamTableEntry = { + bitstream: null, + bundle: bundle, + bundleSize: 5, + originalPosition: 1, + currentPosition: 2, + }; + + comp.handleSelectedEntryChange(selectedA, selectedB); + expect(paginationComponent.doPageChange).toHaveBeenCalledWith(2); + }); + + it('should not change page when we are already on the correct page', () => { + const selectedA: SelectedBitstreamTableEntry = { + bitstream: null, + bundle: bundle, + bundleSize: 5, + originalPosition: 0, + currentPosition: 0, + }; + + const selectedB: SelectedBitstreamTableEntry = { + bitstream: null, + bundle: bundle, + bundleSize: 5, + originalPosition: 0, + currentPosition: 1, + }; + + comp.handleSelectedEntryChange(selectedA, selectedB); + expect(paginationComponent.doPageChange).not.toHaveBeenCalled(); + }); + + it('should change to the original page when cancelling', () => { + const selectedA: SelectedBitstreamTableEntry = { + bitstream: null, + bundle: bundle, + bundleSize: 5, + originalPosition: 3, + currentPosition: 0, + }; + + const selectedB = null; + + comp.handleSelectedEntryChange(selectedA, selectedB); + expect(paginationComponent.doPageChange).toHaveBeenCalledWith(2); + }); + + it('should not change page when we are already on the correct page when cancelling', () => { + const selectedA: SelectedBitstreamTableEntry = { + bitstream: null, + bundle: bundle, + bundleSize: 5, + originalPosition: 0, + currentPosition: 3, + }; + + const selectedB = null; + + comp.handleSelectedEntryChange(selectedA, selectedB); + expect(paginationComponent.doPageChange).not.toHaveBeenCalled(); + }); + }); + + describe('getRowClass', () => { + it('should return \'table-info\' when the bitstream is the selected bitstream', () => { + itemBitstreamsService.getSelectedBitstream.and.returnValue({ + bitstream: { id: 'bitstream-id'} + }); + + const bitstreamEntry = { + id: 'bitstream-id', + } as BitstreamTableEntry; + + expect(comp.getRowClass(undefined, bitstreamEntry)).toEqual('table-info'); + }); + + it('should return \'table-warning\' when the update is of type \'UPDATE\'', () => { + const update = { + changeType: FieldChangeType.UPDATE, + } as FieldUpdate; + + expect(comp.getRowClass(update, undefined)).toEqual('table-warning'); + }); + + it('should return \'table-success\' when the update is of type \'ADD\'', () => { + const update = { + changeType: FieldChangeType.ADD, + } as FieldUpdate; + + expect(comp.getRowClass(update, undefined)).toEqual('table-success'); + }); + + it('should return \'table-danger\' when the update is of type \'REMOVE\'', () => { + const update = { + changeType: FieldChangeType.REMOVE, + } as FieldUpdate; + + expect(comp.getRowClass(update, undefined)).toEqual('table-danger'); + }); + + it('should return \'bg-white\' in any other case', () => { + const update = { + changeType: undefined, + } as FieldUpdate; + + expect(comp.getRowClass(update, undefined)).toEqual('bg-white'); + }); + }); + + describe('drag', () => { + let dragTooltip; + let paginationComponent; + + beforeEach(() => { + dragTooltip = jasmine.createSpyObj('dragTooltip', { + open: undefined, + close: undefined, + }); + comp.dragTooltip = dragTooltip; + }); + + describe('Start', () => { + it('should open the tooltip when there are multiple pages', () => { + paginationComponent = jasmine.createSpyObj('paginationComponent', { + doPageChange: undefined, + }, { + shouldShowBottomPager: of(true), + }); + comp.paginationComponent = paginationComponent; + + comp.dragStart(); + expect(dragTooltip.open).toHaveBeenCalled(); + }); + + it('should not open the tooltip when there is only a single page', () => { + paginationComponent = jasmine.createSpyObj('paginationComponent', { + doPageChange: undefined, + }, { + shouldShowBottomPager: of(false), + }); + comp.paginationComponent = paginationComponent; + + comp.dragStart(); + expect(dragTooltip.open).not.toHaveBeenCalled(); + }); + }); + + describe('end', () => { + it('should always close the tooltip', () => { + paginationComponent = jasmine.createSpyObj('paginationComponent', { + doPageChange: undefined, + }, { + shouldShowBottomPager: of(false), + }); + comp.paginationComponent = paginationComponent; + + comp.dragEnd(); + expect(dragTooltip.close).toHaveBeenCalled(); + }); + }); + }); + + describe('drop', () => { + it('should correctly move the bitstream on drop', () => { + const event = { + previousIndex: 1, + currentIndex: 8, + dropPoint: { x: 100, y: 200 }, + } as CdkDragDrop; + + comp.drop(event); + expect(itemBitstreamsService.performBitstreamMoveRequest).toHaveBeenCalledWith(jasmine.any(Bundle), 1, 8, jasmine.any(Function)); + }); + + it('should not move the bitstream if dropped in the same place', () => { + const event = { + previousIndex: 1, + currentIndex: 1, + dropPoint: { x: 100, y: 200 }, + } as CdkDragDrop; + + comp.drop(event); + expect(itemBitstreamsService.performBitstreamMoveRequest).not.toHaveBeenCalled(); + }); + + it('should move to a different page if dropped on a page number', () => { + spyOn(document, 'elementFromPoint').and.returnValue({ + textContent: '2', + classList: { contains: (token: string) => true }, + } as Element); + + const event = { + previousIndex: 1, + currentIndex: 1, + dropPoint: { x: 100, y: 200 }, + } as CdkDragDrop; + + comp.drop(event); + expect(itemBitstreamsService.performBitstreamMoveRequest).toHaveBeenCalledWith(jasmine.any(Bundle), 1, 20, jasmine.any(Function)); + }); + }); + + describe('select', () => { + it('should select the bitstream', () => { + const event = new KeyboardEvent('keydown'); + spyOnProperty(event, 'repeat', 'get').and.returnValue(false); + + const entry = { } as BitstreamTableEntry; + comp.tableEntries$.next([entry]); + + comp.select(event, entry); + expect(itemBitstreamsService.selectBitstreamEntry).toHaveBeenCalledWith(jasmine.objectContaining({ bitstream: entry })); + }); + + it('should cancel the selection if the bitstream already is selected', () => { + const event = new KeyboardEvent('keydown'); + spyOnProperty(event, 'repeat', 'get').and.returnValue(false); + + const entry = { } as BitstreamTableEntry; + comp.tableEntries$.next([entry]); + + itemBitstreamsService.getSelectedBitstream.and.returnValue({ bitstream: entry }); + + comp.select(event, entry); + expect(itemBitstreamsService.selectBitstreamEntry).not.toHaveBeenCalled(); + expect(itemBitstreamsService.cancelSelection).toHaveBeenCalled(); + }); + + it('should not do anything if the user is holding down the select key', () => { + const event = new KeyboardEvent('keydown'); + spyOnProperty(event, 'repeat', 'get').and.returnValue(true); + + const entry = { } as BitstreamTableEntry; + comp.tableEntries$.next([entry]); + + itemBitstreamsService.getSelectedBitstream.and.returnValue({ bitstream: entry }); + + comp.select(event, entry); + expect(itemBitstreamsService.selectBitstreamEntry).not.toHaveBeenCalled(); + expect(itemBitstreamsService.cancelSelection).not.toHaveBeenCalled(); + }); + }); }); diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts index 4079ad225b..7a70ba80dd 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts @@ -243,9 +243,8 @@ export class ItemEditBitstreamBundleComponent implements OnInit, OnDestroy { * Handles a change in selected bitstream by changing the pagination if the change happened on a different page * @param previousSelectedEntry The previously selected entry * @param currentSelectedEntry The currently selected entry - * @protected */ - protected handleSelectedEntryChange( + handleSelectedEntryChange( previousSelectedEntry: SelectedBitstreamTableEntry, currentSelectedEntry: SelectedBitstreamTableEntry ) { From 2b1b9d83d7d2e58a8f26b9843202f1705110fea5 Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Wed, 9 Oct 2024 11:14:28 +0200 Subject: [PATCH 0628/1286] 118223: Include selection action with selection --- .../item-bitstreams.service.spec.ts | 176 ++++++++++++++---- .../item-bitstreams.service.stub.ts | 2 +- .../item-bitstreams.service.ts | 86 ++++++--- ...em-edit-bitstream-bundle.component.spec.ts | 35 +--- .../item-edit-bitstream-bundle.component.ts | 44 +++-- 5 files changed, 237 insertions(+), 106 deletions(-) diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.spec.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.spec.ts index 94adb5f23a..f2af25f22f 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.spec.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.spec.ts @@ -77,20 +77,20 @@ describe('ItemBitstreamsService', () => { describe('selectBitstreamEntry', () => { it('should correctly make getSelectedBitstream$ emit', fakeAsync(() => { - const emittedEntries = []; + const emittedActions = []; - service.getSelectedBitstream$().subscribe(selected => emittedEntries.push(selected)); + service.getSelectionAction$().subscribe(selected => emittedActions.push(selected)); - expect(emittedEntries.length).toBe(1); - expect(emittedEntries[0]).toBeNull(); + expect(emittedActions.length).toBe(1); + expect(emittedActions[0]).toBeNull(); const entry = Object.assign({}, defaultEntry); service.selectBitstreamEntry(entry); tick(); - expect(emittedEntries.length).toBe(2); - expect(emittedEntries[1]).toEqual(entry); + expect(emittedActions.length).toBe(2); + expect(emittedActions[1]).toEqual({ action: 'Selected', selectedEntry: entry }); })); it('should correctly make getSelectedBitstream return the bitstream', () => { @@ -112,26 +112,26 @@ describe('ItemBitstreamsService', () => { }); it('should do nothing if no entry was provided', fakeAsync(() => { - const emittedEntries = []; + const emittedActions = []; - service.getSelectedBitstream$().subscribe(selected => emittedEntries.push(selected)); + service.getSelectionAction$().subscribe(selected => emittedActions.push(selected)); - expect(emittedEntries.length).toBe(1); - expect(emittedEntries[0]).toBeNull(); + expect(emittedActions.length).toBe(1); + expect(emittedActions[0]).toBeNull(); const entry = Object.assign({}, defaultEntry); service.selectBitstreamEntry(entry); tick(); - expect(emittedEntries.length).toBe(2); - expect(emittedEntries[1]).toEqual(entry); + expect(emittedActions.length).toBe(2); + expect(emittedActions[1]).toEqual({ action: 'Selected', selectedEntry: entry }); service.selectBitstreamEntry(null); tick(); - expect(emittedEntries.length).toBe(2); - expect(emittedEntries[1]).toEqual(entry); + expect(emittedActions.length).toBe(2); + expect(emittedActions[1]).toEqual({ action: 'Selected', selectedEntry: entry }); })); it('should announce the selected bitstream', () => { @@ -146,41 +146,41 @@ describe('ItemBitstreamsService', () => { describe('clearSelection', () => { it('should clear the selected bitstream', fakeAsync(() => { - const emittedEntries = []; + const emittedActions = []; - service.getSelectedBitstream$().subscribe(selected => emittedEntries.push(selected)); + service.getSelectionAction$().subscribe(selected => emittedActions.push(selected)); - expect(emittedEntries.length).toBe(1); - expect(emittedEntries[0]).toBeNull(); + expect(emittedActions.length).toBe(1); + expect(emittedActions[0]).toBeNull(); const entry = Object.assign({}, defaultEntry); service.selectBitstreamEntry(entry); tick(); - expect(emittedEntries.length).toBe(2); - expect(emittedEntries[1]).toEqual(entry); + expect(emittedActions.length).toBe(2); + expect(emittedActions[1]).toEqual({ action: 'Selected', selectedEntry: entry }); service.clearSelection(); tick(); - expect(emittedEntries.length).toBe(3); - expect(emittedEntries[2]).toBeNull(); + expect(emittedActions.length).toBe(3); + expect(emittedActions[2]).toEqual({ action: 'Cleared', selectedEntry: entry }); })); it('should not do anything if there is no selected bitstream', fakeAsync(() => { - const emittedEntries = []; + const emittedActions = []; - service.getSelectedBitstream$().subscribe(selected => emittedEntries.push(selected)); + service.getSelectionAction$().subscribe(selected => emittedActions.push(selected)); - expect(emittedEntries.length).toBe(1); - expect(emittedEntries[0]).toBeNull(); + expect(emittedActions.length).toBe(1); + expect(emittedActions[0]).toBeNull(); service.clearSelection(); tick(); - expect(emittedEntries.length).toBe(1); - expect(emittedEntries[0]).toBeNull(); + expect(emittedActions.length).toBe(1); + expect(emittedActions[0]).toBeNull(); })); it('should announce the cleared bitstream', () => { @@ -225,27 +225,53 @@ describe('ItemBitstreamsService', () => { }); describe('cancelSelection', () => { - it('should clear the selected bitstream', fakeAsync(() => { - const emittedEntries = []; + it('should clear the selected bitstream if it has not moved', fakeAsync(() => { + const emittedActions = []; - service.getSelectedBitstream$().subscribe(selected => emittedEntries.push(selected)); + service.getSelectionAction$().subscribe(selected => emittedActions.push(selected)); - expect(emittedEntries.length).toBe(1); - expect(emittedEntries[0]).toBeNull(); + expect(emittedActions.length).toBe(1); + expect(emittedActions[0]).toBeNull(); const entry = Object.assign({}, defaultEntry); service.selectBitstreamEntry(entry); tick(); - expect(emittedEntries.length).toBe(2); - expect(emittedEntries[1]).toEqual(entry); + expect(emittedActions.length).toBe(2); + expect(emittedActions[1]).toEqual({ action: 'Selected', selectedEntry: entry }); service.cancelSelection(); tick(); - expect(emittedEntries.length).toBe(3); - expect(emittedEntries[2]).toBeNull(); + expect(emittedActions.length).toBe(3); + expect(emittedActions[2]).toEqual({ action: 'Cleared', selectedEntry: entry }); + })); + + it('should cancel the selected bitstream if it has moved', fakeAsync(() => { + const emittedActions = []; + + service.getSelectionAction$().subscribe(selected => emittedActions.push(selected)); + + expect(emittedActions.length).toBe(1); + expect(emittedActions[0]).toBeNull(); + + const entry = Object.assign({}, defaultEntry, { + originalPosition: 0, + currentPosition: 3, + }); + + service.selectBitstreamEntry(entry); + tick(); + + expect(emittedActions.length).toBe(2); + expect(emittedActions[1]).toEqual({ action: 'Selected', selectedEntry: entry }); + + service.cancelSelection(); + tick(); + + expect(emittedActions.length).toBe(3); + expect(emittedActions[2]).toEqual({ action: 'Cancelled', selectedEntry: entry }); })); it('should announce a clear if the bitstream has not moved', () => { @@ -359,6 +385,44 @@ describe('ItemBitstreamsService', () => { expect(service.getSelectedBitstream()).toEqual(movedEntry); }); + it('should emit the move', fakeAsync(() => { + const emittedActions = []; + + service.getSelectionAction$().subscribe(selected => emittedActions.push(selected)); + + expect(emittedActions.length).toBe(1); + expect(emittedActions[0]).toBeNull(); + + const startPosition = 7; + const endPosition = startPosition - 1; + + const entry = Object.assign({}, defaultEntry, + { + originalPosition: 5, + currentPosition: startPosition, + } + ); + + const movedEntry = Object.assign({}, defaultEntry, + { + originalPosition: 5, + currentPosition: endPosition, + } + ); + + service.selectBitstreamEntry(entry); + tick(); + + expect(emittedActions.length).toBe(2); + expect(emittedActions[1]).toEqual({ action: 'Selected', selectedEntry: entry }); + + service.moveSelectedBitstreamUp(); + tick(); + + expect(emittedActions.length).toBe(3); + expect(emittedActions[2]).toEqual({ action: 'Moved', selectedEntry: movedEntry }); + })); + it('should announce the move', () => { const startPosition = 7; const endPosition = startPosition - 1; @@ -424,6 +488,44 @@ describe('ItemBitstreamsService', () => { expect(service.getSelectedBitstream()).toEqual(movedEntry); }); + it('should emit the move', fakeAsync(() => { + const emittedActions = []; + + service.getSelectionAction$().subscribe(selected => emittedActions.push(selected)); + + expect(emittedActions.length).toBe(1); + expect(emittedActions[0]).toBeNull(); + + const startPosition = 7; + const endPosition = startPosition + 1; + + const entry = Object.assign({}, defaultEntry, + { + originalPosition: 5, + currentPosition: startPosition, + } + ); + + const movedEntry = Object.assign({}, defaultEntry, + { + originalPosition: 5, + currentPosition: endPosition, + } + ); + + service.selectBitstreamEntry(entry); + tick(); + + expect(emittedActions.length).toBe(2); + expect(emittedActions[1]).toEqual({ action: 'Selected', selectedEntry: entry }); + + service.moveSelectedBitstreamDown(); + tick(); + + expect(emittedActions.length).toBe(3); + expect(emittedActions[2]).toEqual({ action: 'Moved', selectedEntry: movedEntry }); + })); + it('should announce the move', () => { const startPosition = 7; const endPosition = startPosition + 1; diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.stub.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.stub.ts index 0521bf47f6..7aac79fe69 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.stub.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.stub.ts @@ -9,7 +9,7 @@ export function getItemBitstreamsServiceStub(): ItemBitstreamsServiceStub { } export class ItemBitstreamsServiceStub { - getSelectedBitstream$ = jasmine.createSpy('getSelectedBitstream$').and + getSelectionAction$ = jasmine.createSpy('getSelectedBitstream$').and .returnValue(of(null)); getSelectedBitstream = jasmine.createSpy('getSelectedBitstream').and diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.ts index 5b5fb7d63c..2329107c29 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.ts @@ -87,6 +87,24 @@ export interface SelectedBitstreamTableEntry { currentPosition: number, } +/** + * Interface storing data regarding a change in selected bitstream + */ +export interface SelectionAction { + /** + * The different types of actions: + * - Selected: Bitstream was selected + * - Moved: Bitstream was moved + * - Cleared: Selection was cleared, bitstream remains at its current position + * - Cancelled: Selection was cancelled, bitstream returns to its original position + */ + action: 'Selected' | 'Moved' | 'Cleared' | 'Cancelled' + /** + * The table entry to which the selection action applies + */ + selectedEntry: SelectedBitstreamTableEntry, +} + /** * This service handles the selection and updating of the bitstreams and their order on the * 'Edit Item' -> 'Bitstreams' page. @@ -99,7 +117,7 @@ export class ItemBitstreamsService { /** * BehaviorSubject which emits every time the selected bitstream changes. */ - protected selectedBitstream$: BehaviorSubject = new BehaviorSubject(null); + protected selectionAction$: BehaviorSubject = new BehaviorSubject(null); protected isPerformingMoveRequest = false; @@ -116,45 +134,68 @@ export class ItemBitstreamsService { } /** - * Returns the observable emitting the currently selected bitstream + * Returns the observable emitting the selection actions */ - getSelectedBitstream$(): Observable { - return this.selectedBitstream$; + getSelectionAction$(): Observable { + return this.selectionAction$; + } + + /** + * Returns the latest selection action + */ + getSelectionAction(): SelectionAction { + const action = this.selectionAction$.value; + + if (hasNoValue(action)) { + return null; + } + + return Object.assign({}, action); + } + + /** + * Returns true if there currently is a selected bitstream + */ + hasSelectedBitstream(): boolean { + const selectionAction = this.getSelectionAction(); + + if (hasNoValue(selectionAction)) { + return false; + } + + const action = selectionAction.action; + + return action === 'Selected' || action === 'Moved'; } /** * Returns a copy of the currently selected bitstream */ getSelectedBitstream(): SelectedBitstreamTableEntry { - const selected = this.selectedBitstream$.getValue(); - - if (hasNoValue(selected)) { - return selected; + if (!this.hasSelectedBitstream()) { + return null; } - return Object.assign({}, selected); - } - - hasSelectedBitstream(): boolean { - return hasValue(this.getSelectedBitstream()); + const selectionAction = this.getSelectionAction(); + return Object.assign({}, selectionAction.selectedEntry); } /** * Select the provided entry */ selectBitstreamEntry(entry: SelectedBitstreamTableEntry) { - if (hasValue(entry) && entry !== this.selectedBitstream$.getValue()) { + if (hasValue(entry) && entry.bitstream !== this.getSelectedBitstream()?.bitstream) { this.announceSelect(entry.bitstream.name); - this.updateSelectedBitstream(entry); + this.updateSelectionAction({ action: 'Selected', selectedEntry: entry }); } } /** - * Makes the {@link selectedBitstream$} observable emit the provided {@link SelectedBitstreamTableEntry}. + * Makes the {@link selectionAction$} observable emit the provided {@link SelectedBitstreamTableEntry}. * @protected */ - protected updateSelectedBitstream(entry: SelectedBitstreamTableEntry) { - this.selectedBitstream$.next(entry); + protected updateSelectionAction(action: SelectionAction) { + this.selectionAction$.next(action); } /** @@ -164,7 +205,7 @@ export class ItemBitstreamsService { const selected = this.getSelectedBitstream(); if (hasValue(selected)) { - this.updateSelectedBitstream(null); + this.updateSelectionAction({ action: 'Cleared', selectedEntry: selected }); this.announceClear(selected.bitstream.name); if (selected.currentPosition !== selected.originalPosition) { @@ -184,7 +225,6 @@ export class ItemBitstreamsService { return; } - this.updateSelectedBitstream(null); const originalPosition = selected.originalPosition; const currentPosition = selected.currentPosition; @@ -192,9 +232,11 @@ export class ItemBitstreamsService { // If the selected bitstream has not moved, there is no need to return it to its original position if (currentPosition === originalPosition) { this.announceClear(selected.bitstream.name); + this.updateSelectionAction({ action: 'Cleared', selectedEntry: selected }); } else { this.announceCancel(selected.bitstream.name, originalPosition); this.performBitstreamMoveRequest(selected.bundle, currentPosition, originalPosition); + this.updateSelectionAction({ action: 'Cancelled', selectedEntry: selected }); } } @@ -219,7 +261,7 @@ export class ItemBitstreamsService { }; this.performBitstreamMoveRequest(selected.bundle, originalPosition, newPosition, onRequestCompleted); - this.updateSelectedBitstream(selected); + this.updateSelectionAction({ action: 'Moved', selectedEntry: selected }); } } @@ -244,7 +286,7 @@ export class ItemBitstreamsService { }; this.performBitstreamMoveRequest(selected.bundle, originalPosition, newPosition, onRequestCompleted); - this.updateSelectedBitstream(selected); + this.updateSelectionAction({ action: 'Moved', selectedEntry: selected }); } } diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.spec.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.spec.ts index 6008b5431f..26a1b0e913 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.spec.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.spec.ts @@ -107,15 +107,8 @@ describe('ItemEditBitstreamBundleComponent', () => { }); it('should move to the page the selected entry is on if were not on that page', () => { - const selectedA: SelectedBitstreamTableEntry = { - bitstream: null, - bundle: bundle, - bundleSize: 5, - originalPosition: 1, - currentPosition: 1, - }; - const selectedB: SelectedBitstreamTableEntry = { + const entry: SelectedBitstreamTableEntry = { bitstream: null, bundle: bundle, bundleSize: 5, @@ -123,20 +116,12 @@ describe('ItemEditBitstreamBundleComponent', () => { currentPosition: 2, }; - comp.handleSelectedEntryChange(selectedA, selectedB); + comp.handleSelectionAction({ action: 'Moved', selectedEntry: entry }); expect(paginationComponent.doPageChange).toHaveBeenCalledWith(2); }); it('should not change page when we are already on the correct page', () => { - const selectedA: SelectedBitstreamTableEntry = { - bitstream: null, - bundle: bundle, - bundleSize: 5, - originalPosition: 0, - currentPosition: 0, - }; - - const selectedB: SelectedBitstreamTableEntry = { + const entry: SelectedBitstreamTableEntry = { bitstream: null, bundle: bundle, bundleSize: 5, @@ -144,12 +129,12 @@ describe('ItemEditBitstreamBundleComponent', () => { currentPosition: 1, }; - comp.handleSelectedEntryChange(selectedA, selectedB); + comp.handleSelectionAction({ action: 'Moved', selectedEntry: entry }); expect(paginationComponent.doPageChange).not.toHaveBeenCalled(); }); it('should change to the original page when cancelling', () => { - const selectedA: SelectedBitstreamTableEntry = { + const entry: SelectedBitstreamTableEntry = { bitstream: null, bundle: bundle, bundleSize: 5, @@ -157,14 +142,12 @@ describe('ItemEditBitstreamBundleComponent', () => { currentPosition: 0, }; - const selectedB = null; - - comp.handleSelectedEntryChange(selectedA, selectedB); + comp.handleSelectionAction({ action: 'Cancelled', selectedEntry: entry }); expect(paginationComponent.doPageChange).toHaveBeenCalledWith(2); }); it('should not change page when we are already on the correct page when cancelling', () => { - const selectedA: SelectedBitstreamTableEntry = { + const entry: SelectedBitstreamTableEntry = { bitstream: null, bundle: bundle, bundleSize: 5, @@ -172,9 +155,7 @@ describe('ItemEditBitstreamBundleComponent', () => { currentPosition: 3, }; - const selectedB = null; - - comp.handleSelectedEntryChange(selectedA, selectedB); + comp.handleSelectionAction({ action: 'Cancelled', selectedEntry: entry }); expect(paginationComponent.doPageChange).not.toHaveBeenCalled(); }); }); diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts index 7a70ba80dd..2c7d8ca60f 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts @@ -25,7 +25,7 @@ import { paginatedListToArray, } from '../../../../core/shared/operators'; import { ObjectUpdatesService } from '../../../../core/data/object-updates/object-updates.service'; -import { map, take, filter, tap, pairwise } from 'rxjs/operators'; +import { map, take, filter, tap } from 'rxjs/operators'; import { FieldChangeType } from '../../../../core/data/object-updates/field-change-type.model'; import { FieldUpdate } from '../../../../core/data/object-updates/field-update.model'; import { PaginationService } from '../../../../core/pagination/pagination.service'; @@ -35,7 +35,7 @@ import { ItemBitstreamsService, BitstreamTableEntry, SelectedBitstreamTableEntry, - MOVE_KEY + MOVE_KEY, SelectionAction } from '../item-bitstreams.service'; import { CdkDragDrop } from '@angular/cdk/drag-drop'; import { hasValue, hasNoValue } from '../../../../shared/empty.util'; @@ -233,31 +233,37 @@ export class ItemEditBitstreamBundleComponent implements OnInit, OnDestroy { protected initializeSelectionActions() { this.subscriptions.push( - this.itemBitstreamsService.getSelectedBitstream$().pipe(pairwise()).subscribe( - ([previousSelection, currentSelection]) => - this.handleSelectedEntryChange(previousSelection, currentSelection)) + this.itemBitstreamsService.getSelectionAction$().subscribe( + selectionAction => this.handleSelectionAction(selectionAction)) ); } /** * Handles a change in selected bitstream by changing the pagination if the change happened on a different page - * @param previousSelectedEntry The previously selected entry - * @param currentSelectedEntry The currently selected entry + * @param selectionAction */ - handleSelectedEntryChange( - previousSelectedEntry: SelectedBitstreamTableEntry, - currentSelectedEntry: SelectedBitstreamTableEntry - ) { - if (hasValue(currentSelectedEntry) && currentSelectedEntry.bundle === this.bundle) { - // If the currently selected bitstream belongs to this bundle, it has possibly moved to a different page. - // In that case we want to change the pagination to the new page. - this.redirectToCurrentPage(currentSelectedEntry); + handleSelectionAction(selectionAction: SelectionAction) { + if (hasNoValue(selectionAction) || selectionAction.selectedEntry.bundle !== this.bundle) { + return; } - // If the selection is cancelled or cleared, it is possible the selected bitstream is currently on a different page - // In that case we want to change the pagination to the place where the bitstream was returned to - if (hasNoValue(currentSelectedEntry) && hasValue(previousSelectedEntry) && previousSelectedEntry.bundle === this.bundle) { - this.redirectToOriginalPage(previousSelectedEntry); + if (selectionAction.action === 'Moved') { + // If the currently selected bitstream belongs to this bundle, it has possibly moved to a different page. + // In that case we want to change the pagination to the new page. + this.redirectToCurrentPage(selectionAction.selectedEntry); + } + + if (selectionAction.action === 'Cancelled') { + // If the selection is cancelled (and returned to its original position), it is possible the previously selected + // bitstream is returned to a different page. In that case we want to change the pagination to the place where + // the bitstream was returned to. + this.redirectToOriginalPage(selectionAction.selectedEntry); + } + + if (selectionAction.action === 'Cleared') { + // If the selection is cleared, it is possible the previously selected bitstream is on a different page. In that + // case we want to change the pagination to the place where the bitstream is. + this.redirectToCurrentPage(selectionAction.selectedEntry); } } From 8d93f22767edbf18396edc49b16629967f04c287 Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Wed, 9 Oct 2024 12:01:33 +0200 Subject: [PATCH 0629/1286] 119176: Make table horizontally scrollable For most screen sizes, the ResponsiveTableSizes is enough to resize the table columns. On very small screens, or when zoomed in a lot, even the smallest column sizes are too big. To make it possible to view the rest of the content even in these situations, the ability to scroll horizontally is added. --- .../item-bitstreams/item-bitstreams.component.html | 2 +- .../item-bitstreams/item-bitstreams.component.scss | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html index b9af2a7d18..7789b68278 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html @@ -27,7 +27,7 @@ -
+
Date: Mon, 14 Oct 2024 11:30:48 +0200 Subject: [PATCH 0630/1286] 119176: Announce notification content in live region --- .../models/notification-options.model.ts | 12 +++- .../notifications-board.component.spec.ts | 49 ++++++++++++++- .../notifications-board.component.ts | 60 +++++++++++++------ 3 files changed, 97 insertions(+), 24 deletions(-) diff --git a/src/app/shared/notifications/models/notification-options.model.ts b/src/app/shared/notifications/models/notification-options.model.ts index 65011496b3..c891781d9d 100644 --- a/src/app/shared/notifications/models/notification-options.model.ts +++ b/src/app/shared/notifications/models/notification-options.model.ts @@ -4,19 +4,25 @@ export interface INotificationOptions { timeOut: number; clickToClose: boolean; animate: NotificationAnimationsType | string; + announceContentInLiveRegion: boolean; } export class NotificationOptions implements INotificationOptions { public timeOut: number; public clickToClose: boolean; public animate: any; + public announceContentInLiveRegion: boolean; - constructor(timeOut = 5000, - clickToClose = true, - animate: NotificationAnimationsType | string = NotificationAnimationsType.Scale) { + constructor( + timeOut = 5000, + clickToClose = true, + animate: NotificationAnimationsType | string = NotificationAnimationsType.Scale, + announceContentInLiveRegion: boolean = true, + ) { this.timeOut = timeOut; this.clickToClose = clickToClose; this.animate = animate; + this.announceContentInLiveRegion = announceContentInLiveRegion; } } diff --git a/src/app/shared/notifications/notifications-board/notifications-board.component.spec.ts b/src/app/shared/notifications/notifications-board/notifications-board.component.spec.ts index 08b9585a8c..73f4e6b1b1 100644 --- a/src/app/shared/notifications/notifications-board/notifications-board.component.spec.ts +++ b/src/app/shared/notifications/notifications-board/notifications-board.component.spec.ts @@ -1,4 +1,4 @@ -import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, inject, TestBed, waitForAsync, fakeAsync, flush } from '@angular/core/testing'; import { BrowserModule, By } from '@angular/platform-browser'; import { ChangeDetectorRef } from '@angular/core'; @@ -15,14 +15,20 @@ import uniqueId from 'lodash/uniqueId'; import { INotificationBoardOptions } from '../../../../config/notifications-config.interfaces'; import { NotificationsServiceStub } from '../../testing/notifications-service.stub'; import { cold } from 'jasmine-marbles'; +import { LiveRegionService } from '../../live-region/live-region.service'; +import { LiveRegionServiceStub } from '../../live-region/live-region.service.stub'; +import { NotificationOptions } from '../models/notification-options.model'; export const bools = { f: false, t: true }; describe('NotificationsBoardComponent', () => { let comp: NotificationsBoardComponent; let fixture: ComponentFixture; + let liveRegionService: LiveRegionServiceStub; beforeEach(waitForAsync(() => { + liveRegionService = new LiveRegionServiceStub(); + TestBed.configureTestingModule({ imports: [ BrowserModule, @@ -36,7 +42,9 @@ describe('NotificationsBoardComponent', () => { declarations: [NotificationsBoardComponent, NotificationComponent], // declare the test component providers: [ { provide: NotificationsService, useClass: NotificationsServiceStub }, - ChangeDetectorRef] + { provide: LiveRegionService, useValue: liveRegionService }, + ChangeDetectorRef, + ] }).compileComponents(); // compile template and css })); @@ -106,5 +114,42 @@ describe('NotificationsBoardComponent', () => { }); }); + describe('add', () => { + beforeEach(() => { + liveRegionService.addMessage.calls.reset(); + }); + + it('should announce content to the live region', fakeAsync(() => { + const notification = new Notification('id', NotificationType.Info, 'title', 'content'); + comp.add(notification); + + flush(); + + expect(liveRegionService.addMessage).toHaveBeenCalledWith('content'); + })); + + it('should not announce anything if there is no content', fakeAsync(() => { + const notification = new Notification('id', NotificationType.Info, 'title'); + comp.add(notification); + + flush(); + + expect(liveRegionService.addMessage).not.toHaveBeenCalled(); + })); + + it('should not announce the content if disabled', fakeAsync(() => { + const options = new NotificationOptions(); + options.announceContentInLiveRegion = false; + + const notification = new Notification('id', NotificationType.Info, 'title', 'content'); + notification.options = options; + comp.add(notification); + + flush(); + + expect(liveRegionService.addMessage).not.toHaveBeenCalled(); + })); + }); + }) ; diff --git a/src/app/shared/notifications/notifications-board/notifications-board.component.ts b/src/app/shared/notifications/notifications-board/notifications-board.component.ts index 97ae09c1a6..eaba659678 100644 --- a/src/app/shared/notifications/notifications-board/notifications-board.component.ts +++ b/src/app/shared/notifications/notifications-board/notifications-board.component.ts @@ -9,7 +9,7 @@ import { } from '@angular/core'; import { select, Store } from '@ngrx/store'; -import { BehaviorSubject, Subscription } from 'rxjs'; +import { BehaviorSubject, Subscription, of as observableOf } from 'rxjs'; import difference from 'lodash/difference'; import { NotificationsService } from '../notifications.service'; @@ -18,6 +18,9 @@ import { notificationsStateSelector } from '../selectors'; import { INotification } from '../models/notification.model'; import { NotificationsState } from '../notifications.reducers'; import { INotificationBoardOptions } from '../../../../config/notifications-config.interfaces'; +import { LiveRegionService } from '../../live-region/live-region.service'; +import { hasNoValue, isNotEmptyOperator } from '../../empty.util'; +import { take } from 'rxjs/operators'; @Component({ selector: 'ds-notifications-board', @@ -49,9 +52,12 @@ export class NotificationsBoardComponent implements OnInit, OnDestroy { */ public isPaused$: BehaviorSubject = new BehaviorSubject(false); - constructor(private service: NotificationsService, - private store: Store, - private cdr: ChangeDetectorRef) { + constructor( + private service: NotificationsService, + private store: Store, + private cdr: ChangeDetectorRef, + protected liveRegionService: LiveRegionService, + ) { } ngOnInit(): void { @@ -85,6 +91,7 @@ export class NotificationsBoardComponent implements OnInit, OnDestroy { this.notifications.splice(this.notifications.length - 1, 1); } this.notifications.splice(0, 0, item); + this.addContentToLiveRegion(item); } else { // Remove the notification from the store // This notification was in the store, but not in this.notifications @@ -93,29 +100,44 @@ export class NotificationsBoardComponent implements OnInit, OnDestroy { } } + /** + * Adds the content of the notification (if any) to the live region, so it can be announced by screen readers. + */ + private addContentToLiveRegion(item: INotification) { + let content = item.content; + + if (!item.options.announceContentInLiveRegion || hasNoValue(content)) { + return; + } + + if (typeof content === 'string') { + content = observableOf(content); + } + + content.pipe( + isNotEmptyOperator(), + take(1), + ).subscribe(contentStr => this.liveRegionService.addMessage(contentStr)); + } + + /** + * Whether to block the provided item because a duplicate notification with the exact same information already + * exists within the notifications array. + * @param item The item to check + * @return true if the notifications array already contains a notification with the exact same information as the + * provided item. false otherwise. + * @private + */ private block(item: INotification): boolean { const toCheck = item.html ? this.checkHtml : this.checkStandard; + this.notifications.forEach((notification) => { if (toCheck(notification, item)) { return true; } }); - if (this.notifications.length > 0) { - this.notifications.forEach((notification) => { - if (toCheck(notification, item)) { - return true; - } - }); - } - - let comp: INotification; - if (this.notifications.length > 0) { - comp = this.notifications[0]; - } else { - return false; - } - return toCheck(comp, item); + return false; } private checkStandard(checker: INotification, item: INotification): boolean { From 93f9341387755efc14d3272f7f9cca452ab91996 Mon Sep 17 00:00:00 2001 From: Andreas Awouters Date: Wed, 16 Oct 2024 14:11:01 +0200 Subject: [PATCH 0631/1286] 119176: Add aria-labels to buttons --- .../item-edit-bitstream-bundle.component.html | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html index efbdd8c69b..06201b1cbe 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html @@ -40,6 +40,7 @@
-
+
+ + diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.scss b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.scss index 985516ab12..7fd1f4b31e 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.scss +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.scss @@ -43,3 +43,13 @@ .scrollable-table { overflow-x: auto; } + +.disabled-overlay { + opacity: 0.6; +} + +.loading-overlay { + position: fixed; + top: 50%; + left: 50%; +} diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts index 6ee5dcb545..72f85675c9 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts @@ -59,6 +59,11 @@ export class ItemBitstreamsComponent extends AbstractItemUpdateComponent impleme */ itemUpdateSubscription: Subscription; + /** + * An observable which emits a boolean which represents whether the service is currently handling a 'move' request + */ + isProcessingMoveRequest: Observable; + constructor( public itemService: ItemDataService, public objectUpdatesService: ObjectUpdatesService, @@ -84,6 +89,7 @@ export class ItemBitstreamsComponent extends AbstractItemUpdateComponent impleme */ postItemInit(): void { const bundlesOptions = this.itemBitstreamsService.getInitialBundlesPaginationOptions(); + this.isProcessingMoveRequest = this.itemBitstreamsService.getPerformingMoveRequest$(); this.bundles$ = this.itemService.getBundles(this.item.id, new PaginatedSearchOptions({pagination: bundlesOptions})).pipe( getFirstSucceededRemoteData(), diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.spec.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.spec.ts index f2af25f22f..a0277ef064 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.spec.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.spec.ts @@ -573,8 +573,6 @@ describe('ItemBitstreamsService', () => { const to = 7; const callback = createSpy('callbackFunction'); - console.log('bundle:', bundle); - it('should correctly create the Move request', () => { const expectedOperation: MoveOperation = { op: 'move', @@ -601,6 +599,22 @@ describe('ItemBitstreamsService', () => { service.performBitstreamMoveRequest(bundle, from, to, callback); expect(callback).toHaveBeenCalled(); }); + + it('should emit at the start and end of the request', fakeAsync(() => { + const emittedActions = []; + + service.getPerformingMoveRequest$().subscribe(selected => emittedActions.push(selected)); + + expect(emittedActions.length).toBe(1); + expect(emittedActions[0]).toBeFalse(); + + service.performBitstreamMoveRequest(bundle, from, to, callback); + tick(); + + expect(emittedActions.length).toBe(3); + expect(emittedActions[1]).toBeTrue(); + expect(emittedActions[2]).toBeFalse(); + })); }); describe('displayNotifications', () => { diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.stub.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.stub.ts index 7aac79fe69..f60693f726 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.stub.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.stub.ts @@ -30,6 +30,10 @@ export class ItemBitstreamsServiceStub { performBitstreamMoveRequest = jasmine.createSpy('performBitstreamMoveRequest'); + getPerformingMoveRequest = jasmine.createSpy('getPerformingMoveRequest').and.returnValue(false); + + getPerformingMoveRequest$ = jasmine.createSpy('getPerformingMoveRequest$').and.returnValue(of(false)); + getInitialBundlesPaginationOptions = jasmine.createSpy('getInitialBundlesPaginationOptions').and .returnValue(new PaginationComponentOptions()); diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.ts index 2329107c29..9bbf380487 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.service.ts @@ -119,7 +119,7 @@ export class ItemBitstreamsService { */ protected selectionAction$: BehaviorSubject = new BehaviorSubject(null); - protected isPerformingMoveRequest = false; + protected isPerformingMoveRequest: BehaviorSubject = new BehaviorSubject(false); constructor( protected notificationsService: NotificationsService, @@ -221,7 +221,7 @@ export class ItemBitstreamsService { cancelSelection() { const selected = this.getSelectedBitstream(); - if (hasNoValue(selected) || this.isPerformingMoveRequest) { + if (hasNoValue(selected) || this.getPerformingMoveRequest()) { return; } @@ -247,7 +247,7 @@ export class ItemBitstreamsService { moveSelectedBitstreamUp() { const selected = this.getSelectedBitstream(); - if (hasNoValue(selected) || this.isPerformingMoveRequest) { + if (hasNoValue(selected) || this.getPerformingMoveRequest()) { return; } @@ -272,7 +272,7 @@ export class ItemBitstreamsService { moveSelectedBitstreamDown() { const selected = this.getSelectedBitstream(); - if (hasNoValue(selected) || this.isPerformingMoveRequest) { + if (hasNoValue(selected) || this.getPerformingMoveRequest()) { return; } @@ -299,7 +299,7 @@ export class ItemBitstreamsService { * @param finish Optional: Function to execute once the response has been received */ performBitstreamMoveRequest(bundle: Bundle, fromIndex: number, toIndex: number, finish?: () => void) { - if (this.isPerformingMoveRequest) { + if (this.getPerformingMoveRequest()) { console.warn('Attempted to perform move request while previous request has not completed yet'); return; } @@ -310,18 +310,34 @@ export class ItemBitstreamsService { path: `/_links/bitstreams/${toIndex}/href`, }; - this.isPerformingMoveRequest = true; + this.announceLoading(); + this.isPerformingMoveRequest.next(true); this.bundleService.patch(bundle, [moveOperation]).pipe( getFirstCompletedRemoteData(), tap((response: RemoteData) => this.displayFailedResponseNotifications(MOVE_KEY, [response])), switchMap(() => this.requestService.setStaleByHrefSubstring(bundle.self)), take(1), ).subscribe(() => { - this.isPerformingMoveRequest = false; + console.log('got here!'); + this.isPerformingMoveRequest.next(false); finish?.(); }); } + /** + * Whether the service currently is processing a 'move' request + */ + getPerformingMoveRequest(): boolean { + return this.isPerformingMoveRequest.value; + } + + /** + * Returns an observable which emits when the service starts, or ends, processing a 'move' request + */ + getPerformingMoveRequest$(): Observable { + return this.isPerformingMoveRequest; + } + /** * Returns the pagination options to use when fetching the bundles */ @@ -526,4 +542,12 @@ export class ItemBitstreamsService { { bitstream: bitstreamName }); this.liveRegionService.addMessage(message); } + + /** + * Adds a message to the live region mentioning that the + */ + announceLoading() { + const message = this.translateService.instant('item.edit.bitstreams.edit.live.loading'); + this.liveRegionService.addMessage(message); + } } diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 519189ed69..9007982a72 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1954,6 +1954,8 @@ "item.edit.bitstreams.edit.live.clear": "{{ bitstream }} is no longer selected.", + "item.edit.bitstreams.edit.live.loading": "Waiting for move to complete.", + "item.edit.bitstreams.edit.live.select": "{{ bitstream }} is selected.", "item.edit.bitstreams.edit.live.move": "{{ bitstream }} is now in position {{ toIndex }}.", From 207e2ac9aee7fbc7958ae4aba332fa84c21bbea2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Oct 2024 14:08:36 +0000 Subject: [PATCH 0707/1286] Bump typescript from 5.3.3 to 5.4.5 Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.3.3 to 5.4.5. - [Release notes](https://github.com/microsoft/TypeScript/releases) - [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml) - [Commits](https://github.com/microsoft/TypeScript/compare/v5.3.3...v5.4.5) --- updated-dependencies: - dependency-name: typescript dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 654548a528..0a15a4538e 100644 --- a/package.json +++ b/package.json @@ -208,7 +208,7 @@ "sass-loader": "^12.6.0", "sass-resources-loader": "^2.2.5", "ts-node": "^8.10.2", - "typescript": "~5.3.3", + "typescript": "~5.4.5", "webpack": "5.95.0", "webpack-bundle-analyzer": "^4.8.0", "webpack-cli": "^5.1.4", diff --git a/yarn.lock b/yarn.lock index 8aecb589a8..48a66bae41 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11332,10 +11332,10 @@ typescript@^2.5.0: resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c" integrity sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w== -typescript@~5.3.3: - version "5.3.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" - integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== +typescript@~5.4.5: + version "5.4.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611" + integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== ua-parser-js@^0.7.30: version "0.7.38" From 87dc6be213666b3079df6285b755bd7aef0683db Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 22 Oct 2024 11:35:09 -0500 Subject: [PATCH 0708/1286] Remove unnecessary @ts-expect-error, as the bug they are expecting is fixed in webpack 5.95.0. --- webpack/webpack.common.ts | 1 - webpack/webpack.prod.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/webpack/webpack.common.ts b/webpack/webpack.common.ts index d8155288cb..8d433edf39 100644 --- a/webpack/webpack.common.ts +++ b/webpack/webpack.common.ts @@ -79,7 +79,6 @@ const SCSS_LOADERS = [ export const commonExports = { plugins: [ - // @ts-expect-error: EnvironmentPlugin constructor types are currently to strict see issue https://github.com/webpack/webpack/issues/18719 new EnvironmentPlugin({ languageHashes: getFileHashes(path.join(__dirname, '..', 'src', 'assets', 'i18n'), /.*\.json5/g), }), diff --git a/webpack/webpack.prod.ts b/webpack/webpack.prod.ts index fce321d152..e35bc0c907 100644 --- a/webpack/webpack.prod.ts +++ b/webpack/webpack.prod.ts @@ -6,7 +6,6 @@ import { commonExports } from './webpack.common'; module.exports = Object.assign({}, commonExports, { plugins: [ ...commonExports.plugins, - // @ts-expect-error: EnvironmentPlugin constructor types are currently to strict see issue https://github.com/webpack/webpack/issues/18719 new EnvironmentPlugin({ 'process.env': { NODE_ENV: 'production', From 92ee89e8e5150920dc225384b9f7f4a543af31a5 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 23 Oct 2024 11:31:16 -0500 Subject: [PATCH 0709/1286] Fix bug in dependabot.yml "security-updates" settings "security-updates" configs can only be in sections where there is no "target-branch". This is because they only apply to the primary branch. --- .github/dependabot.yml | 122 ++--------------------------------------- 1 file changed, 6 insertions(+), 116 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 51c8be4bbc..4d49cc5117 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,12 +1,16 @@ -# Enable Dependabot NPM updates for all dependencies on a weekly basis +#------------------- +# DSpace's dependabot rules. Enables npm updates for all dependencies on a weekly basis +# for main and any maintenance branches. Security updates only apply to main. +#------------------- version: 2 updates: ############### ## Main branch ############### + # NOTE: At this time, "security-updates" rules only apply if "target-branch" is unspecified + # So, only this first section can include "applies-to: security-updates" - package-ecosystem: "npm" directory: "/" - target-branch: main schedule: interval: "weekly" # Allow up to 10 open PRs for dependencies @@ -159,14 +163,6 @@ updates: update-types: - "minor" - "patch" - # Group together all security updates for Angular. Only accept minor/patch types. - angular-security: - applies-to: security-updates - patterns: - - "@angular*" - update-types: - - "minor" - - "patch" # Group together all minor/patch version updates for NgRx in a single PR ngrx: applies-to: version-updates @@ -175,14 +171,6 @@ updates: update-types: - "minor" - "patch" - # Group together all security updates for NgRx. Only accept minor/patch types. - ngrx-security: - applies-to: security-updates - patterns: - - "@ngrx*" - update-types: - - "minor" - - "patch" # Group together all patch version updates for eslint in a single PR eslint: applies-to: version-updates @@ -192,15 +180,6 @@ updates: update-types: - "minor" - "patch" - # Group together all security updates for eslint. - eslint-security: - applies-to: security-updates - patterns: - - "@typescript-eslint*" - - "eslint*" - update-types: - - "minor" - - "patch" # Group together any testing related version updates testing: applies-to: version-updates @@ -213,18 +192,6 @@ updates: update-types: - "minor" - "patch" - # Group together any testing related security updates - testing: - applies-to: security-updates - patterns: - - "@cypress*" - - "cypress*" - - "jasmine*" - - "karma*" - - "ng-mocks" - update-types: - - "minor" - - "patch" # Group together any postcss related version updates postcss: applies-to: version-updates @@ -233,23 +200,7 @@ updates: update-types: - "minor" - "patch" - # Group together any postcss related security updates - postcss: - applies-to: security-updates - patterns: - - "postcss*" - update-types: - - "minor" - - "patch" # Group together any sass related version updates - sass: - applies-to: version-updates - patterns: - - "sass*" - update-types: - - "minor" - - "patch" - # Group together any sass related security updates sass: applies-to: version-updates patterns: @@ -265,14 +216,6 @@ updates: update-types: - "minor" - "patch" - # Group together any webpack related seurity updates - webpack: - applies-to: security-updates - patterns: - - "webpack*" - update-types: - - "minor" - - "patch" ignore: # Ignore all major version updates for all dependencies. We'll only automate minor/patch updates. - dependency-name: "*" @@ -297,14 +240,6 @@ updates: update-types: - "minor" - "patch" - # Group together all security updates for Angular. Only accept minor/patch types. - angular-security: - applies-to: security-updates - patterns: - - "@angular*" - update-types: - - "minor" - - "patch" # Group together all minor/patch version updates for NgRx in a single PR ngrx: applies-to: version-updates @@ -313,14 +248,6 @@ updates: update-types: - "minor" - "patch" - # Group together all security updates for NgRx. Only accept minor/patch types. - ngrx-security: - applies-to: security-updates - patterns: - - "@ngrx*" - update-types: - - "minor" - - "patch" # Group together all patch version updates for eslint in a single PR eslint: applies-to: version-updates @@ -330,15 +257,6 @@ updates: update-types: - "minor" - "patch" - # Group together all security updates for eslint. - eslint-security: - applies-to: security-updates - patterns: - - "@typescript-eslint*" - - "eslint*" - update-types: - - "minor" - - "patch" # Group together any testing related version updates testing: applies-to: version-updates @@ -351,18 +269,6 @@ updates: update-types: - "minor" - "patch" - # Group together any testing related security updates - testing: - applies-to: security-updates - patterns: - - "@cypress*" - - "cypress*" - - "jasmine*" - - "karma*" - - "ng-mocks" - update-types: - - "minor" - - "patch" # Group together any postcss related version updates postcss: applies-to: version-updates @@ -371,14 +277,6 @@ updates: update-types: - "minor" - "patch" - # Group together any postcss related security updates - postcss: - applies-to: security-updates - patterns: - - "postcss*" - update-types: - - "minor" - - "patch" # Group together any sass related version updates sass: applies-to: version-updates @@ -387,14 +285,6 @@ updates: update-types: - "minor" - "patch" - # Group together any sass related security updates - sass: - applies-to: version-updates - patterns: - - "sass*" - update-types: - - "minor" - - "patch" ignore: # 7.x Cannot update Webpack past v5.76.1 as later versions not supported by Angular 15 # See also https://github.com/DSpace/dspace-angular/pull/3283#issuecomment-2372488489 From ea8f24d41071f3f146dbbbfe2f43617d38a1713a Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 23 Oct 2024 11:33:28 -0500 Subject: [PATCH 0710/1286] Fix bug where all security-updates need unique IDs --- .github/dependabot.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 4d49cc5117..0ebfc93793 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -80,7 +80,7 @@ updates: - "minor" - "patch" # Group together any testing related security updates - testing: + testing-security: applies-to: security-updates patterns: - "@cypress*" @@ -100,7 +100,7 @@ updates: - "minor" - "patch" # Group together any postcss related security updates - postcss: + postcss-security: applies-to: security-updates patterns: - "postcss*" @@ -116,8 +116,8 @@ updates: - "minor" - "patch" # Group together any sass related security updates - sass: - applies-to: version-updates + sass-security: + applies-to: security-updates patterns: - "sass*" update-types: @@ -132,7 +132,7 @@ updates: - "minor" - "patch" # Group together any webpack related seurity updates - webpack: + webpack-security: applies-to: security-updates patterns: - "webpack*" From 74e85c79e745980e96412dd641c221edc0253b39 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 23 Oct 2024 11:42:09 -0500 Subject: [PATCH 0711/1286] Remove unused @types/sanitize-html --- package-lock.json | 10 ---------- package.json | 1 - 2 files changed, 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5a662e3a04..f9712c2779 100644 --- a/package-lock.json +++ b/package-lock.json @@ -102,7 +102,6 @@ "@types/js-cookie": "2.2.6", "@types/lodash": "^4.17.12", "@types/node": "^14.14.9", - "@types/sanitize-html": "^2.9.0", "@typescript-eslint/eslint-plugin": "^7.18.0", "@typescript-eslint/parser": "^7.18.0", "@typescript-eslint/rule-tester": "^7.18.0", @@ -7053,15 +7052,6 @@ "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", "dev": true }, - "node_modules/@types/sanitize-html": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/@types/sanitize-html/-/sanitize-html-2.11.0.tgz", - "integrity": "sha512-7oxPGNQHXLHE48r/r/qjn7q0hlrs3kL7oZnGj0Wf/h9tj/6ibFyRkNbsDxaBBZ4XUZ0Dx5LGCyDJ04ytSofacQ==", - "dev": true, - "dependencies": { - "htmlparser2": "^8.0.0" - } - }, "node_modules/@types/scheduler": { "version": "0.16.8", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", diff --git a/package.json b/package.json index 8fc0e42a17..768b028dd9 100644 --- a/package.json +++ b/package.json @@ -189,7 +189,6 @@ "@types/js-cookie": "2.2.6", "@types/lodash": "^4.17.12", "@types/node": "^14.14.9", - "@types/sanitize-html": "^2.9.0", "@typescript-eslint/eslint-plugin": "^7.18.0", "@typescript-eslint/parser": "^7.18.0", "@typescript-eslint/rule-tester": "^7.18.0", From 9486ab5fa1d3d0fc11ceb9f5063bbda61a078924 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 18 Oct 2024 14:26:48 -0500 Subject: [PATCH 0712/1286] Fix code scanning alert no. 6: Incomplete string escaping or encoding Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> (cherry picked from commit 372444c50ac28a6c7f68b20695bea616a3ab8b7f) --- src/app/core/shared/metadata.utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/core/shared/metadata.utils.ts b/src/app/core/shared/metadata.utils.ts index 87a90b53a3..e48b2b0c44 100644 --- a/src/app/core/shared/metadata.utils.ts +++ b/src/app/core/shared/metadata.utils.ts @@ -157,7 +157,7 @@ export class Metadata { const outputKeys: string[] = []; for (const inputKey of inputKeys) { if (inputKey.includes('*')) { - const inputKeyRegex = new RegExp('^' + inputKey.replace(/\./g, '\\.').replace(/\*/g, '.*') + '$'); + const inputKeyRegex = new RegExp('^' + inputKey.replace(/\\/g, '\\\\').replace(/\./g, '\\.').replace(/\*/g, '.*') + '$'); for (const mapKey of Object.keys(mdMap)) { if (!outputKeys.includes(mapKey) && inputKeyRegex.test(mapKey)) { outputKeys.push(mapKey); From bb84d86cf521fe6c25f12c3d07390289db87f96b Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 18 Oct 2024 14:26:48 -0500 Subject: [PATCH 0713/1286] Fix code scanning alert no. 6: Incomplete string escaping or encoding Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> (cherry picked from commit 372444c50ac28a6c7f68b20695bea616a3ab8b7f) --- src/app/core/shared/metadata.utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/core/shared/metadata.utils.ts b/src/app/core/shared/metadata.utils.ts index 1ad10356fb..f0290eac39 100644 --- a/src/app/core/shared/metadata.utils.ts +++ b/src/app/core/shared/metadata.utils.ts @@ -163,7 +163,7 @@ export class Metadata { const outputKeys: string[] = []; for (const inputKey of inputKeys) { if (inputKey.includes('*')) { - const inputKeyRegex = new RegExp('^' + inputKey.replace(/\./g, '\\.').replace(/\*/g, '.*') + '$'); + const inputKeyRegex = new RegExp('^' + inputKey.replace(/\\/g, '\\\\').replace(/\./g, '\\.').replace(/\*/g, '.*') + '$'); for (const mapKey of Object.keys(mdMap)) { if (!outputKeys.includes(mapKey) && inputKeyRegex.test(mapKey)) { outputKeys.push(mapKey); From c93ed03004ddff1186548342b853df2281bdb43a Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 23 Oct 2024 13:26:55 -0500 Subject: [PATCH 0714/1286] Remove unused/unmaintained postcss-apply dep --- package-lock.json | 43 ------------------------------------------- package.json | 1 - postcss.config.js | 1 - 3 files changed, 45 deletions(-) diff --git a/package-lock.json b/package-lock.json index f9712c2779..0b4111366b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -140,7 +140,6 @@ "ngx-mask": "14.2.4", "nodemon": "^2.0.22", "postcss": "^8.4", - "postcss-apply": "0.12.0", "postcss-import": "^14.0.0", "postcss-loader": "^4.0.3", "postcss-preset-env": "^7.4.2", @@ -18353,48 +18352,6 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/postcss-apply": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/postcss-apply/-/postcss-apply-0.12.0.tgz", - "integrity": "sha512-u8qZLyA9P86cD08IhqjSVV8tf1eGiKQ4fPvjcG3Ic/eOU65EAkDQClp8We7d15TG+RIWRVPSy9v7cJ2D9OReqw==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "postcss": "^7.0.14" - } - }, - "node_modules/postcss-apply/node_modules/picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", - "dev": true - }, - "node_modules/postcss-apply/node_modules/postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dev": true, - "dependencies": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - } - }, - "node_modules/postcss-apply/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/postcss-attribute-case-insensitive": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz", diff --git a/package.json b/package.json index 768b028dd9..2f11659730 100644 --- a/package.json +++ b/package.json @@ -227,7 +227,6 @@ "ngx-mask": "14.2.4", "nodemon": "^2.0.22", "postcss": "^8.4", - "postcss-apply": "0.12.0", "postcss-import": "^14.0.0", "postcss-loader": "^4.0.3", "postcss-preset-env": "^7.4.2", diff --git a/postcss.config.js b/postcss.config.js index df092d1d39..14013bd4f8 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -2,7 +2,6 @@ module.exports = { plugins: [ require('postcss-import')(), require('postcss-preset-env')(), - require('postcss-apply')(), require('postcss-responsive-type')() ] }; From 39c5c755d75339230681d45fec5b4878634d7e16 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 23 Oct 2024 13:39:01 -0500 Subject: [PATCH 0715/1286] Remove unused postcss-responsive-type --- package-lock.json | 33 --------------------------------- package.json | 1 - postcss.config.js | 3 +-- 3 files changed, 1 insertion(+), 36 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0b4111366b..2a0990de9b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -143,7 +143,6 @@ "postcss-import": "^14.0.0", "postcss-loader": "^4.0.3", "postcss-preset-env": "^7.4.2", - "postcss-responsive-type": "1.0.0", "react": "^16.14.0", "react-dom": "^16.14.0", "rimraf": "^3.0.2", @@ -19033,38 +19032,6 @@ "postcss": "^8.0.3" } }, - "node_modules/postcss-responsive-type": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postcss-responsive-type/-/postcss-responsive-type-1.0.0.tgz", - "integrity": "sha512-O4kAKbc4RLnSkzcguJ6ojW67uOfeILaj+8xjsO0quLU94d8BKCqYwwFEUVRNbj0YcXA6d3uF/byhbaEATMRVig==", - "dev": true, - "dependencies": { - "postcss": "^6.0.6" - } - }, - "node_modules/postcss-responsive-type/node_modules/postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "dependencies": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/postcss-responsive-type/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/postcss-selector-not": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-6.0.1.tgz", diff --git a/package.json b/package.json index 2f11659730..71c0d5272e 100644 --- a/package.json +++ b/package.json @@ -230,7 +230,6 @@ "postcss-import": "^14.0.0", "postcss-loader": "^4.0.3", "postcss-preset-env": "^7.4.2", - "postcss-responsive-type": "1.0.0", "react": "^16.14.0", "react-dom": "^16.14.0", "rimraf": "^3.0.2", diff --git a/postcss.config.js b/postcss.config.js index 14013bd4f8..f8b9666b31 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -1,7 +1,6 @@ module.exports = { plugins: [ require('postcss-import')(), - require('postcss-preset-env')(), - require('postcss-responsive-type')() + require('postcss-preset-env')() ] }; From 04410485a5e08f125b6a595115921a45d6982860 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 23 Oct 2024 13:55:36 -0500 Subject: [PATCH 0716/1286] Remove unused/unmaintained postcss-apply --- package.json | 1 - postcss.config.js | 1 - yarn.lock | 23 ++--------------------- 3 files changed, 2 insertions(+), 23 deletions(-) diff --git a/package.json b/package.json index c48d1e3154..65a03efe6c 100644 --- a/package.json +++ b/package.json @@ -195,7 +195,6 @@ "ngx-mask": "14.2.4", "nodemon": "^2.0.22", "postcss": "^8.4", - "postcss-apply": "0.12.0", "postcss-import": "^14.0.0", "postcss-loader": "^4.0.3", "postcss-preset-env": "^7.4.2", diff --git a/postcss.config.js b/postcss.config.js index df092d1d39..14013bd4f8 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -2,7 +2,6 @@ module.exports = { plugins: [ require('postcss-import')(), require('postcss-preset-env')(), - require('postcss-apply')(), require('postcss-responsive-type')() ] }; diff --git a/yarn.lock b/yarn.lock index 961ce5de26..dcebeb2972 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5517,9 +5517,11 @@ eslint-plugin-deprecation@^1.4.1: "eslint-plugin-dspace-angular-html@link:./lint/dist/src/rules/html": version "0.0.0" + uid "" "eslint-plugin-dspace-angular-ts@link:./lint/dist/src/rules/ts": version "0.0.0" + uid "" eslint-plugin-import-newlines@^1.3.1: version "1.4.0" @@ -8962,11 +8964,6 @@ performance-now@^2.1.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== -picocolors@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f" - integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA== - picocolors@^1.0.0, picocolors@^1.0.1, picocolors@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" @@ -9043,14 +9040,6 @@ possible-typed-array-names@^1.0.0: resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== -postcss-apply@0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/postcss-apply/-/postcss-apply-0.12.0.tgz#11a47b271b14d81db97ed7f51a6c409d025a9c34" - integrity sha512-u8qZLyA9P86cD08IhqjSVV8tf1eGiKQ4fPvjcG3Ic/eOU65EAkDQClp8We7d15TG+RIWRVPSy9v7cJ2D9OReqw== - dependencies: - balanced-match "^1.0.0" - postcss "^7.0.14" - postcss-attribute-case-insensitive@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz#03d761b24afc04c09e757e92ff53716ae8ea2741" @@ -9389,14 +9378,6 @@ postcss@^6.0.6: source-map "^0.6.1" supports-color "^5.4.0" -postcss@^7.0.14: - version "7.0.39" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.39.tgz#9624375d965630e2e1f2c02a935c82a59cb48309" - integrity sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA== - dependencies: - picocolors "^0.2.1" - source-map "^0.6.1" - postcss@^8.2.14, postcss@^8.4, postcss@^8.4.23, postcss@^8.4.33, postcss@^8.4.35: version "8.4.47" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.47.tgz#5bf6c9a010f3e724c503bf03ef7947dcb0fea365" From e7ff5646084696d96d33c56bd0ea04568c375d85 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 23 Oct 2024 13:56:46 -0500 Subject: [PATCH 0717/1286] Remove unused postcss-responsive-type --- package.json | 1 - postcss.config.js | 3 +-- yarn.lock | 20 ++------------------ 3 files changed, 3 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index 65a03efe6c..ae74beaae4 100644 --- a/package.json +++ b/package.json @@ -198,7 +198,6 @@ "postcss-import": "^14.0.0", "postcss-loader": "^4.0.3", "postcss-preset-env": "^7.4.2", - "postcss-responsive-type": "1.0.0", "react": "^16.14.0", "react-dom": "^16.14.0", "rimraf": "^3.0.2", diff --git a/postcss.config.js b/postcss.config.js index 14013bd4f8..f8b9666b31 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -1,7 +1,6 @@ module.exports = { plugins: [ require('postcss-import')(), - require('postcss-preset-env')(), - require('postcss-responsive-type')() + require('postcss-preset-env')() ] }; diff --git a/yarn.lock b/yarn.lock index dcebeb2972..e63ae27112 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4164,7 +4164,7 @@ chalk@^1.1.1: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -9333,13 +9333,6 @@ postcss-replace-overflow-wrap@^4.0.0: resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz#d2df6bed10b477bf9c52fab28c568b4b29ca4319" integrity sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw== -postcss-responsive-type@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/postcss-responsive-type/-/postcss-responsive-type-1.0.0.tgz#bb2d57d830beb9586ec4fda7994f07e37953aad8" - integrity sha512-O4kAKbc4RLnSkzcguJ6ojW67uOfeILaj+8xjsO0quLU94d8BKCqYwwFEUVRNbj0YcXA6d3uF/byhbaEATMRVig== - dependencies: - postcss "^6.0.6" - postcss-selector-not@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-6.0.1.tgz#8f0a709bf7d4b45222793fc34409be407537556d" @@ -9369,15 +9362,6 @@ postcss@8.4.35: picocolors "^1.0.0" source-map-js "^1.0.2" -postcss@^6.0.6: - version "6.0.23" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" - integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag== - dependencies: - chalk "^2.4.1" - source-map "^0.6.1" - supports-color "^5.4.0" - postcss@^8.2.14, postcss@^8.4, postcss@^8.4.23, postcss@^8.4.33, postcss@^8.4.35: version "8.4.47" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.47.tgz#5bf6c9a010f3e724c503bf03ef7947dcb0fea365" @@ -10904,7 +10888,7 @@ supports-color@^2.0.0: resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g== -supports-color@^5.3.0, supports-color@^5.4.0, supports-color@^5.5.0: +supports-color@^5.3.0, supports-color@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== From 5c877f56e92e07633efecab036a1493b8a06c465 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 23 Oct 2024 14:11:53 -0500 Subject: [PATCH 0718/1286] Remove unused/unmaintained postcss-apply --- package.json | 1 - postcss.config.js | 1 - yarn.lock | 21 --------------------- 3 files changed, 23 deletions(-) diff --git a/package.json b/package.json index 5197b720dc..b3988ad5d0 100644 --- a/package.json +++ b/package.json @@ -185,7 +185,6 @@ "ngx-mask": "^13.1.7", "nodemon": "^2.0.22", "postcss": "^8.4", - "postcss-apply": "0.12.0", "postcss-import": "^14.0.0", "postcss-loader": "^4.0.3", "postcss-preset-env": "^7.4.2", diff --git a/postcss.config.js b/postcss.config.js index df092d1d39..14013bd4f8 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -2,7 +2,6 @@ module.exports = { plugins: [ require('postcss-import')(), require('postcss-preset-env')(), - require('postcss-apply')(), require('postcss-responsive-type')() ] }; diff --git a/yarn.lock b/yarn.lock index 3f6a555df3..3a1f482a96 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9279,11 +9279,6 @@ performance-now@^2.1.0: resolved "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz" integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== -picocolors@^0.2.1: - version "0.2.1" - resolved "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz" - integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA== - picocolors@^1.0.0, picocolors@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" @@ -9352,14 +9347,6 @@ possible-typed-array-names@^1.0.0: resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== -postcss-apply@0.12.0: - version "0.12.0" - resolved "https://registry.npmjs.org/postcss-apply/-/postcss-apply-0.12.0.tgz" - integrity sha512-u8qZLyA9P86cD08IhqjSVV8tf1eGiKQ4fPvjcG3Ic/eOU65EAkDQClp8We7d15TG+RIWRVPSy9v7cJ2D9OReqw== - dependencies: - balanced-match "^1.0.0" - postcss "^7.0.14" - postcss-attribute-case-insensitive@^5.0.2: version "5.0.2" resolved "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz" @@ -9693,14 +9680,6 @@ postcss@^6.0.6: source-map "^0.6.1" supports-color "^5.4.0" -postcss@^7.0.14: - version "7.0.39" - resolved "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz" - integrity sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA== - dependencies: - picocolors "^0.2.1" - source-map "^0.6.1" - postcss@^8.2.14, postcss@^8.3.11, postcss@^8.3.7, postcss@^8.4, postcss@^8.4.19: version "8.4.47" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.47.tgz#5bf6c9a010f3e724c503bf03ef7947dcb0fea365" From 425078dc4e60aac89151c5ab516597faca2271f6 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 23 Oct 2024 14:13:33 -0500 Subject: [PATCH 0719/1286] Remove unused postcss-responsive-type --- package.json | 1 - postcss.config.js | 3 +-- yarn.lock | 20 ++------------------ 3 files changed, 3 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index b3988ad5d0..aaf3c17656 100644 --- a/package.json +++ b/package.json @@ -188,7 +188,6 @@ "postcss-import": "^14.0.0", "postcss-loader": "^4.0.3", "postcss-preset-env": "^7.4.2", - "postcss-responsive-type": "1.0.0", "react": "^16.14.0", "react-dom": "^16.14.0", "rimraf": "^3.0.2", diff --git a/postcss.config.js b/postcss.config.js index 14013bd4f8..f8b9666b31 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -1,7 +1,6 @@ module.exports = { plugins: [ require('postcss-import')(), - require('postcss-preset-env')(), - require('postcss-responsive-type')() + require('postcss-preset-env')() ] }; diff --git a/yarn.lock b/yarn.lock index 3a1f482a96..b05cebf7cd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3937,7 +3937,7 @@ chalk@^1.1.1: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.2: version "2.4.2" resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -9635,13 +9635,6 @@ postcss-replace-overflow-wrap@^4.0.0: resolved "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz" integrity sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw== -postcss-responsive-type@1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/postcss-responsive-type/-/postcss-responsive-type-1.0.0.tgz" - integrity sha512-O4kAKbc4RLnSkzcguJ6ojW67uOfeILaj+8xjsO0quLU94d8BKCqYwwFEUVRNbj0YcXA6d3uF/byhbaEATMRVig== - dependencies: - postcss "^6.0.6" - postcss-selector-not@^6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-6.0.1.tgz" @@ -9671,15 +9664,6 @@ postcss@8.4.31: picocolors "^1.0.0" source-map-js "^1.0.2" -postcss@^6.0.6: - version "6.0.23" - resolved "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz" - integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag== - dependencies: - chalk "^2.4.1" - source-map "^0.6.1" - supports-color "^5.4.0" - postcss@^8.2.14, postcss@^8.3.11, postcss@^8.3.7, postcss@^8.4, postcss@^8.4.19: version "8.4.47" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.47.tgz#5bf6c9a010f3e724c503bf03ef7947dcb0fea365" @@ -11315,7 +11299,7 @@ supports-color@^2.0.0: resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g== -supports-color@^5.3.0, supports-color@^5.4.0, supports-color@^5.5.0: +supports-color@^5.3.0, supports-color@^5.5.0: version "5.5.0" resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== From 693adc7cfc8467b33f4bf4614ee33a0095a1f773 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 23 Oct 2024 14:34:12 -0500 Subject: [PATCH 0720/1286] Bump http-proxy-middleware from 1.0.5 to 2.0.7 --- package-lock.json | 65 ++++++++++++++++++----------------------------- package.json | 2 +- 2 files changed, 26 insertions(+), 41 deletions(-) diff --git a/package-lock.json b/package-lock.json index f9712c2779..1c3d4c4dd9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -50,7 +50,7 @@ "express-rate-limit": "^5.1.3", "fast-json-patch": "^3.1.1", "filesize": "^6.1.0", - "http-proxy-middleware": "^1.0.5", + "http-proxy-middleware": "^2.0.7", "http-terminator": "^3.2.0", "isbot": "^5.1.17", "js-cookie": "2.2.1", @@ -6813,7 +6813,7 @@ "version": "1.19.5", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", - "dev": true, + "devOptional": true, "dependencies": { "@types/connect": "*", "@types/node": "*" @@ -6838,7 +6838,7 @@ "version": "3.4.38", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, + "devOptional": true, "dependencies": { "@types/node": "*" } @@ -6890,7 +6890,7 @@ "version": "4.17.21", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", - "dev": true, + "devOptional": true, "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", @@ -6902,7 +6902,7 @@ "version": "4.19.5", "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", - "dev": true, + "devOptional": true, "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -6928,7 +6928,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", - "dev": true + "devOptional": true }, "node_modules/@types/http-proxy": { "version": "1.17.14", @@ -6972,7 +6972,7 @@ "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true + "devOptional": true }, "node_modules/@types/node": { "version": "14.18.63", @@ -7003,13 +7003,13 @@ "version": "6.9.15", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", - "dev": true + "devOptional": true }, "node_modules/@types/range-parser": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true + "devOptional": true }, "node_modules/@types/react": { "version": "17.0.80", @@ -7068,7 +7068,7 @@ "version": "0.17.4", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", - "dev": true, + "devOptional": true, "dependencies": { "@types/mime": "^1", "@types/node": "*" @@ -7087,7 +7087,7 @@ "version": "1.15.7", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", - "dev": true, + "devOptional": true, "dependencies": { "@types/http-errors": "*", "@types/node": "*", @@ -13607,18 +13607,27 @@ } }, "node_modules/http-proxy-middleware": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-1.3.1.tgz", - "integrity": "sha512-13eVVDYS4z79w7f1+NPllJtOQFx/FdUW4btIvVRMaRlUY9VGstAbo5MOhLEuUgZFRHn3x50ufn25zkj/boZnEg==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz", + "integrity": "sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==", + "license": "MIT", "dependencies": { - "@types/http-proxy": "^1.17.5", + "@types/http-proxy": "^1.17.8", "http-proxy": "^1.18.1", "is-glob": "^4.0.1", "is-plain-obj": "^3.0.0", "micromatch": "^4.0.2" }, "engines": { - "node": ">=8.0.0" + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } } }, "node_modules/http-signature": { @@ -22906,30 +22915,6 @@ "node": ">=0.8" } }, - "node_modules/webpack-dev-server/node_modules/http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", - "dev": true, - "dependencies": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@types/express": "^4.17.13" - }, - "peerDependenciesMeta": { - "@types/express": { - "optional": true - } - } - }, "node_modules/webpack-dev-server/node_modules/ipaddr.js": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", diff --git a/package.json b/package.json index 768b028dd9..b608625725 100644 --- a/package.json +++ b/package.json @@ -137,7 +137,7 @@ "express-rate-limit": "^5.1.3", "fast-json-patch": "^3.1.1", "filesize": "^6.1.0", - "http-proxy-middleware": "^1.0.5", + "http-proxy-middleware": "^2.0.7", "http-terminator": "^3.2.0", "isbot": "^5.1.17", "js-cookie": "2.2.1", From 0ed8c05e1c40824d8d428a96c9fb5a0fddd5131a Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 23 Oct 2024 15:01:54 -0500 Subject: [PATCH 0721/1286] Bump http-proxy-middleware from 1.0.5 to 2.0.7 --- package.json | 2 +- yarn.lock | 21 +++++---------------- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index 5197b720dc..d9251da2b9 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,7 @@ "express-rate-limit": "^5.1.3", "fast-json-patch": "^3.1.1", "filesize": "^6.1.0", - "http-proxy-middleware": "^1.0.5", + "http-proxy-middleware": "^2.0.7", "http-terminator": "^3.2.0", "isbot": "^5.1.17", "js-cookie": "2.2.1", diff --git a/yarn.lock b/yarn.lock index 3f6a555df3..dd61f43ddb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2522,7 +2522,7 @@ "@types/react" "*" hoist-non-react-statics "^3.3.0" -"@types/http-proxy@^1.17.5", "@types/http-proxy@^1.17.8": +"@types/http-proxy@^1.17.8": version "1.17.10" resolved "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.10.tgz" integrity sha512-Qs5aULi+zV1bwKAg5z1PWnDXWmsn+LxIvUGv6E2+OOMYhclZMO+OXd9pYVf2gLykf2I7IV2u7oTHwChPNsvJ7g== @@ -6629,21 +6629,10 @@ http-proxy-agent@^5.0.0: agent-base "6" debug "4" -http-proxy-middleware@^1.0.5: - version "1.3.1" - resolved "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-1.3.1.tgz" - integrity sha512-13eVVDYS4z79w7f1+NPllJtOQFx/FdUW4btIvVRMaRlUY9VGstAbo5MOhLEuUgZFRHn3x50ufn25zkj/boZnEg== - dependencies: - "@types/http-proxy" "^1.17.5" - http-proxy "^1.18.1" - is-glob "^4.0.1" - is-plain-obj "^3.0.0" - micromatch "^4.0.2" - -http-proxy-middleware@^2.0.3, http-proxy-middleware@^2.0.6: - version "2.0.6" - resolved "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz" - integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw== +http-proxy-middleware@^2.0.3, http-proxy-middleware@^2.0.6, http-proxy-middleware@^2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz#915f236d92ae98ef48278a95dedf17e991936ec6" + integrity sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA== dependencies: "@types/http-proxy" "^1.17.8" http-proxy "^1.18.1" From 26f6dc562bd07597ad2bf161d1151d6824d88f9b Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 23 Oct 2024 14:57:51 -0500 Subject: [PATCH 0722/1286] Bump http-proxy-middleware from 1.0.5 to 2.0.7 --- package.json | 2 +- yarn.lock | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index c48d1e3154..c32aea3711 100644 --- a/package.json +++ b/package.json @@ -104,7 +104,7 @@ "express-rate-limit": "^5.1.3", "fast-json-patch": "^3.1.1", "filesize": "^6.1.0", - "http-proxy-middleware": "^1.0.5", + "http-proxy-middleware": "^2.0.7", "http-terminator": "^3.2.0", "isbot": "^5.1.17", "js-cookie": "2.2.1", diff --git a/yarn.lock b/yarn.lock index 961ce5de26..d93534d387 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2735,7 +2735,7 @@ resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f" integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA== -"@types/http-proxy@^1.17.5", "@types/http-proxy@^1.17.8": +"@types/http-proxy@^1.17.8": version "1.17.15" resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.15.tgz#12118141ce9775a6499ecb4c01d02f90fc839d36" integrity sha512-25g5atgiVNTIv0LBDTg1H74Hvayx0ajtJPLLcYE3whFv75J0pWNtOBzaXJQgDTmrX1bx5U9YC2w/n65BN1HwRQ== @@ -5517,9 +5517,11 @@ eslint-plugin-deprecation@^1.4.1: "eslint-plugin-dspace-angular-html@link:./lint/dist/src/rules/html": version "0.0.0" + uid "" "eslint-plugin-dspace-angular-ts@link:./lint/dist/src/rules/ts": version "0.0.0" + uid "" eslint-plugin-import-newlines@^1.3.1: version "1.4.0" @@ -6586,7 +6588,7 @@ http-proxy-agent@^7.0.0: agent-base "^7.1.0" debug "^4.3.4" -http-proxy-middleware@2.0.6, http-proxy-middleware@^2.0.3: +http-proxy-middleware@2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f" integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw== @@ -6597,12 +6599,12 @@ http-proxy-middleware@2.0.6, http-proxy-middleware@^2.0.3: is-plain-obj "^3.0.0" micromatch "^4.0.2" -http-proxy-middleware@^1.0.5: - version "1.3.1" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-1.3.1.tgz#43700d6d9eecb7419bf086a128d0f7205d9eb665" - integrity sha512-13eVVDYS4z79w7f1+NPllJtOQFx/FdUW4btIvVRMaRlUY9VGstAbo5MOhLEuUgZFRHn3x50ufn25zkj/boZnEg== +http-proxy-middleware@^2.0.3, http-proxy-middleware@^2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz#915f236d92ae98ef48278a95dedf17e991936ec6" + integrity sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA== dependencies: - "@types/http-proxy" "^1.17.5" + "@types/http-proxy" "^1.17.8" http-proxy "^1.18.1" is-glob "^4.0.1" is-plain-obj "^3.0.0" From d4bb79ca18d20111786015bd4657c468a29985f2 Mon Sep 17 00:00:00 2001 From: andreaNeki Date: Tue, 22 Oct 2024 13:29:05 -0300 Subject: [PATCH 0723/1286] Issue 3426 - Aligning the browse button (cherry picked from commit ddafda33b8c4730a732a133147451390ee2c7ab7) --- src/app/shared/upload/uploader/uploader.component.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/shared/upload/uploader/uploader.component.html b/src/app/shared/upload/uploader/uploader.component.html index b1fd8199d8..4c1db13d13 100644 --- a/src/app/shared/upload/uploader/uploader.component.html +++ b/src/app/shared/upload/uploader/uploader.component.html @@ -19,8 +19,8 @@ (fileOver)="fileOverBase($event)" class="well ds-base-drop-zone mt-1 mb-3 text-muted">
- - + + {{dropMsg | translate}}{{'uploader.or' | translate}}
{{ dsoNameService.getName(undefined) }} + {{ dsoNameService.getName((group.object | async)?.payload) }} +
diff --git a/src/app/access-control/group-registry/group-form/group-form.component.ts b/src/app/access-control/group-registry/group-form/group-form.component.ts index 37ce30473f..c0ea034fbb 100644 --- a/src/app/access-control/group-registry/group-form/group-form.component.ts +++ b/src/app/access-control/group-registry/group-form/group-form.component.ts @@ -13,7 +13,7 @@ import { Observable, Subscription, combineLatest, } from 'rxjs'; -import { map, switchMap, take, debounceTime, startWith, filter } from 'rxjs/operators'; +import { map, switchMap, take, debounceTime } from 'rxjs/operators'; import { getCollectionEditRolesRoute } from '../../../collection-page/collection-page-routing-paths'; import { getCommunityEditRolesRoute } from '../../../community-page/community-page-routing-paths'; import { DSpaceObjectDataService } from '../../../core/data/dspace-object-data.service'; @@ -35,7 +35,7 @@ import { } from '../../../core/shared/operators'; import { AlertType } from '../../../shared/alert/aletr-type'; import { ConfirmationModalComponent } from '../../../shared/confirmation-modal/confirmation-modal.component'; -import { hasValue, isNotEmpty, hasValueOperator, hasNoValue } from '../../../shared/empty.util'; +import { hasValue, isNotEmpty, hasValueOperator } from '../../../shared/empty.util'; import { FormBuilderService } from '../../../shared/form/builder/form-builder.service'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; import { followLink } from '../../../shared/utils/follow-link-config.model'; @@ -164,11 +164,16 @@ export class GroupFormComponent implements OnInit, OnDestroy { this.activeGroupLinkedDSO$ = this.getActiveGroupLinkedDSO(); this.linkedEditRolesRoute$ = this.getLinkedEditRolesRoute(); this.canEdit$ = this.activeGroupLinkedDSO$.pipe( - filter((dso: DSpaceObject) => hasNoValue(dso)), - switchMap(() => this.activeGroup$), - hasValueOperator(), - switchMap((group: Group) => this.authorizationService.isAuthorized(FeatureID.CanDelete, group.self)), - startWith(false), + switchMap((dso: DSpaceObject) => { + if (hasValue(dso)) { + return [false]; + } else { + return this.activeGroup$.pipe( + hasValueOperator(), + switchMap((group: Group) => this.authorizationService.isAuthorized(FeatureID.CanDelete, group.self)), + ); + } + }), ); this.initialisePage(); } @@ -216,7 +221,7 @@ export class GroupFormComponent implements OnInit, OnDestroy { combineLatest([ this.activeGroup$, this.canEdit$, - this.activeGroupLinkedDSO$.pipe(take(1)), + this.activeGroupLinkedDSO$, ]).subscribe(([activeGroup, canEdit, linkedObject]) => { if (activeGroup != null) { @@ -224,25 +229,31 @@ export class GroupFormComponent implements OnInit, OnDestroy { // Disable group name exists validator this.formGroup.controls.groupName.clearAsyncValidators(); - if (linkedObject?.name) { - this.formBuilderService.insertFormGroupControl(1, this.formGroup, this.formModel, groupCommunityModel); - this.groupDescription = this.formGroup.get('groupCommunity'); + if (isNotEmpty(linkedObject?.name)) { + if (!this.formGroup.controls.groupCommunity) { + this.formBuilderService.insertFormGroupControl(1, this.formGroup, this.formModel, groupCommunityModel); + this.groupDescription = this.formGroup.get('groupCommunity'); + } this.formGroup.patchValue({ groupName: activeGroup.name, groupCommunity: linkedObject?.name ?? '', groupDescription: activeGroup.firstMetadataValue('dc.description'), }); } else { + this.formModel = [ + groupNameModel, + groupDescriptionModel, + ]; this.formGroup.patchValue({ groupName: activeGroup.name, groupDescription: activeGroup.firstMetadataValue('dc.description'), }); } - setTimeout(() => { - if (!canEdit || activeGroup.permanent) { - this.formGroup.disable(); - } - }, 200); + if (!canEdit || activeGroup.permanent) { + this.formGroup.disable(); + } else { + this.formGroup.enable(); + } } }) ); @@ -471,6 +482,7 @@ export class GroupFormComponent implements OnInit, OnDestroy { */ getLinkedEditRolesRoute(): Observable { return this.activeGroupLinkedDSO$.pipe( + hasValueOperator(), map((dso: DSpaceObject) => { switch ((dso as any).type) { case Community.type.value: @@ -478,7 +490,7 @@ export class GroupFormComponent implements OnInit, OnDestroy { case Collection.type.value: return getCollectionEditRolesRoute(dso.id); } - }) + }), ); } } From 976ac7604be2458c31f92b6af05e94df453a74ea Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Tue, 29 Oct 2024 17:36:33 +0100 Subject: [PATCH 0767/1286] 117287: Fixed UI freezing on withdrawn item pages --- .../alerts/item-alerts.component.html | 2 +- .../alerts/item-alerts.component.spec.ts | 2 +- .../item-page/alerts/item-alerts.component.ts | 27 ++++++++++++++----- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/app/item-page/alerts/item-alerts.component.html b/src/app/item-page/alerts/item-alerts.component.html index f6304340f3..b964327e39 100644 --- a/src/app/item-page/alerts/item-alerts.component.html +++ b/src/app/item-page/alerts/item-alerts.component.html @@ -8,7 +8,7 @@ {{'item.alerts.withdrawn' | translate}} 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 d2541f9d0d..ef788c47ec 100644 --- a/src/app/item-page/alerts/item-alerts.component.spec.ts +++ b/src/app/item-page/alerts/item-alerts.component.spec.ts @@ -161,7 +161,7 @@ describe('ItemAlertsComponent', () => { (authorizationService.isAuthorized).and.returnValue(isAdmin$); (correctionTypeDataService.findByItem).and.returnValue(correction$); - expectObservable(component.showReinstateButton$()).toBe(expectedMarble, expectedValues); + expectObservable(component.shouldShowReinstateButton()).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 1984de0324..bcf940e69d 100644 --- a/src/app/item-page/alerts/item-alerts.component.ts +++ b/src/app/item-page/alerts/item-alerts.component.ts @@ -5,6 +5,8 @@ import { import { Component, Input, + OnChanges, + SimpleChanges, } from '@angular/core'; import { RouterLink } from '@angular/router'; import { TranslateModule } from '@ngx-translate/core'; @@ -45,12 +47,17 @@ import { /** * Component displaying alerts for an item */ -export class ItemAlertsComponent { +export class ItemAlertsComponent implements OnChanges { /** * The Item to display alerts for */ @Input() item: Item; + /** + * Whether the reinstate button should be shown + */ + showReinstateButton$: Observable; + /** * The AlertType enumeration * @type {AlertType} @@ -58,18 +65,24 @@ export class ItemAlertsComponent { public AlertTypeEnum = AlertType; constructor( - private authService: AuthorizationDataService, - private dsoWithdrawnReinstateModalService: DsoWithdrawnReinstateModalService, - private correctionTypeDataService: CorrectionTypeDataService, + protected authService: AuthorizationDataService, + protected dsoWithdrawnReinstateModalService: DsoWithdrawnReinstateModalService, + protected correctionTypeDataService: CorrectionTypeDataService, ) { } + ngOnChanges(changes: SimpleChanges): void { + if (changes.item?.currentValue.withdrawn && this.showReinstateButton$) { + this.showReinstateButton$ = this.shouldShowReinstateButton(); + } + } + /** * 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 { + shouldShowReinstateButton(): Observable { const correction$ = this.correctionTypeDataService.findByItem(this.item.uuid, true).pipe( getFirstCompletedRemoteData(), map((correctionTypeRD: RemoteData>) => correctionTypeRD.hasSucceeded ? correctionTypeRD.payload.page : []), @@ -78,8 +91,8 @@ export class ItemAlertsComponent { return combineLatest([isAdmin$, correction$]).pipe( map(([isAdmin, correction]) => { return !isAdmin && correction.some((correctionType) => correctionType.topic === REQUEST_REINSTATE); - }, - )); + }), + ); } /** From 0cb5b76159ce41b8b15192010ff7c89ab9911d21 Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Tue, 29 Oct 2024 18:33:01 +0100 Subject: [PATCH 0768/1286] 117287: Prevent /api/eperson/epersons/undefined from being fired on the create ePerson page --- .../eperson-form/eperson-form.component.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts b/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts index 4a1d907990..8aa7f15250 100644 --- a/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts +++ b/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts @@ -278,9 +278,11 @@ export class EPersonFormComponent implements OnInit, OnDestroy { * This method will initialise the page */ initialisePage() { - this.subs.push(this.epersonService.findById(this.route.snapshot.params.id).subscribe((ePersonRD: RemoteData) => { - this.epersonService.editEPerson(ePersonRD.payload); - })); + if (this.route.snapshot.params.id) { + this.subs.push(this.epersonService.findById(this.route.snapshot.params.id).subscribe((ePersonRD: RemoteData) => { + this.epersonService.editEPerson(ePersonRD.payload); + })); + } this.firstName = new DynamicInputModel({ id: 'firstName', label: this.translateService.instant(`${this.messagePrefix}.firstName`), From 8d00d435c432db20409a2d01835442196a4b94e9 Mon Sep 17 00:00:00 2001 From: Nima Behforouz <92104872+nimabehforouz@users.noreply.github.com> Date: Tue, 29 Oct 2024 15:48:53 -0400 Subject: [PATCH 0769/1286] Update fr.json5 Translation updates to fr.json5 file regarding the Access Control sections. --- src/assets/i18n/fr.json5 | 96 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/src/assets/i18n/fr.json5 b/src/assets/i18n/fr.json5 index 185576e186..b2a03fad7d 100644 --- a/src/assets/i18n/fr.json5 +++ b/src/assets/i18n/fr.json5 @@ -357,6 +357,18 @@ // "admin.access-control.epeople.breadcrumbs": "EPeople", "admin.access-control.epeople.breadcrumbs": "EPeople", + // "admin.access-control.epeople.edit.breadcrumbs": "New EPerson", + "admin.access-control.epeople.edit.breadcrumbs": "Nouvelle EPerson", + + // "admin.access-control.epeople.edit.title": "New EPerson", + "admin.access-control.epeople.edit.title": "Nouvelle EPerson", + + // "admin.access-control.epeople.add.breadcrumbs": "Add EPerson", + "admin.access-control.epeople.add.breadcrumbs": "Ajouter EPerson", + + // "admin.access-control.epeople.add.title": "Add EPerson", + "admin.access-control.epeople.add.title": "Ajouter EPerson", + // "admin.access-control.epeople.title": "EPeople", "admin.access-control.epeople.title": "EPeople", @@ -747,6 +759,30 @@ // "admin.access-control.groups.form.return": "Back", "admin.access-control.groups.form.return": "Retour", + // "admin.quality-assurance.breadcrumbs": "Quality Assurance", + "admin.quality-assurance.breadcrumbs": "Assurance qualité", + + // "admin.notifications.event.breadcrumbs": "Quality Assurance Suggestions", + "admin.notifications.event.breadcrumbs": "Suggestions d'assurance qualité", + + // "admin.notifications.event.page.title": "Quality Assurance Suggestions", + "admin.notifications.event.page.title": "Suggestions d'assurance qualité", + + // "admin.quality-assurance.page.title": "Quality Assurance", + "admin.quality-assurance.page.title": "Assurance qualité", + + // "admin.notifications.source.breadcrumbs": "Quality Assurance", + "admin.notifications.source.breadcrumbs": "Assurance qualité", + + // "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": "Sur cette page, vous pouvez modifier les propriétés et les membres d'un groupe. Dans la section supérieure, vous pouvez éditer le nom et la description du groupe, sauf s'il s'agit d'un groupe d'administrateurs d'une collection ou d'une communauté ; dans ce cas, le nom et la description du groupe sont générés automatiquement et ne peuvent pas être modifiés. Dans les sections suivantes, vous pouvez modifier l'appartenance au groupe. Voir [le wiki](https://wiki.lyrasis.org/display/DSDOC7x/Create+or+manage+a+user+group) pour plus de détails.", + + // "admin.access-control.groups.form.tooltip.editGroup.addEpeople": "To add or remove an EPerson to/from this group, either click the 'Browse All' button or use the search bar below to search for users (use the dropdown to the left of the search bar to choose whether to search by metadata or by email). 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.", + "admin.access-control.groups.form.tooltip.editGroup.addEpeople": "Pour ajouter ou retirer une EPerson à/de ce groupe, cliquez sur le bouton « Parcourir tout », ou utilisez la barre de recherche ci-dessous pour rechercher des utilisateurs (utilisez le menu déroulant à gauche de la barre de recherche pour choisir si vous souhaitez effectuer la recherche par métadonnées ou par courriel). Ensuite, cliquez sur l'icône + pour chaque utilisateur que vous souhaitez ajouter dans la liste ci-dessous, ou sur l'icône de la corbeille pour chaque utilisateur que vous souhaitez retirer. La liste ci-dessous peut comporter plusieurs pages : utilisez les contrôles de pagination sous la liste pour naviguer vers les pages suivantes.", + + // "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.access-control.groups.form.tooltip.editGroup.addSubgroups": "Pour ajouter ou retirer un sous-groupe à/de ce groupe, cliquez sur le bouton « Parcourir tout », ou utilisez la barre de recherche ci-dessous pour rechercher des groupes. Ensuite, cliquez sur l'icône + pour chaque groupe que vous souhaitez ajouter dans la liste ci-dessous, ou sur l'icône de la corbeille pour chaque groupe que vous souhaitez retirer. La liste ci-dessous peut comporter plusieurs pages : utilisez les contrôles de pagination sous la liste pour naviguer vers les pages suivantes.", + //"admin.reports.collections.title": "Collection Filter Report", "admin.reports.collections.title": "Rapport de collections filtrées", @@ -1576,6 +1612,12 @@ // "collection.edit.return": "Back", "collection.edit.return": "Retour", + // "collection.edit.tabs.access-control.head": "Access Control", + "collection.edit.tabs.access-control.head": "Contrôle d'accès", + + // "collection.edit.tabs.access-control.title": "Collection Edit - Access Control", + "collection.edit.tabs.access-control.title": "Édition de Collection - Contrôle d'accès", + // "collection.edit.tabs.curate.head": "Curate", "collection.edit.tabs.curate.head": "Gestion du contenu", @@ -1932,6 +1974,12 @@ // "community.edit.tabs.curate.title": "Community Edit - Curate", "community.edit.tabs.curate.title": "Édition de communauté - Gestion du contenu", + // "community.edit.tabs.access-control.head": "Access Control", + "community.edit.tabs.access-control.head": "Contrôle d'accès", + + // "community.edit.tabs.access-control.title": "Community Edit - Access Control", + "community.edit.tabs.access-control.title": "Édition de Communauté - Contrôle d'accès", + // "community.edit.tabs.metadata.head": "Edit Metadata", "community.edit.tabs.metadata.head": "Éditer Métadonnées", @@ -3227,6 +3275,15 @@ // "item.edit.tabs.curate.title": "Item Edit - Curate", "item.edit.tabs.curate.title": "Édition d'Item - Gestion de contenu", + // "item.edit.curate.title": "Curate Item: {{item}}", + "item.edit.curate.title": "Gestion de contenu de l'Item: {{item}}", + + // "item.edit.tabs.access-control.head": "Access Control", + "item.edit.tabs.access-control.head": "Contrôle d'accès", + + // "item.edit.tabs.access-control.title": "Item Edit - Access Control", + "item.edit.tabs.access-control.title": "Édition de l'Item - Contrôle d'accès", + // "item.edit.tabs.metadata.head": "Metadata", "item.edit.tabs.metadata.head": "Métadonnées", @@ -6687,6 +6744,45 @@ //"access-control-cancel": "Cancel", "access-control-cancel": "Annuler", + // "item-access-control-title": "This form allows you to perform changes to the access conditions of the item's metadata or its bitstreams.", + "item-access-control-title": "Ce formulaire vous permet de modifier les conditions d'accès aux métadonnées de l'Item ou à ses Bitstreams.", + + // "access-control-execute": "Execute", + "access-control-execute": "Exécuter", + + // "access-control-add-more": "Add more", + "access-control-add-more": "Ajouter plus", + + // "access-control-remove": "Remove access condition", + "access-control-remove": "Supprimer la condition d'accès", + + // "access-control-select-bitstreams-modal.title": "Select bitstreams", + "access-control-select-bitstreams-modal.title": "Sélectionner les Bitstreams", + + // "access-control-select-bitstreams-modal.no-items": "No items to show.", + "access-control-select-bitstreams-modal.no-items": "Aucun Item à afficher.", + + // "access-control-select-bitstreams-modal.close": "Close", + "access-control-select-bitstreams-modal.close": "Fermer", + + // "access-control-option-label": "Access condition type", + "access-control-option-label": "Type de condition d'accès", + + // "access-control-option-note": "Choose an access condition to apply to selected objects.", + "access-control-option-note": "Choisissez une condition d'accès à appliquer aux objets sélectionnés.", + + // "access-control-option-start-date": "Grant access from", + "access-control-option-start-date": "Accorder l'accès à partir de", + + //"access-control-option-start-date-note": "Select the date from which the related access condition is applied", + "access-control-option-start-date-note": "Sélectionnez la date à partir de laquelle la condition d'accès liée est appliquée", + + // "access-control-option-end-date": "Grant access until", + "access-control-option-end-date": "Accorder l'accès jusqu'à", + + // "access-control-option-end-date-note": "Select the date until which the related access condition is applied", + "access-control-option-end-date-note": "Sélectionnez la date jusqu'à laquelle la condition d'accès liée est appliquée", + } From 8dd132d7a7b4d69864dfcd6fe0d4269c5726b86f Mon Sep 17 00:00:00 2001 From: DanGastardelli <55243638+DanGastardelli@users.noreply.github.com> Date: Tue, 1 Oct 2024 17:15:53 -0300 Subject: [PATCH 0770/1286] Changing the bitstream title in the submission form to use the view component title, avoiding disappearance with changes to the form (cherry picked from commit fec4aa6df1bd6c5ea1ca9eeb10e4bc643a16d39e) --- .../sections/upload/file/section-upload-file.component.html | 3 +-- .../upload/file/view/section-upload-file-view.component.html | 5 +++-- .../upload/file/view/section-upload-file-view.component.ts | 4 +++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/app/submission/sections/upload/file/section-upload-file.component.html b/src/app/submission/sections/upload/file/section-upload-file.component.html index da83e3f9a0..4698fdf68a 100644 --- a/src/app/submission/sections/upload/file/section-upload-file.component.html +++ b/src/app/submission/sections/upload/file/section-upload-file.component.html @@ -18,7 +18,7 @@
-

{{fileName}} ({{fileData?.sizeBytes | dsFileSize}})

+
@@ -43,7 +43,6 @@
-
diff --git a/src/app/submission/sections/upload/file/view/section-upload-file-view.component.html b/src/app/submission/sections/upload/file/view/section-upload-file-view.component.html index cc12b5dea6..dc72fbdad0 100644 --- a/src/app/submission/sections/upload/file/view/section-upload-file-view.component.html +++ b/src/app/submission/sections/upload/file/view/section-upload-file-view.component.html @@ -2,9 +2,10 @@ -
+

{{entry.value}} -

+ ({{fileData?.sizeBytes | dsFileSize}}) +
diff --git a/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts b/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts index 0630a28a76..7ab21fb85b 100644 --- a/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts +++ b/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts @@ -18,6 +18,7 @@ import { WorkspaceitemSectionUploadFileObject } from '../../../../../core/submis import { isNotEmpty } from '../../../../../shared/empty.util'; import { TruncatePipe } from '../../../../../shared/utils/truncate.pipe'; import { SubmissionSectionUploadAccessConditionsComponent } from '../../accessConditions/submission-section-upload-access-conditions.component'; +import { FileSizePipe } from "../../../../../shared/utils/file-size-pipe"; /** * This component allow to show bitstream's metadata @@ -31,7 +32,8 @@ import { SubmissionSectionUploadAccessConditionsComponent } from '../../accessCo TruncatePipe, NgIf, NgForOf, - ], + FileSizePipe +], standalone: true, }) export class SubmissionSectionUploadFileViewComponent implements OnInit { From 3104264cd4b1801cb1ab1ee8938d45374204ec9a Mon Sep 17 00:00:00 2001 From: DanGastardelli <55243638+DanGastardelli@users.noreply.github.com> Date: Wed, 2 Oct 2024 08:38:42 -0300 Subject: [PATCH 0771/1286] Adjusting spacing and good rules (cherry picked from commit df24a63a464c3f88adedf982cdf540241414a86a) --- .../upload/file/view/section-upload-file-view.component.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts b/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts index 7ab21fb85b..378753a1e6 100644 --- a/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts +++ b/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts @@ -18,7 +18,7 @@ import { WorkspaceitemSectionUploadFileObject } from '../../../../../core/submis import { isNotEmpty } from '../../../../../shared/empty.util'; import { TruncatePipe } from '../../../../../shared/utils/truncate.pipe'; import { SubmissionSectionUploadAccessConditionsComponent } from '../../accessConditions/submission-section-upload-access-conditions.component'; -import { FileSizePipe } from "../../../../../shared/utils/file-size-pipe"; +import { FileSizePipe } from '../../../../../shared/utils/file-size-pipe'; /** * This component allow to show bitstream's metadata @@ -32,8 +32,8 @@ import { FileSizePipe } from "../../../../../shared/utils/file-size-pipe"; TruncatePipe, NgIf, NgForOf, - FileSizePipe -], + FileSizePipe, + ], standalone: true, }) export class SubmissionSectionUploadFileViewComponent implements OnInit { From 10f11a55fff372a40bb85250d433a54ed915caa9 Mon Sep 17 00:00:00 2001 From: DanGastardelli <55243638+DanGastardelli@users.noreply.github.com> Date: Wed, 2 Oct 2024 08:46:37 -0300 Subject: [PATCH 0772/1286] Adjusting spacing (cherry picked from commit 762bc8ce8c5a87a1dc7ba9763916addaabe06398) --- .../upload/file/view/section-upload-file-view.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts b/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts index 378753a1e6..7b8e870400 100644 --- a/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts +++ b/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts @@ -54,13 +54,13 @@ export class SubmissionSectionUploadFileViewComponent implements OnInit { * The bitstream's title key * @type {string} */ - public fileTitleKey = 'Title'; + public fileTitleKey: string = 'Title'; /** * The bitstream's description key * @type {string} */ - public fileDescrKey = 'Description'; + public fileDescrKey: string = 'Description'; public fileFormat!: string; From 784f5c180861f8d79aac119a951a42e1e455b10a Mon Sep 17 00:00:00 2001 From: DanGastardelli <55243638+DanGastardelli@users.noreply.github.com> Date: Wed, 2 Oct 2024 09:01:56 -0300 Subject: [PATCH 0773/1286] Fix last commit (cherry picked from commit 62006c00cacf7e74661d6cc3dd4b5a53f47aeb72) --- .../upload/file/view/section-upload-file-view.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts b/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts index 7b8e870400..378753a1e6 100644 --- a/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts +++ b/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts @@ -54,13 +54,13 @@ export class SubmissionSectionUploadFileViewComponent implements OnInit { * The bitstream's title key * @type {string} */ - public fileTitleKey: string = 'Title'; + public fileTitleKey = 'Title'; /** * The bitstream's description key * @type {string} */ - public fileDescrKey: string = 'Description'; + public fileDescrKey = 'Description'; public fileFormat!: string; From fccfc93a10f895d065d67eb49a9c2c8bb0b8386b Mon Sep 17 00:00:00 2001 From: DanGastardelli <55243638+DanGastardelli@users.noreply.github.com> Date: Wed, 2 Oct 2024 09:10:48 -0300 Subject: [PATCH 0774/1286] Import order adjustment (cherry picked from commit eeaac8965b8b82e8d21f712350781c3e7f627157) --- .../upload/file/view/section-upload-file-view.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts b/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts index 378753a1e6..20e86a492d 100644 --- a/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts +++ b/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts @@ -17,8 +17,8 @@ import { Metadata } from '../../../../../core/shared/metadata.utils'; import { WorkspaceitemSectionUploadFileObject } from '../../../../../core/submission/models/workspaceitem-section-upload-file.model'; import { isNotEmpty } from '../../../../../shared/empty.util'; import { TruncatePipe } from '../../../../../shared/utils/truncate.pipe'; -import { SubmissionSectionUploadAccessConditionsComponent } from '../../accessConditions/submission-section-upload-access-conditions.component'; import { FileSizePipe } from '../../../../../shared/utils/file-size-pipe'; +import { SubmissionSectionUploadAccessConditionsComponent } from '../../accessConditions/submission-section-upload-access-conditions.component'; /** * This component allow to show bitstream's metadata From 7e827165e930d0235a8561aa8a0783e3aaa8856f Mon Sep 17 00:00:00 2001 From: DanGastardelli <55243638+DanGastardelli@users.noreply.github.com> Date: Wed, 2 Oct 2024 09:24:46 -0300 Subject: [PATCH 0775/1286] Import order adjustment (cherry picked from commit 2643a459b6a1213b4edb16f245732ba0a1b32bcb) --- .../upload/file/view/section-upload-file-view.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts b/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts index 20e86a492d..f065fc9e19 100644 --- a/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts +++ b/src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts @@ -16,8 +16,8 @@ import { import { Metadata } from '../../../../../core/shared/metadata.utils'; import { WorkspaceitemSectionUploadFileObject } from '../../../../../core/submission/models/workspaceitem-section-upload-file.model'; import { isNotEmpty } from '../../../../../shared/empty.util'; -import { TruncatePipe } from '../../../../../shared/utils/truncate.pipe'; import { FileSizePipe } from '../../../../../shared/utils/file-size-pipe'; +import { TruncatePipe } from '../../../../../shared/utils/truncate.pipe'; import { SubmissionSectionUploadAccessConditionsComponent } from '../../accessConditions/submission-section-upload-access-conditions.component'; /** From 3b8a075049c52b569ebe1a7f0cb4d31808cdbf4d Mon Sep 17 00:00:00 2001 From: Nima Behforouz <92104872+nimabehforouz@users.noreply.github.com> Date: Tue, 29 Oct 2024 15:48:53 -0400 Subject: [PATCH 0776/1286] Update fr.json5 Translation updates to fr.json5 file regarding the Access Control sections. (cherry picked from commit 8d00d435c432db20409a2d01835442196a4b94e9) --- src/assets/i18n/fr.json5 | 96 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/src/assets/i18n/fr.json5 b/src/assets/i18n/fr.json5 index 185576e186..b2a03fad7d 100644 --- a/src/assets/i18n/fr.json5 +++ b/src/assets/i18n/fr.json5 @@ -357,6 +357,18 @@ // "admin.access-control.epeople.breadcrumbs": "EPeople", "admin.access-control.epeople.breadcrumbs": "EPeople", + // "admin.access-control.epeople.edit.breadcrumbs": "New EPerson", + "admin.access-control.epeople.edit.breadcrumbs": "Nouvelle EPerson", + + // "admin.access-control.epeople.edit.title": "New EPerson", + "admin.access-control.epeople.edit.title": "Nouvelle EPerson", + + // "admin.access-control.epeople.add.breadcrumbs": "Add EPerson", + "admin.access-control.epeople.add.breadcrumbs": "Ajouter EPerson", + + // "admin.access-control.epeople.add.title": "Add EPerson", + "admin.access-control.epeople.add.title": "Ajouter EPerson", + // "admin.access-control.epeople.title": "EPeople", "admin.access-control.epeople.title": "EPeople", @@ -747,6 +759,30 @@ // "admin.access-control.groups.form.return": "Back", "admin.access-control.groups.form.return": "Retour", + // "admin.quality-assurance.breadcrumbs": "Quality Assurance", + "admin.quality-assurance.breadcrumbs": "Assurance qualité", + + // "admin.notifications.event.breadcrumbs": "Quality Assurance Suggestions", + "admin.notifications.event.breadcrumbs": "Suggestions d'assurance qualité", + + // "admin.notifications.event.page.title": "Quality Assurance Suggestions", + "admin.notifications.event.page.title": "Suggestions d'assurance qualité", + + // "admin.quality-assurance.page.title": "Quality Assurance", + "admin.quality-assurance.page.title": "Assurance qualité", + + // "admin.notifications.source.breadcrumbs": "Quality Assurance", + "admin.notifications.source.breadcrumbs": "Assurance qualité", + + // "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": "Sur cette page, vous pouvez modifier les propriétés et les membres d'un groupe. Dans la section supérieure, vous pouvez éditer le nom et la description du groupe, sauf s'il s'agit d'un groupe d'administrateurs d'une collection ou d'une communauté ; dans ce cas, le nom et la description du groupe sont générés automatiquement et ne peuvent pas être modifiés. Dans les sections suivantes, vous pouvez modifier l'appartenance au groupe. Voir [le wiki](https://wiki.lyrasis.org/display/DSDOC7x/Create+or+manage+a+user+group) pour plus de détails.", + + // "admin.access-control.groups.form.tooltip.editGroup.addEpeople": "To add or remove an EPerson to/from this group, either click the 'Browse All' button or use the search bar below to search for users (use the dropdown to the left of the search bar to choose whether to search by metadata or by email). 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.", + "admin.access-control.groups.form.tooltip.editGroup.addEpeople": "Pour ajouter ou retirer une EPerson à/de ce groupe, cliquez sur le bouton « Parcourir tout », ou utilisez la barre de recherche ci-dessous pour rechercher des utilisateurs (utilisez le menu déroulant à gauche de la barre de recherche pour choisir si vous souhaitez effectuer la recherche par métadonnées ou par courriel). Ensuite, cliquez sur l'icône + pour chaque utilisateur que vous souhaitez ajouter dans la liste ci-dessous, ou sur l'icône de la corbeille pour chaque utilisateur que vous souhaitez retirer. La liste ci-dessous peut comporter plusieurs pages : utilisez les contrôles de pagination sous la liste pour naviguer vers les pages suivantes.", + + // "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.access-control.groups.form.tooltip.editGroup.addSubgroups": "Pour ajouter ou retirer un sous-groupe à/de ce groupe, cliquez sur le bouton « Parcourir tout », ou utilisez la barre de recherche ci-dessous pour rechercher des groupes. Ensuite, cliquez sur l'icône + pour chaque groupe que vous souhaitez ajouter dans la liste ci-dessous, ou sur l'icône de la corbeille pour chaque groupe que vous souhaitez retirer. La liste ci-dessous peut comporter plusieurs pages : utilisez les contrôles de pagination sous la liste pour naviguer vers les pages suivantes.", + //"admin.reports.collections.title": "Collection Filter Report", "admin.reports.collections.title": "Rapport de collections filtrées", @@ -1576,6 +1612,12 @@ // "collection.edit.return": "Back", "collection.edit.return": "Retour", + // "collection.edit.tabs.access-control.head": "Access Control", + "collection.edit.tabs.access-control.head": "Contrôle d'accès", + + // "collection.edit.tabs.access-control.title": "Collection Edit - Access Control", + "collection.edit.tabs.access-control.title": "Édition de Collection - Contrôle d'accès", + // "collection.edit.tabs.curate.head": "Curate", "collection.edit.tabs.curate.head": "Gestion du contenu", @@ -1932,6 +1974,12 @@ // "community.edit.tabs.curate.title": "Community Edit - Curate", "community.edit.tabs.curate.title": "Édition de communauté - Gestion du contenu", + // "community.edit.tabs.access-control.head": "Access Control", + "community.edit.tabs.access-control.head": "Contrôle d'accès", + + // "community.edit.tabs.access-control.title": "Community Edit - Access Control", + "community.edit.tabs.access-control.title": "Édition de Communauté - Contrôle d'accès", + // "community.edit.tabs.metadata.head": "Edit Metadata", "community.edit.tabs.metadata.head": "Éditer Métadonnées", @@ -3227,6 +3275,15 @@ // "item.edit.tabs.curate.title": "Item Edit - Curate", "item.edit.tabs.curate.title": "Édition d'Item - Gestion de contenu", + // "item.edit.curate.title": "Curate Item: {{item}}", + "item.edit.curate.title": "Gestion de contenu de l'Item: {{item}}", + + // "item.edit.tabs.access-control.head": "Access Control", + "item.edit.tabs.access-control.head": "Contrôle d'accès", + + // "item.edit.tabs.access-control.title": "Item Edit - Access Control", + "item.edit.tabs.access-control.title": "Édition de l'Item - Contrôle d'accès", + // "item.edit.tabs.metadata.head": "Metadata", "item.edit.tabs.metadata.head": "Métadonnées", @@ -6687,6 +6744,45 @@ //"access-control-cancel": "Cancel", "access-control-cancel": "Annuler", + // "item-access-control-title": "This form allows you to perform changes to the access conditions of the item's metadata or its bitstreams.", + "item-access-control-title": "Ce formulaire vous permet de modifier les conditions d'accès aux métadonnées de l'Item ou à ses Bitstreams.", + + // "access-control-execute": "Execute", + "access-control-execute": "Exécuter", + + // "access-control-add-more": "Add more", + "access-control-add-more": "Ajouter plus", + + // "access-control-remove": "Remove access condition", + "access-control-remove": "Supprimer la condition d'accès", + + // "access-control-select-bitstreams-modal.title": "Select bitstreams", + "access-control-select-bitstreams-modal.title": "Sélectionner les Bitstreams", + + // "access-control-select-bitstreams-modal.no-items": "No items to show.", + "access-control-select-bitstreams-modal.no-items": "Aucun Item à afficher.", + + // "access-control-select-bitstreams-modal.close": "Close", + "access-control-select-bitstreams-modal.close": "Fermer", + + // "access-control-option-label": "Access condition type", + "access-control-option-label": "Type de condition d'accès", + + // "access-control-option-note": "Choose an access condition to apply to selected objects.", + "access-control-option-note": "Choisissez une condition d'accès à appliquer aux objets sélectionnés.", + + // "access-control-option-start-date": "Grant access from", + "access-control-option-start-date": "Accorder l'accès à partir de", + + //"access-control-option-start-date-note": "Select the date from which the related access condition is applied", + "access-control-option-start-date-note": "Sélectionnez la date à partir de laquelle la condition d'accès liée est appliquée", + + // "access-control-option-end-date": "Grant access until", + "access-control-option-end-date": "Accorder l'accès jusqu'à", + + // "access-control-option-end-date-note": "Select the date until which the related access condition is applied", + "access-control-option-end-date-note": "Sélectionnez la date jusqu'à laquelle la condition d'accès liée est appliquée", + } From 0ab4d903d958c1564e73c2ff1ab5a766b3648ea7 Mon Sep 17 00:00:00 2001 From: Andrea Barbasso <´andrea.barbasso@4science.com´> Date: Thu, 31 Oct 2024 10:44:27 +0100 Subject: [PATCH 0777/1286] [CST-15593] fix orejime cookie name, a11y issues and package-lock --- cypress/support/e2e.ts | 4 ++-- package-lock.json | 19 ++++++++++++++++++- .../google-recaptcha.service.ts | 2 +- .../register-email-form.component.ts | 2 +- .../shared/cookies/orejime-configuration.ts | 2 +- src/styles/_custom_variables.scss | 2 +- src/styles/_global-styles.scss | 2 +- 7 files changed, 25 insertions(+), 8 deletions(-) diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts index c1b6bc6d3f..3c9f4e7b56 100644 --- a/cypress/support/e2e.ts +++ b/cypress/support/e2e.ts @@ -54,9 +54,9 @@ before(() => { // Runs once before the first test in each "block" beforeEach(() => { - // Pre-agree to all Orejime cookies by setting the orejime-anonymous cookie + // Pre-agree to all Orejime cookies by setting the orejime cookie // This just ensures it doesn't get in the way of matching other objects in the page. - cy.setCookie('orejime-anonymous', '{%22authentication%22:true%2C%22preferences%22:true%2C%22acknowledgement%22:true%2C%22google-analytics%22:true%2C%22google-recaptcha%22:true}'); + cy.setCookie('orejime', '{%22authentication%22:true%2C%22preferences%22:true%2C%22acknowledgement%22:true%2C%22google-analytics%22:true%2C%22google-recaptcha%22:true}'); // Remove any CSRF cookies saved from prior tests cy.clearCookie(DSPACE_XSRF_COOKIE); diff --git a/package-lock.json b/package-lock.json index 43798601f9..4cbcfca916 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5975,6 +5975,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.4.1.tgz", "integrity": "sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==", + "dev": true, "dependencies": { "detect-libc": "^1.0.3", "is-glob": "^4.0.3", @@ -6010,6 +6011,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "android" @@ -6029,6 +6031,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "darwin" @@ -6048,6 +6051,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "darwin" @@ -6067,6 +6071,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "freebsd" @@ -6086,6 +6091,7 @@ "cpu": [ "arm" ], + "dev": true, "optional": true, "os": [ "linux" @@ -6105,6 +6111,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -6124,6 +6131,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -6143,6 +6151,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -6162,6 +6171,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -6181,6 +6191,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -6200,6 +6211,7 @@ "cpu": [ "ia32" ], + "dev": true, "optional": true, "os": [ "win32" @@ -6219,6 +6231,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -6234,7 +6247,8 @@ "node_modules/@parcel/watcher/node_modules/node-addon-api": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", - "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==" + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "dev": true }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", @@ -10735,6 +10749,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "dev": true, "bin": { "detect-libc": "bin/detect-libc.js" }, @@ -20599,6 +20614,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", + "dev": true, "dependencies": { "readdirp": "^4.0.1" }, @@ -20619,6 +20635,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", + "dev": true, "engines": { "node": ">= 14.16.0" }, diff --git a/src/app/core/google-recaptcha/google-recaptcha.service.ts b/src/app/core/google-recaptcha/google-recaptcha.service.ts index c23223b678..580bc876f4 100644 --- a/src/app/core/google-recaptcha/google-recaptcha.service.ts +++ b/src/app/core/google-recaptcha/google-recaptcha.service.ts @@ -105,7 +105,7 @@ export class GoogleRecaptchaService { tap(([recaptchaVersionRD, recaptchaModeRD, recaptchaKeyRD]) => { if ( - this.cookieService.get('orejime-anonymous') && this.cookieService.get('orejime-anonymous')[CAPTCHA_NAME] && + this.cookieService.get('orejime') && this.cookieService.get('orejime')[CAPTCHA_NAME] && recaptchaKeyRD.hasSucceeded && recaptchaVersionRD.hasSucceeded && isNotEmpty(recaptchaVersionRD.payload?.values) && isNotEmpty(recaptchaKeyRD.payload?.values) ) { diff --git a/src/app/register-email-form/register-email-form.component.ts b/src/app/register-email-form/register-email-form.component.ts index 90841f3088..e71227f504 100644 --- a/src/app/register-email-form/register-email-form.component.ts +++ b/src/app/register-email-form/register-email-form.component.ts @@ -247,7 +247,7 @@ export class RegisterEmailFormComponent implements OnDestroy, OnInit { * Return true if the user has accepted the required cookies for reCaptcha */ isRecaptchaCookieAccepted(): boolean { - const orejimeAnonymousCookie = this.cookieService.get('orejime-anonymous'); + const orejimeAnonymousCookie = this.cookieService.get('orejime'); return isNotEmpty(orejimeAnonymousCookie) ? orejimeAnonymousCookie[CAPTCHA_NAME] : false; } diff --git a/src/app/shared/cookies/orejime-configuration.ts b/src/app/shared/cookies/orejime-configuration.ts index fd275f7e77..e995e04ef5 100644 --- a/src/app/shared/cookies/orejime-configuration.ts +++ b/src/app/shared/cookies/orejime-configuration.ts @@ -15,7 +15,7 @@ import { NativeWindowRef } from '../../core/services/window.service'; */ export const HAS_AGREED_END_USER = 'dsHasAgreedEndUser'; -export const ANONYMOUS_STORAGE_NAME_OREJIME = 'orejime-anonymous'; +export const ANONYMOUS_STORAGE_NAME_OREJIME = 'orejime'; export const GOOGLE_ANALYTICS_OREJIME_KEY = 'google-analytics'; diff --git a/src/styles/_custom_variables.scss b/src/styles/_custom_variables.scss index 682306c636..6bddfd58e9 100644 --- a/src/styles/_custom_variables.scss +++ b/src/styles/_custom_variables.scss @@ -148,6 +148,6 @@ --ds-process-overview-table-info-column-width: 250px; --ds-process-overview-table-actions-column-width: 80px; - --green1: #1FB300; // This variable represents the success color for the Orejime cookie banner + --green1: #1c710a; // This variable represents the success color for the Orejime cookie banner --button-text-color-cookie: #fff; // This variable represents the text color for buttons in the Orejime cookie banner } diff --git a/src/styles/_global-styles.scss b/src/styles/_global-styles.scss index 3e0e8c5f82..4934ec3d35 100644 --- a/src/styles/_global-styles.scss +++ b/src/styles/_global-styles.scss @@ -56,7 +56,7 @@ body { } a { - color: var(--green1); + color: var(--bs-white); } } From e516ae86532904223e3dd65c6dc95d63d977c070 Mon Sep 17 00:00:00 2001 From: Andrea Barbasso <´andrea.barbasso@4science.com´> Date: Thu, 31 Oct 2024 11:32:54 +0100 Subject: [PATCH 0778/1286] [CST-15593] go back to orejime-anonymous cookie --- cypress/support/e2e.ts | 4 ++-- src/app/core/google-recaptcha/google-recaptcha.service.ts | 2 +- src/app/register-email-form/register-email-form.component.ts | 2 +- src/app/shared/cookies/orejime-configuration.ts | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts index 3c9f4e7b56..c1b6bc6d3f 100644 --- a/cypress/support/e2e.ts +++ b/cypress/support/e2e.ts @@ -54,9 +54,9 @@ before(() => { // Runs once before the first test in each "block" beforeEach(() => { - // Pre-agree to all Orejime cookies by setting the orejime cookie + // Pre-agree to all Orejime cookies by setting the orejime-anonymous cookie // This just ensures it doesn't get in the way of matching other objects in the page. - cy.setCookie('orejime', '{%22authentication%22:true%2C%22preferences%22:true%2C%22acknowledgement%22:true%2C%22google-analytics%22:true%2C%22google-recaptcha%22:true}'); + cy.setCookie('orejime-anonymous', '{%22authentication%22:true%2C%22preferences%22:true%2C%22acknowledgement%22:true%2C%22google-analytics%22:true%2C%22google-recaptcha%22:true}'); // Remove any CSRF cookies saved from prior tests cy.clearCookie(DSPACE_XSRF_COOKIE); diff --git a/src/app/core/google-recaptcha/google-recaptcha.service.ts b/src/app/core/google-recaptcha/google-recaptcha.service.ts index 580bc876f4..c23223b678 100644 --- a/src/app/core/google-recaptcha/google-recaptcha.service.ts +++ b/src/app/core/google-recaptcha/google-recaptcha.service.ts @@ -105,7 +105,7 @@ export class GoogleRecaptchaService { tap(([recaptchaVersionRD, recaptchaModeRD, recaptchaKeyRD]) => { if ( - this.cookieService.get('orejime') && this.cookieService.get('orejime')[CAPTCHA_NAME] && + this.cookieService.get('orejime-anonymous') && this.cookieService.get('orejime-anonymous')[CAPTCHA_NAME] && recaptchaKeyRD.hasSucceeded && recaptchaVersionRD.hasSucceeded && isNotEmpty(recaptchaVersionRD.payload?.values) && isNotEmpty(recaptchaKeyRD.payload?.values) ) { diff --git a/src/app/register-email-form/register-email-form.component.ts b/src/app/register-email-form/register-email-form.component.ts index e71227f504..90841f3088 100644 --- a/src/app/register-email-form/register-email-form.component.ts +++ b/src/app/register-email-form/register-email-form.component.ts @@ -247,7 +247,7 @@ export class RegisterEmailFormComponent implements OnDestroy, OnInit { * Return true if the user has accepted the required cookies for reCaptcha */ isRecaptchaCookieAccepted(): boolean { - const orejimeAnonymousCookie = this.cookieService.get('orejime'); + const orejimeAnonymousCookie = this.cookieService.get('orejime-anonymous'); return isNotEmpty(orejimeAnonymousCookie) ? orejimeAnonymousCookie[CAPTCHA_NAME] : false; } diff --git a/src/app/shared/cookies/orejime-configuration.ts b/src/app/shared/cookies/orejime-configuration.ts index e995e04ef5..aea2bc3338 100644 --- a/src/app/shared/cookies/orejime-configuration.ts +++ b/src/app/shared/cookies/orejime-configuration.ts @@ -15,7 +15,7 @@ import { NativeWindowRef } from '../../core/services/window.service'; */ export const HAS_AGREED_END_USER = 'dsHasAgreedEndUser'; -export const ANONYMOUS_STORAGE_NAME_OREJIME = 'orejime'; +export const ANONYMOUS_STORAGE_NAME_OREJIME = 'orejime-anonymous'; export const GOOGLE_ANALYTICS_OREJIME_KEY = 'google-analytics'; @@ -26,7 +26,7 @@ export const GOOGLE_ANALYTICS_OREJIME_KEY = 'google-analytics'; export function getOrejimeConfiguration(_window: NativeWindowRef): any { return { - storageName: ANONYMOUS_STORAGE_NAME_OREJIME, + cookieName: ANONYMOUS_STORAGE_NAME_OREJIME, privacyPolicy: './info/privacy', From 625771837770a9fa1d5b6441474660ce256e18f2 Mon Sep 17 00:00:00 2001 From: Andrea Barbasso <´andrea.barbasso@4science.com´> Date: Thu, 31 Oct 2024 13:00:21 +0100 Subject: [PATCH 0779/1286] [CST-15593] improve tests reliability --- cypress/e2e/admin-add-new-modals.cy.ts | 12 ++++++------ cypress/e2e/admin-edit-modals.cy.ts | 6 +++--- cypress/e2e/admin-export-modals.cy.ts | 4 ++-- cypress/e2e/admin-sidebar.cy.ts | 2 +- .../admin-sidebar-section.component.html | 4 +++- .../admin-sidebar-section.component.ts | 3 ++- .../admin/admin-sidebar/admin-sidebar.component.html | 1 + .../admin/admin-sidebar/admin-sidebar.component.ts | 3 ++- .../expandable-admin-sidebar-section.component.html | 2 +- .../expandable-admin-sidebar-section.component.ts | 3 ++- .../collection-item-mapper.component.html | 2 +- .../collection-item-mapper.component.ts | 2 ++ .../item-collection-mapper.component.html | 2 +- .../item-collection-mapper.component.ts | 2 ++ .../admin/admin-sidebar/admin-sidebar.component.ts | 3 ++- 15 files changed, 31 insertions(+), 20 deletions(-) diff --git a/cypress/e2e/admin-add-new-modals.cy.ts b/cypress/e2e/admin-add-new-modals.cy.ts index 565ae154f1..c783972b75 100644 --- a/cypress/e2e/admin-add-new-modals.cy.ts +++ b/cypress/e2e/admin-add-new-modals.cy.ts @@ -9,10 +9,10 @@ describe('Admin Add New Modals', () => { it('Add new Community modal should pass accessibility tests', () => { // Pin the sidebar open - cy.get('#sidebar-collapse-toggle').click(); + cy.get('[data-test="sidebar-collapse-toggle"]').click(); // Click on entry of menu - cy.get('#admin-menu-section-new-title').click(); + cy.get('[data-test="admin-menu-section-new-title"]').click(); cy.get('a[data-test="menu.section.new_community"]').click(); @@ -22,10 +22,10 @@ describe('Admin Add New Modals', () => { it('Add new Collection modal should pass accessibility tests', () => { // Pin the sidebar open - cy.get('#sidebar-collapse-toggle').click(); + cy.get('[data-test="sidebar-collapse-toggle"]').click(); // Click on entry of menu - cy.get('#admin-menu-section-new-title').click(); + cy.get('[data-test="admin-menu-section-new-title"]').click(); cy.get('a[data-test="menu.section.new_collection"]').click(); @@ -35,10 +35,10 @@ describe('Admin Add New Modals', () => { it('Add new Item modal should pass accessibility tests', () => { // Pin the sidebar open - cy.get('#sidebar-collapse-toggle').click(); + cy.get('[data-test="sidebar-collapse-toggle"]').click(); // Click on entry of menu - cy.get('#admin-menu-section-new-title').click(); + cy.get('[data-test="admin-menu-section-new-title"]').click(); cy.get('a[data-test="menu.section.new_item"]').click(); diff --git a/cypress/e2e/admin-edit-modals.cy.ts b/cypress/e2e/admin-edit-modals.cy.ts index e96d6ce898..f2f18de877 100644 --- a/cypress/e2e/admin-edit-modals.cy.ts +++ b/cypress/e2e/admin-edit-modals.cy.ts @@ -9,7 +9,7 @@ describe('Admin Edit Modals', () => { it('Edit Community modal should pass accessibility tests', () => { // Pin the sidebar open - cy.get('#sidebar-collapse-toggle').click(); + cy.get('[data-test="sidebar-collapse-toggle"]').click(); // Click on entry of menu cy.get('#admin-menu-section-edit-title').click(); @@ -22,7 +22,7 @@ describe('Admin Edit Modals', () => { it('Edit Collection modal should pass accessibility tests', () => { // Pin the sidebar open - cy.get('#sidebar-collapse-toggle').click(); + cy.get('[data-test="sidebar-collapse-toggle"]').click(); // Click on entry of menu cy.get('#admin-menu-section-edit-title').click(); @@ -35,7 +35,7 @@ describe('Admin Edit Modals', () => { it('Edit Item modal should pass accessibility tests', () => { // Pin the sidebar open - cy.get('#sidebar-collapse-toggle').click(); + cy.get('[data-test="sidebar-collapse-toggle"]').click(); // Click on entry of menu cy.get('#admin-menu-section-edit-title').click(); diff --git a/cypress/e2e/admin-export-modals.cy.ts b/cypress/e2e/admin-export-modals.cy.ts index 9f69764d19..0efe040fc8 100644 --- a/cypress/e2e/admin-export-modals.cy.ts +++ b/cypress/e2e/admin-export-modals.cy.ts @@ -9,7 +9,7 @@ describe('Admin Export Modals', () => { it('Export metadata modal should pass accessibility tests', () => { // Pin the sidebar open - cy.get('#sidebar-collapse-toggle').click(); + cy.get('[data-test="sidebar-collapse-toggle"]').click(); // Click on entry of menu cy.get('#admin-menu-section-export-title').click(); @@ -22,7 +22,7 @@ describe('Admin Export Modals', () => { it('Export batch modal should pass accessibility tests', () => { // Pin the sidebar open - cy.get('#sidebar-collapse-toggle').click(); + cy.get('[data-test="sidebar-collapse-toggle"]').click(); // Click on entry of menu cy.get('#admin-menu-section-export-title').click(); diff --git a/cypress/e2e/admin-sidebar.cy.ts b/cypress/e2e/admin-sidebar.cy.ts index be1c9d4ef2..318bf2b27e 100644 --- a/cypress/e2e/admin-sidebar.cy.ts +++ b/cypress/e2e/admin-sidebar.cy.ts @@ -10,7 +10,7 @@ describe('Admin Sidebar', () => { it('should be pinnable and pass accessibility tests', () => { // Pin the sidebar open - cy.get('#sidebar-collapse-toggle').click(); + cy.get('[data-test="sidebar-collapse-toggle"]').click(); // Click on every expandable section to open all menus cy.get('ds-expandable-admin-sidebar-section').click({ multiple: true }); diff --git a/src/app/admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component.html b/src/app/admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component.html index 24ba17fff4..30a7a3353b 100644 --- a/src/app/admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component.html +++ b/src/app/admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component.html @@ -14,7 +14,9 @@ diff --git a/src/app/admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component.ts b/src/app/admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component.ts index ff9897ce9e..2910f948a2 100644 --- a/src/app/admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component.ts +++ b/src/app/admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component.ts @@ -17,6 +17,7 @@ import { MenuID } from '../../../shared/menu/menu-id.model'; import { LinkMenuItemModel } from '../../../shared/menu/menu-item/models/link.model'; import { MenuSection } from '../../../shared/menu/menu-section.model'; import { MenuSectionComponent } from '../../../shared/menu/menu-section/menu-section.component'; +import { BrowserOnlyPipe } from '../../../shared/utils/browser-only.pipe'; /** * Represents a non-expandable section in the admin sidebar @@ -26,7 +27,7 @@ import { MenuSectionComponent } from '../../../shared/menu/menu-section/menu-sec templateUrl: './admin-sidebar-section.component.html', styleUrls: ['./admin-sidebar-section.component.scss'], standalone: true, - imports: [NgClass, RouterLink, TranslateModule], + imports: [NgClass, RouterLink, TranslateModule, BrowserOnlyPipe], }) export class AdminSidebarSectionComponent extends MenuSectionComponent implements OnInit { diff --git a/src/app/admin/admin-sidebar/admin-sidebar.component.html b/src/app/admin/admin-sidebar/admin-sidebar.component.html index f3d5409a64..41376f777e 100644 --- a/src/app/admin/admin-sidebar/admin-sidebar.component.html +++ b/src/app/admin/admin-sidebar/admin-sidebar.component.html @@ -42,6 +42,7 @@
@@ -17,9 +17,9 @@
-

+

{{'quality-assurance.events.topic' | translate}} {{this.showTopic}} -

+ @@ -247,7 +247,7 @@